码迷,mamicode.com
首页 > 移动开发 > 详细

Android8.0(API26)之Activity启动流程(显示启动)

时间:2018-01-24 22:24:51      阅读:1981      评论:0      收藏:0      [点我收藏+]

标签:callback   说明   ++   argument   lang   ges   before   opp   为我   

 

 

我们自己的启动Activity方法

技术分享图片

调用Activity对象的方法

@Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

继续调用Activity对象方法

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

继续调用Activity对象方法

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
    }

继续调用Activity对象方法

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {//mParent指的是ActivityGroup,可以在一个界面里嵌套多个Activity。随着版本的升级,在API13以后就废弃掉了。
            options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar
= mInstrumentation.execStartActivity(//调用了方法Instrumentation$execStartActivity,因为mParent为null。 this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); if (ar != null) { mMainThread.sendActivityResult(//mMainThread是一个ActivityThread对象,该对象初始化在当前Activity的attach方法中。 mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } if (requestCode >= 0) { // 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 { if (options != null) { mParent.startActivityFromChild(this, intent, requestCode, options); } else { // Note we want to go through this method for compatibility with // existing applications that may have overridden it. mParent.startActivityFromChild(this, intent, requestCode); } } }

在startActivityForResult这个方法中 我们发现如果

requestCode > 0会把标志位mStartedActivity改成true(这个关于)
@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    }

这个方法是否回调。

在回头查看启动的重点:根据上面的注释我们继续查看Instrumentation的execStartActivity方法

 1     public void execStartActivitiesAsUser(Context who, IBinder contextThread,
 2             IBinder token, Activity target, Intent[] intents, Bundle options,
 3             int userId) {
 4         IApplicationThread whoThread = (IApplicationThread) contextThread;//ActivityThread的ApplictionThread对象
 5         if (mActivityMonitors != null) {
 6             synchronized (mSync) {
 7                 final int N = mActivityMonitors.size();
 8                 for (int i=0; i<N; i++) {
 9                     final ActivityMonitor am = mActivityMonitors.get(i);//List<ActivityMonitor> mActivityMonitors
10                     ActivityResult result = null;
11                     if (am.ignoreMatchingSpecificIntents()) {
12                         result = am.onStartActivity(intents[0]);//这个方法返回的是null
13                     }
14                     if (result != null) {
15                         am.mHits++;
16                         return;
17                     } else if (am.match(who, null, intents[0])) {//用于拦截任何已启动的活动
18                         am.mHits++;
19                         if (am.isBlocking()) {
20                             return;
21                         }
22                         break;
23                     }
24                 }
25             }
26         }
27         try {
28             String[] resolvedTypes = new String[intents.length];
29             for (int i=0; i<intents.length; i++) {
30                 intents[i].migrateExtraStreamToClipData();
31                 intents[i].prepareToLeaveProcess(who);
32                 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
33             }
34             int result = ActivityManager.getService()
35                 .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes,
36                         token, options, userId);
37             checkStartActivityResult(result, intents[0]);
38         } catch (RemoteException e) {
39             throw new RuntimeException("Failure from system", e);
40         }
41     }
第4行代码:private class ApplicationThread extends IApplicationThread.Stub{}是在ActivityThread中ApplictionThread的构造方法、
通过代码分析(有注释)可知这里的重点事:

技术分享图片

 

我们再来查看ActivityManager.getService()方法返回的对象:

 1    public static IActivityManager getService() {
 2         return IActivityManagerSingleton.get();
 3     }
 4 
 5     private static final Singleton<IActivityManager> IActivityManagerSingleton =
 6             new Singleton<IActivityManager>() {
 7                 @Override
 8                 protected IActivityManager create() {
 9                     final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
10                     final IActivityManager am = IActivityManager.Stub.asInterface(b);
11                     return am;
12                 }
13             };

 

返回的对象是一个IActivityManager,其中Singleton<T>是创建一个T的单列对象通过get()方法获取T对象。所以这里获取的是一个IActivityManager对象

这里的大概意思就是基于(Bidler机制)获取ActivityManagerServer在应用进程的代理对象IActivityManager(这里需要了解Binder机制,会另外写bidler机制)

所以这里的Instrumentation中的getMananger.getServer.startActivity 等价于--IActivityManager.startActivity----等价于ActivityManagerServer.startActivity方法。

 

继续查看ActivityManagerServer对象的startActivity方法:

 1     /**
 2      * Instrumentaion 调用的是这个方法
 3      * @return 返回值用于判断Activity是否启动
 4      */
 5     @Override
 6     public final int startActivity(IApplicationThread caller, String callingPackage,
 7             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
 8             int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
 9         return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
10                 resultWho, requestCode, startFlags, profilerInfo, bOptions,
11                 UserHandle.getCallingUserId());
12     }

继续查看startActivityAsUer方法

    @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
        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");
    }

  继续查看mActivityStarter.startActivityMayWait方法,mActivityStarter是ActivityStarter对象

