当前位置:   article > 正文

Android Framework 常见解决方案(24)屏蔽FallbackHome,去除 Android正在启动,直接进入Launcher_android fallbackhome

android fallbackhome

1 原理说明

开机以后,设备会有一个“android正在启动”这样的弹框,这个界面是一个叫FallbackHome的Activity来展示的。FallbackHome机制是Android系统启动过程中的一种降级处理机制。当系统启动时,如果默认的Launcher应用无法正常加载或出现错误,系统会自动启用FallbackHome来替代默认Launcher。但一般为了改善产品体验,最终决定移除弹窗页面,直接进入默认的Launcher,避免弹窗对用户界面的干扰。具体而言,FallbackHome机制包括以下内容:

  • 默认Launcher故障检测:系统会检测默认的Launcher应用是否能够正常加载和运行。如果检测到故障,系统将启动FallbackHome。
  • 解锁过程中的弹窗:在系统解锁之前,可能会出现一个"Android正在启动"的弹窗页面,用于指示系统正在加载和准备。这个弹窗页面通常出现在桌面壁纸上,用户需要等待系统完全解锁后才能进入默认的Launcher。

去掉FallbackHome的效果实际上是让FallbackHome的view不显示,然后开机启动动画延长一下,直到系统解锁后再停止开机动画,完成这样较为顺滑的过渡。

2 修改方案(Android Q R S)

具体修改方案如下(这里以S版本修改为主,Q和R有一些差异但原理不变)

@1 修改文件为:AOSP/packages/apps/Settings$ vim src/com/android/settings/FallbackHome.java,目的为FallbackHome不显示View,所以注释掉。修改内容为:

  1. public class FallbackHome extends Activity {
  2. private static final String TAG = "FallbackHome";
  3. private static final int PROGRESS_TIMEOUT = 2000;
  4. private boolean mProvisioned;
  5. private WallpaperManager mWallManager;
  6. private final Runnable mProgressTimeoutRunnable = () -> {
  7. //AGS add start
  8. //不显示任何内容,如果是黑色衔接,直接改这里就足够了,如果不是则需要 2,3步骤内容的修改
  9. /* View v = getLayoutInflater().inflate(
  10. R.layout.fallback_home_finishing_boot, null);
  11. setContentView(v);
  12. v.setAlpha(0f);
  13. v.animate()
  14. .alpha(1f)
  15. .setDuration(500)
  16. .setInterpolator(AnimationUtils.loadInterpolator(
  17. this, android.R.interpolator.fast_out_slow_in))
  18. .start();*/
  19. //AGS add end
  20. getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
  21. };
  22. //...
  23. }

