一开始还是以为是Launcher起来后线程空闲回调Ams的接口开始进行关闭开机动画,但实际上看了下不仅仅是这个条件。不过还是从这里开始结合日志一起看。
在ActivityThread::handleLaunchActivity的过程中,会在resume阶段handleResumeActivity方法里面在加载完window之后将自己实现的Idlehandler添加到自己的消息队列里面,当Looper发现消息队列空闲的时候就会回调queueIdle方法
r.nextIdle = mNewActivities;
mNewActivities = r;
if (localLOGV) Slog.v(
TAG, "Scheduling idle handler for " + r);
Looper.myQueue().addIdleHandler(new Idler());
Idler实现的MessageQueue.IdleHandler接口就一个queueIdle方法,里面关键的就是会回调ams的activityIdle。
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;
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 {
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();
}
ensureJitEnabled();
return false;
}
}
Ams
@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) {
ActivityRecord r =
mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,
false /* processPausingActivities */, config);
if (stopProfiling) {
if ((mProfileProc == r.app) && mProfilerInfo != null) {
clearProfilerLocked();
}
}
}
}
Binder.restoreCallingIdentity(origId);
}
ActivityStackSuperVisor的activityIdleInternalLocked方法,会报告启动时间结束,还有就是检查是否是还在开机阶段然后结束开机流程。意思就是桌面都已经拿到焦点显示好了,开机动画可以退役了。在这里会修改Ams的mBooting全局变量为true,然后enableScreen也是true,发送Message给Ams进行处理,也就是开篇提到的。
//Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
if (isFocusedStack(r.getStack()) || fromTimeout) {
booting = checkFinishBootingLocked();
}
/**
* Called when the frontmost task is idle.
* @return the state of mService.mBooting before this was called.
*/
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) {
mService.postFinishBooting(booting, enableScreen);
}
return booting;
}
void postFinishBooting(boolean finishBooting, boolean enableScreen) {
Exception e = new Exception("xian postFinishBooting");
e.printStackTrace();
mHandler.sendMessage(mHandler.obtainMessage(FINISH_BOOTING_MSG,
finishBooting ? 1 : 0, enableScreen ? 1 : 0));
}
这是对应的log打印的栈
07-03 10:20:26.632 3015 3027 W System.err: java.lang.Exception: xian postFinishBooting
07-03 10:20:26.633 3015 3027 W System.err: at com.android.server.am.ActivityManagerService.postFinishBooting(ActivityManagerService.java:7244)
07-03 10:20:26.633 3015 3027 W System.err: at com.android.server.am.ActivityStackSupervisor.checkFinishBootingLocked(ActivityStackSupervisor.java:1874)
07-03 10:20:26.633 3015 3027 W System.err: at com.android.server.am.ActivityStackSupervisor.activityIdleInternalLocked(ActivityStackSupervisor.java:1916)
07-03 10:20:26.633 3015 3027 W System.err: at com.android.server.am.ActivityManagerService.activityIdle(ActivityManagerService.java:7231)
07-03 10:20:26.633 3015 3027 W System.err: at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:309)
07-03 10:20:26.633 3015 3027 W System.err: at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2919)
07-03 10:20:26.633 3015 3027 W System.err: at android.os.Binder.execTransact(Binder.java:697)
处理Message是要干两件事,一件是finishBooting,一件是enableScreenAfterBoot。
case FINISH_BOOTING_MSG: {
if (msg.arg1 != 0) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "FinishBooting");
finishBooting();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
if (msg.arg2 != 0) {
enableScreenAfterBoot();
}
break;
}
在finishBooting里面,一开始会判断mBootAnimationComplete,然后启动一些一直被hold的进程等,最后会通过UserController的sendBootCompletedLocked发送开机广播,这个也不是一下子就发了最后再说。
final void finishBooting() {
synchronized (this) {
if (!mBootAnimationComplete) {
mCallFinishBooting = true;
return;
}
mCallFinishBooting = false;
}
......
// Let system services know.
mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);
......
mUserController.sendBootCompletedLocked(
new IIntentReceiver.Stub() {
@Override
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered,
boolean sticky, int sendingUser) {
synchronized (ActivityManagerService.this) {
requestPssAllProcsLocked(SystemClock.uptimeMillis(),
true, false);
}
}
});
scheduleStartProfilesLocked();
}
刚进来这里的时候mBootAnimationComplete肯定是false,所以没戏唱了,但是注意到mCallFinishBooting是赋值为true的, ,后面是有用的。实际上它只会在系统结束开机动画之后才会变成true,然后再进行一遍finishBooting的动作。bootAnimationComplete方法是由Wms回调的,等下再说。继续看上面的第二件事enableScreenAfterBoot.
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();
performEnableScreen();
}
这里会将mSystemBooted设置为true,然后在hideBootMessagesLocked方法里面把mShowingBootMessages true改成false,然后设定一个强制的30s启动超时Message,随后调用PhoneWindowManager的systemBooted方法,通知keyguard进行相关动作,最后也是我们这次分析的重点,进行performEnableScreen。performEnableScreen里面会关掉开机动画,通知SurfaceFlinger开机结束等等,但是一次就能关掉吗?先看下打印的日志。
Line 3801: 07-03 10:20:26.756 3015 3030 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 3930: 07-03 10:20:26.832 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 3974: 07-03 10:20:26.851 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4013: 07-03 10:20:26.869 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4046: 07-03 10:20:26.879 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4069: 07-03 10:20:26.895 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4096: 07-03 10:20:26.913 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4114: 07-03 10:20:26.916 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4133: 07-03 10:20:26.939 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4196: 07-03 10:20:27.089 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4215: 07-03 10:20:27.095 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4279: 07-03 10:20:27.135 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4302: 07-03 10:20:27.144 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4358: 07-03 10:20:27.226 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4390: 07-03 10:20:27.249 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4411: 07-03 10:20:27.261 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4451: 07-03 10:20:27.312 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4490: 07-03 10:20:27.357 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
Line 4600: 07-03 10:20:27.762 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
除了这个从Launcher发起的流程是第一次的调用之外,其他的都是这样的。也就是在Wms里面经enableScreenIfNeededLocked方法发送ENABLE_SCREEN Message给在android.display线程的H Handler进行处理。
07-03 10:20:26.939 3015 3037 I WindowManager: java.lang.RuntimeException: here
07-03 10:20:26.939 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
07-03 10:20:26.939 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.-wrap6(Unknown Source:0)
07-03 10:20:26.939 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService$H.handleMessage(WindowManagerService.java:5065)
07-03 10:20:26.939 3015 3037 I WindowManager: at android.os.Handler.dispatchMessage(Handler.java:106)
07-03 10:20:26.939 3015 3037 I WindowManager: at android.os.Looper.loop(Looper.java:164)
07-03 10:20:26.939 3015 3037 I WindowManager: at android.os.HandlerThread.run(HandlerThread.java:65)
07-03 10:20:26.939 3015 3037 I WindowManager: at com.android.server.ServiceThread.run(ServiceThread.java:46)
enableScreenIfNeededLocked调用非常的频繁,调用点也是有多个位置,在wms进行每次performSurfacePlacement等主要是完成绘制布局之后都会检查进行调用。主要的栈是这个
07-03 10:20:26.628 3015 3070 I WindowManager: enableScreenIfNeededLocked: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=false
07-03 10:20:26.628 3015 3070 I WindowManager: java.lang.RuntimeException: here
07-03 10:20:26.628 3015 3070 I WindowManager: at com.android.server.wm.WindowManagerService.enableScreenIfNeededLocked(WindowManagerService.java:3445)
07-03 10:20:26.628 3015 3070 I WindowManager: at com.android.server.wm.RootWindowContainer.performSurfacePlacement(RootWindowContainer.java:822)
07-03 10:20:26.628 3015 3070 I WindowManager: at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop(WindowSurfacePlacer.java:197)
07-03 10:20:26.628 3015 3070 I WindowManager: at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement(WindowSurfacePlacer.java:145)
07-03 10:20:26.628 3015 3070 I WindowManager: at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement(WindowSurfacePlacer.java:135)
07-03 10:20:26.628 3015 3070 I WindowManager: at com.android.server.wm.WindowSurfacePlacer.lambda$-com_android_server_wm_WindowSurfacePlacer_5337(WindowSurfacePlacer.java:108)
07-03 10:20:26.628 3015 3070 I WindowManager: at com.android.server.wm.-$Lambda$aEpJ2RCAIjecjyIIYTv6ricEwh4.$m$12(Unknown Source:4)
07-03 10:20:26.628 3015 3070 I WindowManager: at com.android.server.wm.-$Lambda$aEpJ2RCAIjecjyIIYTv6ricEwh4.run(Unknown Source:59)
07-03 10:20:26.628 3015 3070 I WindowManager: at android.os.Handler.handleCallback(Handler.java:790)
07-03 10:20:26.628 3015 3070 I WindowManager: at android.os.Handler.dispatchMessage(Handler.java:99)
07-03 10:20:26.628 3015 3070 I WindowManager: at android.os.Looper.loop(Looper.java:164)
07-03 10:20:26.628 3015 3070 I WindowManager: at android.os.HandlerThread.run(HandlerThread.java:65)
07-03 10:20:26.628 3015 3070 I WindowManager: at com.android.server.ServiceThread.run(ServiceThread.java:46)
在发送ENABLE_SCREEN Message之前,会判断mDisplayEnabled, 是否enable的状态变量,peformEnableScreen完成后置为true,避免重复操作。mSystemBooted就是Launcher启动空闲后通过Idler回调Ams设置的状态标记位,前面已经设置为true了,mShowingBootMessages是是否在显示“Android系统正在启动”,或者“Android系统正在升级”,在SystemServer启动时会调用PKMS进行packages的dexoat升级,然后在enableScreenAfterBoot里面会调用hideBootMessagesLocked取消掉这个dialog,现在这个肯定是false了。所以只要mSystemBooted开关一打开,后面就开始调用performEnableScreen尝试干活。
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);
}
前面几个判断已经做过一遍了,现在主要要等checkWaitingForWindows,除非是现有的windows都已经完成绘制了,否则还是不能说系统真正启动了。除了Launcher,还有SystemUI的壁纸,导航栏, Keyguard等。当然每个Window完成绘制的时候都会再重来一遍看要不要performEnableScreen.
然后终于要停止开机动画了,SystemProperties.set("service.bootanim.exit", "1"); system/bin/bootanimation一般会在显示的时候循环进行这个prop的检查,变成1它就可以退出了,本身它就是一个线程。checkBootAnimationCompleteLocked是ServiceManager找不到bootanimation服务了,然后就通知SurfaceFlinger启动已经完成,打印也是经典的日志“******* TELLING SURFACE FLINGER WE ARE BOOTED!”。然后再回调AMS的bootAnimationComplete,这里会处理开机广播的发送工作。
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;
}
if (!mSystemBooted && !mShowingBootMessages) {
return;
}
if (!mShowingBootMessages && !mPolicy.canDismissBootAnimation()) {
return;
}
// Don't enable the screen until all existing windows have been drawn.
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;
}
if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: Waiting for anim complete");
return;
}
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_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);
}
下面是到此时会打印的一些日志。
07-03 10:20:27.762 3015 3037 I WindowManager: performEnableScreen: mDisplayEnabled=false mForceDisplayEnabled=false mShowingBootMessages=false mSystemBooted=true mOnlyCore=false
07-03 10:20:27.762 3015 3037 I WindowManager: java.lang.RuntimeException: here
07-03 10:20:27.762 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.performEnableScreen(WindowManagerService.java:3487)
07-03 10:20:27.762 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService.-wrap6(Unknown Source:0)
07-03 10:20:27.762 3015 3037 I WindowManager: at com.android.server.wm.WindowManagerService$H.handleMessage(WindowManagerService.java:5266)
07-03 10:20:27.762 3015 3037 I WindowManager: at android.os.Handler.dispatchMessage(Handler.java:106)
07-03 10:20:27.762 3015 3037 I WindowManager: at android.os.Looper.loop(Looper.java:164)
07-03 10:20:27.762 3015 3037 I WindowManager: at android.os.HandlerThread.run(HandlerThread.java:65)
07-03 10:20:27.762 3015 3037 I WindowManager: at com.android.server.ServiceThread.run(ServiceThread.java:46)
07-03 10:20:27.763 3015 3037 I WindowManager: ******** booted=true msg=false haveBoot=false haveApp=false haveWall=true wallEnabled=true haveKeyguard=true
07-03 10:20:27.763 3015 3037 I WindowManager: checkBootAnimationComplete: Animation complete!
07-03 10:20:27.765 3015 3037 I WindowManager: ******* TELLING SURFACE FLINGER WE ARE BOOTED!
07-03 10:20:27.765 2764 2938 I SurfaceFlinger: Boot is finished (44022 ms)
07-03 10:20:27.773 3015 3037 I WindowManager: ******************** ENABLING SCREEN!
07-03 10:20:27.778 3015 3037 I SystemServiceManager: Starting phase 1000
Ams在这里打开了开关mBootAnimationComplete
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);
}
}
finishBooting里面,startBootPhase(SystemService.PHASE_BOOT_COMPLETED)对应着上面日志的start phase 1000,这是最后了。随后就是通过UserController发送开机广播,带的IIntentReceiver.Stub主要是完成各个进程的信息搜集工作。
.....
// Let system services know.
mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);
......
mUserController.sendBootCompletedLocked(
new IIntentReceiver.Stub() {
@Override
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered,
boolean sticky, int sendingUser) {
synchronized (ActivityManagerService.this) {
requestPssAllProcsLocked(SystemClock.uptimeMillis(),
true, false);
}
}
});
......
UserController主要是来做多用户方面的动作。
void sendBootCompletedLocked(IIntentReceiver resultTo) {
for (int i = 0; i < mStartedUsers.size(); i++) {
UserState uss = mStartedUsers.valueAt(i);
finishUserBoot(uss, resultTo);
}
}
先发了一个锁屏开机广播ACTION_LOCKED_BOOT_COMPLETED,然后是maybeUnlockUser,解锁用户的 credential-encrypted storage,这是7.0引入的direct boot mode相关的,应用的数据都是放在这里的,解锁前不能用。
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)) {
......
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.broadcastIntentLocked(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);
}
// 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);
.....
maybeUnlockUser(userId);
......
}
StorageManagerService unlockUserKey就是解锁的逻辑,然后是finishUserUnlocking
/**
* 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.
*/
boolean maybeUnlockUser(final int userId) {
// Try unlocking storage using empty token
return unlockUserCleared(userId, null, null, null);
}
boolean unlockUserCleared(final int userId, byte[] token, byte[] secret,
IProgressListener listener) {
UserState uss;
synchronized (mLock) {
// TODO Move this block outside of synchronized if it causes lock contention
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());
}
}
// Bail if user isn't actually running, otherwise register the given
// listener to watch for unlock progress
uss = mStartedUsers.get(userId);
if (uss == null) {
notifyFinished(userId, listener);
return false;
} else {
uss.mUnlockProgress.addListener(listener);
uss.tokenProvided = (token != null);
}
}
finishUserUnlocking(uss);
.....
}
UserState从STATE_RUNNING_LOCKED变成STATE_RUNNING_UNLOCKING,发送message给Ams在UIThread上处理
/**
* Step from {@link UserState#STATE_RUNNING_LOCKED} to
* {@link UserState#STATE_RUNNING_UNLOCKING}.
*/
private void finishUserUnlocking(final UserState uss) {
....
if (proceedWithUnlock) {
uss.mUnlockProgress.start();
// Prepare app storage before we go any further
uss.mUnlockProgress.setProgress(5,
mInjector.getContext().getString(R.string.android_start_title));
mInjector.getUserManager().onBeforeUnlockUser(userId);
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();
}
}
SystemService先unlockUser,加载RecentTask,启动符合条件的Persistent应用进程,加载encryption-unaware providers,最后再调回UserController执行解锁的收尾工作。
case SYSTEM_USER_UNLOCK_MSG: {
final int userId = msg.arg1;
mSystemServiceManager.unlockUser(userId);
synchronized (ActivityManagerService.this) {
mRecentTasks.loadUserRecentsLocked(userId);
}
if (userId == UserHandle.USER_SYSTEM) {
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
}
installEncryptionUnawareProviders(userId);
mUserController.finishUserUnlocked((UserState) msg.obj);
break;
}
需要的话先发ACTION_USER_INITIALIZE广播去给user初始化,然后打印关键日志“Sending BOOT_COMPLETE user # ”,最后发送开机广播ACTION_BOOT_COMPLETED,发完后打印“Finished processing BOOT_COMPLETED for u”
private void finishUserUnlockedCompleted(UserState uss) {
....
if (!userInfo.isInitialized()) {
if (userId != UserHandle.USER_SYSTEM) {
Slog.d(TAG, "Initializing user #" + userId);
Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mInjector.broadcastIntentLocked(intent, null,
......
Slog.i(TAG, "Sending BOOT_COMPLETE user #" + userId);
...
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.broadcastIntentLocked(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);
}