技术分享图片
  1     final int startActivityMayWait(IApplicationThread caller, int callingUid,
  2             String callingPackage, Intent intent, String resolvedType,
  3             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
  4             IBinder resultTo, String resultWho, int requestCode, int startFlags,
  5             ProfilerInfo profilerInfo, WaitResult outResult,
  6             Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
  7             IActivityContainer iContainer, TaskRecord inTask, String reason) {
  8         // Refuse possible leaked file descriptors
  9         if (intent != null && intent.hasFileDescriptors()) {
 10             throw new IllegalArgumentException("File descriptors passed in Intent");
 11         }
 12         //调用底层的方法 给ActivityMetricsLogger的INVALID_START_TIME赋值
 13         mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
 14         boolean componentSpecified = intent.getComponent() != null;//显示启动为true
 15 
 16         // Save a copy in case ephemeral needs it
 17         final Intent ephemeralIntent = new Intent(intent);
 18         // Don‘t modify the client‘s object!
 19         //为了不改变用户的intent
 20         intent = new Intent(intent);
 21         if (componentSpecified
 22                 && intent.getData() != null
 23                 && Intent.ACTION_VIEW.equals(intent.getAction())
 24                 && mService.getPackageManagerInternalLocked()
 25                         .isInstantAppInstallerComponent(intent.getComponent())) {//判断是否调用系统功能
 26             // intercept intents targeted directly to the ephemeral installer the
 27             // ephemeral installer should never be started with a raw URL; instead
 28             // adjust the intent so it looks like a "normal" instant app launch
 29             intent.setComponent(null /*component*/);
 30             componentSpecified = false;
 31         }
 32         //收集Intent所指向的Activity信息, 当存在多个可供选择的Activity,则直接向用户弹出resolveActivity
 33         ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
 34         if (rInfo == null) {
 35             UserInfo userInfo = mSupervisor.getUserInfo(userId);//UserInfo 保存了应用相关信息 名字 图片....
 36             if (userInfo != null && userInfo.isManagedProfile()) {//不会执行(估计)
 37                 // Special case for managed profiles, if attempting to launch non-cryto aware
 38                 // app in a locked managed profile from an unlocked parent allow it to resolve
 39                 // as user will be sent via confirm credentials to unlock the profile.
 40                 UserManager userManager = UserManager.get(mService.mContext);
 41                 boolean profileLockedAndParentUnlockingOrUnlocked = false;
 42                 long token = Binder.clearCallingIdentity();
 43                 try {
 44                     UserInfo parent = userManager.getProfileParent(userId);
 45                     profileLockedAndParentUnlockingOrUnlocked = (parent != null)
 46                             && userManager.isUserUnlockingOrUnlocked(parent.id)
 47                             && !userManager.isUserUnlockingOrUnlocked(userId);
 48                 } finally {
 49                     Binder.restoreCallingIdentity(token);
 50                 }
 51                 if (profileLockedAndParentUnlockingOrUnlocked) {
 52                     rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
 53                             PackageManager.MATCH_DIRECT_BOOT_AWARE
 54                                     | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
 55                 }
 56             }
 57         }
 58         // 收集有关目标的信息。(Collect information about the target of the Intent.)
 59         //收集目标intent的信息,在resolveActivity方法中与PKMS交互获得
 60         //该过程主要功能:通过resolveActivity来获取ActivityInfo信息, 找到相应的Activity组件,并保存到intent对象,然后再进入startActivityLocked()
 61         ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
 62 
 63         ActivityOptions options = ActivityOptions.fromBundle(bOptions);
 64         ActivityStackSupervisor.ActivityContainer container =
 65                 (ActivityStackSupervisor.ActivityContainer)iContainer;
 66         synchronized (mService) {
 67             if (container != null && container.mParentActivity != null &&
 68                     container.mParentActivity.state != RESUMED) {
 69                 // Cannot start a child activity if the parent is not resumed.
 70                 return ActivityManager.START_CANCELED;
 71             }
 72             final int realCallingPid = Binder.getCallingPid();
 73             final int realCallingUid = Binder.getCallingUid();
 74             int callingPid;
 75             if (callingUid >= 0) {
 76                 callingPid = -1;
 77             } else if (caller == null) {
 78                 callingPid = realCallingPid;
 79                 callingUid = realCallingUid;
 80             } else {
 81                 callingPid = callingUid = -1;
 82             }
 83 
 84             final ActivityStack stack;
 85             //取得需要启动的ActivityStack栈
 86             if (container == null || container.mStack.isOnHomeDisplay()) {
 87                 stack = mSupervisor.mFocusedStack;
 88             } else {
 89                 stack = container.mStack;
 90             }
 91             stack.mConfigWillChange = globalConfig != null
 92                     && mService.getGlobalConfiguration().diff(globalConfig) != 0;
 93             if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
 94                     "Starting activity when config will change = " + stack.mConfigWillChange);
 95 
 96             final long origId = Binder.clearCallingIdentity();
 97 
 98             if (aInfo != null &&
 99                     (aInfo.applicationInfo.privateFlags
100                             & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
101                 // This may be a heavy-weight process!  Check to see if we already
102                 // have another, different heavy-weight process running.
103                 //Androidmanifest.xml中的Application标签可以声明一个cantSaveState属性,若设置,其将不享受系统提
104                 //供的状态保存/恢复功能。主要是为了保证用户体验的连续性
105                 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
106                     final ProcessRecord heavy = mService.mHeavyWeightProcess;
107                     if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
108                             || !heavy.processName.equals(aInfo.processName))) {
109                         int appCallingUid = callingUid;
110                         if (caller != null) {
111                             ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
112                             if (callerApp != null) {
113                                 appCallingUid = callerApp.info.uid;
114                             } else {
115                                 Slog.w(TAG, "Unable to find app for caller " + caller
116                                         + " (pid=" + callingPid + ") when starting: "
117                                         + intent.toString());
118                                 ActivityOptions.abort(options);
119                                 return ActivityManager.START_PERMISSION_DENIED;
120                             }
121                         }
122 
123                         IIntentSender target = mService.getIntentSenderLocked(
124                                 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
125                                 appCallingUid, userId, null, null, 0, new Intent[] { intent },
126                                 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
127                                         | PendingIntent.FLAG_ONE_SHOT, null);
128 
129                         Intent newIntent = new Intent();
130                         if (requestCode >= 0) {
131                             // Caller is requesting a result.
132                             newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
133                         }
134                         newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
135                                 new IntentSender(target));
136                         if (heavy.activities.size() > 0) {
137                             ActivityRecord hist = heavy.activities.get(0);
138                             newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
139                                     hist.packageName);
140                             newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
141                                     hist.getTask().taskId);
142                         }
143                         newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
144                                 aInfo.packageName);
145                         newIntent.setFlags(intent.getFlags());
146                         newIntent.setClassName("android",
147                                 HeavyWeightSwitcherActivity.class.getName());
148                         intent = newIntent;
149                         resolvedType = null;
150                         caller = null;
151                         callingUid = Binder.getCallingUid();
152                         callingPid = Binder.getCallingPid();
153                         componentSpecified = true;
154                         rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
155                         aInfo = rInfo != null ? rInfo.activityInfo : null;
156                         if (aInfo != null) {
157                             aInfo = mService.getActivityInfoForUser(aInfo, userId);
158                         }
159                     }
160                 }
161             }
162             final ActivityRecord[] outRecord = new ActivityRecord[1];
163             //启动Activity
164             int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
165                     aInfo, rInfo, voiceSession, voiceInteractor,
166                     resultTo, resultWho, requestCode, callingPid,
167                     callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
168                     options, ignoreTargetSecurity, componentSpecified, outRecord, container,
169                     inTask, reason);
170 
171             Binder.restoreCallingIdentity(origId);
172             //如果配置Configration发生变化,则调用AMS的updateConfigurationLocked进行处理
173             if (stack.mConfigWillChange) {
174                 // If the caller also wants to switch to a new configuration,
175                 // do so now.  This allows a clean switch, as we are waiting
176                 // for the current activity to pause (so we will not destroy
177                 // it), and have not yet started the next activity.
178                 //如果调用方也希望切换到新配置
179                 //现在就这样做。这允许一个干净的开关,因为我们正在等待
180                 //为当前活动暂停(因此我们不会破坏)
181                 //它还没有启动下一个活动。
182                 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
183                         "updateConfiguration()");
184                 stack.mConfigWillChange = false;
185                 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
186                         "Updating to new configuration after starting activity.");
187                 mService.updateConfigurationLocked(globalConfig, null, false);
188             }
189 
190             if (outResult != null) {
191                 outResult.result = res;
192                 if (res == ActivityManager.START_SUCCESS) {
193                     //将结果放入mWaitingActivityLaunced中保存
194                     mSupervisor.mWaitingActivityLaunched.add(outResult);
195                     do {
196                         try {
197                             //等待启动结果
198                             mService.wait();
199                         } catch (InterruptedException e) {
200                         }
201                     } while (outResult.result != START_TASK_TO_FRONT
202                             && !outResult.timeout && outResult.who == null);
203                     if (outResult.result == START_TASK_TO_FRONT) {
204                         res = START_TASK_TO_FRONT;
205                     }
206                 }
207                 if (res == START_TASK_TO_FRONT) {
208                     final ActivityRecord r = outRecord[0];
209 
210                     // ActivityRecord may represent a different activity, but it should not be in
211                     // the resumed state.
212                     if (r.nowVisible && r.state == RESUMED) {
213                         outResult.timeout = false;
214                         outResult.who = r.realActivity;
215                         outResult.totalTime = 0;
216                         outResult.thisTime = 0;
217                     } else {
218                         outResult.thisTime = SystemClock.uptimeMillis();
219                         mSupervisor.waitActivityVisible(r.realActivity, outResult);
220                         // Note: the timeout variable is not currently not ever set.
221                         do {
222                             try {
223                                 //等待启动结果
224                                 mService.wait();
225                             } catch (InterruptedException e) {
226                             }
227                         } while (!outResult.timeout && outResult.who == null);
228                     }
229                 }
230             }
231 
232             mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]);
233             return res;
234         }
235     }
View Code

