Android 6.0 Launcher 启动 Activity 过程源码分析(二)

目录

技术答疑,成长进阶,可以加入我的知识星球:音视频领域专业问答的小圈子

Android 6.0 Launcher 启动 Activity 过程源码分析(一) 分析完了 Launcher 组件中启动的步骤,接下来的环节是该 ActivityManagerService 出场了。

通过 ActivityManagerNative.getDefault() 方法得到 ActivityManagerService 的代理对象后执行的 startActivity 方法,最终会发起进程间通信请求,通过 Binder 驱动,再调用 ActivityManagerService 中对应的方法。

ActivityManagerService 类的 startActivity()方法

1 @Override
2    public final int startActivity(IApplicationThread caller, String callingPackage,
3            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
4            int startFlags, ProfilerInfo profilerInfo, Bundle options) {
5        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
6            resultWho, requestCode, startFlags, profilerInfo, options,
7            UserHandle.getCallingUserId());
8    }
JAVA

显然,最后调用了 startActivityAsUser 方法:

ActivityManagerService 类的 startActivityAsUser()方法

 1@Override
 2    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
 3            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
 4            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
 5        // 相关验证过程
 6        enforceNotIsolatedCaller("startActivity");
 7        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
 8                false, ALLOW_FULL_ONLY, "startActivity", null);
 9        // 
10        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
11                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
12                profilerInfo, null, null, options, false, userId, null, null);
13    }
JAVA

startActivityAsUser先是执行了相关的验证过程,然后调用了类型为 ActivityStackSupervisormStackSupervisorstartActivityMayWait()方法。

ActivityStackSupervisor 类的 startActivityMayWait() 方法

Android 中的 Activity 组件堆栈信息,也就是 Task,是用 ActivityStack 类管理的,而ActivityStackSupervisor则是一个管理所有的ActivityStack的类。

 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, Configuration config,
 6            Bundle options, boolean ignoreTargetSecurity, int userId,
 7            IActivityContainer iContainer, TaskRecord inTask) {
 8	    // 省略部分代码
 9     
10        // Collect information about the target of the Intent.
11        // 通过 PackageManagerService 解析 Intent 参数内容,获得更多信息,保存到 ActivityInfo 类中
12        ActivityInfo aInfo =
13                resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
14		
15		// 省略部分关于 aInfo 代码
16
17            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
18                    voiceSession, voiceInteractor, resultTo, resultWho,
19                    requestCode, callingPid, callingUid, callingPackage,
20                    realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
21                    componentSpecified, null, container, inTask);
22
23            Binder.restoreCallingIdentity(origId);
24            return res;
25        }
26    }
27
28// resolveActivity 函数
29    ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
30            ProfilerInfo profilerInfo, int userId) {
31        // Collect information about the target of the Intent.
32        ActivityInfo aInfo;
33        try {
34            ResolveInfo rInfo =
35                AppGlobals.getPackageManager().resolveIntent(
36                        intent, resolvedType,
37                        PackageManager.MATCH_DEFAULT_ONLY
38                                    | ActivityManagerService.STOCK_PM_FLAGS, userId);
39            aInfo = rInfo != null ? rInfo.activityInfo : null;
40        } catch (RemoteException e) {
41            aInfo = null;
42        }
43        // 省略部分代码
44        
45    }
JAVA

首先会先调用resolveActivity函数,通过 PackageManagerService 解析 Intent 得到更多信息,返回ActivityInfo对象之后,便执行 startActivityLocked方法。

