赞
踩
Android 是先启动FallbackHome,再启动Launcher,就导致了在Launcher启动之前,开机动画就退出了,产生黑屏现象。关于开机动画的退出流程,请参考:Android 11 开机动画启动流程分析
解决这个问题,思想就是将开机动画延长到Launcher启动后再退出,有两种方案:
方案一:
在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最后才调用的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。