欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android10.0 开机广播BOOT_COMPLETED发送流程分析

程序员文章站 2022-06-10 16:12:24
...

原文地址: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等交互,其具体的时序图如下。
Android10.0 开机广播BOOT_COMPLETED发送流程分析

二、开机广播启动过程

在AMS启动那篇文章中已经讲到桌面如何的启动,在桌面启动完成后即桌面Activity onResume之后,就会发送开机广播。桌面Activity onResume阶段,执行了handleResumeActivity方法,见Activity启动过程。handleResumeActivity中加载完window之后将自己实现的IdleHandler添加到自己的消息队列中。

1.1 AT.handleResumeActivity

[->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());
    }

1.2 MQ.addIdleHandler

[->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()的回调。

1.3 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;
        }
    }

1.4 AMS.activityIdle

[->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);
    }

1.5 ASS.activityIdleInternalLocked

[->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<ActivityRecord> finishes = null;
        ArrayList<UserState> 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<ActivityRecord> 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;
    }

这个和开机广播相关的是检查是否还在开机阶段。如果桌面启动完成,开机动画就结束了。

1.6 ASS.checkFinishBootingLocked

[->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方法。

1.7 AMS.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

1.8 AMS.finishBooting

[->ActivityManagerService.java]

final void finishBooting() {
        synchronized (this) {
            //第一次进入为false,所以这里直接返回了
            if (!mBootAnimationComplete) {
                mCallFinishBooting = true;
                return;
            }
            mCallFinishBooting = false;
        }
        ....
    }

第一次进来时mBootAnimationComplete是为false的,只有动画完成了才会回调方法bootAnimationComplete设置为true,所以这里直接返回了,这里再看下第二件事情enableScreenAfterBoot。

1.9 AMS.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方法。

1.9.1 WMS.hideBootMessagesLocked

[->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();
        }
    }

1.9.2 PWM.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<PackageParser.Package> 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;
        }
    }

1.9.3 PWM.systemBooted

[->PhoneWindowManager.java]

    /** {@inheritDoc} */
    @Override
    public void systemBooted() {
        bindKeyguard();
        synchronized (mLock) {
            mSystemBooted = true;
            //在systemserver启动中,设置成了true
            if (mSystemReady) {
                //通知keyguard,开机完成
                mKeyguardDelegate.onBootCompleted();
            }
        }
        startedWakingUp();
        screenTurningOn(null);
        screenTurnedOn();
    }

1.9.4 mH.sendEmptyMessageDelayed

[->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();
    }

1.10 WMS.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则推出。

1.10.1 PWM.canDismissBootAnimation

[->PhoneWindowManager.java]

  @Override
    public boolean canDismissBootAnimation() {
        synchronized (mLock) {
            return mKeyguardDrawComplete;
        }
    }

mKeyguardDrawComplete是Keyguard是否绘制完成,绘制完成才会进入下面的方法。

1.10.2 checkWaitingForWindows

[->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;
    }

1.10.3 WMS.checkWaitingForWindows

[->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服务是否在运行。

1.10.4 WMS.enableScreenIfNeeded

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

1.11 AMS.bootAnimationComplete

[->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方法。

1.12 AMS.finishBooting

[->ActivityManagerService.java]

 final void finishBooting() {
        synchronized (this) {
            //在1.8节中进入到这里,这次会跳过
            if (!mBootAnimationComplete) {
                mCallFinishBooting = true;
                return;
            }
            mCallFinishBooting = false;
        }
        //abi设置开机完成flag
        ArraySet<String> completedIsas = new ArraySet<String>();
        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<ProcessRecord> procs =
                    new ArrayList<ProcessRecord>(mProcessesOnHold);
                for (int ip=0; ip<NP; ip++) {
                    if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "Starting process on hold: "
                            + procs.get(ip));
                    startProcessLocked(procs.get(ip), "on-hold", null);
                }
            }
            if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                return;
            }
            // Start looking for apps that are abusing wake locks.
            Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_POWER_USE_MSG);
            mHandler.sendMessageDelayed(nmsg, mConstants.POWER_CHECK_INTERVAL);
            // Tell anyone interested that we are done booting!
            SystemProperties.set("sys.boot_completed", "1");

            // And trigger dev.bootcomplete if we are not showing encryption progress
            if (!"trigger_restart_min_framework".equals(VoldProperties.decrypt().orElse(""))
                    || "".equals(VoldProperties.encrypt_progress().orElse(""))) {
                SystemProperties.set("dev.bootcomplete", "1");
            }
            //发送开机完成广播
            mUserController.sendBootCompleted(
                    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);
                            }
                        }
                    });
            mUserController.scheduleStartProfiles();
        }
    }

这里主要的工作是设置abi开机完成的flag,注册ACTION_QUERY_PACKAGE_RESTART和ACTION_DELETE_DUMPHEAP广播,通知系统服务开机启动完成,开启onhold进程,而后发送开机广播。

1.13 UC.sendBootCompleted

[->UserController.java]

 void sendBootCompleted(IIntentReceiver resultTo) {
        // Get a copy of mStartedUsers to use outside of lock
        SparseArray<UserState> startedUsers;
        synchronized (mLock) {
            startedUsers = mStartedUsers.clone();
        }
        //通知多个用户
        for (int i = 0; i < startedUsers.size(); i++) {
            UserState uss = startedUsers.valueAt(i);
            finishUserBoot(uss, resultTo);
        }
    }

1.14 UC.finishUserBoot

[->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) ? "<null>" : String.valueOf(parent.id);
                Slog.d(TAG, "User " + userId + " (parent " + parentId
                        + "): delaying unlock because parent is locked");
            }
        } else {
            maybeUnlockUser(userId);
        }
    }

1.15 UC.maybeUnlockUser

[->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);
    }

1.16 UC.maybeUnlockUser

[->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;
    }

1.17 UC.finishUserUnlocking

[->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类中。

1.18 UC.handleMessage

[->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

1.19 UC.finishUserUnlocked

[->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);
        }
    }

1.20 UC.finishUserUnlockedCompleted

[->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

相关标签: Android进阶