Android 8.1 开机启动流程的收尾_bootanimation开机动画结束和BOOT_COMPLETE广播发送流程整理

一开始还是以为是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);
}





你可能感兴趣的:(Android 8.1 开机启动流程的收尾_bootanimation开机动画结束和BOOT_COMPLETE广播发送流程整理)