activity 启动流程分析

在这里插入图片描述1.
public void startActivity(Intent intent, @Nullable Bundle options)就两个参数,第二个参数可以空
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
一般情况下,不带options参数将会走else流程。将会调用对应在的多态startActivityForResult函数

  1. public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
    startActivityForResult(intent, requestCode, null);
    }
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
    @Nullable Bundle options) {
    //这里requestCode= -1 , options=NULL
    if (mParent == null) { //mParent为NULL,除非你调用setParent来设置其值
    options = transferSpringboardActivityOptions(options);//获取父类的opt
    Instrumentation.ActivityResult ar =
    mInstrumentation.execStartActivity(
    this, mMainThread.getApplicationThread(), mToken, this,
    intent, requestCode, options);
    //mMainThread.getApplicationThread() 就是ApplicationThread对象,用来作回调用的,主要用来派发消息
    **mToken是ActivityRecord对象,指向caller的ActivityRecord,通过它访问成员变量pendingOptions可以拿到 Caller的opt,**activity是Context的子类,所以里面有两个this实参。requestCode=-1 options=NULL

         if (ar != null) {
             mMainThread.sendActivityResult(
                 mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                 ar.getResultData());
         }
         if (requestCode >= 0) {**//**这里requestCode 为-1,不会走下面的赋值流程,mStartedActivity 用来控制视图是否显示。如果为true将会尝试将视图显示在activityThread resume时候来读取这个值****
             // If this start is requesting a result, we can avoid making
             // the activity visible until the result is received.  Setting
             // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
             // activity hidden during this time, to avoid flickering.
             // This can only be done when a result is requested because
             // that guarantees we will get information back when the
             // activity is finished, no matter what happens to it.
             mStartedActivity = true;
         }
         cancelInputsAndStartExitTransition(options);
         // TODO Consider clearing/flushing other event sources and events for child windows.
     } else {
        ......这个分支不作分析
     }
    

    }

  2. public ActivityResult execStartActivity(
    Context who, IBinder contextThread, IBinder token, Activity target,
    Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    //referrer 为空,下面代码没用到
    Uri referrer = target != null ? target.onProvideReferrer() : null;
    if (referrer != null) {
    intent.putExtra(Intent.EXTRA_REFERRER, referrer);
    }
    //搜遍framework没发现有add activityMonitor的,除了几个测试类。所以mActivityMonitors 也是NULL
    if (mActivityMonitors != null) {
    synchronized (mSync) {
    final int N = mActivityMonitors.size();
    for (int i=0; i<N; i++) {
    final ActivityMonitor am = mActivityMonitors.get(i);
    ActivityResult result = null;
    if (am.ignoreMatchingSpecificIntents()) {
    result = am.onStartActivity(intent);
    }
    if (result != null) {
    am.mHits++;
    return result;
    } else if (am.match(who, null, intent)) {
    am.mHits++;
    if (am.isBlocking()) {
    return requestCode >= 0 ? am.getResult() : null;
    }
    break;
    }
    }
    }
    }
    try {
    //下面这个函数调用,就是根据intent.setAction设置的字符串进行一些标记的修改
    当action为ACTION_CHOOSER时,把choose所有的intent遍历一遍以便为这些intent添加标记
    当action为 ACTION_SEND 添加FLAG_GRANT_READ_URI_PERMISSION flag
    当action为 ACTION_SEND_MULTIPLE 添加FLAG_GRANT_READ_URI_PERMISSION flag
    当action为MediaStore.ACTION_IMAGE_CAPTURE 添加 FLAG_GRANT_WRITE_URI_PERMISSION|FLAG_GRANT_READ_URI_PERMISSION flag

    intent.migrateExtraStreamToClipData();
    //下面这个调用在正常情况下是可以认为是空函数,因为里面的执行环境除了特定条件是不会进去的
    intent.prepareToLeaveProcess(who);
    //ActivityManager.getService() 就是Activitymanagerservice类对象
    int result = ActivityManager.getService()
    .startActivity(whoThread, who.getBasePackageName(), intent,
    intent.resolveTypeIfNeeded(who.getContentResolver()),
    token, target != null ? target.mEmbeddedID : null,
    requestCode, 0, null, options);
    checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
    throw new RuntimeException(“Failure from system”, e);
    }
    return null;
    }

  3. @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
    Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
    int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
    resultWho, requestCode, startFlags, profilerInfo, bOptions,
    UserHandle.getCallingUserId());
    }
    //没做什么事,就是参数传递
    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
    Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
    int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
    //下面这行代码作个判断,当caller UID大于99000且小于99999时扔出异常
    enforceNotIsolatedCaller(“startActivity”);
    //在这个流程调用里面userId = Binder.getCallingUid()的,就是上个函数传进的UID,它们获取的方式是一样的
    userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
    userId, false, ALLOW_FULL_ONLY, “startActivity”, null);
    // TODO: Switch to user app stacks here.
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
    resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
    profilerInfo, null, null, bOptions, false, userId, null, null,
    “startActivityAsUser”);
    }

  4. @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
    Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
    int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
    enforceNotIsolatedCaller(“startActivity”);
    userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
    userId, false, ALLOW_FULL_ONLY, “startActivity”, null);
    // TODO: Switch to user app stacks here.
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
    resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
    profilerInfo, null, null, bOptions, false, userId, null, null,
    “startActivityAsUser”);
    }

  5. final int startActivityMayWait(IApplicationThread caller, int callingUid,
    String callingPackage, Intent intent, String resolvedType,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    IBinder resultTo, String resultWho, int requestCode, int startFlags,
    ProfilerInfo profilerInfo, WaitResult outResult,
    Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
    IActivityContainer iContainer, TaskRecord inTask, String reason) {
    // Refuse possible leaked file descriptors
    //callingUid = -1 voiceSession=NULL,voiceInteractor=NULL,outResult=NULL,globalConfig=NULL,iContainer=NULL,inTask=NULL
    //如果 intent里面有有mExtras属性且mExtras里面有CONTENTS_FILE_DESCRIPTOR,则扔出异常
    if (intent != null && intent.hasFileDescriptors()) {
    throw new IllegalArgumentException(“File descriptors passed in Intent”);
    }
    //在ActivityMetricsLogger类中,记录下开始启动APP的时间
    mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
    //判断intent里面是否包含组件,也就是包名类名
    boolean componentSpecified = intent.getComponent() != null;

     // Save a copy in case ephemeral needs it
     final Intent ephemeralIntent = new Intent(intent);
     // Don't modify the client's object!
     intent = new Intent(intent);
     **//如果组件不为空,如果intent里面包含ACTION_VIEW属性,且此组件是目前正在安装的组件则重置组件名为空**
     if (componentSpecified
             && intent.getData() != null
             && Intent.ACTION_VIEW.equals(intent.getAction())
             && mService.getPackageManagerInternalLocked()
                     .isInstantAppInstallerComponent(intent.getComponent())) {
         // intercept intents targeted directly to the ephemeral installer the
         // ephemeral installer should never be started with a raw URL; instead
         // adjust the intent so it looks like a "normal" instant app launch
         intent.setComponent(null /*component*/);
         componentSpecified = false;
     **}
     //下面这行代码获取一个rinfo的属性,通过跟踪代码分析得知,当intent的组件不为空的时候就从所有安装包里面查找这个组件对应的activity,如果找到就返回这个activity里面的info
             private final ArrayMap<ComponentName, PackageParser.Activity> mActivities
             = new ArrayMap<ComponentName, PackageParser.Activity>();  mActivities包含所有的安装文件信息****
     ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
     if (rInfo == null) {
         UserInfo userInfo = mSupervisor.getUserInfo(userId);
         if (userInfo != null && userInfo.isManagedProfile()) {
             // Special case for managed profiles, if attempting to launch non-cryto aware
             // app in a locked managed profile from an unlocked parent allow it to resolve
             // as user will be sent via confirm credentials to unlock the profile.
             UserManager userManager = UserManager.get(mService.mContext);
             boolean profileLockedAndParentUnlockingOrUnlocked = false;
             long token = Binder.clearCallingIdentity();
             try {
                 UserInfo parent = userManager.getProfileParent(userId);
                 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
                         && userManager.isUserUnlockingOrUnlocked(parent.id)
                         && !userManager.isUserUnlockingOrUnlocked(userId);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
             if (profileLockedAndParentUnlockingOrUnlocked) {
                 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
             }
         }
     }
     // Collect information about the target of the Intent.
     **//当rInfo不为空的时候,直接从rInfo里面拿到ainfo**
     ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
    
     **//从bOptions提取各种信息用来生成一个新的ActivityOption对象**
     ActivityOptions options = ActivityOptions.fromBundle(bOptions);
     ActivityStackSupervisor.ActivityContainer container =
             (ActivityStackSupervisor.ActivityContainer)iContainer;
     synchronized (mService) {
         if (container != null && container.mParentActivity != null &&
                 container.mParentActivity.state != RESUMED) {
             // Cannot start a child activity if the parent is not resumed.
             return ActivityManager.START_CANCELED;
         }
         final int realCallingPid = Binder.getCallingPid();
         final int realCallingUid = Binder.getCallingUid();
         int callingPid;
         if (callingUid >= 0) {
             callingPid = -1;
         } else if (caller == null) {
             callingPid = realCallingPid;
             callingUid = realCallingUid;
         } else {
             callingPid = callingUid = -1;
         }
    
         final ActivityStack stack;
         if (container == null || container.mStack.isOnHomeDisplay()) {
             stack = mSupervisor.mFocusedStack;
         } else {
             stack = container.mStack;
         }
         stack.mConfigWillChange = globalConfig != null
                 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
         if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                 "Starting activity when config will change = " + stack.mConfigWillChange);
    
         final long origId = Binder.clearCallingIdentity();
    
    
     	**//下面这个if语句主要这个intent是不是与已经存运行的APP的进程名是一样的,如果是一样则用HeavyWeightSwitcherActivity类创建一个选择器**
    
         if (aInfo != null &&
                 (aInfo.applicationInfo.privateFlags
                         & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
             // This may be a heavy-weight process!  Check to see if we already
             // have another, different heavy-weight process running.
             if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
                 final ProcessRecord heavy = mService.mHeavyWeightProcess;
                 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
                         || !heavy.processName.equals(aInfo.processName))) {
                     int appCallingUid = callingUid;
                     if (caller != null) {
                         ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
                         if (callerApp != null) {
                             appCallingUid = callerApp.info.uid;
                         } else {
                             Slog.w(TAG, "Unable to find app for caller " + caller
                                     + " (pid=" + callingPid + ") when starting: "
                                     + intent.toString());
                             ActivityOptions.abort(options);
                             return ActivityManager.START_PERMISSION_DENIED;
                         }
                     }
    
                     IIntentSender target = mService.getIntentSenderLocked(
                             ActivityManager.INTENT_SENDER_ACTIVITY, "android",
                             appCallingUid, userId, null, null, 0, new Intent[] { intent },
                             new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
                                     | PendingIntent.FLAG_ONE_SHOT, null);
    
                     Intent newIntent = new Intent();
                     if (requestCode >= 0) {
                         // Caller is requesting a result.
                         newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
                     }
                     newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
                             new IntentSender(target));
                     if (heavy.activities.size() > 0) {
                         ActivityRecord hist = heavy.activities.get(0);
                         newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
                                 hist.packageName);
                         newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
                                 hist.getTask().taskId);
                     }
                     newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
                             aInfo.packageName);
                     newIntent.setFlags(intent.getFlags());
                     newIntent.setClassName("android",
                             HeavyWeightSwitcherActivity.class.getName());
                     intent = newIntent;
                     resolvedType = null;
                     caller = null;
                     callingUid = Binder.getCallingUid();
                     callingPid = Binder.getCallingPid();
                     componentSpecified = true;
                     rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
                     aInfo = rInfo != null ? rInfo.activityInfo : null;
                     if (aInfo != null) {
                         aInfo = mService.getActivityInfoForUser(aInfo, userId);
                     }
                 }
             }
         }
    
         final ActivityRecord[] outRecord = new ActivityRecord[1];
         int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                 aInfo, rInfo, voiceSession, voiceInteractor,
                 resultTo, resultWho, requestCode, callingPid,
                 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                 inTask, reason);
                 .......
    
  6. //中转,参数传递没实际的东西
    int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
    String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
    String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
    ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
    ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
    TaskRecord inTask, String reason) {

     if (TextUtils.isEmpty(reason)) {
         throw new IllegalArgumentException("Need to specify a reason.");
     }
     mLastStartReason = reason;
     mLastStartActivityTimeMs = System.currentTimeMillis();
     mLastStartActivityRecord[0] = null;
    
     mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
             aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
             callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
             options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
             container, inTask);
    

  1. private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
    String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
    String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
    ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
    ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
    TaskRecord inTask) {
    int err = ActivityManager.START_SUCCESS;
    // Pull the optional Ephemeral Installer-only bundle out of the options early.
    final Bundle verificationBundle
    = options != null ? options.popAppVerificationBundle() : null;

    ProcessRecord callerApp = null;
    if (caller != null) {
    //从之前记录的对象ArrayList里找出Caller
    //当APP Launcher成功后,会把ProcessRecord加到arraylist数组里面,当APP死掉或者启动超时后从数组移除
    callerApp = mService.getRecordForAppLocked(caller);
    if (callerApp != null) {
    callingPid = callerApp.pid;
    callingUid = callerApp.info.uid;
    } else {
    Slog.w(TAG, “Unable to find app for caller " + caller
    + " (pid=” + callingPid + ") when starting: "
    + intent.toString());
    err = ActivityManager.START_PERMISSION_DENIED;
    }
    }

    final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;

    if (err == ActivityManager.START_SUCCESS) {
    Slog.i(TAG, “START u” + userId + " {" + intent.toShortString(true, true, true, false)
    + "} from uid " + callingUid);
    }


    //省略部分是各种检查,没太仔细看
    boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
    requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
    resultRecord, resultStack, options);
    abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
    callingPid, resolvedType, aInfo.applicationInfo);

    if (mService.mController != null) {
    try {
    // The Intent we give to the watcher has the extra data
    // stripped off, since it can contain private information.
    Intent watchIntent = intent.cloneFilter();
    abort |= !mService.mController.activityStarting(watchIntent,
    aInfo.applicationInfo.packageName);
    } catch (RemoteException e) {
    mService.mController = null;
    }
    }

    mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
    mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
    options);
    intent = mInterceptor.mIntent;
    rInfo = mInterceptor.mRInfo;
    aInfo = mInterceptor.mAInfo;
    resolvedType = mInterceptor.mResolvedType;
    inTask = mInterceptor.mInTask;
    callingPid = mInterceptor.mCallingPid;
    callingUid = mInterceptor.mCallingUid;
    options = mInterceptor.mActivityOptions;
    if (abort) {
    if (resultRecord != null) {
    resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
    RESULT_CANCELED, null);
    }
    // We pretend to the caller that it was really started, but
    // they will just get a cancel result.
    ActivityOptions.abort(options);
    return START_SUCCESS;
    }

    // If permissions need a review before any of the app components can run, we
    // launch the review activity and pass a pending intent to start the activity
    // we are to launching now after the review is completed.
    if (mService.mPermissionReviewRequired && aInfo != null) {
    if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
    aInfo.packageName, userId)) {
    IIntentSender target = mService.getIntentSenderLocked(
    ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
    callingUid, userId, null, null, 0, new Intent[]{intent},
    new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
    | PendingIntent.FLAG_ONE_SHOT, null);

          final int flags = intent.getFlags();
          Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
          newIntent.setFlags(flags
                  | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
          newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
          newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
          if (resultRecord != null) {
              newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
          }
          intent = newIntent;
    
          resolvedType = null;
          callingUid = realCallingUid;
          callingPid = realCallingPid;
    
          rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
          aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
                  null /*profilerInfo*/);
    
          if (DEBUG_PERMISSIONS_REVIEW) {
              Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
                      true, false) + "} from uid " + callingUid + " on display "
                      + (container == null ? (mSupervisor.mFocusedStack == null ?
                      DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
                      (container.mActivityDisplay == null ? DEFAULT_DISPLAY :
                              container.mActivityDisplay.mDisplayId)));
          }
      }
    

    }

    // If we have an ephemeral app, abort the process of launching the resolved intent.
    // Instead, launch the ephemeral installer. Once the installer is finished, it
    // starts either the intent we resolved here [on install error] or the ephemeral
    // app [on install success].
    if (rInfo != null && rInfo.auxiliaryInfo != null) {
    intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
    callingPackage, verificationBundle, resolvedType, userId);
    resolvedType = null;
    callingUid = realCallingUid;
    callingPid = realCallingPid;

      aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
    

    }
    //使用现成的数据,生成一个ActivityRecord参数。便于管理,传参更方便
    ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
    callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
    resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
    mSupervisor, container, options, sourceRecord);
    if (outActivity != null) {
    outActivity[0] = r;
    }

    if (r.appTimeTracker == null && sourceRecord != null) {
    // If the caller didn’t specify an explicit time tracker, we want to continue
    // tracking under any it has.
    r.appTimeTracker = sourceRecord.appTimeTracker;
    }

    final ActivityStack stack = mSupervisor.mFocusedStack;
    if (voiceSession == null && (stack.mResumedActivity == null
    || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
    if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
    realCallingPid, realCallingUid, “Activity start”)) {
    PendingActivityLaunch pal = new PendingActivityLaunch(r,
    sourceRecord, startFlags, stack, callerApp);
    mPendingActivityLaunches.add(pal);
    ActivityOptions.abort(options);
    return ActivityManager.START_SWITCHES_CANCELED;
    }
    }

    if (mService.mDidAppSwitch) {
    // This is the second allowed switch since we stopped switches,
    // so now just generally allow switches. Use case: user presses
    // home (switches disabled, switch to home, mDidAppSwitch now true);
    // user taps a home icon (coming from home so allowed, we hit here
    // and now allow anyone to switch again).
    mService.mAppSwitchesAllowedTime = 0;
    } else {
    mService.mDidAppSwitch = true;
    }

    doPendingActivityLaunchesLocked(false);

    return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
    options, inTask, outActivity);
    }

  2. private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
    ActivityRecord[] outActivity) {
    int result = START_CANCELED;
    try {
    //下面这句话作用是记录启动的APP数量,自加一 mDeferDepth++;
    mService.mWindowManager.deferSurfaceLayout();
    result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
    startFlags, doResume, options, inTask, outActivity);
    } finally {
    // If we are not able to proceed, disassociate the activity from the task. Leaving an
    // activity in an incomplete state can lead to issues, such as performing operations
    // without a window container.
    if (!ActivityManager.isStartResultSuccessful(result)
    && mStartActivity.getTask() != null) {
    mStartActivity.getTask().removeActivity(mStartActivity);
    }
    mService.mWindowManager.continueSurfaceLayout();
    }

     postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId,  mSourceRecord,
             mTargetStack);
    
     return result;
    

    }
    10。
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
    ActivityRecord[] outActivity) {

     setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
             voiceInteractor);
     **/为launchflag增加FLAG_ACTIVITY_NEW_TASK标志**
     computeLaunchingTaskFlags();
    
     computeSourceStack();
    
     mIntent.setFlags(mLaunchFlags);
    
     **//这个函数调用的主要作用是查找有没有可以重复使用的activity,因为有的activity被设置成singleTask or singleInstance成这样的属性,如果这个属性的Activity已经存在task里面就使用它。**
     ActivityRecord reusedActivity = getReusableIntentActivity();
    
     final int preferredLaunchStackId =
             (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
     final int preferredLaunchDisplayId =
             (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;
    

//activity第一次启动时为NULL,不会走这个流程.先不看这部分代码
if (reusedActivity != null) {
// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
// still needs to be a lock task mode violation since the task gets cleared out and
// the device would otherwise leave the locked task.
if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
(mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
mSupervisor.showLockTaskToast();
Slog.e(TAG, “startActivityUnchecked: Attempt to violate Lock Task Mode”);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}

        if (mStartActivity.getTask() == null) {
            mStartActivity.setTask(reusedActivity.getTask());
        }
        if (reusedActivity.getTask().intent == null) {
            // This task was started because of movement of the activity based on affinity...
            // Now that we are actually launching it, we can assign the base intent.
            reusedActivity.getTask().setIntent(mStartActivity);
        }

        // This code path leads to delivering a new intent, we want to make sure we schedule it
        // as the first operation, in case the activity will be resumed as a result of later
        // operations.
        if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                || isDocumentLaunchesIntoExisting(mLaunchFlags)
                || mLaunchSingleInstance || mLaunchSingleTask) {
            final TaskRecord task = reusedActivity.getTask();

            // In this situation we want to remove all activities from the task up to the one
            // being started. In most cases this means we are resetting the task to its initial
            // state.
            final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
                    mLaunchFlags);

            // The above code can remove {@code reusedActivity} from the task, leading to the
            // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
            // task reference is needed in the call below to
            // {@link setTargetStackAndMoveToFrontIfNeeded}.
            if (reusedActivity.getTask() == null) {
                reusedActivity.setTask(task);
            }

            if (top != null) {
                if (top.frontOfTask) {
                    // Activity aliases may mean we use different intents for the top activity,
                    // so make sure the task now has the identity of the new intent.
                    top.getTask().setIntent(mStartActivity);
                }
                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
                top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
                        mStartActivity.launchedFromPackage);
            }
        }

        sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);

        reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);

        final ActivityRecord outResult =
                outActivity != null && outActivity.length > 0 ? outActivity[0] : null;

        // When there is a reused activity and the current result is a trampoline activity,
        // set the reused activity as the result.
        if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
            outActivity[0] = reusedActivity;
        }

        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
            // We don't need to start a new activity, and the client said not to do anything
            // if that is the case, so this is it!  And for paranoia, make sure we have
            // correctly resumed the top activity.
            resumeTargetStackIfNeeded();
            return START_RETURN_INTENT_TO_CALLER;
        }
        setTaskFromIntentActivity(reusedActivity);

        if (!mAddingToTask && mReuseTask == null) {
            // We didn't do anything...  but it was needed (a.k.a., client don't use that
            // intent!)  And for paranoia, make sure we have correctly resumed the top activity.
            resumeTargetStackIfNeeded();
            if (outActivity != null && outActivity.length > 0) {
                outActivity[0] = reusedActivity;
            }
            return START_TASK_TO_FRONT;
        }
    }

    if (mStartActivity.packageName == null) {
        final ActivityStack sourceStack = mStartActivity.resultTo != null
                ? mStartActivity.resultTo.getStack() : null;
        if (sourceStack != null) {
            sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
                    null /* data */);
        }
        ActivityOptions.abort(mOptions);
        return START_CLASS_NOT_FOUND;
    }

    // If the activity being launched is the same as the one currently at the top, then
    // we need to check if it should only be launched once.
    final ActivityStack topStack = mSupervisor.mFocusedStack;
    final ActivityRecord topFocused = topStack.topActivity();
    final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
    final boolean dontStart = top != null && mStartActivity.resultTo == null
            && top.realActivity.equals(mStartActivity.realActivity)
            && top.userId == mStartActivity.userId
            && top.app != null && top.app.thread != null
            && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
            || mLaunchSingleTop || mLaunchSingleTask);