这个方法内容比较多我们来查看重要的部分

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

 继续查看startLocked方法

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

        if (outActivity != null) {
            // mLastStartActivityRecord[0] is set in the call to startActivity above.
            outActivity[0] = mLastStartActivityRecord[0];
        }
        return mLastStartActivityResult;
    }

继续查看startActivity方法:

技术分享图片
    /** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */
    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) {//如果caller不为空,从AMS中找到它所属的ProcessRecord即进程,本文此处为null
            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);
        }
        //sourceRecord用于描述启动目标Activity的那个Activity
        ActivityRecord sourceRecord = null;
        //resultRecord用于描述接收启动结果的Activity,即onActivityResult将被调用以通知启动结果
        ActivityRecord resultRecord = null;
        if (resultTo != null) {
            sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                    "Will send result to " + resultTo + " " + sourceRecord);
            if (sourceRecord != null) {
                if (requestCode >= 0 && !sourceRecord.finishing) {
                    resultRecord = sourceRecord;
                }
            }
        }
        //获取Intent设置的启动标志
        final int launchFlags = intent.getFlags();
        //此部分与LaunchMode类似,它用于控制Activity启动结果的通知
        if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
            // Transfer the result target from the source activity to the new
            // one being started, including any failures.
            if (requestCode >= 0) {
                ActivityOptions.abort(options);
                return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
            }
            resultRecord = sourceRecord.resultTo;
            if (resultRecord != null && !resultRecord.isInStackLocked()) {
                resultRecord = null;
            }
            resultWho = sourceRecord.resultWho;
            requestCode = sourceRecord.requestCode;
            sourceRecord.resultTo = null;
            if (resultRecord != null) {
                resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
            }
            if (sourceRecord.launchedFromUid == callingUid) {
                // The new activity is being launched from the same uid as the previous
                // activity in the flow, and asking to forward its result back to the
                // previous.  In this case the activity is serving as a trampoline between
                // the two, so we also want to update its launchedFromPackage to be the
                // same as the previous activity.  Note that this is safe, since we know
                // these two packages come from the same uid; the caller could just as
                // well have supplied that same package name itself.  This specifially
                // deals with the case of an intent picker/chooser being launched in the app
                // flow to redirect to an activity picked by the user, where we want the final
                // activity to consider it to have been launched by the previous app activity.
                callingPackage = sourceRecord.launchedFromPackage;
            }
        }

        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
            // We couldn‘t find a class that can handle the given Intent.
            // That‘s the end of that!
            err = ActivityManager.START_INTENT_NOT_RESOLVED;
        }

        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
            // We couldn‘t find the specific class specified in the Intent.
            // Also the end of the line.
            err = ActivityManager.START_CLASS_NOT_FOUND;
        }

        if (err == ActivityManager.START_SUCCESS && sourceRecord != null
                && sourceRecord.getTask().voiceSession != null) {
            // If this activity is being launched as part of a voice session, we need
            // to ensure that it is safe to do so.  If the upcoming activity will also
            // be part of the voice session, we can only launch it if it has explicitly
            // said it supports the VOICE category, or it is a part of the calling app.
            if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
                    && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
                try {
                    intent.addCategory(Intent.CATEGORY_VOICE);
                    if (!AppGlobals.getPackageManager().activitySupportsIntent(
                            intent.getComponent(), intent, resolvedType)) {
                        Slog.w(TAG,
                                "Activity being started in current voice task does not support voice: "
                                        + intent);
                        err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                    }
                } catch (RemoteException e) {
                    Slog.w(TAG, "Failure checking voice capabilities", e);
                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                }
            }
        }

        if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
            // If the caller is starting a new voice session, just make sure the target
            // is actually allowing it to run this way.
            try {
                if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
                        intent, resolvedType)) {
                    Slog.w(TAG,
                            "Activity being started in new voice task does not support: "
                                    + intent);
                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                }
            } catch (RemoteException e) {
                Slog.w(TAG, "Failure checking voice capabilities", e);
                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
            }
        }

        final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();

        if (err != START_SUCCESS) {
            if (resultRecord != null) {
                resultStack.sendActivityResultLocked(
                        -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
            }
            ActivityOptions.abort(options);
            return err;
        }

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

这个方法内容比较多会去检查Activity是否在Mainfest.xml中是否注册等,假如一切正常,我们接下来查看关键部分:

        doPendingActivityLaunchesLocked(false);

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

先查看dopeingActivityLauchesLocked方法

    final void doPendingActivityLaunchesLocked(boolean doResume) {
        while (!mPendingActivityLaunches.isEmpty()) {
            final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
            final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
            try {
                startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
                        null, null /*outRecords*/);
            } catch (Exception e) {
                Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
                pal.sendErrorResult(e.getMessage());
            }
        }
    }

 到这里我们发现

技术分享图片

这里都会去执行startActivity方法只是传的参数不一样,我们继续查看startActivity方法

    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 {
            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);//这个与期待应用进程有关。也是调用2次startActivity的原因(可能理解有误)

        return result;
    }

 我们继续查看

            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity);

startActivityUnChecked方法

