Android 11 解决开机动画到Launcher黑屏问题
Android 是先启动FallbackHome,再启动Launcher,就导致了在Launcher启动之前,开机动画就退出了,产生黑屏现象。
·
Android 是先启动FallbackHome,再启动Launcher,就导致了在Launcher启动之前,开机动画就退出了,产生黑屏现象。关于开机动画的退出流程,请参考:Android 11 开机动画启动流程分析
解决这个问题,思想就是将开机动画延长到Launcher启动后再退出,有两种方案:
- 将performEnableScreen中的设置关闭开机动画属性的代码移动到Launcher绘制的地方
- Launcher启动后,再调用WindowManagerService的enableScreenAfterBoot方法,设置mSystemBooted为true,让performEnableScreen继续往下执行,设置关闭开机动画
代码实现
方案一:
在APP绘制的时候,都会调用到ActivityRecord.java的onWindowsDrawn方法,调用栈如下:
onWindowsDrawn shortComponentName:com.android.settings/.FallbackHome
java.lang.Exception
at com.android.server.wm.ActivityRecord.onWindowsDrawn(ActivityRecord.java:5419)
at com.android.server.wm.ActivityRecord.updateReportedVisibilityLocked(ActivityRecord.java:5544)
at com.android.server.wm.ActivityRecord.onFirstWindowDrawn(ActivityRecord.java:5349)
at com.android.server.wm.WindowState.performShowLocked(WindowState.java:4438)
at com.android.server.wm.WindowStateAnimator.commitFinishDrawingLocked(WindowStateAnimator.java:375)
at com.android.server.wm.DisplayContent.lambda$new$8$DisplayContent(DisplayContent.java:889)
at com.android.server.wm.-$$Lambda$DisplayContent$qxt4izS31fb0LF2uo_OF9DMa7gc.accept(Unknown Source:4)
at com.android.server.wm.WindowContainer$ForAllWindowsConsumerWrapper.apply(WindowContainer.java:1984)
at com.android.server.wm.WindowContainer$ForAllWindowsConsumerWrapper.apply(WindowContainer.java:1974)
at com.android.server.wm.WindowState.applyInOrderWithImeWindows(WindowState.java:4651)
at com.android.server.wm.WindowState.forAllWindows(WindowState.java:4550)
at com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:1302)
at com.android.server.wm.ActivityRecord.forAllWindowsUnchecked(ActivityRecord.java:3641)
at com.android.server.wm.ActivityRecord.forAllWindows(ActivityRecord.java:3636)
at com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:1302)
at com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:1302)
at com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:1302)
at com.android.server.wm.TaskDisplayArea.forAllWindows(TaskDisplayArea.java:488)
at com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:1302)
at com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:1302)
at com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:1319)
at com.android.server.wm.DisplayContent.applySurfaceChangesTransaction(DisplayContent.java:4016)
at com.android.server.wm.RootWindowContainer.applySurfaceChangesTransaction(RootWindowContainer.java:1070)
at com.android.server.wm.RootWindowContainer.performSurfacePlacementNoTrace(RootWindowContainer.java:850)
at com.android.server.wm.RootWindowContainer.performSurfacePlacement(RootWindowContainer.java:807)
at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop(WindowSurfacePlacer.java:178)
at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement(WindowSurfacePlacer.java:127)
at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement(WindowSurfacePlacer.java:116)
at com.android.server.wm.WindowSurfacePlacer$Traverser.run(WindowSurfacePlacer.java:58)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.os.HandlerThread.run(HandlerThread.java:67)
at com.android.server.ServiceThread.run(ServiceThread.java:44)
所以实现方案如下:
1,在onWindowsDrawn方法中添加:
//启动的是home且不是FallbackHome,表示是Launcher,Launcher绘制再退出开机动画
if (isHomeIntent(intent) && shortComponentName != null && !shortComponentName.contains("FallbackHome")) {
SystemProperties.set("service.bootanim.exit", "1");
Log.e(TAG_WM, "real home....." + shortComponentName);
try {
IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
if (surfaceFlinger != null) {
Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
Parcel data = Parcel.obtain();
data.writeInterfaceToken("android.ui.ISurfaceComposer");
surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
data.recycle();
}
} catch (RemoteException ex) {
Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
}
}
2,将 performEnableScreen中的代码注释掉
//frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java
private void performEnableScreen() {
//......
/*if (!mBootAnimationStopped) {
Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
// stop boot animation
// formerly we would just kill the process, but we now ask it to exit so it
// can choose where to stop the animation.
android.util.Log.d("test1","performEnableScreen2:",new Exception());
SystemProperties.set("service.bootanim.exit", "1");
mBootAnimationStopped = true;
}
if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
ProtoLog.i(WM_DEBUG_BOOT, "performEnableScreen: Waiting for anim complete");
return;
}
try {
IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
if (surfaceFlinger != null) {
ProtoLog.i(WM_ERROR, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
android.util.Log.d("test1","performEnableScreen3:",new Exception());
Parcel data = Parcel.obtain();
data.writeInterfaceToken("android.ui.ISurfaceComposer");
surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
data, null, 0);
data.recycle();
}
} catch (RemoteException ex) {
ProtoLog.e(WM_ERROR, "Boot completed: SurfaceFlinger is dead!");
}
*/
//......
}
方案二
//frameworks\base\services\core\java\com\android\server\wm\ActivityTaskManagerService.java
public static boolean isNeedDelayEnableScreenAfterBoot = false;
@Override
public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityIdle");
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r == null) {
return;
}
//add:如果是FallbackHome,则设置延迟调用EnableScreenAfterBoot
if (r.info.packageName.equals("com.android.settings") && r.info.name.equals("com.android.settings.FallbackHome")) {
isNeedDelayEnableScreenAfterBoot = true;
} else {
if (isNeedDelayEnableScreenAfterBoot) {
mWindowManager.enableScreenAfterBoot();
}
isNeedDelayEnableScreenAfterBoot = false;
}
//add end
@Override
public void enableScreenAfterBoot(boolean booted) {
writeBootProgressEnableScreen(SystemClock.uptimeMillis());
//add:如果表示延迟启动,则在这里不调用enableScreenAfterBoot
if (!isNeedDelayEnableScreenAfterBoot) {
mWindowManager.enableScreenAfterBoot();
}
//mWindowManager.enableScreenAfterBoot();
//add end
synchronized (mGlobalLock) {
updateEventDispatchingLocked(booted);
}
}
final void finishBooting() {
TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
Trace.TRACE_TAG_ACTIVITY_MANAGER);
t.traceBegin("FinishBooting");
synchronized (this) {
//add: 注意这里需要添加条件判断,否则导致fallbackhome 不退出
if (!mBootAnimationComplete && !ActivityTaskManagerService.isNeedDelayEnableScreenAfterBoot) {
注意要增加条件判断,否则导致fallbackhome 不退出卡在开机动画。因为mBootAnimationComplete只有在bootAnimationComplete里设置为true。flase的情况下,finishBooting代码往下不会继续执行。而 bootAnimationComplete是在performEnableScreen最后才调用的。
更多推荐
已为社区贡献2条内容
所有评论(0)