原文地址:https://skytoby.github.io/2019/%E5%BC%80%E6%9C%BA%E5%B9%BF%E6%92%ADBOOT_COMPLETED%E5%8F%91%E9%80%81%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90/
基于Android10.0,分析BOOT_COMPLETED的发送流程
开机广播在很多应用中都会用到,用来启动应用程序,下面将介绍开机广播的广播过程。这个过程比较复杂,需要和AcitvityManagerService、WindowManagerService、PackageManagerService等交互,其具体的时序图如下。
在AMS启动那篇文章中已经讲到桌面如何的启动,在桌面启动完成后即桌面Activity onResume之后,就会发送开机广播。桌面Activity onResume阶段,执行了handleResumeActivity方法,见Activity启动过程。handleResumeActivity中加载完window之后将自己实现的IdleHandler添加到自己的消息队列中。
[->ActivityThread.java]
@Override
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
...
//执行onResume方法
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
...
r.nextIdle = mNewActivities;
mNewActivities = r;
if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
//见1.2节
Looper.myQueue().addIdleHandler(new Idler());
}
[->MessageQueue.java]
public void addIdleHandler(@NonNull IdleHandler handler) {
if (handler == null) {
throw new NullPointerException("Can't add a null IdleHandler");
}
synchronized (this) {
//见1.3节
mIdleHandlers.add(handler);
}
}
将IdleHandler加入到消息队列,当消息队列空闲的时候执行idler.queueIdle()的回调。
[->ActivityThread.java]
private class Idler implements MessageQueue.IdleHandler {
@Override
public final boolean queueIdle() {
ActivityClientRecord a = mNewActivities;
boolean stopProfiling = false;
if (mBoundApplication != null && mProfiler.profileFd != null
&& mProfiler.autoStopProfiler) {
stopProfiling = true;
}
if (a != null) {
mNewActivities = null;
//获取AMS的代理
IActivityManager am = ActivityManager.getService();
ActivityClientRecord prev;
do {
if (localLOGV) Slog.v(
TAG, "Reporting idle of " + a +
" finished=" +
(a.activity != null && a.activity.mFinished));
if (a.activity != null && !a.activity.mFinished) {
try {
//见1.4节
am.activityIdle(a.token, a.createdConfig, stopProfiling);
a.createdConfig = null;
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
prev = a;
a = a.nextIdle;
prev.nextIdle = null;
} while (a != null);
}
if (stopProfiling) {
mProfiler.stopProfiling();
}
return false;
}
}
[->ActivityManagerService.java]
@Override
public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
final long origId = Binder.clearCallingIdentity();
synchronized (this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
//见1.5节
ActivityRecord r =
mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,
false /* processPausingActivities */, config);
if (stopProfiling) {
if ((mProfileProc == r.app) && mProfilerInfo != null) {
clearProfilerLocked();
}
}
}
}
Binder.restoreCallingIdentity(origId);
}
[->ActivityStackSupervisor.java]
// Checked.
@GuardedBy("mService")
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
boolean processPausingActivities, Configuration config) {
if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token);
ArrayList finishes = null;
ArrayList startingUsers = null;
int NS = 0;
int NF = 0;
boolean booting = false;
boolean activityRemoved = false;
ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r != null) {
if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternalLocked: Callers="
+ Debug.getCallers(4));
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
//启动结束
r.finishLaunchTickingLocked();
if (fromTimeout) {
reportActivityLaunchedLocked(fromTimeout, r, INVALID_DELAY);
}
// This is a hack to semi-deal with a race condition
// in the client where it can be constructed with a
// newer configuration from when we asked it to launch.
// We'll update with whatever configuration it now says
// it used to launch.
if (config != null) {
r.setLastReportedGlobalConfiguration(config);
}
// We are now idle. If someone is waiting for a thumbnail from
// us, we can now deliver.
r.idle = true;
//Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
if (isFocusedStack(r.getStack()) || fromTimeout) {
//检查系统是否开机完成,见1.5节
booting = checkFinishBootingLocked();
}
}
//移除超时
if (allResumedActivitiesIdle()) {
if (r != null) {
mService.scheduleAppGcsLocked();
}
if (mLaunchingActivity.isHeld()) {
mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
if (VALIDATE_WAKE_LOCK_CALLER &&
Binder.getCallingUid() != Process.myUid()) {
throw new IllegalStateException("Calling must be system uid");
}
mLaunchingActivity.release();
}
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
// Atomically retrieve all of the other things to do.
final ArrayList stops = processStoppingActivitiesLocked(r,
true /* remove */, processPausingActivities);
NS = stops != null ? stops.size() : 0;
if ((NF = mFinishingActivities.size()) > 0) {
finishes = new ArrayList<>(mFinishingActivities);
mFinishingActivities.clear();
}
if (mStartingUsers.size() > 0) {
startingUsers = new ArrayList<>(mStartingUsers);
mStartingUsers.clear();
}
//停止其他Activity
// Stop any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (int i = 0; i < NS; i++) {
r = stops.get(i);
final ActivityStack stack = r.getStack();
if (stack != null) {
if (r.finishing) {
stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false,
"activityIdleInternalLocked");
} else {
stack.stopActivityLocked(r);
}
}
}
// Finish any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (int i = 0; i < NF; i++) {
r = finishes.get(i);
final ActivityStack stack = r.getStack();
if (stack != null) {
activityRemoved |= stack.destroyActivityLocked(r, true, "finish-idle");
}
}
//没有开机完成,切换user
if (!booting) {
// Complete user switch
if (startingUsers != null) {
for (int i = 0; i < startingUsers.size(); i++) {
mService.mUserController.finishUserSwitch(startingUsers.get(i));
}
}
}
mService.trimApplications();
//dump();
//mWindowManager.dump();
if (activityRemoved) {
resumeFocusedStackTopActivityLocked();
}
return r;
}
这个和开机广播相关的是检查是否还在开机阶段。如果桌面启动完成,开机动画就结束了。
[->ActivityStackSupervisor.java]
/**
* Called when the frontmost task is idle.
* @return the state of mService.mBooting before this was called.
*/
@GuardedBy("mService")
private boolean checkFinishBootingLocked() {
final boolean booting = mService.mBooting;
boolean enableScreen = false;
mService.mBooting = false;
if (!mService.mBooted) {
mService.mBooted = true;
enableScreen = true;
}
if (booting || enableScreen) {
//booting = true,enableScreen = true
mService.postFinishBooting(booting, enableScreen);
}
return booting;
}
mService.mBooting是在ASM.systemReady中设置为true的,这里会修改 mService.mBooting为false;这里由于booting为true,所以会执行postFinishBooting方法。
[->ActivityManagerService.java]
void postFinishBooting(boolean finishBooting, boolean enableScreen) {
//传入的是true,true
mHandler.sendMessage(mHandler.obtainMessage(FINISH_BOOTING_MSG,
finishBooting ? 1 : 0, enableScreen ? 1 : 0));
}
public void handleMessage(Message msg) {
switch (msg.what) {
//msg.arg1 = 1;msg.arg2=1
case FINISH_BOOTING_MSG: {
if (msg.arg1 != 0) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "FinishBooting");
//见1.8节
finishBooting();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
if (msg.arg2 != 0) {
//见1.9节
enableScreenAfterBoot();
}
break;
}
}
}
这里Message要做两件事情finishBooting和enableScreenAfterBoot
[->ActivityManagerService.java]
final void finishBooting() {
synchronized (this) {
//第一次进入为false,所以这里直接返回了
if (!mBootAnimationComplete) {
mCallFinishBooting = true;
return;
}
mCallFinishBooting = false;
}
....
}
第一次进来时mBootAnimationComplete是为false的,只有动画完成了才会回调方法bootAnimationComplete设置为true,所以这里直接返回了,这里再看下第二件事情enableScreenAfterBoot。
[->ActivityManagerService.java]
void enableScreenAfterBoot() {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
SystemClock.uptimeMillis());
mWindowManager.enableScreenAfterBoot();
synchronized (this) {
updateEventDispatchingLocked();
}
}
[->WindowManagerService.java]
public void enableScreenAfterBoot() {
synchronized(mWindowMap) {
if (DEBUG_BOOT) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.i(TAG_WM, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
+ " mForceDisplayEnabled=" + mForceDisplayEnabled
+ " mShowingBootMessages=" + mShowingBootMessages
+ " mSystemBooted=" + mSystemBooted, here);
}
if (mSystemBooted) {
return;
}
mSystemBooted = true;
/见下文
hideBootMessagesLocked();
// If the screen still doesn't come up after 30 seconds, give
// up and turn it on.
mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30 * 1000);
}
mPolicy.systemBooted();
//见1.10节
performEnableScreen();
}
mSystemBooted初始值为false,这里会设置成true。mShowingBootMessages为true时改成false,然后设置一个30s的延迟消息,随后调用systemBooted方法,通知keyguard开机完成,最后执行performEnableScreen方法。
[->WindowManagerService.java]
public void hideBootMessagesLocked() {
if (DEBUG_BOOT) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.i(TAG_WM, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
+ " mForceDisplayEnabled=" + mForceDisplayEnabled
+ " mShowingBootMessages=" + mShowingBootMessages
+ " mSystemBooted=" + mSystemBooted, here);
}
if (mShowingBootMessages) {
mShowingBootMessages = false;
mPolicy.hideBootMessages();
}
}
[->PhoneWindowManager.java]
/** {@inheritDoc} */
@Override
public void hideBootMessages() {
mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
}
public void handleMessage(Message msg) {
case MSG_HIDE_BOOT_MESSAGE:
handleHideBootMessage();
break;
}
这个过程主要是隐藏开机过程中显示的Android系统正在启动或者Android系统正在升级的dialog提示。
该dialog的启动是在SystemServer中启动PKMS初始化开始的,可以参考文章PKMS的启动过程。
在启动过程中会执行mPackageManagerService.updatePackagesIfNeeded方法,其中有performDexOptUpgrade方法。
这个方法主要是对package进行dexoat升级。
private int[] performDexOptUpgrade(List pkgs, boolean showDialog,
final int compilationReason, boolean bootComplete) {
...
if (showDialog) {
try {
//启动开机过程中出现的dialog
ActivityManager.getService().showBootMessage(
mContext.getResources().getString(R.string.android_upgrading_apk,
numberOfPackagesVisited, numberOfPackagesToDexopt), true);
} catch (RemoteException e) {
}
synchronized (mPackages) {
mDexOptDialogShown = true;
}
}
...
return new int[] { numberOfPackagesOptimized, numberOfPackagesSkipped,
numberOfPackagesFailed };
}
@Override
public void showBootMessage(final CharSequence msg, final boolean always) {
if (Binder.getCallingUid() != myUid()) {
throw new SecurityException();
}
mWindowManager.showBootMessage(msg, always);
}
调用显示正在开机的dialog。
[->WindowManagerService.java]
public void showBootMessage(final CharSequence msg, final boolean always) {
boolean first = false;
synchronized(mWindowMap) {
if (DEBUG_BOOT) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.i(TAG_WM, "showBootMessage: msg=" + msg + " always=" + always
+ " mAllowBootMessages=" + mAllowBootMessages
+ " mShowingBootMessages=" + mShowingBootMessages
+ " mSystemBooted=" + mSystemBooted, here);
}
if (!mAllowBootMessages) {
return;
}
if (!mShowingBootMessages) {
if (!always) {
return;
}
first = true;
}
if (mSystemBooted) {
return;
}
mShowingBootMessages = true;
mPolicy.showBootMessage(msg, always);
}
if (first) {
performEnableScreen();
}
}
下面正式显示dialog,mShowingBootMessages这里设置成true。
[->PhoneWindowManager.java]
/** {@inheritDoc} */
@Override
public void showBootMessage(final CharSequence msg, final boolean always) {
mHandler.post(new Runnable() {
@Override public void run() {
if (mBootMsgDialog == null) {
int theme;
if (mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK)) {
theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
} else {
theme = 0;
}
mBootMsgDialog = new ProgressDialog(mContext, theme) {
// This dialog will consume all events coming in to
// it, to avoid it trying to do things too early in boot.
@Override public boolean dispatchKeyEvent(KeyEvent event) {
return true;
}
@Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
return true;
}
@Override public boolean dispatchTouchEvent(MotionEvent ev) {
return true;
}
@Override public boolean dispatchTrackballEvent(MotionEvent ev) {
return true;
}
@Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
return true;
}
@Override public boolean dispatchPopulateAccessibilityEvent(
AccessibilityEvent event) {
return true;
}
};
if (mContext.getPackageManager().isUpgrade()) {
mBootMsgDialog.setTitle(R.string.android_upgrading_title);
} else {
mBootMsgDialog.setTitle(R.string.android_start_title);
}
mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mBootMsgDialog.setIndeterminate(true);
mBootMsgDialog.getWindow().setType(
WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
mBootMsgDialog.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_DIM_BEHIND
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
mBootMsgDialog.getWindow().setDimAmount(1);
WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
mBootMsgDialog.getWindow().setAttributes(lp);
mBootMsgDialog.setCancelable(false);
mBootMsgDialog.show();
}
mBootMsgDialog.setMessage(msg);
}
});
}
最后看下handleHideBootMessage,这里会取消dialog显示
private void handleHideBootMessage() {
synchronized (mLock) {
if (!mKeyguardDrawnOnce) {
mBootMessageNeedsHiding = true;
return; // keyguard hasn't drawn the first time yet, not done booting
}
}
if (mBootMsgDialog != null) {
if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
mBootMsgDialog.dismiss();
mBootMsgDialog = null;
}
}
[->PhoneWindowManager.java]
/** {@inheritDoc} */
@Override
public void systemBooted() {
bindKeyguard();
synchronized (mLock) {
mSystemBooted = true;
//在systemserver启动中,设置成了true
if (mSystemReady) {
//通知keyguard,开机完成
mKeyguardDelegate.onBootCompleted();
}
}
startedWakingUp();
screenTurningOn(null);
screenTurnedOn();
}
[->WindowManagerService.java]
发送消息,最后执行performBootTimeout方法,可以看到performBootTimeout最后执行的是performEnableScreen方法。
@Override
public void handleMessage(Message msg) {case BOOT_TIMEOUT: {
performBootTimeout();
break;
}
public void performBootTimeout() {
synchronized(mWindowMap) {
//这个参数在动画结束时才为true,见1.10节
if (mDisplayEnabled) {
return;
}
Slog.w(TAG_WM, "***** BOOT TIMEOUT: forcing display enabled");
mForceDisplayEnabled = true;
}
//如果30s内动画还没完完成则,再执行performEnableScreen
performEnableScreen();
}
[->WindowManagerService.java]
private void performEnableScreen() {
synchronized(mWindowMap) {
if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
+ " mForceDisplayEnabled=" + mForceDisplayEnabled
+ " mShowingBootMessages=" + mShowingBootMessages
+ " mSystemBooted=" + mSystemBooted
+ " mOnlyCore=" + mOnlyCore,
new RuntimeException("here").fillInStackTrace());
if (mDisplayEnabled) {
return;
}
//mSystemBooted为true,在1.9节中设置
if (!mSystemBooted && !mShowingBootMessages) {
return;
}
//1.9.1节mShowingBootMessages设置成了false,关键判断canDismissBootAnimation
if (!mShowingBootMessages && !mPolicy.canDismissBootAnimation()) {
return;
}
// Don't enable the screen until all existing windows have been drawn.
//等所有的窗口都绘制完成,才能使能屏幕,见1.10.2节
if (!mForceDisplayEnabled
// TODO(multidisplay): Expand to all displays?
&& getDefaultDisplayContentLocked().checkWaitingForWindows()) {
return;
}
//没有停止动画
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;
}
//检查开机动画是否完成,见1.10.3节
if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: Waiting for anim complete");
return;
}
try {
//通知surfaceFlinger完成
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_WM, "Boot completed: SurfaceFlinger is dead!");
}
EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis());
Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
//这里开机动画已经结束
mDisplayEnabled = true;
if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, "******************** ENABLING SCREEN!");
// Enable input dispatch.
mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
}
try {
mActivityManager.bootAnimationComplete();
} catch (RemoteException e) {
}
mPolicy.enableScreenAfterBoot();
// Make sure the last requested orientation has been applied.
updateRotationUnchecked(false, false);
}
这里主要的工作是停止开机动画,通知SurfaceFlinger开机结束等。在停止开机动画前会有很多的判断,如果现有的window(桌面,状态栏,keyguard,壁纸等)都已经绘制完成包括,才会停止动画。
停止动画是执行了SystemProperties.set(“service.bootanim.exit”, “1”);在system/bin/bootanimation一般会在显示的时候循环查询这个prop的值,如果变成了1则推出。
[->PhoneWindowManager.java]
@Override
public boolean canDismissBootAnimation() {
synchronized (mLock) {
return mKeyguardDrawComplete;
}
}
mKeyguardDrawComplete是Keyguard是否绘制完成,绘制完成才会进入下面的方法。
[->DisplayContent.java]
boolean checkWaitingForWindows() {
mHaveBootMsg = false;
mHaveApp = false;
mHaveWallpaper = false;
mHaveKeyguard = true;
final WindowState visibleWindow = getWindow(w -> {
if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
return true;
}
if (w.isDrawnLw()) {
if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
mHaveBootMsg = true;
} else if (w.mAttrs.type == TYPE_APPLICATION
|| w.mAttrs.type == TYPE_DRAWN_APPLICATION) {
mHaveApp = true;
} else if (w.mAttrs.type == TYPE_WALLPAPER) {
mHaveWallpaper = true;
} else if (w.mAttrs.type == TYPE_STATUS_BAR) {
mHaveKeyguard = mService.mPolicy.isKeyguardDrawnLw();
}
}
return false;
});
if (visibleWindow != null) {
// We have a visible window.
return true;
}
// if the wallpaper service is disabled on the device, we're never going to have
// wallpaper, don't bother waiting for it
boolean wallpaperEnabled = mService.mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enableWallpaperService)
&& mService.mContext.getResources().getBoolean(
com.android.internal.R.bool.config_checkWallpaperAtBoot)
&& !mService.mOnlyCore;
if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM,
"******** booted=" + mService.mSystemBooted
+ " msg=" + mService.mShowingBootMessages
+ " haveBoot=" + mHaveBootMsg + " haveApp=" + mHaveApp
+ " haveWall=" + mHaveWallpaper + " wallEnabled=" + wallpaperEnabled
+ " haveKeyguard=" + mHaveKeyguard);
// If we are turning on the screen to show the boot message, don't do it until the boot
// message is actually displayed.
if (!mService.mSystemBooted && !mHaveBootMsg) {
return true;
}
// If we are turning on the screen after the boot is completed normally, don't do so until
// we have the application and wallpaper.
if (mService.mSystemBooted
&& ((!mHaveApp && !mHaveKeyguard) || (wallpaperEnabled && !mHaveWallpaper))) {
return true;
}
return false;
}
[->WindowManagerService.java]
private boolean checkBootAnimationCompleteLocked() {
if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) {
mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED);
mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED,
BOOT_ANIMATION_POLL_INTERVAL);
if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Waiting for anim complete");
return false;
}
if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Animation complete!");
return true;
}
这里判断开机动画是否停止通过判断BOOT_ANIMATION_SERVICE服务是否在运行。
performEnableScreen里面并不能一次就能停止动画,查看日志:
01-01 22:00:26.180 2496 3127 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
01-01 22:00:26.180 2496 3127 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:6073)
01-01 22:00:26.182 2496 3120 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
01-01 22:00:26.182 2496 3120 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:6073)
01-01 22:00:26.521 2496 3127 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
01-01 22:00:26.521 2496 3127 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:6073)
01-01 22:00:27.166 2496 3127 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
01-01 22:00:27.166 2496 3127 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:6073)
01-01 22:00:27.193 2496 3127 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
01-01 22:00:27.193 2496 3127 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:6073)
01-01 22:00:27.198 2496 3127 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
01-01 22:00:27.198 2496 3127 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:6073)
01-01 22:00:27.200 2496 3127 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
01-01 22:00:27.200 2496 3127 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:6073)
01-01 22:00:27.201 2496 3127 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
01-01 22:00:27.201 2496 3127 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:6073)
01-01 22:00:27.207 2496 3127 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
01-01 22:00:27.207 2496 3127 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:6073)
01-01 22:00:27.873 2496 3127 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
01-01 22:00:27.873 2496 3127 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:6073)
01-01 22:00:37.807 2496 3127 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
01-01 22:00:37.807 2496 3127 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:6073)
01-01 22:00:37.809 2496 3127 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
01-01 22:00:37.809 2496 3127 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:6073)
01-01 22:00:37.819 2496 3127 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
01-01 22:00:37.819 2496 3127 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:6073)
01-01 22:00:37.825 2496 3127 I WindowManager: performEnableScreen: Waiting for anim complete
01-01 22:00:37.830 2496 3127 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
01-01 22:00:37.830 2496 3127 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:6073)
01-01 22:00:37.830 2496 3127 I WindowManager: performEnableScreen: Waiting for anim complete
01-01 22:00:37.839 2496 3127 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
01-01 22:00:37.839 2496 3127 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:6073)
01-01 22:00:37.840 2496 3127 I WindowManager: performEnableScreen: Waiting for anim complete
除了从Launch发起的流程调用这里之外,还有其他的调用点,在WMS里面经过enableScreenIfNeeded方法发送ENABLE_SCREEN 消息给Handler进行处理。
[->WindowManagerService.java]
@Override
public void enableScreenIfNeeded() {
synchronized (mWindowMap) {
enableScreenIfNeededLocked();
}
}
void enableScreenIfNeededLocked() {
if (DEBUG_BOOT) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.i(TAG_WM, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
+ " mForceDisplayEnabled=" + mForceDisplayEnabled
+ " mShowingBootMessages=" + mShowingBootMessages
+ " mSystemBooted=" + mSystemBooted, here);
}
if (mDisplayEnabled) {
return;
}
if (!mSystemBooted && !mShowingBootMessages) {
return;
}
mH.sendEmptyMessage(H.ENABLE_SCREEN);
}
public void handleMessage(Message msg) {
...
case ENABLE_SCREEN: {
performEnableScreen();
break;
}
...
}
enableScreenIfNeededLocked这个方法也调用的十分的频繁,调用点也有多个位置,大部分的调用栈如下,在WMS每次进行performSurfacePlacement等主要是完成绘制布局之后检查调用。在发送ENABLE_SCREEN消息之前会判断mDisplayEnabled是否为true,如果通过performEnableScreen设置为true,则不再执行,避免了重复操作。
10-08 08:43:06.756 1592 2422 I WindowManager: enableScreenIfNeededLocked: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true
10-08 08:43:06.756 1592 2422 I WindowManager: java.lang.RuntimeException: here
10-08 08:43:06.756 1592 2422 I WindowManager: at com.android.server.wm.WindowManagerService.enableScreenIfNeededLocked(WindowManagerService.java:3417)
10-08 08:43:06.756 1592 2422 I WindowManager: at com.android.server.wm.RootWindowContainer.performSurfacePlacement(RootWindowContainer.java:818)
10-08 08:43:06.756 1592 2422 I WindowManager: at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop(WindowSurfacePlacer.java:207)
10-08 08:43:06.756 1592 2422 I WindowManager: at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement(WindowSurfacePlacer.java:155)
10-08 08:43:06.756 1592 2422 I WindowManager: at com.android.server.wm.WindowManagerService.relayoutWindow(WindowManagerService.java:2031)
10-08 08:43:06.756 1592 2422 I WindowManager: at com.android.server.wm.Session.relayout(Session.java:244)
10-08 08:43:06.756 1592 2422 I WindowManager: at android.view.IWindowSession$Stub.onTransact(IWindowSession.java:309)
10-08 08:43:06.756 1592 2422 I WindowManager: at com.android.server.wm.Session.onTransact(Session.java:164)
10-08 08:43:06.756 1592 2422 I WindowManager: at android.os.Binder.execTransact(Binder.java:731)
10-08 08:43:06.763 1592 1811 I WindowManager: skytoby performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
10-08 08:43:06.763 1592 1811 I WindowManager: java.lang.RuntimeException: here
10-08 08:43:06.763 1592 1811 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3457)
10-08 08:43:06.763 1592 1811 I WindowManager: at com.android.server.wm.WindowManagerService.access$1100(WindowManagerService.java:274)
10-08 08:43:06.763 1592 1811 I WindowManager: at com.android.server.wm.WindowManagerService$H.handleMessage(WindowManagerService.java:4845)
10-08 08:43:06.763 1592 1811 I WindowManager: at android.os.Handler.dispatchMessage(Handler.java:106)
10-08 08:43:06.763 1592 1811 I WindowManager: at android.os.Looper.loop(Looper.java:193)
10-08 08:43:06.763 1592 1811 I WindowManager: at android.os.HandlerThread.run(HandlerThread.java:65)
10-08 08:43:06.763 1592 1811 I WindowManager: at com.android.server.ServiceThread.run(ServiceThread.java:44
[->ActivityManagerService.java]
@Override
public void bootAnimationComplete() {
final boolean callFinishBooting;
synchronized (this) {
callFinishBooting = mCallFinishBooting;
mBootAnimationComplete = true;
}
if (callFinishBooting) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "FinishBooting");
finishBooting();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
在1.8节中mCallFinishBooting设置成true了,所以这里会执行finishBooting方法。通过bootAnimationComplete这个回调方法,再一次进入到了finishBooting方法。
[->ActivityManagerService.java]
final void finishBooting() {
synchronized (this) {
//在1.8节中进入到这里,这次会跳过
if (!mBootAnimationComplete) {
mCallFinishBooting = true;
return;
}
mCallFinishBooting = false;
}
//abi设置开机完成flag
ArraySet completedIsas = new ArraySet();
for (String abi : Build.SUPPORTED_ABIS) {
ZYGOTE_PROCESS.establishZygoteConnectionForAbi(abi);
final String instructionSet = VMRuntime.getInstructionSet(abi);
if (!completedIsas.contains(instructionSet)) {
try {
mInstaller.markBootComplete(VMRuntime.getInstructionSet(abi));
} catch (InstallerException e) {
if (!VMRuntime.didPruneDalvikCache()) {
// This is technically not the right filter, as different zygotes may
// have made different pruning decisions. But the log is best effort,
// anyways.
Slog.w(TAG, "Unable to mark boot complete for abi: " + abi + " (" +
e.getMessage() +")");
}
}
completedIsas.add(instructionSet);
}
}
//注册应用重启广播
IntentFilter pkgFilter = new IntentFilter();
pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
pkgFilter.addDataScheme("package");
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
if (pkgs != null) {
for (String pkg : pkgs) {
synchronized (ActivityManagerService.this) {
if (forceStopPackageLocked(pkg, -1, false, false, false, false, false,
0, "query restart")) {
setResultCode(Activity.RESULT_OK);
return;
}
}
}
}
}
}, pkgFilter);
//注册ACTION_DELETE_DUMPHEAP广播
IntentFilter dumpheapFilter = new IntentFilter();
dumpheapFilter.addAction(DumpHeapActivity.ACTION_DELETE_DUMPHEAP);
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getBooleanExtra(DumpHeapActivity.EXTRA_DELAY_DELETE, false)) {
mHandler.sendEmptyMessageDelayed(POST_DUMP_HEAP_NOTIFICATION_MSG, 5*60*1000);
} else {
mHandler.sendEmptyMessage(POST_DUMP_HEAP_NOTIFICATION_MSG);
}
}
}, dumpheapFilter);
//通知系统服务开机完成
// Let system services know.
mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);
synchronized (this) {
//之前onhold的进程,开始启动
// Ensure that any processes we had put on hold are now started
// up.
final int NP = mProcessesOnHold.size();
if (NP > 0) {
ArrayList procs =
new ArrayList(mProcessesOnHold);
for (int ip=0; ip
这里主要的工作是设置abi开机完成的flag,注册ACTION_QUERY_PACKAGE_RESTART和ACTION_DELETE_DUMPHEAP广播,通知系统服务开机启动完成,开启onhold进程,而后发送开机广播。
[->UserController.java]
void sendBootCompleted(IIntentReceiver resultTo) {
// Get a copy of mStartedUsers to use outside of lock
SparseArray startedUsers;
synchronized (mLock) {
startedUsers = mStartedUsers.clone();
}
//通知多个用户
for (int i = 0; i < startedUsers.size(); i++) {
UserState uss = startedUsers.valueAt(i);
finishUserBoot(uss, resultTo);
}
}
[->UserController.java]
private void finishUserBoot(UserState uss, IIntentReceiver resultTo) {
final int userId = uss.mHandle.getIdentifier();
//用户不匹配则返回
Slog.d(TAG, "Finishing user boot " + userId);
synchronized (mLock) {
// Bail if we ended up with a stale user
if (mStartedUsers.get(userId) != uss) {
return;
}
}
// We always walk through all the user lifecycle states to send
// consistent developer events. We step into RUNNING_LOCKED here,
// but we might immediately step into RUNNING below if the user
// storage is already unlocked.
//如果用户在锁定状态
if (uss.setState(STATE_BOOTING, STATE_RUNNING_LOCKED)) {
mInjector.getUserManagerInternal().setUserState(userId, uss.state);
// Do not report secondary users, runtime restarts or first boot/upgrade
if (userId == UserHandle.USER_SYSTEM
&& !mInjector.isRuntimeRestarted() && !mInjector.isFirstBootOrUpgrade()) {
int uptimeSeconds = (int)(SystemClock.elapsedRealtime() / 1000);
MetricsLogger.histogram(mInjector.getContext(),
"framework_locked_boot_completed", uptimeSeconds);
final int MAX_UPTIME_SECONDS = 120;
if (uptimeSeconds > MAX_UPTIME_SECONDS) {
Slog.wtf("SystemServerTiming",
"finishUserBoot took too long. uptimeSeconds=" + uptimeSeconds);
}
}
mHandler.sendMessage(mHandler.obtainMessage(REPORT_LOCKED_BOOT_COMPLETE_MSG,
userId, 0));
//发送锁屏开机广播 ,为串行广播
Intent intent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED, null);
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mInjector.broadcastIntent(intent, null, resultTo, 0, null, null,
new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
}
//解锁用户的credential-encrypted storage
// We need to delay unlocking managed profiles until the parent user
// is also unlocked.
if (mInjector.getUserManager().isManagedProfile(userId)) {
final UserInfo parent = mInjector.getUserManager().getProfileParent(userId);
if (parent != null
&& isUserRunning(parent.id, ActivityManager.FLAG_AND_UNLOCKED)) {
Slog.d(TAG, "User " + userId + " (parent " + parent.id
+ "): attempting unlock because parent is unlocked");
maybeUnlockUser(userId);
} else {
String parentId = (parent == null) ? "" : String.valueOf(parent.id);
Slog.d(TAG, "User " + userId + " (parent " + parentId
+ "): delaying unlock because parent is locked");
}
} else {
maybeUnlockUser(userId);
}
}
[->UserController.java]
/**
* Attempt to unlock user without a credential token. This typically
* succeeds when the device doesn't have credential-encrypted storage, or
* when the the credential-encrypted storage isn't tied to a user-provided
* PIN or pattern.
*/
private boolean maybeUnlockUser(final int userId) {
// Try unlocking storage using empty token
return unlockUserCleared(userId, null, null, null);
}
[->UserController.java]
private boolean unlockUserCleared(final int userId, byte[] token, byte[] secret,
IProgressListener listener) {
UserState uss;
//解锁user storage
if (!StorageManager.isUserKeyUnlocked(userId)) {
final UserInfo userInfo = getUserInfo(userId);
final IStorageManager storageManager = getStorageManager();
try {
// We always want to unlock user storage, even user is not started yet
storageManager.unlockUserKey(userId, userInfo.serialNumber, token, secret);
} catch (RemoteException | RuntimeException e) {
Slog.w(TAG, "Failed to unlock: " + e.getMessage());
}
}
synchronized (mLock) {
// Register the given listener to watch for unlock progress
uss = mStartedUsers.get(userId);
if (uss != null) {
uss.mUnlockProgress.addListener(listener);
uss.tokenProvided = (token != null);
}
}
// Bail if user isn't actually running
if (uss == null) {
notifyFinished(userId, listener);
return false;
}
//完成解锁
if (!finishUserUnlocking(uss)) {
notifyFinished(userId, listener);
return false;
}
//解锁其他的用户
// We just unlocked a user, so let's now attempt to unlock any
// managed profiles under that user.
// First, get list of userIds. Requires mLock, so we cannot make external calls, e.g. to UMS
int[] userIds;
synchronized (mLock) {
userIds = new int[mStartedUsers.size()];
for (int i = 0; i < userIds.length; i++) {
userIds[i] = mStartedUsers.keyAt(i);
}
}
for (int testUserId : userIds) {
final UserInfo parent = mInjector.getUserManager().getProfileParent(testUserId);
if (parent != null && parent.id == userId && testUserId != userId) {
Slog.d(TAG, "User " + testUserId + " (parent " + parent.id
+ "): attempting unlock because parent was just unlocked");
maybeUnlockUser(testUserId);
}
}
return true;
}
[->UserController.java]
/**
* Step from {@link UserState#STATE_RUNNING_LOCKED} to
* {@link UserState#STATE_RUNNING_UNLOCKING}.
*/
private boolean finishUserUnlocking(final UserState uss) {
final int userId = uss.mHandle.getIdentifier();
// Only keep marching forward if user is actually unlocked
if (!StorageManager.isUserKeyUnlocked(userId)) return false;
synchronized (mLock) {
// Do not proceed if unexpected state or a stale user
if (mStartedUsers.get(userId) != uss || uss.state != STATE_RUNNING_LOCKED) {
return false;
}
}
uss.mUnlockProgress.start();
// 设置进度
// Prepare app storage before we go any further
uss.mUnlockProgress.setProgress(5,
mInjector.getContext().getString(R.string.android_start_title));
// Call onBeforeUnlockUser on a worker thread that allows disk I/O
FgThread.getHandler().post(() -> {
if (!StorageManager.isUserKeyUnlocked(userId)) {
Slog.w(TAG, "User key got locked unexpectedly, leaving user locked.");
return;
}
mInjector.getUserManager().onBeforeUnlockUser(userId);
synchronized (mLock) {
// Do not proceed if unexpected state
if (!uss.setState(STATE_RUNNING_LOCKED, STATE_RUNNING_UNLOCKING)) {
return;
}
}
mInjector.getUserManagerInternal().setUserState(userId, uss.state);
uss.mUnlockProgress.setProgress(20);
//通知系统服务解锁完成
// Dispatch unlocked to system services; when fully dispatched,
// that calls through to the next "unlocked" phase
mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0, uss)
.sendToTarget();
});
return true;
}
通过mHandler发送到AMS的主Handler处理,由于UserController继承了Handler.Callback,其handleMessage就在UserController类中。
[->UserController.java]
public boolean handleMessage(Message msg) {
...
case SYSTEM_USER_UNLOCK_MSG:
final int userId = msg.arg1;
mInjector.getSystemServiceManager().unlockUser(userId);
// Loads recents on a worker thread that allows disk I/O
FgThread.getHandler().post(() -> {
mInjector.loadUserRecents(userId);
});
finishUserUnlocked((UserState) msg.obj);
break;
...
}
首先unlockUser,加载RecentTask
[->UserController.java]
/**
* Step from {@link UserState#STATE_RUNNING_UNLOCKING} to
* {@link UserState#STATE_RUNNING_UNLOCKED}.
*/
void finishUserUnlocked(final UserState uss) {
final int userId = uss.mHandle.getIdentifier();
// Only keep marching forward if user is actually unlocked
//没有解锁返回
if (!StorageManager.isUserKeyUnlocked(userId)) return;
synchronized (mLock) {
// Bail if we ended up with a stale user
if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return;
// Do not proceed if unexpected state
if (!uss.setState(STATE_RUNNING_UNLOCKING, STATE_RUNNING_UNLOCKED)) {
return;
}
}
//解锁完成
mInjector.getUserManagerInternal().setUserState(userId, uss.state);
uss.mUnlockProgress.finish();
// Get unaware persistent apps running and start any unaware providers
// in already-running apps that are partially aware
if (userId == UserHandle.USER_SYSTEM) {
mInjector.startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
}
//加载credential-encrypted Providers
mInjector.installEncryptionUnawareProviders(userId);
// Dispatch unlocked to external apps
//发送ACTION_USER_UNLOCKED广播,并行广播
final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED);
unlockedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
unlockedIntent.addFlags(
Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
mInjector.broadcastIntent(unlockedIntent, null, null, 0, null,
null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
userId);
if (getUserInfo(userId).isManagedProfile()) {
UserInfo parent = mInjector.getUserManager().getProfileParent(userId);
if (parent != null) {
//发送ACTION_MANAGED_PROFILE_UNLOCKED广播,并行广播
final Intent profileUnlockedIntent = new Intent(
Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
profileUnlockedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId));
profileUnlockedIntent.addFlags(
Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
mInjector.broadcastIntent(profileUnlockedIntent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
null, false, false, MY_PID, SYSTEM_UID,
parent.id);
}
}
// Send PRE_BOOT broadcasts if user fingerprint changed; we
// purposefully block sending BOOT_COMPLETED until after all
// PRE_BOOT receivers are finished to avoid ANR'ing apps
//用户fingerprint改变,则发送广播
final UserInfo info = getUserInfo(userId);
if (!Objects.equals(info.lastLoggedInFingerprint, Build.FINGERPRINT)) {
// Suppress double notifications for managed profiles that
// were unlocked automatically as part of their parent user
// being unlocked.
final boolean quiet;
if (info.isManagedProfile()) {
quiet = !uss.tokenProvided
|| !mLockPatternUtils.isSeparateProfileChallengeEnabled(userId);
} else {
quiet = false;
}
mInjector.sendPreBootBroadcast(userId, quiet,
() -> finishUserUnlockedCompleted(uss));
} else {
finishUserUnlockedCompleted(uss);
}
}
[->UserController.java]
private void finishUserUnlockedCompleted(UserState uss) {
final int userId = uss.mHandle.getIdentifier();
synchronized (mLock) {
// Bail if we ended up with a stale user
if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return;
}
UserInfo userInfo = getUserInfo(userId);
if (userInfo == null) {
return;
}
// Only keep marching forward if user is actually unlocked
if (!StorageManager.isUserKeyUnlocked(userId)) return;
// Remember that we logged in
mInjector.getUserManager().onUserLoggedIn(userId);
if (!userInfo.isInitialized()) {
if (userId != UserHandle.USER_SYSTEM) {
Slog.d(TAG, "Initializing user #" + userId);
//发送ACTION_USER_INITIALIZE广播去给user初始化,,串行广播
Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mInjector.broadcastIntent(intent, null,
new IIntentReceiver.Stub() {
@Override
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered,
boolean sticky, int sendingUser) {
// Note: performReceive is called with mService lock held
mInjector.getUserManager().makeInitialized(userInfo.id);
}
}, 0, null, null, null, AppOpsManager.OP_NONE,
null, true, false, MY_PID, SYSTEM_UID, userId);
}
}
// Spin up app widgets prior to boot-complete, so they can be ready promptly
mInjector.startUserWidgets(userId);
Slog.i(TAG, "Sending BOOT_COMPLETE user #" + userId);
// Do not report secondary users, runtime restarts or first boot/upgrade
if (userId == UserHandle.USER_SYSTEM
&& !mInjector.isRuntimeRestarted() && !mInjector.isFirstBootOrUpgrade()) {
int uptimeSeconds = (int) (SystemClock.elapsedRealtime() / 1000);
MetricsLogger.histogram(mInjector.getContext(), "framework_boot_completed",
uptimeSeconds);
}
//发送ACTION_BOOT_COMPLETED广播,串行广播
final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mInjector.broadcastIntent(bootIntent, null, new IIntentReceiver.Stub() {
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser)
throws RemoteException {
Slog.i(UserController.TAG, "Finished processing BOOT_COMPLETED for u" + userId);
}
}, 0, null, null,
new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
}
到这里已经发送了ACTION_BOOT_COMPLETED广播。
从开机完成启动到发送开机广播,其中的流程有很多,之前的文章有讲过systemserver启动,AMS、PMS的启动,同时还有Activity和广播的启动,综合着一些再来看这个过程就相对轻松些,同时通过编译版本调试打印出日志,更加证明了分析流程的正确性。
1.在Launch界面resume阶段,会向主线程消息队列放入new Idler(),在消息队列空闲的时候,就会调用。
2.通过Binder机制执行AMS的activityIdle,这个方法里面会检查是否完成开机。
3.调用finishBooting方法,来完成开机。在这个过程中第一次进入由于开机动画还没有停止从而会直接返回。
4.调用performEnableScreen方法,确定所有的窗口都已经绘制完成,包括Launch,状态栏,壁纸,同时要求开机动画停止,在等待开机动画停止的过程中,有一个30s的超时,同时还有其他的入口来调用WMS的performEnableScreen方法,当动画包停止后通过回调再次执行finishBooting方法。
5.在对credential-encrypted storage解锁后就正式的发送开机广播BOOT_COMPLETED。
源码路径
frameworks/base/core/java/android/app/ActivityThread.java
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
frameworks/base/core/java/android/os/MessageQueue.java
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
frameworks/base/services/core/java/com/android/server/am/UserController.java