技术分享图片
    // Note: This method should only be called from {@link startActivity}.
    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);

        computeLaunchingTaskFlags();

        computeSourceStack();

        mIntent.setFlags(mLaunchFlags);

        ActivityRecord reusedActivity = getReusableIntentActivity();

        final int preferredLaunchStackId =
                (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
        final int preferredLaunchDisplayId =
                (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;

        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 (dontStart) {
            ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
            // For paranoia, make sure we have correctly resumed the top activity.
            topStack.mLastPausedActivity = null;
            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;
    }
startActivityUnChecked

这个方法内容比较多,我们查看

技术分享图片

技术分享图片

继续查看resumeFocusedStackTopActivityLocked方法属于(ActivityStackSupervisor)对象

boolean resumeFocusedStackTopActivityLocked() {
        return resumeFocusedStackTopActivityLocked(null, null, null);
    }

  调用的是3个参数的重载方法

boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        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;
    }

  继续查看resumeTopAcitivityUncheckLocked方法(ActivityStatk对象)

 1     boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
 2         if (mStackSupervisor.inResumeTopActivity) {
 3             // Don‘t even start recursing.
 4             return false;
 5         }
 6 
 7         boolean result = false;
 8         try {
 9             // Protect against recursion.
10             mStackSupervisor.inResumeTopActivity = true;
11             result = resumeTopActivityInnerLocked(prev, options);
12         } finally {
13             mStackSupervisor.inResumeTopActivity = false;
14         }
15         // When resuming the top activity, it may be necessary to pause the top activity (for
16         // example, returning to the lock screen. We suppress the normal pause logic in
17         // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the end.
18         // We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here to ensure
19         // any necessary pause logic occurs.
20         mStackSupervisor.checkReadyForSleepLocked();
21 
22         return result;
23     }

继续查看resumeTopActivityInnerLocked方法