ActivityStackSupervisor 类的 startActivityLocked() 方法

 1final int startActivityLocked(IApplicationThread caller,
 2            Intent intent, String resolvedType, ActivityInfo aInfo,
 3            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
 4            IBinder resultTo, String resultWho, int requestCode,
 5            int callingPid, int callingUid, String callingPackage,
 6            int realCallingPid, int realCallingUid, int startFlags, Bundle options,
 7            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
 8            ActivityContainer container, TaskRecord inTask) {
 9        int err = ActivityManager.START_SUCCESS;
10		ProcessRecord callerApp = null;
11        if (caller != null) {
12            callerApp = mService.getRecordForAppLocked(caller); // 得到调用者的 ProcessRecord
13            if (callerApp != null) {
14                callingPid = callerApp.pid;  // 调用者的 PID
15                callingUid = callerApp.info.uid; // 调用者的 UID 
16            } else {
17                err = ActivityManager.START_PERMISSION_DENIED;
18            }
19        }
20		
21		// 省略部分代码 ,得到描述 Launcher 组件的 ActivityRecord 对象,保存在变量 sourceRecord 中
22		ActivityRecord sourceRecord = null;
23        ActivityRecord resultRecord = null;
24        if (resultTo != null) {
25            sourceRecord = isInAnyStackLocked(resultTo);
26            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
27                    "Will send result to " + resultTo + " " + sourceRecord);
28            if (sourceRecord != null) { 
29            // 从 Launcher 启动,requestCode 为 -1 ,下面的if不成立,resultRecord 为 null 。
30                if (requestCode >= 0 && !sourceRecord.finishing) {
31                    resultRecord = sourceRecord;
32                }
33            }
34        }
35		
36		// 创建用来描述被启动的 Activity 组件的 ActivityRecord 。
37		ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage, intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, this, container, options);
38                	
39		err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
40                startFlags, true, options, inTask);
41}
42
43// 根据 token 找到对应的 ActivityRecord 变量,相当于一个数组变量里面的每个元素又持有一个数组。
44ActivityRecord isInAnyStackLocked(IBinder token) {
45		// mActivityDisplays 变量的类型为 SparseArray<ActivityDisplay>
46        int numDisplays = mActivityDisplays.size();
47        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
48        // 内部持有一个 ArrayList<ActivityStack> 类型的变量 mStacks
49            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
50            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
51                final ActivityRecord r = stacks.get(stackNdx).isInStackLocked(token);
52                if (r != null) {
53                    return r;
54                }
55            }
56        }
57        return null;
58    }
JAVA

每一个应用程序进程都使用一个 ProcessRecord对象来描述,并且保存在 ActivityManagerService 内部。ActivityStackSupervisor 的 mService 变量指向了ActivityManagerService 。通过它的成员函数getRecordForAppLocked来获得参数caller对应的一个ProcessRecord对象callerApp。而参数caller指向的是 Launcher 组件所运行的应用程序进程的一个 ApplicationThread 对象,因此,ProcessRecord对象 callerApp实际上就指向了 Launcher 组件所运行的应用程序进程,接着得到这个应用程序进程的 PID 和 UID ,保存在参数callingPidcallingUid中。

ActivityStackSupervisor 变量内部有一个变量 mActivityDisplays,类型为SparseArray<ActivityDisplay>,而ActivityDisplay变量内部又持有一个mStack变量,类型为ArrayList<ActivityStack>,通过找到Activity 组件堆栈 ActivityStack,从而得到用来描述Launcher组件的ActivityRecord对象,保存在变量sourceRecord中,而由于 requestCode 为 -1 ,则 resultRecord继续为 null 。

最后,创建了一个 ActivityRecord 对象r用来描述即将启动的 Activity 组件。

现在,就已经得到请求启动 Activity 组件的 Launcher ActivityRecord 信息sourceRecord以及需要启动的 Activity 的组件信息r,下一步就执行startActivityUncheckedLocked操作。

