美文网首页面试android之开机流程探索
Android系统中Launcher的启动流程分析

Android系统中Launcher的启动流程分析

作者: 依玲之风 | 来源:发表于2020-03-21 20:50 被阅读0次

    Android中的Launcher就是Android系统的桌面,用于启动应用程序;作为Android的系统桌面,用于显示和管理应用程序的快捷图标或者其它桌面组件。

    1.应用程序加载

    在SystemServer进程启动的过程中会把PackageManagerServer启动,PackageManagerServer启动后会将系统中的应用程序安装完成;ActivityManagerServer(简称:AMS)是在PackageManagerServer之前启动的,当PackageManagerServer把应用程序安装完成后;AMS会把Launcher应用程序调起来。SystemServer中AMS与PMS的启动顺序:

     private void startBootstrapServices() {
     
            Installer installer = mSystemServiceManager.startService(Installer.class);
    
            // Activity manager runs the show.
            //这是AMS启动
            mActivityManagerService = mSystemServiceManager.startService(
                    ActivityManagerService.Lifecycle.class).getService();
            mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
            mActivityManagerService.setInstaller(installer);
            
            //电源管理服务在这是启动
            mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
    
            // Now that the power manager has been started, let the activity manager
            // initialize power management features.
            mActivityManagerService.initPowerManagement();
    
            // Manages LEDs and display backlight so we need it to bring up the display.
            mSystemServiceManager.startService(LightsService.class);
    
            // Display manager is needed to provide display metrics before package manager
            // starts up.
            mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
    
            // We need the default display before we can initialize the package manager.
            mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
    
           String cryptState = SystemProperties.get("vold.decrypt");
            if (ENCRYPTING_STATE.equals(cryptState)) {
                Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
                mOnlyCore = true;
            } else if (ENCRYPTED_STATE.equals(cryptState)) {
                Slog.w(TAG, "Device encrypted - only parsing core apps");
                mOnlyCore = true;
            }
    
            // Start the package manager.
            //PMS在这里启动起来
            Slog.i(TAG, "Package Manager");
            mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
            mFirstBoot = mPackageManagerService.isFirstBoot();
            mPackageManager = mSystemContext.getPackageManager();
    
            Slog.i(TAG, "User Service");
            ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());
       // Initialize attribute cache used to cache resources from packages.
            AttributeCache.init(mSystemContext);
    
            // Set up the Application instance for the system process and get started.
            mActivityManagerService.setSystemProcess();
    
            // The sensor service needs access to package manager service, app ops
            // service, and permissions service, therefore we start it after them.
            startSensorService();
    }
    

    以上就是AMS和PMS的启动顺序,首先是AMS启动然后PMS再启动。
    系统原码目录在:frameworks/base/services/java/com/android/server/SystemServer.java中可以看上述源码。

    2.Launcher启动

    启动Launcher入口在AMS的systemReady方法中,而调用这个方法的还是SystemServer,在SystemServer的startOtherServices中调用了AMS中的systemReady方法让Launcher启动;由于SystemServer的startOtherServices方法代码行数太多,这里给出调用AMS的中的systemReady方法部分源码:

     private void startOtherServices() {
            .................
         mActivityManagerService.systemReady(new Runnable() {
                @Override
                public void run() {
                    Slog.i(TAG, "Making services ready");
                    mSystemServiceManager.startBootPhase(
                            SystemService.PHASE_ACTIVITY_MANAGER_READY);
                ....................
                  }
                ....................
    }
    

    接下来到AMS中的systemReady方法中看Launcher是如何启动的,在Android8.0的部分代码中引入了Java的Lambad表达式,systemReady具体干了什么:

    public void systemReady(final Runnble goingCallbac){
      .....
      synchronized(this){
                ....
                mStackSupervisor.resumeFocusedStackTopActivityLocked();
                mUserController.sendUserSwitchBroadcastsLocked(-1,currentUserId);
            }
    }
    

    systemReady方法中调用了ActivityStatckSupervisor中的resumeFocusedStackTopActivityLocked的方法,方法具体如下:

    boolean resumeFocusedStackTopActivityLocked(
                ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    
            if (!readyToResume()) {
                return false;
            }
    
            if (targetStack != null && isFocusedStack(targetStack)) {
                return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
            }
    
            final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
            if (r == null || !r.isState(RESUMED)) {
                mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
            } else if (r.isState(RESUMED)) {
                // Kick off any lingering app transitions form the MoveTaskToFront operation.
                mFocusedStack.executeAppTransition(targetOptions);
            }
    
            return false;
        }
    

    其中ActivityStack 是用来描述Activity的堆栈信息的,resumeTopActivityUncheckedLocked具体又干了什么事情,代码如下:

     boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
            if (mStackSupervisor.inResumeTopActivity) {
                // Don't even start recursing.
                return false;
            }
    
            boolean result = false;
            try {
                // Protect against recursion.
                mStackSupervisor.inResumeTopActivity = true;
                result = resumeTopActivityInnerLocked(prev, options);
    
                // When resuming the top activity, it may be necessary to pause the top activity (for
                // example, returning to the lock screen. We suppress the normal pause logic in
                // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
                // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
                // to ensure any necessary pause logic occurs. In the case where the Activity will be
                // shown regardless of the lock screen, the call to
                // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
                final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
                if (next == null || !next.canTurnScreenOn()) {
                    checkReadyForSleep();
                }
            } finally {
                mStackSupervisor.inResumeTopActivity = false;
            }
    
            return result;
        }
    

    resumeTopActivityUncheckedLocked中主要调用了resumeTopActivityInnerLocked方法,由于该方法的代码比较多这里只给出关键的代码

     private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    
          ....
          if (!hasRunningActivity) {
                // There are no activities left in the stack, let's look somewhere else.
                return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
            }
          .....
    }
    

    这里面又调用了resumeTopActivityInNextFocusableStack方法

    private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev,
                ActivityOptions options, String reason) {
            if (adjustFocusToNextFocusableStack(reason)) {
                // Try to move focus to the next visible stack with a running activity if this
                // stack is not covering the entire screen or is on a secondary display (with no home
                // stack).
                return mStackSupervisor.resumeFocusedStackTopActivityLocked(
                        mStackSupervisor.getFocusedStack(), prev, null);
            }
    
            // Let's just start up the Launcher...
            ActivityOptions.abort(options);
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityInNextFocusableStack: " + reason + ", go home");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            // Only resume home if on home display
            return isOnHomeDisplay() &&
                    mStackSupervisor.resumeHomeStackTask(prev, reason);
        }
    

    从上面又可以看到又调用了ActivityStackSupervisor中的resumeHomeStackTask方法

        boolean resumeHomeStackTask(ActivityRecord prev, String reason) {
            if (!mService.mBooting && !mService.mBooted) {
                // Not ready yet!
                return false;
            }
    
            mHomeStack.moveHomeStackTaskToTop();
            ActivityRecord r = getHomeActivity();
            final String myReason = reason + " resumeHomeStackTask";
    
            // Only resume home activity if isn't finishing.
            if (r != null && !r.finishing) {
                moveFocusableActivityStackToFrontLocked(r, myReason);
                return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null);
            }
            return mService.startHomeActivityLocked(mCurrentUser, myReason);
        }
    

    在resumeHomeStackTask中可以看到最终看到调用了mService的startHomeActivityLocked方法来启动Launcher而这个mService就是ActivityManagerService(AMS)。

    boolean startHomeActivityLocked(int userId, String reason) {
            if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                    && mTopAction == null) {
                // We are running in factory test mode, but unable to find
                // the factory test app, so just sit around displaying the
                // error message and don't try to start anything.
                return false;
            }
            Intent intent = getHomeIntent();//创建 Launcher启动所需要的Intent
            ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
            if (aInfo != null) {
                intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
                // Don't do this if the home app is currently being
                // instrumented.
                aInfo = new ActivityInfo(aInfo);
                aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
                ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                        aInfo.applicationInfo.uid, true);
                if (app == null || app.instr == null) {
                    intent.setFlags(intent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
                    final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
                    // For ANR debugging to verify if the user activity is the one that actually
                    // launched.
                    final String myReason = reason + ":" + userId + ":" + resolvedUserId;
                    mActivityStartController.startHomeActivity(intent, aInfo, myReason);//启动Launcher的Activity
                }
            } else {
                Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
            }
    
            return true;
        }
    

    接下来看一下getHomeIntent方法是怎么构建Launcher的Intent的

    Intent getHomeIntent() {
            Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
            intent.setComponent(mTopComponent);
            intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
            if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                intent.addCategory(Intent.CATEGORY_HOME);
            }
            return intent;
        }
    

    最后看到Launcher的启动调用了 mActivityStartController.startHomeActivity方法,该方法如下:

      void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
            mSupervisor.moveHomeStackTaskToTop(reason);//1
    
            mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
                    .setOutActivity(tmpOutRecord)
                    .setCallingUid(0)
                    .setActivityInfo(aInfo)
                    .execute();
            mLastHomeActivityStartRecord = tmpOutRecord[0];
            if (mSupervisor.inResumeTopActivity) {
                // If we are in resume section already, home activity will be initialized, but not
                // resumed (to avoid recursive resume) and will stay that way until something pokes it
                // again. We need to schedule another resume.
                mSupervisor.scheduleResumeTopActivities();
            }
        }
    

    这里注释1中将Launcher放入到HomeStack中,HomStack是在ActivityStackSupervisor中定义的用来存储Launcher的变量。接下来就是启动Launcher的Activity了,Activity的启动过程下次有机会再分享;到这里Launcher的启动完成了。接下来附上Launcher启动的流程图


    Launcher启动流程图.png

    到这里Launcher的启动流程就分享到这里了;如果觉得该文章你有get到干货请给作者点个赞吧!

    相关文章

      网友评论

        本文标题:Android系统中Launcher的启动流程分析

        本文链接:https://www.haomeiwen.com/subject/ogsgjhtx.html