一.开机时出现问题:很抱歉,”启动器“已停止运行,源码级调试如下:
日志中Java调用栈如下:
8044 03-27 15:37:40.747 3023 3039 E AndroidRuntime: FATAL EXCEPTION: setWallpaperDimension
8045 03-27 15:37:40.747 3023 3039 E AndroidRuntime: Process: com.android.launcher, PID: 3023
8046 03-27 15:37:40.747 3023 3039 E AndroidRuntime: java.lang.IllegalArgumentException: width and height must be > 0
8047 03-27 15:37:40.747 3023 3039 E AndroidRuntime: at android.os.Parcel.readException(Parcel.java:1544)
8048 03-27 15:37:40.747 3023 3039 E AndroidRuntime: at android.os.Parcel.readException(Parcel.java:1493)
8049 03-27 15:37:40.747 3023 3039 E AndroidRuntime: at android.app.IWallpaperManager$Stub$Proxy.setDimensionHints(IWallpaperManager.java :361)
8050 03-27 15:37:40.747 3023 3039 E AndroidRuntime: at android.app.WallpaperManager.suggestDesiredDimensions(WallpaperManager.java:947)
8051 03-27 15:37:40.747 3023 3039 E AndroidRuntime: at com.android.launcher2.Workspace$2.run(Workspace.java:864)
在源码中添加打印信息,修改如下:
private float wallpaperTravelToScreenWidthRatio(int width, int height) {
// float aspectRatio = width / (float) height;
float h = (float) height;
float aspectRatio = width / h;
Log.d(TAG, "float height:" + h + " aspectRatio:" + aspectRatio);
final float ASPECT_RATIO_LANDSCAPE = 16/10f;
final float ASPECT_RATIO_PORTRAIT = 10/16f;
Log.d(TAG, "SCAPE:" + ASPECT_RATIO_LANDSCAPE + " TRAIT:" + ASPECT_RATIO_PORTRAIT );
final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE = 1.5f;
final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT = 1.2f;
// final float x =
// (WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE - WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT) /
// (ASPECT_RATIO_LANDSCAPE - ASPECT_RATIO_PORTRAIT);
// final float y = WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT - x * ASPECT_RATIO_PORTRAIT;
// Log.d(TAG, "x:" + x + " y:" + y + " aspectRatio:" + aspectRatio);
// return x * aspectRatio + y;
float lp = WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE - WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT;
float st = ASPECT_RATIO_LANDSCAPE - ASPECT_RATIO_PORTRAIT;
final float x = lp / st;
Log.d(TAG, "LANDSCAPE - PORTRAIT:" + lp + " SCAPE - TRAIT:" + st + " x:" + x);
float t = x * ASPECT_RATIO_PORTRAIT;
final float y = WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT - t;
float xt = x * aspectRatio;
Log.d(TAG, "t:" + t + " y:" + y + " xt:" + xt);
return xt + y;
}
protected void setWallpaperDimension() {
Point minDims = new Point();
Point maxDims = new Point();
mLauncher.getWindowManager().getDefaultDisplay().getCurrentSizeRange(minDims, maxDims);
final int maxDim = Math.max(maxDims.x, maxDims.y);
final int minDim = Math.min(minDims.x, minDims.y);
Log.d(TAG, "minDim:" + minDim + " maxDim:" + maxDim);
if (LauncherApplication.isScreenLarge()) {
// mWallpaperWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim));
mWallpaperHeight = maxDim;
float a = wallpaperTravelToScreenWidthRatio(maxDim, minDim);
float b = maxDim * a;
mWallpaperWidth = (int) (b);
Log.d(TAG, "WallpaperTravel:" + a);
Log.d(TAG, "WallpaperTravel * maxDim:" + b);
} else {
mWallpaperWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim);
mWallpaperHeight = maxDim;
}
Log.d(TAG, "mWallpaperWidth:" + mWallpaperWidth + " mWallpaperHeight:" + mWallpaperHeight);
new Thread("setWallpaperDimension") {
public void run() {
mWallpaperManager.suggestDesiredDimensions(mWallpaperWidth, mWallpaperHeight);
}
}.start();
}
打印的日志如下:
03-28 08:47:39.573 2395 2395 D Launcher.Workspace: float height:7.70372E-34 aspectRatio:1.0
03-28 08:47:39.573 2395 2395 D Launcher.Workspace: SCAPE:1.6 TRAIT:0.625
03-28 08:47:39.574 2395 2395 D Launcher.Workspace: LANDSCAPE - PORTRAIT:0.29999995 SCAPE - TRAIT:0.975 x:1.0
03-28 08:47:39.575 2395 2395 D Launcher.Workspace: t:1.0 y:0.0 xt:1.0
03-28 08:47:40.176 2395 2395 D Launcher.Workspace: minDim:951 maxDim:1280
03-28 08:47:40.177 2395 2395 D Launcher.Workspace: float height:7.70372E-34 aspectRatio:1.0
03-28 08:47:40.177 2395 2395 D Launcher.Workspace: SCAPE:1.6 TRAIT:0.625
03-28 08:47:40.178 2395 2395 D Launcher.Workspace: LANDSCAPE - PORTRAIT:0.29999995 SCAPE - TRAIT:0.975 x:1.0
03-28 08:47:40.178 2395 2395 D Launcher.Workspace: t:1.0 y:0.0 xt:1.0
03-28 08:47:40.179 2395 2395 D Launcher.Workspace: WallpaperTravel:2.0
03-28 08:47:40.179 2395 2395 D Launcher.Workspace: WallpaperTravel * maxDim:1.733337E-33
03-28 08:47:40.180 2395 2395 D Launcher.Workspace: mWallpaperWidth:0 mWallpaperHeight:1280
二. 写了一个实现上述运算的TestFloatTC.apk,在interpret-only模式下运行
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
verify();
}
private static final String TAG = "Launcher.Workspace";
//main
public static void verify() {
final int maxDim = 1280;
final int minDim = 951;
float a = wallpaperTravelToScreenWidthRatio(maxDim, minDim);
float b = maxDim * a;
int mWallpaperWidth = (int) (b);
Log.d(TAG, "WallpaperTravel:" + a);
Log.d(TAG, "WallpaperTravel * maxDim:" + b);
Log.d(TAG, "mWallpaperWidth:" + mWallpaperWidth);
}
static float wallpaperTravelToScreenWidthRatio(int width, int height) {
float h = (float) height;
float aspectRatio = width / h;
Log.d(TAG, "float height:" + h + " aspectRatio:" + aspectRatio);
final float SCAPE = 16/10f;
final float TRAIT = 10/16f;
Log.d(TAG, "SCAPE:" + SCAPE + " TRAIT:" + TRAIT );
final float LANDSCAPE = 1.5f;
final float PORTRAIT = 1.2f;
float lp = LANDSCAPE - PORTRAIT;
float st = SCAPE - TRAIT;
final float x = lp / st;
Log.d(TAG, "LANDSCAPE - PORTRAIT:" + lp + " SCAPE - TRAIT:" + st + " x:" + x);
float t = x * TRAIT;
final float y = PORTRAIT - t;
float xt = x * aspectRatio;
Log.d(TAG, "t:" + t + " y:" + y + " xt:" + xt);
return xt + y;
}
}
TestFloatTC.apk 在 interpret-only 模式下测得的结果如下:
6076 03-27 21:25:13.810 2427 2427 D Launcher.Workspace: float height:951.0 aspectRatio:1.3459517
6077 03-27 21:25:13.810 2427 2427 D Launcher.Workspace: SCAPE:1.6 TRAIT:0.625
6078 03-27 21:25:13.813 2427 2427 D Launcher.Workspace: LANDSCAPE - PORTRAIT:0.29999995 SCAPE - TRAIT:0.975 x:0.30769226
6079 03-27 21:25:13.814 2427 2427 D Launcher.Workspace: t:0.19230767 y:1.0076923 xt:0.4141389
6080 03-27 21:25:13.814 2427 2427 D Launcher.Workspace: float height:951.0 aspectRatio:1.3459517
6081 03-27 21:25:13.815 2427 2427 D Launcher.Workspace: SCAPE:1.6 TRAIT:0.625
6082 03-27 21:25:13.816 2427 2427 D Launcher.Workspace: LANDSCAPE - PORTRAIT:0.29999995 SCAPE - TRAIT:0.975 x:0.30769226
6083 03-27 21:25:13.818 2427 2427 D Launcher.Workspace: t:0.19230767 y:1.0076923 xt:0.4141389
6084 03-27 21:25:13.818 2427 2427 D Launcher.Workspace: WallpaperTravel:1.4218313
6085 03-27 21:25:13.819 2427 2427 D Launcher.Workspace: WallpaperTravel * maxDim:1819.944
6086 03-27 21:25:13.820 2427 2427 D Launcher.Workspace: mWallpaperWidth:1819
由此判断,硬件上没有出现问题,是speed模式下整型数据转浮点数据时出现了问题。
三.启动器停止运行的汇编级调试
问题对应的函数的java源代码的简化版:
private float wallpaperTravelToScreenWidthRatio(int width, int height) {
// float aspectRatio = width / (float) height;
// Log.d(TAG, "enter height:" + height);
float h = (float) height;
Log.d(TAG, "after height:" + h);
float t = 951.0f;
Log.d(TAG, "after t:" + t);
return 0.0f;
}
对应的oatdump反汇编的dalvik字节码:
50: float com.android.launcher2.Workspace.wallpaperTravelToScreenWidthRatio(int, int) (dex_method_idx=5418)
DEX CODE:
0x0000: 8270 | int-to-float v0, v7
0x0001: 1a02 d404 | const-string v2, "Launcher.Workspace" // string@1236
0x0003: 2203 1f03 | new-instance v3, java.lang.StringBuilder // type@799
0x0005: 7010 a715 0300 | invoke-direct {v3}, void java.lang.StringBuilder.() // method@5543
0x0008: 1a04 a009 | const-string v4, "after height:" // string@2464
0x000a: 6e20 b015 4300 | invoke-virtual {v3, v4}, java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) // method@5552
0x000d: 0c03 | move-result-object v3
0x000e: 6e20 ab15 0300 | invoke-virtual {v3, v0}, java.lang.StringBuilder java.lang.StringBuilder.append(float) // method@5547
0x0011: 0c03 | move-result-object v3
0x0012: 6e10 b515 0300 | invoke-virtual {v3}, java.lang.String java.lang.StringBuilder.toString() // method@5557
0x0015: 0c03 | move-result-object v3
0x0016: 7120 3707 3200 | invoke-static {v2, v3}, int android.util.Log.d(java.lang.String, java.lang.String) // method@1847
0x0019: 1401 00c0 6d44 | const v1, #+1148043264
0x001c: 1a02 d404 | const-string v2, "Launcher.Workspace" // string@1236
0x001e: 2203 1f03 | new-instance v3, java.lang.StringBuilder // type@799
0x0020: 7010 a715 0300 | invoke-direct {v3}, void java.lang.StringBuilder.() // method@5543
0x0023: 1a04 a109 | const-string v4, "after t:" // string@2465
0x0025: 6e20 b015 4300 | invoke-virtual {v3, v4}, java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) // method@5552
0x0028: 0c03 | move-result-object v3
0x0029: 6e20 ab15 1300 | invoke-virtual {v3, v1}, java.lang.StringBuilder java.lang.StringBuilder.append(float) // method@5547
0x002c: 0c03 | move-result-object v3
0x002d: 6e10 b515 0300 | invoke-virtual {v3}, java.lang.String java.lang.StringBuilder.toString() // method@5557
0x0030: 0c03 | move-result-object v3
0x0031: 7120 3707 3200 | invoke-static {v2, v3}, int android.util.Log.d(java.lang.String, java.lang.String) // method@1847
0x0034: 1202 | const/4 v2, #+0
0x0035: 0f02 | return v2
对应的oatdump反汇编mips代码:
CODE: (code_offset=0x00307f9c size_offset=0x00307f98 size=920)...
// build stack & check overflow
0x00307f9c: 8e220080 lw r2, +128(r17) ; stack_end
0x00307fa0: 27bdfffc addiu r29, r29, -4
0x00307fa4: afbf0000 sw r31, +0(r29)
0x00307fa8: 27a3ffd4 addiu r3, r29, -44
0x00307fac: 0062402b sltu r8, r3, r2
0x00307fb0: 150000a2 bne r8, r0, 0x0030823c ; +652
0x00307fb4: 00000000 nop
0x00307fb8: 0060e825 or r29, r3, r0 // <-- SP(r29)
0x00307fbc: afa40000 sw r4, +0(r29)
0x00307fc0: afa50034 sw r5, +52(r29)
0x00307fc4: afa60038 sw r6, +56(r29)
0x00307fc8: afa7003c sw r7, +60(r29)
print r7
0x00307fcc: c7a0003c lwc1 f0, +60(r29)
0x00307fd0: 46800060 cvt.s.w f1, f0
print f1
0x00307fd4: e7a10014 swc1 f1, +20(r29)
0x00307fd8: 8fa60000 lw r6, +0(r29)
0x00307fdc: 8cc40008 lw r4, +8(r6)
0x00307fe0: 8c840014 lw r4, +20(r4)
0x00307fe4: 8c82135c lw r2, +4956(r4)
0x00307fe8: 10400099 beq r2, r0, 0x00308250 ; +616
0x00307fec: 00000000 nop
0x00307ff0: afa2001c sw r2, +28(r29)
0x00307ff4: 8e390114 lw r25, +276(r17) ; pAllocObject
0x00307ff8: 8fa50000 lw r5, +0(r29)
0x00307ffc: 3404031f ori r4, r0, 799
0x00308000: 0320f809 jalr r25
0x00308004: 00000000 nop
问题比较复杂,等待高人解决。