//如果是单例,且上面的if语句被执行过,代表这个ACTIVITY已经存在TASK栈中,直接走resume就可以了,mDoResume这个变量是上个startactivity传进的实参为True
if (dontStart) {
ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
//如果有已经存在的单例属性的Activity,Resume它就可以了
if (mDoResume) {
mSupervisor.resumeFocusedStackTopActivityLocked();
}
ActivityOptions.abort(mOptions);
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don’t need to start a new activity, and the client said not to do
// anything if that is the case, so this is it!
return START_RETURN_INTENT_TO_CALLER;
}
top.deliverNewIntentLocked(
mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);

        // Don't use mStartActivity.task to show the toast. We're not starting a new activity
        // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
        mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
                preferredLaunchDisplayId, topStack.mStackId);

        return START_DELIVERED_TO_TOP;
    }

    boolean newTask = false;
    final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
            ? mSourceRecord.getTask() : null;

    // Should this be considered a new task?
    int result = START_SUCCESS;
    if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
            && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
        newTask = true;
        result = setTaskFromReuseOrCreateNewTask(
                taskToAffiliate, preferredLaunchStackId, topStack);
    } else if (mSourceRecord != null) {
        result = setTaskFromSourceRecord();
    } else if (mInTask != null) {
        result = setTaskFromInTask();
    } else {
        // This not being started from an existing activity, and not part of a new task...
        // just put it in the top task, though these days this case should never happen.
        setTaskToCurrentTopOrCreateNewTask();
    }
    if (result != START_SUCCESS) {
        return result;
    }

    mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
            mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
    mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
            mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
    if (mSourceRecord != null) {
        mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
    }
    if (newTask) {
        EventLog.writeEvent(
                EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
                mStartActivity.getTask().taskId);
    }
    ActivityStack.logStartActivity(
            EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
    mTargetStack.mLastPausedActivity = null;

    sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);

    mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
            mOptions);
    if (mDoResume) {
        final ActivityRecord topTaskActivity =
                mStartActivity.getTask().topRunningActivityLocked();
        if (!mTargetStack.isFocusable()
                || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                && mStartActivity != topTaskActivity)) {
            // If the activity is not focusable, we can't resume it, but still would like to
            // make sure it becomes visible as it starts (this will also trigger entry
            // animation). An example of this are PIP activities.
            // Also, we don't want to resume activities in a task that currently has an overlay
            // as the starting activity just needs to be in the visible paused state until the
            // over is removed.
            mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
            // Go ahead and tell window manager to execute app transition for this activity
            // since the app transition will not be triggered through the resume channel.
            mWindowManager.executeAppTransition();
        } else {
            // If the target stack was not previously focusable (previous top running activity
            // on that stack was not visible) then any prior calls to move the stack to the
            // will not update the focused stack.  If starting the new activity now allows the
            // task stack to be focusable, then ensure that we now update the focused stack
            // accordingly.
            if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
                mTargetStack.moveToFront("startActivityUnchecked");
            }
  ***//进行各种条件判断后,可以肯定的是走到了这***
            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                    mOptions);
        }
    } else {
        mTargetStack.addRecentActivityLocked(mStartActivity);
    }
    mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);

    mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
            preferredLaunchDisplayId, mTargetStack.mStackId);

    return START_SUCCESS;
}
  1. boolean resumeFocusedStackTopActivityLocked(
    ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    if (targetStack != null && isFocusedStack(targetStack)) {
    return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }

    final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
    **//找出栈顶的record,由于之前的判断能到这里,栈顶要么为空,要么就是正运气的.不存在单例要被RESUMED的情况**
    if (r == null || r.state != RESUMED) {
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    } else if (r.state == RESUMED) {
        // Kick off any lingering app transitions form the MoveTaskToFront operation.
        mFocusedStack.executeAppTransition(targetOptions);
    }
    return false;
    

    }

  2. 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);
    } finally {
        mStackSupervisor.inResumeTopActivity = false;
    }
    // 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.
    mStackSupervisor.checkReadyForSleepLocked();
    
    return result;
    

    }

