开机以后,设备会有一个“android正在启动”这样的弹框,这个界面是一个叫FallbackHome的Activity来展示的。FallbackHome机制是Android系统启动过程中的一种降级处理机制。当系统启动时,如果默认的Launcher应用无法正常加载或出现错误,系统会自动启用FallbackHome来替代默认Launcher。但一般为了改善产品体验,最终决定移除弹窗页面,直接进入默认的Launcher,避免弹窗对用户界面的干扰。具体而言,FallbackHome机制包括以下内容:
去掉FallbackHome的效果实际上是让FallbackHome的view不显示,然后开机启动动画延长一下,直到系统解锁后再停止开机动画,完成这样较为顺滑的过渡。
具体修改方案如下(这里以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) {
// First time we will start waiting for all windows to be drawn.
mBootWaitForWindowsStartTime = SystemClock.elapsedRealtime();
}
for (int i = mRoot.getChildCount() - 1; i >= 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;
}
//...
}