ActivityStackSupervisor 类的 startActivityUncheckedLocked() 方法

 1final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
 2            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, Bundle options, TaskRecord inTask) {
 3		final Intent intent = r.intent;
 4        final int callingUid = r.launchedFromUid;
 5        // 得到目标 Activity 组件的启动标志位
 6		int launchFlags = intent.getFlags(); 
 7		
 8        // We'll invoke onUserLeaving before onPause only if the launching
 9        // activity did not explicitly state that this is an automated launch.
10        mUserLeaving = (launchFlags & Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
11
12		boolean addingToTask = false; // 是否将需要启动的 Activity 添加到给定的 task 中
13        TaskRecord reuseTask = null; // 
14
15        // If the caller is not coming from another activity, but has given us an
16        // explicit task into which they would like us to launch the new activity,
17        // then let's see about doing that.
18        // 如果调用者
19        if (sourceRecord == null && inTask != null && inTask.stack != null) {
20		 // 省略部分代码
21         // If task is empty, then adopt the interesting intent launch flags in to the
22         // activity being started.
23            if (root == null) {
24                final int flagsOfInterest = Intent.FLAG_ACTIVITY_NEW_TASK
25                        | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT
26                        | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
27                launchFlags = (launchFlags&~flagsOfInterest)
28                        | (baseIntent.getFlags()&flagsOfInterest);
29                intent.setFlags(launchFlags);
30                inTask.setIntent(r);
31                addingToTask = true;
32        }
33		
34		// 省略启动 Activity 已经启动过的情况,主要是将 Activity 移植 Task 栈顶
35		// 启动一个从未启动过的 Activity 
36		boolean newTask = false; // 表示在一个新的 Task 中启动 Activity
37        boolean keepCurTransition = false;
38        
39        // Should this be considered a new task?
40        // 是否要创建一个新的 Task ,当然是要的
41        if (r.resultTo == null && inTask == null && !addingToTask
42                && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
43            newTask = true;
44            targetStack = computeStackFocus(r, newTask);
45            targetStack.moveToFront("startingNewTask");
46
47            if (reuseTask == null) {  // reuseTask 为 null,创建一个新的 Task 
48                r.setTask(targetStack.createTaskRecord(getNextTaskId(),
49                        newTaskInfo != null ? newTaskInfo : r.info,
50                        newTaskIntent != null ? newTaskIntent : intent,
51                        voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
52                        taskToAffiliate);
53                if (DEBUG_TASKS) Slog.v(TAG_TASKS,
54                        "Starting new activity " + r + " in new task " + r.task);
55            } else {
56                r.setTask(reuseTask, taskToAffiliate);
57            }
58            if (isLockTaskModeViolation(r.task)) {
59                Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
60                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
61            }
62            if (!movedHome) {
63                if ((launchFlags &
64                        (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
65                        == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
66                    // Caller wants to appear on home activity, so before starting
67                    // their own activity we will bring home to the front.
68                    r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
69                }
70            }
71        } else if (sourceRecord != null) {
72			// 上面的 if 判断成立,省略代码
73			// 在调用者的 Task 中做操作 ,resumeTopActivityLocked 方法
74		} else if (inTask != null) {
75			// 上面的 if 判断成立,省略代码
76			// 在指定的 Task 中做操作,
77		} else {
78			// 上面的 if 判断成立,省略代码
79		}
80			
81		mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
82                intent, r.getUriPermissionsLocked(), r.userId);
83
84        if (sourceRecord != null && sourceRecord.isRecentsActivity()) {
85            r.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
86        }
87        if (newTask) {
88            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
89        }
90        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
91        targetStack.mLastPausedActivity = null;
92        // 启动 Activity 组件的下一步
93        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
94        if (!launchTaskBehind) {
95            // Don't set focus on an activity that's going to the back.
96            mService.setFocusedActivityLocked(r, "startedActivity");
97        }
98        return ActivityManager.START_SUCCESS;
99}
JAVA

检查 launchFlags 的 Intent.Flag_ACTIVITY_NO_USER_ACTION 是否等于 1 。如果等于 1,则表示目标 Activity 组件不是由用户手动启动的。如果目标 Activity 组件是由用户手动启动的,那么用来启动它的源 Activity 就会获得一个用户离开事件通知。

由于是从 Launcher 启动 Activity 组件,则 Flag_ACTIVITY_NO_USER_ACTION等于 0 ,mUserLeaving 为 True ,表示后面要向 Launcher 组件发送一个用户离开事件通知。

由于从 Launcher 启动的 Activity 运行在另一个 Task 中,则 addingToTask 为 false ,同时 reuseTask也是为 null 的,inTasknull,并且 r.resultTo是一个 ActivityRecord 类型,由于 Activity 组件还没启动,也是为 null。所以,最上面的 if 判断成立,直接创建一个新的 Task 了。

ActivityStack 类的 startActivityLocked() 方法

 1    final void startActivityLocked(ActivityRecord r, boolean newTask,
 2            boolean doResume, boolean keepCurTransition, Bundle options) {
 3		TaskRecord rTask = r.task;
 4        final int taskId = rTask.taskId;
 5        // mLaunchTaskBehind tasks get placed at the back of the task stack.
 6        if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
 7            // Last activity in task had been removed or ActivityManagerService is reusing task.
 8            // Insert or replace.
 9            // Might not even be in.
10            insertTaskAtTop(rTask, r);
11            mWindowManager.moveTaskToTop(taskId);
12        }
13		
14		 if (!newTask) {
15			 // newTask 为 true ,省略部分代码
16		 }
17		 
18		// Place a new activity at top of stack, so it is next to interact
19        // with the user.
20
21        // If we are not placing the new activity frontmost, we do not want
22        // to deliver the onUserLeaving callback to the actual frontmost activity 
23        // task 变量为 null,尚未赋值, IF 判断不成立
24        if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
25            mStackSupervisor.mUserLeaving = false;
26            if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
27                    "startActivity() behind front, mUserLeaving=false");
28        }
29
30		task = r.task;
31		// Slot the activity into the history stack and proceed
32        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
33                new RuntimeException("here").fillInStackTrace());
34        task.addActivityToTop(r);
35        task.setFrontOfTask();
36		 r.putInHistory();
37
38		// 省略 Window 添加部分代码
39        if (doResume) {
40            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
41        }
42    }
43// 将 ActivityRecord 添加到栈的方法
44void addActivityToTop(ActivityRecord r) {
45        addActivityAtIndex(mActivities.size(), r);
46}
JAVA