resumeTopActivityInnerLocked这个函数代码太长就不贴了,大体意思如下
首先会调用topRunningActivityLocked这个函数从栈上获取,目前获取焦点的APP.如果没有就为NULL
if(NULL){
mStackSupervisor.startSpecificActivityLocked(next, true, true);

}else{
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                    mService.isNextTransitionForward(), resumeAnimOptions);
}

14.
    void startSpecificActivityLocked(ActivityRecord r,
        boolean andResume, boolean checkConfig) {
    // Is this activity's application already running?
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);

    r.getStack().setLaunchTime(r);

    if (app != null && app.thread != null) {
        try {
            if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                    || !"android".equals(r.info.packageName)) {
                // Don't add this if it is a platform component that is marked
                // to run in multiple processes, because this is actually
                // part of the framework so doesn't make sense to track as a
                // separate apk in the process.
                app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                        mService.mProcessStats);
            }
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }

        // If a dead object exception was thrown -- fall through to
        // restart the application.
    }

    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}

15
realStartActivityLocked 在这个函数里面就调用
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode®, r.info,
// TODO: Have this take the merged configuration instead of separate global and
// override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);

上面是本人根据代码,自己理解的东西.可能有地方不对,欢迎大家一起来研究.Launch成功会,把attch把自己各种属性加到Activity里面和Record里面,后面就没认真看了.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bruk_spp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值