@2 修改文件为:AOSP/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java,目的为播放完开机动画后不退出开机动画,所以注释掉即可。修改内容为:

  1. public class WindowManagerService extends IWindowManager.Stub
  2. implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
  3. //...
  4. private void performEnableScreen() {
  5. synchronized (mGlobalLock) {
  6. ProtoLog.i(WM_DEBUG_BOOT, "performEnableScreen: mDisplayEnabled=%b"
  7. + " mForceDisplayEnabled=%b" + " mShowingBootMessages=%b"
  8. + " mSystemBooted=%b mOnlyCore=%b. %s", mDisplayEnabled,
  9. mForceDisplayEnabled, mShowingBootMessages, mSystemBooted, mOnlyCore,
  10. new RuntimeException("here").fillInStackTrace());
  11. if (mDisplayEnabled) {
  12. return;
  13. }
  14. if (!mSystemBooted && !mShowingBootMessages) {
  15. return;
  16. }
  17. if (!mShowingBootMessages && !mPolicy.canDismissBootAnimation()) {
  18. return;
  19. }
  20. // Don't enable the screen until all existing windows have been drawn.
  21. if (!mForceDisplayEnabled) {
  22. if (mBootWaitForWindowsStartTime < 0) {
  23. // First time we will start waiting for all windows to be drawn.
  24. mBootWaitForWindowsStartTime = SystemClock.elapsedRealtime();
  25. }
  26. for (int i = mRoot.getChildCount() - 1; i >= 0; i--) {
  27. if (mRoot.getChildAt(i).shouldWaitForSystemDecorWindowsOnBoot()) {
  28. return;
  29. }
  30. }
  31. long waitTime = SystemClock.elapsedRealtime() - mBootWaitForWindowsStartTime;
  32. mBootWaitForWindowsStartTime = -1;
  33. if (waitTime > 10) {
  34. ProtoLog.i(WM_DEBUG_BOOT,
  35. "performEnableScreen: Waited %dms for all windows to be drawn",
  36. waitTime);
  37. }
  38. }
  39. //AGS add start
  40. //播放完开机动画后不退出开机动画,注释掉如下代码即可。
  41. /*
  42. if (!mBootAnimationStopped) {
  43. Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
  44. // stop boot animation
  45. // formerly we would just kill the process, but we now ask it to exit so it
  46. // can choose where to stop the animation.
  47. SystemProperties.set("service.bootanim.exit", "1");
  48. mBootAnimationStopped = true;
  49. }
  50. if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
  51. ProtoLog.i(WM_DEBUG_BOOT, "performEnableScreen: Waiting for anim complete");
  52. return;
  53. }
  54. try {
  55. IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
  56. if (surfaceFlinger != null) {
  57. ProtoLog.i(WM_ERROR, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
  58. Parcel data = Parcel.obtain();
  59. data.writeInterfaceToken("android.ui.ISurfaceComposer");
  60. surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
  61. data, null, 0);
  62. data.recycle();
  63. }
  64. } catch (RemoteException ex) {
  65. ProtoLog.e(WM_ERROR, "Boot completed: SurfaceFlinger is dead!");
  66. }
  67. */
  68. //AGS add end
  69. EventLogTags.writeWmBootAnimationDone(SystemClock.uptimeMillis());
  70. Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
  71. mDisplayEnabled = true;
  72. ProtoLog.i(WM_DEBUG_SCREEN_ON, "******************** ENABLING SCREEN!");
  73. // Enable input dispatch.
  74. mInputManagerCallback.setEventDispatchingLw(mEventDispatchingEnabled);
  75. }
  76. try {
  77. mActivityManager.bootAnimationComplete();
  78. } catch (RemoteException e) {
  79. }
  80. mPolicy.enableScreenAfterBoot();
  81. // Make sure the last requested orientation has been applied.
  82. updateRotationUnchecked(false, false);
  83. }
  84. //...
  85. }

@3 修改文件为:AOSP/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java,目的为解锁后再结束开机动画。修改内容为:

  1. public final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener {
  2. /** Called when the windows associated app window container are drawn. */
  3. //...
  4. private void onWindowsDrawn(long timestampNs) {
  5. if (mPerf != null && perfActivityBoostHandler > 0) {
  6. mPerf.perfLockReleaseHandler(perfActivityBoostHandler);
  7. perfActivityBoostHandler = -1;
  8. } else if (perfActivityBoostHandler > 0) {
  9. Slog.w(TAG, "activity boost didn't release as expected");
  10. }
  11. final TransitionInfoSnapshot info = mTaskSupervisor
  12. .getActivityMetricsLogger().notifyWindowsDrawn(this, timestampNs);
  13. final boolean validInfo = info != null;
  14. final int windowsDrawnDelayMs = validInfo ? info.windowsDrawnDelayMs : INVALID_DELAY;
  15. final @WaitResult.LaunchState int launchState =
  16. validInfo ? info.getLaunchState() : WaitResult.LAUNCH_STATE_UNKNOWN;
  17. // The activity may have been requested to be invisible (another activity has been launched)
  18. // so there is no valid info. But if it is the current top activity (e.g. sleeping), the
  19. // invalid state is still reported to make sure the waiting result is notified.
  20. if (validInfo || this == getDisplayArea().topRunningActivity()) {
  21. mTaskSupervisor.reportActivityLaunched(false /* timeout */, this,
  22. windowsDrawnDelayMs, launchState);
  23. }
  24. finishLaunchTickingLocked();
  25. if (task != null) {
  26. task.setHasBeenVisible(true);
  27. }
  28. //AGS add start
  29. if (isHomeIntent(intent) && shortComponentName != null && !shortComponentName.contains("FallbackHome")) {
  30. SystemProperties.set("service.bootanim.exit", "1");
  31. //这里就是将上面注掉的代码copy过来
  32. try {
  33. IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
  34. if (surfaceFlinger != null) {
  35. Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
  36. Parcel data = Parcel.obtain();
  37. data.writeInterfaceToken("android.ui.ISurfaceComposer");
  38. surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
  39. data, null, 0);
  40. data.recycle();
  41. }
  42. } catch (RemoteException ex) {
  43. Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
  44. }
  45. }
  46. //AGS add end
  47. mLaunchRootTask = null;
  48. }
  49. //...
  50. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/273536
推荐阅读
相关标签
  

闽ICP备14008679号