在上一步中,已经通过 r.setTask()方法创建了一个新的 Task,并且 newTask变量为 true 。当 Activity 是在一个新的 Task 中启动时,需要将它放到 TaskRecord 的中,并且位于堆栈的最上方。

当添加完之后,便继续执行 resumeTopActivitiesLocked 方法。

ActivityStackSupervisor 类的 resumeTopActivitiesLocked() 方法

 1boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
 2            Bundle targetOptions) {
 3        if (targetStack == null) {
 4            targetStack = mFocusedStack;
 5        }
 6        // Do targetStack first.
 7        boolean result = false;
 8        if (isFrontStack(targetStack)) {
 9	        // 调用 ActivityStack 类的 resumeTopActivityLocked 方法
10            result = targetStack.resumeTopActivityLocked(target, targetOptions);
11        }
12
13        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
14            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
15            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
16                final ActivityStack stack = stacks.get(stackNdx);
17                if (stack == targetStack) {
18                    // Already started above.
19                    continue;
20                }
21                if (isFrontStack(stack)) {
22	                // 调用 ActivityStack 类的 resumeTopActivityLocked 方法,参数为 null
23                    stack.resumeTopActivityLocked(null);
24                }
25            }
26        }
27        return result;
28    }
JAVA

ActivityStackSupervisor 类重载了两种形式的 resumeTopActivitiesLocked方法,主要就是将所有ActivityStack栈顶的ActivityRecord迁移到显示状态,都是调用 ActivityStack类的resumeTopActivityLocked方法,只不过参数略有不同了。

ActivityStack 类的 resumeTopActivityLocked() 方法

 1final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle 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            if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
12                mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
13                mService.updateSleepIfNeededLocked();
14            }
15            result = resumeTopActivityInnerLocked(prev, options);
16        } finally {
17            mStackSupervisor.inResumeTopActivity = false;
18        }
19        return result;
20    }
JAVA

在该方法内部最后调用了resumeTopActivityInnerLocked方法。

