AMS系列:
1、Activity生命周期、启动模式和隐式启动总结
2、ActivityManagerService启动分析
3、本文ActivityMnagerService分析之启动一个Acitvity
本文分析代码基于N,首先ActivityManagerService的代码是一个S/C结构,AIDL的通信方式,android端的各种服务端基本都是这种代码结构写的,建议不了解的读者可以先看下笔者这篇文章PackageManagerService服务框架详解和ActivityManagerService是类似的,熟悉了AMS的代码结构阅读起来心里面会更清晰
一、调用的过程
1.1 activity开始start
首先是Activity#startActivity方法
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
//中间省略部分方法,这种常规套用java里面很常见
public void startActivityForResult(
String who, Intent intent, int requestCode, @Nullable Bundle options) {
Uri referrer = onProvideReferrer();
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, who,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, who, requestCode,
ar.getResultCode(), ar.getResultData());
}
cancelInputsAndStartExitTransition(options);
}
然后是Instrumentation#execStartActivity
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
...
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
...
}
1.2 Activity调用转换到ActivityMnagerService
上面是一个普通的start流程,我们看到最后调用到ActivityManagerNative.getDefault().startActivity方法,那么我们来看一下这个getDefault获得了什么
在ActivityManagerNative#getDefault
static public IActivityManager getDefault() {
return gDefault.get();
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
// 获得AMS的binder
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
// 获得AMS的代理类ActivityManagerProxy
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
Actvity的相关方法最后的实现都是在AMS实现的,这里的ActivityManagerNative#getDefault方法其实是获得了AMS的代理类,这里就是笔者一开始说的framework各类服务的一个代码框架,获得了代理类ActivityManagerProxy,就等于走到AMS的具体代码里了。由于获得了代理类,所以这个调用就等于调用到了ActivityManagerService#startActivity方法中了。
这里不能理解的读者强烈建议阅读PackageManagerService服务框架详解
二、AMS服务端
2.1 AMS#startActivity
从ActivityManagerService#startActivity开始
public int startActivity(IBinder whoThread, String callingPackage,
Intent intent, String resolvedType, Bundle bOptions) {
...
return mActivityStarter.startActivityMayWait(appThread, -1, callingPackage, intent,
resolvedType, null, null, null, null, 0, 0, null, null,
null, bOptions, false, callingUser, null, tr);
}
2.2 ActivityStarter的调用
显然调用顺其自然的调用到了ActivityStarter#startActivityMayWait,这里引出了一个新的关键类ActivityStarter
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, IActivityManager.WaitResult outResult, Configuration config,
Bundle bOptions, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask) {
...
// Intent匹配搜索Component
boolean componentSpecified = intent.getComponent() != null;
...
// 这里调用到AppGlobals.getPackageManager().resolveIntent,通过PMS查询把对应的信息取出来
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
...
// 把上面rInfo得到的信息,匹配得到最终的ActivityInfo
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
...
// 调用到startActivityLocked方法
final ActivityRecord[] outRecord = new ActivityRecord[1];
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor,
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, outRecord, container,
inTask);
Binder.restoreCallingIdentity(origId);
...
// 根据返回的res做最后处理
if (outResult != null) {
outResult.result = res;
if (res == ActivityManager.START_SUCCESS) {
mSupervisor.mWaitingActivityLaunched.add(outResult);
do {
try {
mService.wait();
} catch (InterruptedException e) {
}
} while (outResult.result != START_TASK_TO_FRONT
&& !outResult.timeout && outResult.who == null);
if (outResult.result == START_TASK_TO_FRONT) {
res = START_TASK_TO_FRONT;
}
}
if (res == START_TASK_TO_FRONT) {
ActivityRecord r = stack.topRunningActivityLocked();
if (r.nowVisible && r.state == RESUMED) {
outResult.timeout = false;
outResult.who = new ComponentName(r.info.packageName, r.info.name);
outResult.totalTime = 0;
outResult.thisTime = 0;
} else {
outResult.thisTime = SystemClock.uptimeMillis();
mSupervisor.mWaitingActivityVisible.add(outResult);
do {
try {
mService.wait(); // 等待启动结果
} catch (InterruptedException e) {
}
} while (!outResult.timeout && outResult.who == null);
}
}
}
final ActivityRecord launchedActivity = mReusedActivity != null
? mReusedActivity : outRecord[0];
mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
return res;
}
}
startActivityMayWait流程如下:
1、从PMS中搜索匹配信息
2、startActivityLocked处理启动请求
3、根据返回的res做相应处理
2.3 startActivityMayWait中的工作重点由startActivityLocked来启动
2.3.1 startActivityLocked
ActivityStarter#startActivityLocked方法(方法中提到的launchmode即启动模式读者可以阅读:Activity生命周期、启动模式和隐式启动总结里边有讲解,后续代码也会有启动模式的处理)
final 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) {
int err = ActivityManager.START_SUCCESS;
// 得到调用进程的pid和uid
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;
...
//sourceRecord用于描述启动目标Activity的那个Activity,
ActivityRecord sourceRecord = null;
//resultRecord用于描述接收启动结果的Activity,即该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;
}
}
}
// 获得flag,这些flag跟launchmode类似
final int launchFlags = intent.getFlags();
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) {
...
callingPackage = sourceRecord.launchedFromPackage;
}
}
//下面这几段err ==类似的代码 主要是匹配对应信息,给予相应的返回值
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.task.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.task.stack;
// 如果start不成功直接返回
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);
// 给AMS整个监听,比如monkey测试就会调用这里获得Activity运行信息
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;
}
}
// 省略一部份检查代码
...
doPendingActivityLaunchesLocked(false);
try {
mService.mWindowManager.deferSurfaceLayout();
// 处理本次Activity启动请求
err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true, options, inTask);
} finally {
mService.mWindowManager.continueSurfaceLayout();
}
postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
return err;
}
1、得到sourceRecord resultRecord
2、处理launchmode、返回值,都是一些标记,没有实质操作
3、继续调用启动startActivityUnchecked
2.3.2 startActivityUnchecked
我们接着startActivityUnchecked代码分析
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
// 初始化当前传递进来的信息
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor);
// 这里是对flag处理,如:FLAG_ACTIVITY_NEW_TASK这一类
computeLaunchingTaskFlags();
// 判断打开这个acitvity的task还存在否,如果不存在应该new tast
computeSourceStack();
...
// 设置上面处理完后的flag
mIntent.setFlags(mLaunchFlags);
// 获取当前task是否已经有activity了
mReusedActivity = getReusableIntentActivity();
final int preferredLaunchStackId =
(mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
// 如果当前已经有activity了,那么启动的时候就会有各种LanchMode(启动模式)的处理,下面这if (mReusedActivity != null)一大段就是处理这个的
if (mReusedActivity != 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(mReusedActivity.task,
(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.task == null) {
mStartActivity.task = mReusedActivity.task;
}
if (mReusedActivity.task.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.
mReusedActivity.task.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
|| mLaunchSingleInstance || mLaunchSingleTask) {
// 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 = mReusedActivity.task.performClearTaskForReuseLocked(
mStartActivity, mLaunchFlags);
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.task.setIntent(mStartActivity);
}
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
/// M: AMS log enhancement @{
if (DEBUG_TASKS) {
Slog.d(TAG, "ACT-AM_NEW_INTENT " + mStartActivity + " " + top.task);
}
/// @}
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
}
}
mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
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();
/// M: AMS log enhancement @{
if (DEBUG_TASKS) {
Slog.d(TAG, "START_RETURN_INTENT_TO_CALLER");
}
/// @}
return START_RETURN_INTENT_TO_CALLER;
}
setTaskFromIntentActivity(mReusedActivity);
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();
/// M: AMS log enhancement @{
if (DEBUG_TASKS) {
Slog.d(TAG, "START_TASK_TO_FRONT");
}
/// @}
return START_TASK_TO_FRONT;
}
}
// 判断当前要打开的activity的包名,如果为空说明没有这个class
if (mStartActivity.packageName == null) {
if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
mStartActivity.resultTo.task.stack.sendActivityResultLocked(
-1, mStartActivity.resultTo, mStartActivity.resultWho,
mStartActivity.requestCode, RESULT_CANCELED, null);
}
ActivityOptions.abort(mOptions);
/// M: AMS log enhancement @{
if (DEBUG_TASKS) {
Slog.d(TAG, "START_CLASS_NOT_FOUND");
}
/// @}
return START_CLASS_NOT_FOUND;
}
// 检查当前要启动的activity是否已经是已经启动在当前了,以确定是否需要启动
final ActivityStack topStack = mSupervisor.mFocusedStack;
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.task);
// 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;
}
/// M: AMS log enhancement @{
if (DEBUG_TASKS) {
Slog.d(TAG, "ACT-AM_NEW_INTENT " + mStartActivity + " " + top.task);
}
/// @}
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.task, preferredLaunchStackId, topStack.mStackId);
return START_DELIVERED_TO_TOP;
}
boolean newTask = false;
final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
? mSourceRecord.task : null;
// 下面这一段代码处理了应该以什么样的task来运行这个activity
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
setTaskFromReuseOrCreateNewTask(taskToAffiliate);
if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
/// M: ALPS02270164, Show lock task toast when in violation
mSupervisor.showLockTaskToast();
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
if (!mMovedOtherTask) {
updateTaskReturnToType(mStartActivity.task, mLaunchFlags, topStack);
}
} else if (mSourceRecord != null) {
if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
/// M: ALPS02270164, Show lock task toast when in violation
mSupervisor.showLockTaskToast();
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
final int result = setTaskFromSourceRecord();
if (result != START_SUCCESS) {
return result;
}
} else if (mInTask != null) {
// The caller is asking that the new activity be started in an explicit
// task it has provided to us.
if (mSupervisor.isLockTaskModeViolation(mInTask)) {
/// M: ALPS02270164, Show lock task toast when in violation
mSupervisor.showLockTaskToast();
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
final int result = setTaskFromInTask();
if (result != START_SUCCESS) {
return result;
}
} 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();
}
// 权限检查,比如uri打开图片,可能没有sd读权限
mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
}
...
ActivityStack.logStartActivity(
EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
...
mTargetStack.mLastPausedActivity = null;
// 处理了打开acitvity时中间应该播放什么样的动画,和wms一起控制
mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
if (mDoResume) {
if (!mLaunchTaskBehind) {
// 设置启动activity焦点
mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
}
final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
// 弱是一个已经存在的acitvity,则恢复它onresume
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 {
// 启动走到了这里,接着分析
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
// 把activity更新到当前task中
mTargetStack.addRecentActivityLocked(mStartActivity);
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(
mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
return START_SUCCESS;
}
1、处理launchmode
2、以怎样的task来启动activity
3、打开动画处理
4、继续走启动流程resumeFocusedStackTopActivityLocked
总结一句话就是在栈中添加好activity然后用resumeFocusedStackTopActivityLocked来启动它
2.3.3 resumeFocusedStackTopActivityLocked
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {
// 待启动Activity对应的Task为前台Task时,调用该Task对应ActivityStack的resumeTopActivityUncheckedLocked函数
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || r.state != RESUMED) {
// 否则只是调用当前前台栈的resumeTopActivityUncheckedLocked
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
}
return false;
}
代码都是调用的resumeTopActivityUncheckedLocked
然后resumeTopActivityUncheckedLocked里边是一个普通的嵌套,代码又继续走到resumeTopActivityInnerLocked
由于resumeTopActivityInnerLocked方法太长,我只截取了关键部分
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
// 启动的时候需要先pause之前的activity,最终也会走到startSpecificActivityLocked
startPausingLocked(false, false, false, false);
...
// 由此方法来启动
mStackSupervisor.startSpecificActivityLocked(next, true, true);
...
}
这个方法就是这两个大点,省略的代码都是围绕这两个点来处理
1、如果mResumedActivity不为空,则需要先暂停这个Activity。由startPausingLocked来完成
2、当mResumedActivity为空时,若待启动的Activity对应的应用存在,那么仅需要重新启动该Activity 否则,需要调用ActivityStackSupervisor的startSpecificActivityLocked函数,启动整个进程。
那么我们接着分析
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
// 看要打开的activity的app是否已经运行
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
// 如果对应进程已经存在,并向AMS注册过
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
// Don't add this if it is a platform component that is marked
// to run in multiple processes, because this is actually
// part of the framework so doesn't make sense to track as a
// separate apk in the process.
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
// 通知进程启动目标Activity
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
// 如果进程不存在需要创建进程来运行
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
创建进程就是走的启动一个应用的流程了,这里先不分析,本文主要讲一般的启动activity,那么我们看realStartActivityLocked方法
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
...
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
...
}
这里的app.thread.scheduleLaunchActivity其实是一个binder的调用,app.thread就是IApplicationThread
下面列出的是实现方式,这块儿不能理解的建议阅读上面提到的PackageManagerService服务框架详解
ApplicationThreadNative extends Binder implements IApplicationThread
ApplicationThread extends ApplicationThreadNative
public interface IApplicationThread extends IInterface {
...
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) throws RemoteException;.
...
}
所以app.thread.scheduleLaunchActivity调用的等于是调用了 ApplicationThread#scheduleLaunchActivity
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) {
...
sendMessage(H.LAUNCH_ACTIVITY, r);
}
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
}
于是就调用到了handleLaunchActivity,handleLaunchActivity又内套performLaunchActivity
2.3.4 performLaunchActivity
performLaunchActivity这里才是真正的创建的地方
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
// 这里开始new Acitvity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
}
...
try {
// 创建 Application
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
...
if (activity != null) {
// 创建Context
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
// 创建 Configuration
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
// 调用acitvity的attach,将创建的这些对象关联到activity
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window);
...
return activity;
}
2.4 服务端代码总结
1、AMS接到客户端的调用过后,开始启动,把启动的工作交给了ActivityStarter的startActivityMayWait
2、startActivityMayWait分了三步:
2.1>先从PMS中搜索匹配信息
2.2>然后startActivityUnchecked启动activity startActivityUnchecked:处理launchmode、以怎样的task来启动activity、打开动画处理、由resumeTopActivityInnerLocked分两个方向走
2.2.1>>如果mResumedActivity不为空,则需要先暂停这个Activity。由startPausingLocked来完成
2.2.2>>当mResumedActivity为空时,若待启动的Activity对应的应用存在,那么仅需要重新启动该Activity 否则,需要调用ActivityStackSupervisor的startSpecificActivityLocked函数,启动整个进程。
2.2.2.1>>>通知进程启动目标Activity,此流程最后调用到performLaunchActivity直接创建了activity
2.2.2.2>>>如果进程不存在需要创建进程来运行
2.3>最后处理返回值。
三、结束语
Activity是我们最常用的组件了,Activity整个流程走下来代码还很复杂,概要下来主要流程还是比较清晰,具体细节处理这里笔者没有太详细的去分析了,毕竟代码量很大,有碰到对应问题的时候,再去细细研究也不迟,主要是对整个流程得有一个认知,这样更利于理解Activity。处理对应问题的时候,也能快速定位相关代码。
Read the fucking sources code!