技术分享图片
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        if (!mService.mBooting && !mService.mBooted) {
            // Not ready yet!
            return false;
        }

        // Find the next top-most activity to resume in this stack that is not finishing and is
        // focusable. If it is not focusable, we will fall into the case below to resume the
        // top activity in the next focusable task.
        final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);

        final boolean hasRunningActivity = next != null;

        final ActivityRecord parent = mActivityContainer.mParentActivity;
        final boolean isParentNotResumed = parent != null && parent.state != ActivityState.RESUMED;
        if (hasRunningActivity
                && (isParentNotResumed || !mActivityContainer.isAttachedLocked())) {
            // Do not resume this stack if its parent is not resumed.
            // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
            return false;
        }

        mStackSupervisor.cancelInitializingActivities();

        // Remember how we‘ll process this pause/resume situation, and ensure
        // that the state is reset however we wind up proceeding.
        final boolean userLeaving = mStackSupervisor.mUserLeaving;
        mStackSupervisor.mUserLeaving = false;

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

        next.delayedResume = false;

        // If the top activity is the resumed one, nothing to do.
        if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
                    mStackSupervisor.allResumedActivitiesComplete()) {
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            executeAppTransition(options);
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Top activity resumed " + next);
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }

        final TaskRecord nextTask = next.getTask();
        final TaskRecord prevTask = prev != null ? prev.getTask() : null;
        if (prevTask != null && prevTask.getStack() == this &&
                prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
            if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
            if (prevTask == nextTask) {
                prevTask.setFrontOfTask();
            } else if (prevTask != topTask()) {
                // This task is going away but it was supposed to return to the home stack.
                // Now the task above it has to return to the home task instead.
                final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
                mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
            } else if (!isOnHomeDisplay()) {
                return false;
            } else if (!isHomeStack()){
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                        "resumeTopActivityLocked: Launching home next");
                return isOnHomeDisplay() &&
                        mStackSupervisor.resumeHomeStackTask(prev, "prevFinished");
            }
        }

        // If we are sleeping, and there is no resumed activity, and the top
        // activity is paused, well that is the state we want.
        if (mService.isSleepingOrShuttingDownLocked()
                && mLastPausedActivity == next
                && mStackSupervisor.allPausedActivitiesComplete()) {
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            executeAppTransition(options);
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Going to sleep and all paused");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }

        // Make sure that the user who owns this activity is started.  If not,
        // we will just leave it as is because someone should be bringing
        // another user‘s activities to the top of the stack.
        if (!mService.mUserController.hasStartedUserState(next.userId)) {
            Slog.w(TAG, "Skipping resume of top activity " + next
                    + ": user " + next.userId + " is stopped");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }

        // The activity may be waiting for stop, but that is no longer
        // appropriate for it.
        mStackSupervisor.mStoppingActivities.remove(next);
        mStackSupervisor.mGoingToSleepActivities.remove(next);
        next.sleeping = false;
        mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next);

        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);

        // If we are currently pausing an activity, then don‘t do anything until that is done.
        if (!mStackSupervisor.allPausedActivitiesComplete()) {
            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                    "resumeTopActivityLocked: Skip resume: some activity pausing.");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }

        mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);

        boolean lastResumedCanPip = false;
        final ActivityStack lastFocusedStack = mStackSupervisor.getLastStack();
        if (lastFocusedStack != null && lastFocusedStack != this) {
            // So, why aren‘t we using prev here??? See the param comment on the method. prev doesn‘t
            // represent the last resumed activity. However, the last focus stack does if it isn‘t null.
            final ActivityRecord lastResumed = lastFocusedStack.mResumedActivity;
            lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
                    "resumeTopActivity", true /* noThrow */, userLeaving /* beforeStopping */);
        }
        // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
        // to be paused, while at the same time resuming the new resume activity only if the
        // previous activity can‘t go into Pip since we want to give Pip activities a chance to
        // enter Pip before resuming the next activity.
        final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
                && !lastResumedCanPip;

        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, next, false);
        }
        if (pausing && !resumeWhilePausing) {
            if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
                    "resumeTopActivityLocked: Skip resume: need to start pausing");
            // At this point we want to put the upcoming activity‘s process
            // at the top of the LRU list, since we know we will be needing it
            // very soon and it would be a waste to let it get killed if it
            // happens to be sitting towards the end.
            if (next.app != null && next.app.thread != null) {
                mService.updateLruProcessLocked(next.app, true, null);
            }
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return true;
        } else if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
                mStackSupervisor.allResumedActivitiesComplete()) {
            // It is possible for the activity to be resumed when we paused back stacks above if the
            // next activity doesn‘t have to wait for pause to complete.
            // So, nothing else to-do except:
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            executeAppTransition(options);
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return true;
        }

        // If the most recent activity was noHistory but was only stopped rather
        // than stopped+finished because the device went to sleep, we need to make
        // sure to finish it as we‘re making a new activity topmost.
        if (mService.isSleepingLocked() && mLastNoHistoryActivity != null &&
                !mLastNoHistoryActivity.finishing) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "no-history finish of " + mLastNoHistoryActivity + " on new resume");
            requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
                    null, "resume-no-history", false);
            mLastNoHistoryActivity = null;
        }

        if (prev != null && prev != next) {
            if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
                    && next != null && !next.nowVisible) {
                mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(prev);
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                        "Resuming top, waiting visible to hide: " + prev);
            } else {
                // The next activity is already visible, so hide the previous
                // activity‘s windows right now so we can show the new one ASAP.
                // We only do this if the previous is finishing, which should mean
                // it is on top of the one being resumed so hiding it quickly
                // is good.  Otherwise, we want to do the normal route of allowing
                // the resumed activity to be shown so we can decide if the
                // previous should actually be hidden depending on whether the
                // new one is found to be full-screen or not.
                if (prev.finishing) {
                    prev.setVisibility(false);
                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                            "Not waiting for visible to hide: " + prev + ", waitingVisible="
                            + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
                            + ", nowVisible=" + next.nowVisible);
                } else {
                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                            "Previous already visible but still waiting to hide: " + prev
                            + ", waitingVisible="
                            + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
                            + ", nowVisible=" + next.nowVisible);
                }
            }
        }

        // Launching this app‘s activity, make sure the app is no longer
        // considered stopped.
        try {
            AppGlobals.getPackageManager().setPackageStoppedState(
                    next.packageName, false, next.userId); /* TODO: Verify if correct userid */
        } catch (RemoteException e1) {
        } catch (IllegalArgumentException e) {
            Slog.w(TAG, "Failed trying to unstop package "
                    + next.packageName + ": " + e);
        }

        // We are starting up the next activity, so tell the window manager
        // that the previous one will be hidden soon.  This way it can know
        // to ignore it when computing the desired screen orientation.
        boolean anim = true;
        if (prev != null) {
            if (prev.finishing) {
                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                        "Prepare close transition: prev=" + prev);
                if (mNoAnimActivities.contains(prev)) {
                    anim = false;
                    mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
                } else {
                    mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
                            ? TRANSIT_ACTIVITY_CLOSE
                            : TRANSIT_TASK_CLOSE, false);
                }
                prev.setVisibility(false);
            } else {
                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                        "Prepare open transition: prev=" + prev);
                if (mNoAnimActivities.contains(next)) {
                    anim = false;
                    mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
                } else {
                    mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
                            ? TRANSIT_ACTIVITY_OPEN
                            : next.mLaunchTaskBehind
                                    ? TRANSIT_TASK_OPEN_BEHIND
                                    : TRANSIT_TASK_OPEN, false);
                }
            }
        } else {
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
            if (mNoAnimActivities.contains(next)) {
                anim = false;
                mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
            } else {
                mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false);
            }
        }

        Bundle resumeAnimOptions = null;
        if (anim) {
            ActivityOptions opts = next.getOptionsForTargetActivityLocked();
            if (opts != null) {
                resumeAnimOptions = opts.toBundle();
            }
            next.applyOptionsLocked();
        } else {
            next.clearOptionsLocked();
        }

        ActivityStack lastStack = mStackSupervisor.getLastStack();
        if (next.app != null && next.app.thread != null) {
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
                    + " stopped=" + next.stopped + " visible=" + next.visible);

            // If the previous activity is translucent, force a visibility update of
            // the next activity, so that it‘s added to WM‘s opening app list, and
            // transition animation can be set up properly.
            // For example, pressing Home button with a translucent activity in focus.
            // Launcher is already visible in this case. If we don‘t add it to opening
            // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
            // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
            final boolean lastActivityTranslucent = lastStack != null
                    && (!lastStack.mFullscreen
                    || (lastStack.mLastPausedActivity != null
                    && !lastStack.mLastPausedActivity.fullscreen));

            // This activity is now becoming visible.
            if (!next.visible || next.stopped || lastActivityTranslucent) {
                next.setVisibility(true);
            }

            // schedule launch ticks to collect information about slow apps.
            next.startLaunchTickingLocked();

            ActivityRecord lastResumedActivity =
                    lastStack == null ? null :lastStack.mResumedActivity;
            ActivityState lastState = next.state;

            mService.updateCpuStats();

            if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next + " (in existing)");

            setResumedActivityLocked(next, "resumeTopActivityInnerLocked");

            mService.updateLruProcessLocked(next.app, true, null);
            updateLRUListLocked(next);
            mService.updateOomAdjLocked();

            // Have the window manager re-evaluate the orientation of
            // the screen based on the new activity order.
            boolean notUpdated = true;
            if (mStackSupervisor.isFocusedStack(this)) {
                final Configuration config = mWindowManager.updateOrientationFromAppTokens(
                        mStackSupervisor.getDisplayOverrideConfiguration(mDisplayId),
                        next.mayFreezeScreenLocked(next.app) ? next.appToken : null, mDisplayId);
                if (config != null) {
                    next.frozenBeforeDestroy = true;
                }
                notUpdated = !mService.updateDisplayOverrideConfigurationLocked(config, next,
                        false /* deferResume */, mDisplayId);
            }

            if (notUpdated) {
                // The configuration update wasn‘t able to keep the existing
                // instance of the activity, and instead started a new one.
                // We should be all done, but let‘s just make sure our activity
                // is still at the top and schedule another run if something
                // weird happened.
                ActivityRecord nextNext = topRunningActivityLocked();
                if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES,
                        "Activity config changed during resume: " + next
                        + ", new next: " + nextNext);
                if (nextNext != next) {
                    // Do over!
                    mStackSupervisor.scheduleResumeTopActivities();
                }
                if (!next.visible || next.stopped) {
                    next.setVisibility(true);
                }
                next.completeResumeLocked();
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return true;
            }

            try {
                // Deliver all pending results.
                ArrayList<ResultInfo> a = next.results;
                if (a != null) {
                    final int N = a.size();
                    if (!next.finishing && N > 0) {
                        if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                                "Delivering results to " + next + ": " + a);
                        next.app.thread.scheduleSendResult(next.appToken, a);
                    }
                }

                if (next.newIntents != null) {
                    next.app.thread.scheduleNewIntent(
                            next.newIntents, next.appToken, false /* andPause */);
                }

                // Well the app will no longer be stopped.
                // Clear app token stopped state in window manager if needed.
                next.notifyAppResumed(next.stopped);

                EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
                        System.identityHashCode(next), next.getTask().taskId,
                        next.shortComponentName);

                next.sleeping = false;
                mService.showUnsupportedZoomDialogIfNeededLocked(next);
                mService.showAskCompatModeDialogLocked(next);
                next.app.pendingUiClean = true;
                next.app.forceProcessStateUpTo(mService.mTopProcessState);
                next.clearOptionsLocked();
                next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                        mService.isNextTransitionForward(), resumeAnimOptions);

                if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " + next);
            } catch (Exception e) {
                // Whoops, need to restart this activity!
                if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "
                        + lastState + ": " + next);
                next.state = lastState;
                if (lastStack != null) {
                    lastStack.mResumedActivity = lastResumedActivity;
                }
                Slog.i(TAG, "Restarting because process died: " + next);
                if (!next.hasBeenLaunched) {
                    next.hasBeenLaunched = true;
                } else  if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
                        mStackSupervisor.isFrontStackOnDisplay(lastStack)) {
                    next.showStartingWindow(null /* prev */, false /* newTask */,
                            false /* taskSwitch */);
                }
                mStackSupervisor.startSpecificActivityLocked(next, true, false);
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return true;
            }

            // From this point on, if something goes wrong there is no way
            // to recover the activity.
            try {
                next.completeResumeLocked();
            } catch (Exception e) {
                // If any exception gets thrown, toss away this
                // activity and try the next one.
                Slog.w(TAG, "Exception thrown during resume of " + next, e);
                requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
                        "resume-exception", true);
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return true;
            }
        } else {
            // Whoops, need to restart this activity!
            if (!next.hasBeenLaunched) {
                next.hasBeenLaunched = true;
            } else {
                if (SHOW_APP_STARTING_PREVIEW) {
                    next.showStartingWindow(null /* prev */, false /* newTask */,
                            false /* taskSwich */);
                }
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
            }
            if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }

        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    }