ActivityStack 类的 resumeTopActivityInnerLocked() 方法

 1    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
 2		 // Find the first activity that is not finishing.
 3		 // 找到当前 ActivityRecord 的栈顶,指向了要启动的 Activity 组件。
 4        final ActivityRecord next = topRunningActivityLocked(null);
 5		final TaskRecord prevTask = prev != null ? prev.task : null;
 6		
 7		if (next == null) {
 8			进入该分支表示没有要启动的 Activity 
 9		}
10		// 省略部分代码
11		// If the top activity is the resumed one, nothing to do.
12		// 检查要启动的 Activity 组件是否等于当前被激活的 Activity 组件,如果等于,并且处于 RESUMED 状态,直接返回
13        if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
14                    mStackSupervisor.allResumedActivitiesComplete()) {
15            // Make sure we have executed any pending transitions, since there
16            // should be nothing left to do at this point.
17            mWindowManager.executeAppTransition();
18            mNoAnimActivities.clear();
19            ActivityOptions.abort(options);
20            return false;
21        }
22		
23		// If we are sleeping, and there is no resumed activity, and the top
24        // activity is paused, well that is the state we want.
25        // 检查要启动的 Activity 组件是否等于上一次被中止了的 Activity 组件,如果等于,
26        // 并且这时候系统正要进入关机或睡眠状态,则直接退出,启动毫无意义
27        if (mService.isSleepingOrShuttingDown()
28                && mLastPausedActivity == next
29                && mStackSupervisor.allPausedActivitiesComplete()) {
30            // Make sure we have executed any pending transitions, since there
31            // should be nothing left to do at this point.
32            mWindowManager.executeAppTransition();
33            mNoAnimActivities.clear();
34            ActivityOptions.abort(options);
35            return false;
36        }
37
38		// If we are currently pausing an activity, then don't do anything until that is done.
39        // 检查系统中止 Activity 组件是否完成,如果没有,则直接返回了,等待所有的 Activity 进入中止状态
40        if (!mStackSupervisor.allPausedActivitiesComplete()) {
41            return false;
42        }
43
44		// We need to start pausing the current activity so the top one can be resumed...
45        // Launcher 组件进入 onPause 状态
46        boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
47        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
48        if (mResumedActivity != null) {
49        // mResumedActivity 指向了 Launcher 组件,不为 null ,则中止 Launcher 组件
50            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
51        }
52		// 省略部分代码
53		
54		if (next.app != null && next.app.thread != null) {
55			// 待启动的 Activity 在新的进程中,app 变量为 null 
56		} else {
57			// 创建一个新的应用程序进程
58			mStackSupervisor.startSpecificActivityLocked(next, true, true);
59		}
60		
61    }
JAVA

ActivityStack 类有三个成员变量:mResumedActivitymLastPausedActivitymPausingActivity,它们的类型均为 ActivityRecord,分别用来描述系统当前激活的 Activity 组件、上一次被中止的 Activity 组件,以及正在被中止的 Activity 组件。

而在resumeTopActivityInnerLocked方法中,待其的 Activity 的 ActivityRecord 已经位于栈顶了,需要将它运行到 Resumed 状态,而在这之前需要判断满足很多条件,比如当前所有的 Activity 组件要处于 onPaused状态,Launcher 组件要处于onPaused状态,否则会直接 return 退出了。

当满足上面的条件时,最后就是判断待启动的 Activity 组件的应用程序进程是否创建,如果还没有,则通过startSpecificActivityLocked创建一个应用程序进程来启动 Activity 组件。

涉及到的其他类

  • ActivityStack
  • ActivityStackSupervisor
  • ActivityDisplay
  • ActivityRecord
  • ActivityInfo
  • TaskRecord

参考

1、 Android 6.0 源码 2、《Android 系统源代码情景分析》 3、http://duanqz.github.io/2016-07-29-Activity-LaunchProcess-Part1

疑问

  • Activity 的 堆栈 ActivityStack

欢迎关注微信公众号:音视频开发进阶

Licensed under CC BY-NC-SA 4.0
粤ICP备20067247号
使用 Hugo 构建    主题 StackedJimmy 设计,Jacob 修改