當(dāng)我們點擊桌面的圖標(biāo)時闪幽,我們首先會把桌面Launch給pause掉啥辨,然后再顯示我們啟動的應(yīng)用。
一.流程圖
1.ActivityManagerService.startActivity
主要包含調(diào)用者的信息盯腌,調(diào)用者就是Laucher溉知。要啟動的Activity的信息在intent和startFlags里面。加入了userid后腕够,接下來調(diào)用startActivityAsUser级乍。
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}
下面時動態(tài)調(diào)試斷點看到的值。
2.ActivityManagerService.startActivityAsUser
(1) enforceNotIsolatedCaller函數(shù)限制了Isolated process調(diào)用startActivity帚湘。如果是Isolated process調(diào)用startActivity玫荣,會拋出SecurityException引有。
(2)handleIncomingUser校驗CallingUid屬于userid却汉。對于但用戶手機userid==0居灯。
接下來調(diào)用ActivityStackSupervisor.startActivityMayWait方法啟動Activity勉耀。ActivityStackSupervisor是用于管理Activity棧的。全局只有一個ActivityStackSupervisor溉苛。一個stack可以包含多個task缩抡。棧頂?shù)腁ctivity會顯示給用戶看歹叮。
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, options, false, userId, null, null);
}
3. ActivityStackSupervisor.startActivityMayWait
(1)通過resolveActivity來獲取要啟動的應(yīng)用信息贿堰,將應(yīng)用信息保存到aInfo辙芍。
接下來調(diào)用startActivityLocked。
輸入的變量信息如下圖:
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
Bundle options, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask) {
boolean componentSpecified = intent.getComponent() != null;
// 獲取應(yīng)用的信息
ActivityInfo aInfo =
resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
synchronized (mService) {
int res = startActivityLocked(caller, intent, resolvedType, aInfo,
voiceSession, voiceInteractor, resultTo, resultWho,
requestCode, callingPid, callingUid, callingPackage,
realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
componentSpecified, null, container, inTask);
}
}
4. ActivityStackSupervisor.startActivityLocked
1.初始化了callingPid和callingUid羹与,即調(diào)用者Launcher的PID和UID
2.打印啟動信息“START u 0 ...”
3.校驗要啟動的應(yīng)用信息ainfo和intent故硅。
3.初始化sourceRecord,resultRecord注簿,resultStack契吉,如果啟動失敗,將通過resultStack告知調(diào)用者诡渴。當(dāng)然桌面啟動的話,resultRecord和resultStack都是空的菲语。
4.檢查action和compont的啟動權(quán)限妄辩。我覺得這個是這個函數(shù)主要做的事情。用于校驗調(diào)用者的權(quán)限和組件是否是黑名單山上。例如一些rom廠商都會配置一些黑名單應(yīng)用組件眼耀。
5.調(diào)用startActivityUncheckedLocked進(jìn)行下一步。
輸入的變量信息如下圖:
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType, ActivityInfo aInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage,
int realCallingPid, int realCallingUid, int startFlags, Bundle options,
boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
ActivityContainer container, TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
//初始化callingpid和callinguid
ProcessRecord callerApp = null;
if (caller != 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;
//打印啟動log
if (err == ActivityManager.START_SUCCESS) {
Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
+ "} from uid " + callingUid
+ " on display " + (container == null ? (mFocusedStack == null ?
Display.DEFAULT_DISPLAY : mFocusedStack.mDisplayId) :
(container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
container.mActivityDisplay.mDisplayId)));
}
//初始化sourceRecord和resultRecord
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
if (resultTo != null) {
sourceRecord = 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和ainfo信息
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
&& !isCurrentProfileLocked(userId)
&& (aInfo.flags & FLAG_SHOW_FOR_ALL_USERS) == 0) {
// Trying to launch a background activity that doesn't show for all users.
err = ActivityManager.START_NOT_CURRENT_USER_ACTIVITY;
}
//檢查action和compont的啟動權(quán)限
boolean abort = false;
final int startAnyPerm = mService.checkPermission(
START_ANY_ACTIVITY, callingPid, callingUid);
if (startAnyPerm != PERMISSION_GRANTED) {
final int componentRestriction = getComponentRestrictionForCallingPackage(
aInfo, callingPackage, callingPid, callingUid, ignoreTargetSecurity);
final int actionRestriction = getActionRestrictionForCallingPackage(
intent.getAction(), callingPackage, callingPid, callingUid);
if (componentRestriction == ACTIVITY_RESTRICTION_PERMISSION
|| actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) {
if (resultRecord != null) {
resultStack.sendActivityResultLocked(-1,
resultRecord, resultWho, requestCode,
Activity.RESULT_CANCELED, null);
}
String msg;
if (actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) {
msg = "Permission Denial: starting " + intent.toString()
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ")" + " with revoked permission "
+ ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction());
} else if (!aInfo.exported) {
msg = "Permission Denial: starting " + intent.toString()
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " not exported from uid " + aInfo.applicationInfo.uid;
} else {
msg = "Permission Denial: starting " + intent.toString()
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " requires " + aInfo.permission;
}
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
if (actionRestriction == ACTIVITY_RESTRICTION_APPOP) {
String message = "Appop Denial: starting " + intent.toString()
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " requires " + AppOpsManager.permissionToOp(
ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction()));
Slog.w(TAG, message);
abort = true;
} else if (componentRestriction == ACTIVITY_RESTRICTION_APPOP) {
String message = "Appop Denial: starting " + intent.toString()
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " requires appop " + AppOpsManager.permissionToOp(aInfo.permission);
Slog.w(TAG, message);
abort = true;
}
}
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;
}
}
//初始化啟動的ActivityRecord
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, this, container, options);
if (outActivity != null) {
outActivity[0] = r;
}
//調(diào)用startActivityUncheckedLocked
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, true, options, inTask);
return err;
}
5.ActivityStackSupervisor.startActivityUncheckedLocked
1.startActivityUncheckedLocked主要是根據(jù)launchFlags來決定新建還是服用task和stack佩憾。桌面啟動會新建targetStack和task哮伟,把targetStack放在所有stack的最前面(這時沒有設(shè)置task在targetStack的位置哦干花,在下一步才設(shè)置)。設(shè)置要啟動的ActivityRecord為focus楞黄。
2.找到stack后池凄,接下來調(diào)用ActivityStack的startActivityLocked方法來啟動。
final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
boolean doResume, Bundle options, TaskRecord inTask) {
//獲取啟動flag
final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;
int launchFlags = intent.getFlags();
//選擇stack和新建task
// Should this be considered a new task?
if (r.resultTo == null && inTask == null && !addingToTask
&& (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
targetStack = computeStackFocus(r, newTask);
//把stack推到最前面
targetStack.moveToFront("startingNewTask");
//新建task鬼廓,并設(shè)置為ActivityRecord的task
if (reuseTask == null) {
r.setTask(targetStack.createTaskRecord(getNextTaskId(),
newTaskInfo != null ? newTaskInfo : r.info,
newTaskIntent != null ? newTaskIntent : intent,
voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
taskToAffiliate);
if (DEBUG_TASKS) Slog.v(TAG_TASKS,
"Starting new activity " + r + " in new task " + r.task);
} else {
r.setTask(reuseTask, taskToAffiliate);
}
}
targetStack.mLastPausedActivity = null;
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
//設(shè)置focus ActivityRecord
if (!launchTaskBehind) {
// Don't set focus on an activity that's going to the back.
mService.setFocusedActivityLocked(r, "startedActivity");
}
return ActivityManager.START_SUCCESS;
}
6.ActivityStack.startActivityLocked
主要是把task推到stack的top肿仑。然后window做一些切換的準(zhǔn)備動作。最后這個stack的狀態(tài)搞好了碎税,就調(diào)用mStackSupervisor.resumeTopActivitiesLocked來resume所有top的Activities尤慰。
final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
TaskRecord rTask = r.task;
final int taskId = rTask.taskId;
//把task放到stack的top位置
insertTaskAtTop(rTask, r);
mWindowManager.moveTaskToTop(taskId);
}
TaskRecord task = null;
task = r.task;
//把ActivityRecord放在task的top,并且放到History中
task.addActivityToTop(r);
task.setFrontOfTask();
r.putInHistory();
//準(zhǔn)備做動畫
mWindowManager.prepareAppTransition(newTask
? r.mLaunchTaskBehind
? AppTransition.TRANSIT_TASK_OPEN_BEHIND
: AppTransition.TRANSIT_TASK_OPEN
: AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
mNoAnimActivities.remove(r);
if (doResume) {
mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
}
}
7.ActivityStackSupervisor.resumeTopActivitiesLocked
這個函數(shù)比較簡單啦雷蹂,就是找到最top的stack伟端,然后調(diào)用stack的resumeTopActivityLocked。在startActivityUncheckedLocked的時候已經(jīng)通過targetStack.moveToFront把這個targetStack搞定最前面了匪煌。
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
Bundle targetOptions) {
if (targetStack == null) {
targetStack = mFocusedStack;
}
// Do targetStack first.
boolean result = false;
if (isFrontStack(targetStack)) {
result = targetStack.resumeTopActivityLocked(target, targetOptions);
}
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (stack == targetStack) {
// Already started above.
continue;
}
if (isFrontStack(stack)) {
stack.resumeTopActivityLocked(null);
}
}
}
return result;
}
8. ActivityStack.resumeTopActivityLocked
會調(diào)用mStackSupervisor.pauseBackStacks把桌面pause掉责蝠。
桌面pause掉之后會告知AMS,AMS重新走ActivityStackSupervisor.resumeTopActivitiesLocked來拉起TOP的activity虐杯。
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
......
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
if (pausing) {
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;
}
.....
}
過程總結(jié):
1.ActivityManagerService.startActivity是入口
2.ActivityManagerService.startActivityAsUser是包含user id的入口
3.ActivityStackSupervisor.startActivityMayWait 是AMS管理Activity的入口玛歌,主要獲取要啟動Activity的應(yīng)用信息aInfo。
4.ActivityStackSupervisor.startActivityLocked主要是檢驗權(quán)限擎椰,將要啟動的Activity信息包裝到ActiviyRecord中支子。
5.ActivityStackSupervisor.startActivityUncheckedLocked會新建targetStack和task,把targetStack放在所有stack的最前面达舒。
6.ActivityStack.startActivityLocked主要是把task推到stack的top值朋。然后window做一些切換的準(zhǔn)備動作。
7.ActivityStackSupervisor.resumeTopActivitiesLocked 找到最top的stack巩搏,然后調(diào)用stack的resumeTopActivityLocked昨登。
- ActivityStack.resumeTopActivityLocked調(diào)用mStackSupervisor.pauseBackStacks把非front的Stack都pause掉,桌面這時已經(jīng)不是front贯底,所以會被pause掉丰辣。
現(xiàn)在只說到Launcher pause了,但要啟動的Activity還沒有resume禽捆。下節(jié)再來講述他是怎么resume的笙什。