resumeTopActivityInnerLocked

这个方法比较长,我们查看比较重要的部分

技术分享图片

经过startPausingLocked系列处理 会去执行当前Activity的onPause方法。这里不做说明

技术分享图片

我们继续查看ActivityStackSupervisor对象的startSpecificActivityLocked方法

 1     void startSpecificActivityLocked(ActivityRecord r,
 2             boolean andResume, boolean checkConfig) {
 3         // Is this activity‘s application already running?
 4         ProcessRecord app = mService.getProcessRecordLocked(r.processName,
 5                 r.info.applicationInfo.uid, true);
 6 
 7         r.getStack().setLaunchTime(r);
 8 
 9         if (app != null && app.thread != null) {
10             try {
11                 if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
12                         || !"android".equals(r.info.packageName)) {
13                     // Don‘t add this if it is a platform component that is marked
14                     // to run in multiple processes, because this is actually
15                     // part of the framework so doesn‘t make sense to track as a
16                     // separate apk in the process.
17                     app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
18                             mService.mProcessStats);
19                 }
20                 realStartActivityLocked(r, app, andResume, checkConfig);
21                 return;
22             } catch (RemoteException e) {
23                 Slog.w(TAG, "Exception when starting activity "
24                         + r.intent.getComponent().flattenToShortString(), e);
25             }
26 
27             // If a dead object exception was thrown -- fall through to
28             // restart the application.
29         }
30 
31         mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
32                 "activity", r.intent.getComponent(), false, false, true);
33     }

继续查看20行调用的realStartActivityLocked方法

技术分享图片
   final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {

        if (!allPausedActivitiesComplete()) {
            // While there are activities pausing we skipping starting any new activities until
            // pauses are complete. NOTE: that we also do this for activities that are starting in
            // the paused state because they will first be resumed then paused on the client side.
            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                    "realStartActivityLocked: Skipping start of r=" + r
                    + " some activities pausing...");
            return false;
        }

        r.startFreezingScreenLocked(app, 0);
        if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */, true /* isTop */)) {
            // We only set the visibility to true if the activity is allowed to be visible based on
            // keyguard state. This avoids setting this into motion in window manager that is later
            // cancelled due to later calls to ensure visible activities that set visibility back to
            // false.
            r.setVisibility(true);
        }

        // schedule launch ticks to collect information about slow apps.
        r.startLaunchTickingLocked();

        // Have the window manager re-evaluate the orientation of the screen based on the new
        // activity order.  Note that as a result of this, it can call back into the activity
        // manager with a new orientation.  We don‘t care about that, because the activity is not
        // currently running so we are just restarting it anyway.
        if (checkConfig) {
            final int displayId = r.getDisplayId();
            final Configuration config = mWindowManager.updateOrientationFromAppTokens(
                    getDisplayOverrideConfiguration(displayId),
                    r.mayFreezeScreenLocked(app) ? r.appToken : null, displayId);
            // Deferring resume here because we‘re going to launch new activity shortly.
            // We don‘t want to perform a redundant launch of the same record while ensuring
            // configurations and trying to resume top activity of focused stack.
            mService.updateDisplayOverrideConfigurationLocked(config, r, true /* deferResume */,
                    displayId);
        }

        if (mKeyguardController.isKeyguardLocked()) {
            r.notifyUnknownVisibilityLaunched();
        }
        final int applicationInfoUid =
                (r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1;
        if ((r.userId != app.userId) || (r.appInfo.uid != applicationInfoUid)) {
            Slog.wtf(TAG,
                    "User ID for activity changing for " + r
                            + " appInfo.uid=" + r.appInfo.uid
                            + " info.ai.uid=" + applicationInfoUid
                            + " old=" + r.app + " new=" + app);
        }

        r.app = app;
        app.waitingToKill = null;
        r.launchCount++;
        r.lastLaunchTime = SystemClock.uptimeMillis();

        if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);

        int idx = app.activities.indexOf(r);
        if (idx < 0) {
            app.activities.add(r);
        }
        mService.updateLruProcessLocked(app, true, null);
        mService.updateOomAdjLocked();

        final TaskRecord task = r.getTask();
        if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||
                task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {
            setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);
        }

        final ActivityStack stack = task.getStack();
        try {
            if (app.thread == null) {
                throw new RemoteException();
            }
            List<ResultInfo> results = null;
            List<ReferrerIntent> newIntents = null;
            if (andResume) {
                // We don‘t need to deliver new intents and/or set results if activity is going
                // to pause immediately after launch.
                results = r.results;
                newIntents = r.newIntents;
            }
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                    "Launching: " + r + " icicle=" + r.icicle + " with results=" + results
                    + " newIntents=" + newIntents + " andResume=" + andResume);
            EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY, r.userId,
                    System.identityHashCode(r), task.taskId, r.shortComponentName);
            if (r.isHomeActivity()) {
                // Home process is the root process of the task.
                mService.mHomeProcess = task.mActivities.get(0).app;
            }
            mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
                                      PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);
            r.sleeping = false;
            r.forceNewConfig = false;
            mService.showUnsupportedZoomDialogIfNeededLocked(r);
            mService.showAskCompatModeDialogLocked(r);
            r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
            ProfilerInfo profilerInfo = null;
            if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
                if (mService.mProfileProc == null || mService.mProfileProc == app) {
                    mService.mProfileProc = app;
                    final String profileFile = mService.mProfileFile;
                    if (profileFile != null) {
                        ParcelFileDescriptor profileFd = mService.mProfileFd;
                        if (profileFd != null) {
                            try {
                                profileFd = profileFd.dup();
                            } catch (IOException e) {
                                if (profileFd != null) {
                                    try {
                                        profileFd.close();
                                    } catch (IOException o) {
                                    }
                                    profileFd = null;
                                }
                            }
                        }

                        profilerInfo = new ProfilerInfo(profileFile, profileFd,
                                mService.mSamplingInterval, mService.mAutoStopProfiler,
                                mService.mStreamingOutput);
                    }
                }
            }

            app.hasShownUi = true;
            app.pendingUiClean = true;
            app.forceProcessStateUpTo(mService.mTopProcessState);
            // Because we could be starting an Activity in the system process this may not go across
            // a Binder interface which would create a new Configuration. Consequently we have to
            // always create a new Configuration here.

            final MergedConfiguration mergedConfiguration = new MergedConfiguration(
                    mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
            r.setLastReportedConfiguration(mergedConfiguration);

            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), 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);

            if ((app.info.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
                // This may be a heavy-weight process!  Note that the package
                // manager will ensure that only activity can run in the main
                // process of the .apk, which is the only thing that will be
                // considered heavy-weight.
                if (app.processName.equals(app.info.packageName)) {
                    if (mService.mHeavyWeightProcess != null
                            && mService.mHeavyWeightProcess != app) {
                        Slog.w(TAG, "Starting new heavy weight process " + app
                                + " when already running "
                                + mService.mHeavyWeightProcess);
                    }
                    mService.mHeavyWeightProcess = app;
                    Message msg = mService.mHandler.obtainMessage(
                            ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
                    msg.obj = r;
                    mService.mHandler.sendMessage(msg);
                }
            }

        } catch (RemoteException e) {
            if (r.launchFailed) {
                // This is the second time we failed -- finish activity
                // and give up.
                Slog.e(TAG, "Second failure launching "
                      + r.intent.getComponent().flattenToShortString()
                      + ", giving up", e);
                mService.appDiedLocked(app);
                stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
                        "2nd-crash", false);
                return false;
            }

            // This is the first time we failed -- restart process and
            // retry.
            r.launchFailed = true;
            app.activities.remove(r);
            throw e;
        }

        r.launchFailed = false;
        if (stack.updateLRUListLocked(r)) {
            Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list");
        }

        if (andResume) {
            // As part of the process of launching, ActivityThread also performs
            // a resume.
            stack.minimalResumeActivityLocked(r);
        } else {
            // This activity is not starting in the resumed state... which should look like we asked
            // it to pause+stop (but remain visible), and it has done so and reported back the
            // current icicle and other state.
            if (DEBUG_STATES) Slog.v(TAG_STATES,
                    "Moving to PAUSED: " + r + " (starting in paused state)");
            r.state = PAUSED;
        }

        // Launch the new version setup screen if needed.  We do this -after-
        // launching the initial activity (that is, home), so that it can have
        // a chance to initialize itself while in the background, making the
        // switch back to it faster and look better.
        if (isFocusedStack(stack)) {
            mService.startSetupActivityLocked();
        }

        // Update any services we are bound to that might care about whether
        // their client may have activities.
        if (r.app != null) {
            mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
        }

        return true;
    }
