小工具知识网

当前位置: 首页 > 行业知识 > Android Framework 常见解决方案(24)屏蔽FallbackHome,去除 Android正在启动,直接进入Launcher

行业知识

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

2026-11-06 17:17:52 来源:互联网转载

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,所以注释掉。修改内容为:

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

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

    public class WindowManagerService extends IWindowManager.Stub        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {    //...    private void performEnableScreen() {        synchronized (mGlobalLock) {            ProtoLog.i(WM_DEBUG_BOOT, "performEnableScreen: mDisplayEnabled=%b"                            + " mForceDisplayEnabled=%b" + " mShowingBootMessages=%b"                            + " mSystemBooted=%b mOnlyCore=%b. %s", mDisplayEnabled,                    mForceDisplayEnabled, mShowingBootMessages, mSystemBooted, mOnlyCore,                    new RuntimeException("here").fillInStackTrace());            if (mDisplayEnabled) {                return;            }            if (!mSystemBooted && !mShowingBootMessages) {                return;            }            if (!mShowingBootMessages && !mPolicy.canDismissBootAnimation()) {                return;            }            // Don't enable the screen until all existing windows have been drawn.            if (!mForceDisplayEnabled) {                if (mBootWaitForWindowsStartTime = 0; i--) {                    if (mRoot.getChildAt(i).shouldWaitForSystemDecorWindowsOnBoot()) {                        return;                    }                }                long waitTime = SystemClock.elapsedRealtime() - mBootWaitForWindowsStartTime;                mBootWaitForWindowsStartTime = -1;                if (waitTime > 10) {                    ProtoLog.i(WM_DEBUG_BOOT,                            "performEnableScreen: Waited %dms for all windows to be drawn",                            waitTime);                }            }    //AGS add start    //播放完开机动画后不退出开机动画,注释掉如下代码即可。    /*            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.                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!");                    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!");            }            */            //AGS add end            EventLogTags.writeWmBootAnimationDone(SystemClock.uptimeMillis());            Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);            mDisplayEnabled = true;            ProtoLog.i(WM_DEBUG_SCREEN_ON, "******************** ENABLING SCREEN!");            // Enable input dispatch.            mInputManagerCallback.setEventDispatchingLw(mEventDispatchingEnabled);        }        try {            mActivityManager.bootAnimationComplete();        } catch (RemoteException e) {        }        mPolicy.enableScreenAfterBoot();// Make sure the last requested orientation has been applied.        updateRotationUnchecked(false, false);    }    //...}

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

    public final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener {/** Called when the windows associated app window container are drawn. */    //...    private void onWindowsDrawn(long timestampNs) {        if (mPerf != null && perfActivityBoostHandler > 0) {            mPerf.perfLockReleaseHandler(perfActivityBoostHandler);            perfActivityBoostHandler = -1;        } else if (perfActivityBoostHandler > 0) {            Slog.w(TAG, "activity boost didn't release as expected");        }        final TransitionInfoSnapshot info = mTaskSupervisor                .getActivityMetricsLogger().notifyWindowsDrawn(this, timestampNs);        final boolean validInfo = info != null;        final int windowsDrawnDelayMs = validInfo ? info.windowsDrawnDelayMs : INVALID_DELAY;        final @WaitResult.LaunchState int launchState =                validInfo ? info.getLaunchState() : WaitResult.LAUNCH_STATE_UNKNOWN;        // The activity may have been requested to be invisible (another activity has been launched)        // so there is no valid info. But if it is the current top activity (e.g. sleeping), the        // invalid state is still reported to make sure the waiting result is notified.        if (validInfo || this == getDisplayArea().topRunningActivity()) {            mTaskSupervisor.reportActivityLaunched(false /* timeout */, this,                    windowsDrawnDelayMs, launchState);        }        finishLaunchTickingLocked();        if (task != null) {            task.setHasBeenVisible(true);        }        //AGS add start        if (isHomeIntent(intent) && shortComponentName != null && !shortComponentName.contains("FallbackHome")) {            SystemProperties.set("service.bootanim.exit", "1");    //这里就是将上面注掉的代码copy过来            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, // BOOT_FINISHED                            data, null, 0);                    data.recycle();                }            } catch (RemoteException ex) {                Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");            }        }        //AGS add end        mLaunchRootTask = null;    }    //...}

上一篇:穿越Redis单线程迷雾:从面试场景到技术内核的解读

下一篇:银行窗口怎么做好服务器?