frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) {
    ...// 启动Home Activity--Luncher 
    if (bootingSystemUser) {
        // 通过ATM,启动Home Activity
        t.traceBegin("startHomeOnAllDisplays");
        mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
        t.traceEnd();
    }
}

可以看到通过ATM启动启动Home Activity
追踪startHomeOnAllDisplays()会发现该方法位于frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java,是一个抽象方法,实际上mAtmInternal.startHomeOnAllDisplays()最终调用的是frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java的startHomeOnAllDisplays()方法。

public boolean startHomeOnAllDisplays(int userId, String reason) {
    synchronized (mGlobalLock) {
        //调用RootWindowContainer的startHomeOnAllDisplays(),最终到startHomeOnDisplay()
        return mRootWindowContainer.startHomeOnAllDisplays(userId, reason);
    }
}

该方法在Android 10中还位于RootActivityContainer下,而Android 11就位于RootWindowContainer下了,从这里也可以看出google最终的目的是把activity 和window融合。

frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java下的startHomeOnAllDisplays()方法最终调用了startHomeOnDisplay()方法,该部分的调用链如下:

boolean startHomeOnAllDisplays(int userId, String reason) {
    boolean homeStarted = false;
    for (int i = getChildCount() - 1; i >= 0; i--) {
        final int displayId = getChildAt(i).mDisplayId;
        homeStarted |= startHomeOnDisplay(userId, reason, displayId);
    }
    return homeStarted;
}
​
boolean startHomeOnDisplay(int userId, String reason, int displayId) {
    return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,
            false /* fromHomeKey */);
}
​
boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,
        boolean fromHomeKey) {
    // 如果displayId无效,则回退到默认桌面
    if (displayId == INVALID_DISPLAY) {
        final Task rootTask = getTopDisplayFocusedRootTask();
        displayId = rootTask != null ? rootTask.getDisplayId() : DEFAULT_DISPLAY;
    }
​
    final DisplayContent display = getDisplayContent(displayId);
    return display.reduceOnAllTaskDisplayAreas((taskDisplayArea, result) ->
                    result | startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,
                            allowInstrumenting, fromHomeKey),
            false /* initValue */);
}

在安卓11以前,在startHomeOnDisplay()方法下就已经调用了启动Launch的startHomeActivity()了,安卓11又对startHomeActivity()做了一层封装,这层封装既startHomeOnTaskDisplayArea()方法,下面来探究一下该方法。

boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
        boolean allowInstrumenting, boolean fromHomeKey) {
    ...
    
    Intent homeIntent = null;
    ActivityInfo aInfo = null;
    if (taskDisplayArea == getDefaultTaskDisplayArea()) {
        // 构建一个category为CATEGORY_HOME的Intent,表明是Home Activity
        homeIntent = mService.getHomeIntent();// 通过PMS从系统所用已安装的应用中,找到一个符合HomeItent的Activity
        aInfo = resolveHomeActivity(userId, homeIntent);
    } else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) {
        Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, taskDisplayArea);
        aInfo = info.first;
        homeIntent = info.second;
    }
   ...// 启动Home Activity--Luncher
    mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
            taskDisplayArea);
    return true;
}

startHomeOnTaskDisplayArea()首先通过getHomeIntent()来构建一个category为CATEGORY_HOME的Intent,表明是Home Activity;然后通过resolveHomeActivity()从系统所用已安装的引用中,找到一个符合HomeItent的Activity,最终调用startHomeActivity()来启动Activity。

getHomeIntent()方法构建一个category为CATEGORY_HOME的Intent,表明是Home Activity。 Intent.CATEGORY_HOME = “android.intent.category.HOME” 这个category会在Launcher3的 AndroidManifest.xml中配置,表明是Home Acivity

Intent getHomeIntent() {
    Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
    intent.setComponent(mTopComponent);
    intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
    //不是生产模式,add一个CATEGORY_HOME
    if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
        intent.addCategory(Intent.CATEGORY_HOME);
    }
    return intent;
}

resolveHomeActivity()方法通过Binder跨进程通知PackageManagerService从系统所用已安装的引用中,找到一个符合HomeItent的Activity

ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) {
   final int flags = ActivityManagerService.STOCK_PM_FLAGS;
   
   //系统正常启动时,component为null
   final ComponentName comp = homeIntent.getComponent(); 
   ActivityInfo aInfo = null;
   ...
   
       if (comp != null) {
           // Factory test.
           aInfo = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
       } else {
           //系统正常启动时,走该流程
           final String resolvedType =
                   homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
           
           //resolveIntent做了两件事:
           // 1.通过queryIntentActivities来查找符合HomeIntent需求Activities
           // 2.通过chooseBestActivity找到最符合Intent需求的Activity信息
           final ResolveInfo info = AppGlobals.getPackageManager()
                   .resolveIntent(homeIntent, resolvedType, flags, userId);
           if (info != null) {
               aInfo = info.activityInfo;
           }
       }
   ...
   aInfo = new ActivityInfo(aInfo);
   aInfo.applicationInfo = mService.getAppInfoForUser(aInfo.applicationInfo, userId);
   return aInfo;
}

最后一步, mService.getActivityStartController().startHomeActivity这是调用了frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java

      void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason,
              TaskDisplayArea taskDisplayArea) {
          final ActivityOptions options = ActivityOptions.makeBasic();
          options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
          if (!ActivityRecord.isResolverActivity(aInfo.name)) {
              // The resolver activity shouldn't be put in root home task because when the
              // foreground is standard type activity, the resolver activity should be put on the
              // top of current foreground instead of bring root home task to front.
              options.setLaunchActivityType(ACTIVITY_TYPE_HOME);
          }
          final int displayId = taskDisplayArea.getDisplayId();
          options.setLaunchDisplayId(displayId);
          options.setLaunchTaskDisplayArea(taskDisplayArea.mRemoteToken
                  .toWindowContainerToken());
  
          // The home activity will be started later, defer resuming to avoid unnecessary operations
          // (e.g. start home recursively) when creating root home task.
          mSupervisor.beginDeferResume();
          final Task rootHomeTask;
          try {
              // Make sure root home task exists on display area.
              rootHomeTask = taskDisplayArea.getOrCreateRootHomeTask(ON_TOP);
          } finally {
              mSupervisor.endDeferResume();
          }
  
          mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
                  .setOutActivity(tmpOutRecord)
                  .setCallingUid(0)
                  .setActivityInfo(aInfo)
                  .setActivityOptions(options.toBundle())
                  .execute();
          mLastHomeActivityStartRecord = tmpOutRecord[0];
          if (rootHomeTask.mInResumeTopActivity) {
              // 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();
          }
      }

obtainStarter() 方法返回的是 ActivityStarter 对象,它负责 Activity 的启动,一系列 setXXX() 方法传入启动所需的各种参数,最后的 execute() 是真正的启动逻辑。

Logo

鸿蒙生态一站式服务平台。

更多推荐