realStartActivityLocked

这个方法比较长 只看重要部分:

技术分享图片

其中app.thread是一个

 技术分享图片

这里又回归到bilder机制  是以系统进程为客户端,我们自己的进行为服务端。

IAPPlictionThread 就相当APP进程中ActivityThread中ApplictionThread的代理类,

这里实际执行的相当于:ApplictionThread的scheduleLaunchActivity方法。

我们继续查看ApplictionThread中的scheduleLauchActivity方法

        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;

            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;

            r.startsNotResumed = notResumed;
            r.isForward = isForward;

            r.profilerInfo = profilerInfo;

            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

 

这里就是我们熟悉的Handler机制了,不过这个Handler是系统的H对象(继续Handler)

我们继续查看sendMessage方法(在ActivityThread对象中)

技术分享图片

技术分享图片

这里msg.what==H.LAUNCH_ACTIVITY

 1             switch (msg.what) {
 2                 case LAUNCH_ACTIVITY: {
 3                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
 4                     final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
 5 
 6                     r.packageInfo = getPackageInfoNoCheck(
 7                             r.activityInfo.applicationInfo, r.compatInfo);
 8                     handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
 9                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
10                 } break;

这里去执行handleLaunchActivity方法

技术分享图片
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        if (r.profilerInfo != null) {
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        }

        // Make sure we are running with the most recent config.
        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);

        // Initialize before creating the activity
        WindowManagerGlobal.initialize();

        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

            if (!r.activity.mFinished && r.startsNotResumed) {
                // The activity manager actually wants this one to start out paused, because it
                // needs to be visible but isn‘t in the foreground. We accomplish this by going
                // through the normal startup (because activities expect to go through onResume()
                // the first time they run, before their window is displayed), and then pausing it.
                // However, in this case we do -not- need to do the full pause cycle (of freezing
                // and such) because the activity manager assumes it can just retain the current
                // state it has.
                performPauseActivityIfNeeded(r, reason);

                // We need to keep around the original state, in case we need to be created again.
                // But we only do this for pre-Honeycomb apps, which always save their state when
                // pausing, so we can not have them save their state when restarting from a paused
                // state. For HC and later, we want to (and can) let the state be saved as the
                // normal part of stopping the activity.
                if (r.isPreHoneycomb()) {
                    r.state = oldState;
                }
            }
        } else {
            // If there was an error, for any reason, tell the activity manager to stop us.
            try {
                ActivityManager.getService()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }
handleLaunchActivity

技术分享图片

通过performLaunchActivity去创建一个Activity

performLaunchActivity方法下面分析,

如果我们创建的a不为null就去执行

技术分享图片

也就是我们Activity中的onResume方法

如果a是null

技术分享图片

就在向系统发生请求。

停止启动Activity

我们再回过头去查看performLaunchActivity方法

技术分享图片
  1     private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
  2         // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
  3 
  4         ActivityInfo aInfo = r.activityInfo;
  5         // 1.创建ActivityClientRecord对象时没有对他的packageInfo赋值,所以它是null
  6         if (r.packageInfo == null) {
  7             r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
  8                     Context.CONTEXT_INCLUDE_CODE);
  9         }
 10         //r.packageInfo ----> LoadedApk
 11 
 12         ComponentName component = r.intent.getComponent();
 13         if (component == null) {
 14             component = r.intent.resolveActivity(
 15                 mInitialApplication.getPackageManager());
 16             r.intent.setComponent(component);
 17         }
 18 
 19         if (r.activityInfo.targetActivity != null) {
 20             component = new ComponentName(r.activityInfo.packageName,
 21                     r.activityInfo.targetActivity);
 22         }
 23 
 24         ContextImpl appContext = createBaseContextForActivity(r);
 25         Activity activity = null;
 26         try {
 27             // 2.非常重要!!这个ClassLoader保存于LoadedApk对象中,它是用来加载我们写的activity的加载器
 28             java.lang.ClassLoader cl = appContext.getClassLoader();
 29             // 3.用加载器来加载activity类,这个会根据不同的intent加载匹配的activity
 30             activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
 31             StrictMode.incrementExpectedActivityCount(activity.getClass());
 32             r.intent.setExtrasClassLoader(cl);
 33             r.intent.prepareToEnterProcess();
 34             if (r.state != null) {
 35                 r.state.setClassLoader(cl);
 36             }
 37         } catch (Exception e) {
 38             // 4.这里的异常也是非常非常重要的!!!后面就根据这个提示找到突破口。。。
 39             if (!mInstrumentation.onException(activity, e)) {
 40                 throw new RuntimeException(
 41                     "Unable to instantiate activity " + component
 42                     + ": " + e.toString(), e);
 43             }
 44         }
 45 
 46         try {
 47             Application app = r.packageInfo.makeApplication(false, mInstrumentation);
 48 
 49             if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
 50             if (localLOGV) Slog.v(
 51                     TAG, r + ": app=" + app
 52                     + ", appName=" + app.getPackageName()
 53                     + ", pkg=" + r.packageInfo.getPackageName()
 54                     + ", comp=" + r.intent.getComponent().toShortString()
 55                     + ", dir=" + r.packageInfo.getAppDir());
 56 
 57             if (activity != null) {
 58                 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
 59                 Configuration config = new Configuration(mCompatConfiguration);
 60                 if (r.overrideConfig != null) {
 61                     config.updateFrom(r.overrideConfig);
 62                 }
 63                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
 64                         + r.activityInfo.name + " with config " + config);
 65                 Window window = null;
 66                 if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
 67                     window = r.mPendingRemoveWindow;
 68                     r.mPendingRemoveWindow = null;
 69                     r.mPendingRemoveWindowManager = null;
 70                 }
 71                 appContext.setOuterContext(activity);
 72                 activity.attach(appContext, this, getInstrumentation(), r.token,
 73                         r.ident, app, r.intent, r.activityInfo, title, r.parent,
 74                         r.embeddedID, r.lastNonConfigurationInstances, config,
 75                         r.referrer, r.voiceInteractor, window, r.configCallback);
 76 
 77                 if (customIntent != null) {
 78                     activity.mIntent = customIntent;
 79                 }
 80                 r.lastNonConfigurationInstances = null;
 81                 checkAndBlockForNetworkAccess();
 82                 activity.mStartedActivity = false;
 83                 int theme = r.activityInfo.getThemeResource();
 84                 if (theme != 0) {
 85                     activity.setTheme(theme);
 86                 }
 87 
 88                 activity.mCalled = false;
 89                 // 从这里就会执行到我们通常看到的activity的生命周期的onCreate里面
 90                 if (r.isPersistable()) {
 91                     mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
 92                 } else {
 93                     mInstrumentation.callActivityOnCreate(activity, r.state);
 94                 }
 95                 if (!activity.mCalled) {
 96                     throw new SuperNotCalledException(
 97                         "Activity " + r.intent.getComponent().toShortString() +
 98                         " did not call through to super.onCreate()");
 99                 }
