1 原理說明
開機以后,設備會有一個“android正在啟動”這樣的彈框,這個界面是一個叫FallbackHome的Activity來展示的。FallbackHome機制是Android系統(tǒng)啟動過程中的一種降級處理機制。當系統(tǒng)啟動時,如果默認的Launcher應用無法正常加載或出現(xiàn)錯誤,系統(tǒng)會自動啟用FallbackHome來替代默認Launcher。但一般為了改善產(chǎn)品體驗,最終決定移除彈窗頁面,直接進入默認的Launcher,避免彈窗對用戶界面的干擾。具體而言,F(xiàn)allbackHome機制包括以下內(nèi)容:
- 默認Launcher故障檢測:系統(tǒng)會檢測默認的Launcher應用是否能夠正常加載和運行。如果檢測到故障,系統(tǒng)將啟動FallbackHome。
- 解鎖過程中的彈窗:在系統(tǒng)解鎖之前,可能會出現(xiàn)一個"Android正在啟動"的彈窗頁面,用于指示系統(tǒng)正在加載和準備。這個彈窗頁面通常出現(xiàn)在桌面壁紙上,用戶需要等待系統(tǒng)完全解鎖后才能進入默認的Launcher。
去掉FallbackHome的效果實際上是讓FallbackHome的view不顯示,然后開機啟動動畫延長一下,直到系統(tǒng)解鎖后再停止開機動畫,完成這樣較為順滑的過渡。
2 修改方案(Android Q R S)
具體修改方案如下(這里以S版本修改為主,Q和R有一些差異但原理不變):
@1 修改文件為:AOSP/packages/apps/Settings$ vim src/com/android/settings/FallbackHome.java,目的為FallbackHome不顯示View,所以注釋掉。修改內(nèi)容為:
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
//不顯示任何內(nèi)容,如果是黑色銜接,直接改這里就足夠了,如果不是則需要 2,3步驟內(nèi)容的修改
/* 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,目的為播放完開機動畫后不退出開機動畫,所以注釋掉即可。修改內(nèi)容為:文章來源:http://www.zghlxwxcb.cn/news/detail-819579.html
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,目的為解鎖后再結束開機動畫。修改內(nèi)容為:文章來源地址http://www.zghlxwxcb.cn/news/detail-819579.html
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;
}
//...
}
到了這里,關于Android Framework 常見解決方案(24)屏蔽FallbackHome,去除 Android正在啟動,直接進入Launcher的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!