100                 r.activity = activity;
101                 r.stopped = true;
102                 if (!r.activity.mFinished) {
103                     activity.performStart();
104                     r.stopped = false;
105                 }
106                 if (!r.activity.mFinished) {
107                     if (r.isPersistable()) {
108                         if (r.state != null || r.persistentState != null) {
109                             mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
110                                     r.persistentState);
111                         }
112                     } else if (r.state != null) {
113                         mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
114                     }
115                 }
116                 if (!r.activity.mFinished) {
117                     activity.mCalled = false;
118                     if (r.isPersistable()) {
119                         mInstrumentation.callActivityOnPostCreate(activity, r.state,
120                                 r.persistentState);
121                     } else {
122                         mInstrumentation.callActivityOnPostCreate(activity, r.state);
123                     }
124                     if (!activity.mCalled) {
125                         throw new SuperNotCalledException(
126                             "Activity " + r.intent.getComponent().toShortString() +
127                             " did not call through to super.onPostCreate()");
128                     }
129                 }
130             }
131             r.paused = true;
132 
133             mActivities.put(r.token, r);
134 
135         } catch (SuperNotCalledException e) {
136             throw e;
137 
138         } catch (Exception e) {
139             if (!mInstrumentation.onException(activity, e)) {
140                 throw new RuntimeException(
141                     "Unable to start activity " + component
142                     + ": " + e.toString(), e);
143             }
144         }
145 
146         return activity;
147     }
perfromLaunchActivity

技术分享图片

通过反射创建Activity 这里涉及的classLoader的加载机制:http://www.cnblogs.com/kangqi001/p/8318054.html 这里有介绍

 技术分享图片

再看下

技术分享图片

Activity类中的方法

技术分享图片

到这里基本就完成了Activity的创建

 

总结:Activity的启动流程

1.(Activity)经过Activity的重载方法startActivity方法执行startActivityForResult方法(应用进程)

2.(Instrumentation)在执行execStartActivity方法(应用进程)

3.(ActivityManagerService)执行startActivity方法 --》atrtAcitivityAsUser方法(系统进程)

4.(ActivityStarter)执行startActivityMayWait方法 --》startActivityLocked方法 --》startActivity方法 --》

doPengActivityLaunchesLocked方法 --》startAcitivity方法(与上不是同一个方法)--》startActivityUnchecked方法 (系统进程)

5.(ActivityStackSupervisor)执行resumeFocusedStackkTopActivityLocked方法(系统进程)

6.(ActivityStack)执行resumeTopActivityUncheckedLocked方法 --》resumeTopActivityInnerLocked方法  --》 startPausingLocked(这个方法去执行ActivityStack栈顶Activity的OnPause方法)(系统进程)

7.(ActivityStackSupervisor)执行startSpecificActivityLocked方法 --》realStartActivityLocked方法(系统进程)

8.(ActivityThread$ApplictionThread)scheduleLaunchActivity方法(应用进程)

9.(ActivityThread)执行sendMessage方法 --》 handleLaunchActivity方法--》performLaunchActivity方法(应用进程)

到这里就创建完成了Activity

 

Android8.0(API26)之Activity启动流程(显示启动)

标签:callback   说明   ++   argument   lang   ges   before   opp   为我   

原文地址:https://www.cnblogs.com/kangqi001/p/8341998.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!