AMS所在的进程
AMS所在的进程是系统进程,进程执行入口是com.android.server.SystemServer#main,它在系统开机时启动。AMS是SystemServer中的一个线程,且是Binder线程,可通过Binder进行进程间通讯。SystemServer调用com.android.server.am.ActivityManagerService#main启动AMS线程。
AMS接收startActivity消息
根据Binder原理,将会跨进程调用到android.app.ActivityManagerNative#onTransact:
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case START_ACTIVITY_TRANSACTION:
{
//读取Parcel数据 start
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
Intent intent = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
IBinder resultTo = data.readStrongBinder();
String resultWho = data.readString();
int requestCode = data.readInt();
int startFlags = data.readInt();
String profileFile = data.readString();
ParcelFileDescriptor profileFd = data.readInt() != 0
? data.readFileDescriptor() : null;
Bundle options = data.readInt() != 0
? Bundle.CREATOR.createFromParcel(data) : null;
//读取Parcel数据 end
int result = startActivity(app, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags,
profileFile, profileFd, options);
//写入Parcel无异常到reply
reply.writeNoException();
//写入AMS返回结果
reply.writeInt(result);
return true;
}
...
com.android.server.am.ActivityManagerService#startActivity:
public final int startActivity(IApplicationThread caller,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options) {
enforceNotIsolatedCaller("startActivity");
//用户的唯一标识
int userId = 0;
...
//小于Process.FIRST_APPLICATION_UID表示请求方是系统进程
if (Binder.getCallingUid() < Process.FIRST_APPLICATION_UID) {
userId = 0;
} else {
//获取Binder跨进程请求方的userId
userId = Binder.getOrigCallingUser();
}
...
//mMainStack是com.android.server.am.ActivityStack#ActivityStack的实例,在AMS初始化的时候创建
return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
null, null, options, userId);
}
Android系统支持多用户,当前场景未进行用户切换时,主用户的userId始终是0。
通过PMS查询Activity信息
com.android.server.am.ActivityStack#startActivityMayWait:
final int startActivityMayWait(IApplicationThread caller, int callingUid,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, String profileFile,
ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
Bundle options, int userId) {
...
boolean componentSpecified = intent.getComponent() != null;
// Don't modify the client's object!
//把Intent拷贝了一份
intent = new Intent(intent);
// Collect information about the target of the Intent.
//通过PMS(PackageManagerService)获取要启动的Activity信息
ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
profileFile, profileFd, userId);
...
//if else判断了多个场景,当前场景走最后一个else
synchronized (mService) {
int callingPid;
if (callingUid >= 0) {
callingPid = -1;
} else if (caller == null) {
callingPid = Binder.getCallingPid();
callingUid = Binder.getCallingUid();
} else {
callingPid = callingUid = -1;
}
...
//暂存Binder调用方的信息
final long origId = Binder.clearCallingIdentity();
...
int res = startActivityLocked(caller, intent, resolvedType,
aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
startFlags, options, componentSpecified, null);
...
//恢复Binder调用方的信息
Binder.restoreCallingIdentity(origId);
...
return res;
已省略场景无关代码。Binder.clearCallingIdentity()会清除存储的调用方的uid和pid,并返回给origId,其中uid和pid和分别占int类型的高32位和低32位。Binder.restoreCallingIdentity(origId)会恢复暂存的origId。
ActivityInfo aInfo存储了查找得到的Activity信息。
构造Activity在AMS中的记录:ActivityRecord
com.android.server.am.ActivityStack#startActivityLocked(IApplicationThread, android.content.Intent, java.lang.String, android.content.pm.ActivityInfo, android.os.IBinder, java.lang.String, int, int, int, int, android.os.Bundle, boolean, com.android.server.am.ActivityRecord[]):
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
String resultWho, int requestCode,
int callingPid, int callingUid, int startFlags, Bundle options,
boolean componentSpecified, ActivityRecord[] outActivity) {
int err = ActivityManager.START_SUCCESS;
ProcessRecord callerApp = null;
if (caller != null) {
//根据代表调用方进程的IApplicationThread caller,获取存储在AMS中的进程信息记录,ProcessRecord记录了进程相关信息。
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
//拿到调用方的pid和uid
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
}
...
}
...
//表示当前Activity
ActivityRecord sourceRecord = null;
//表示startActivityForResult要返回的到的Activity
ActivityRecord resultRecord = null;
if (resultTo != null) {
int index = indexOfTokenLocked(resultTo);
...
if (index >= 0) {
sourceRecord = mHistory.get(index);
//若是requestCode>=0表示startActivity要返回结果,发起startActiviy的地方就是要获返回到的地方
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;//
}
}
}
int launchFlags = intent.getFlags();
//FLAG_ACTIVITY_FORWARD_RESULT允许对startActivity的result进行转发,这里是相关逻辑,本场景走不到。
if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
&& sourceRecord != null) {
...
}
//一些失败场景的处理会直接return err,略。
...
//START_ANY_ACTIVITY:可以启动任何Activity的权限。第三方应用设置了uses-permission的START_ANY_ACTIVITY无效,它要求必须和系统app签名一致,因此权鉴失败。
final int startAnyPerm = mService.checkPermission(
START_ANY_ACTIVITY, callingPid, callingUid);final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
callingUid, aInfo.applicationInfo.uid, aInfo.exported);
//要启动的Activity设置了android:permission,也要检查是否能启动TargetActivity,当前场景设置Activity权限,因此权鉴通过。
final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
callingUid, aInfo.applicationInfo.uid, aInfo.exported);
//权鉴失败的处理,不走这
if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
}
//mMainStack是true,ActivityStack创建时设置的
if (mMainStack) {
//mController可以通过android.app.ActivityManagerProxy#setActivityController设置,可以监听、拦截App的启动,不走这。
if (mService.mController != null) {
...
}
}
//创建ActivityRecord,它是Activity在AMS中的记录
ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid,
intent, resolvedType, aInfo, mService.mConfiguration,
resultRecord, resultWho, requestCode, componentSpecified);
//outActivity传入的null,不走这
if (outActivity != null) {
outActivity[0] = r;
}
if (mMainStack) {
//处于后台的Activity发起startActivity请求,这样的操作google有限制,代码就在这里,略。
if (mResumedActivity == null
|| mResumedActivity.info.applicationInfo.uid != callingUid) {
...
}
err = startActivityUncheckedLocked(r, sourceRecord,
startFlags, true, options);
...
return err;
这里做了这几件事:
- uid和pid的获取
-需要result时的处理 - startActivity权鉴
- 创建ActivityRecord
com.android.server.am.ActivityStack#startActivityUncheckedLocked:
final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
final Intent intent = r.intent;
final int callingUid = r.launchedFromUid;
final int userId = r.userId;
int launchFlags = intent.getFlags();
//一些flag和其它的无关逻辑,略
...
//sourceRecord是null表示从Application Context而不是从Activity启动,singleInstance、singleInstance、singleTask这些场景都强制加上FLAG_ACTIVITY_NEW_TASK。这里不会走
if (sourceRecord == null) {
...
} else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE)
...
} else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
...
}
//一大堆无关逻辑,包括Task处理、startActivity返回result的异常处理等等
...
boolean newTask = false;
boolean keepCurTransition = false;
if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
//需要创建Task的情况,不走这里
...
} else if (sourceRecord != null) {
if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
//FLAG_ACTIVITY_CLEAR_TOP相关逻辑,不走这里
} else if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
//FLAG_ACTIVITY_REORDER_TO_FRONT相关处理,不走这里
}
//把MainActivity所在的Task共享给了TargetActivity,后文分析
r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
} else {
//从Application Context启动,直接把最近的Activity所在栈设置给要启动Activity,不走这里
}
...
startActivityLocked(r, newTask, doResume, keepCurTransition, options);
return ActivityManager.START_SUCCESS;
}
Task和mHistory的处理
先分析r.setTask再分析startActivityLocked
com.android.server.am.ActivityRecord#setTask:
void setTask(TaskRecord newTask, ThumbnailHolder newThumbHolder, boolean isRoot) {
//如果该Activity已经在被AMS启动过了,换新的Task,要做一些处理,不走这
if (inHistory && !finishing) {
if (task != null) {
task.numActivities--;
}
if (newTask != null) {
newTask.numActivities++;
}
}
if (newThumbHolder == null) {
newThumbHolder = newTask;
}
//赋值新Task
task = newTask;
// 无关逻辑
if (!isRoot && (intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
if (thumbHolder == null) {
thumbHolder = new ThumbnailHolder();
}
} else {
thumbHolder = newThumbHolder;
}
}
com.android.server.am.ActivityStack#startActivityLocked(com.android.server.am.ActivityRecord, boolean, boolean, boolean, android.os.Bundle):
//传入值r:刚创建的ActivityRecord,newTask:false,doResume:true,keepCurTransition:false,options:null
private final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
//mHistory是AMS中启动的Activity的个数
final int NH = mHistory.size();
int addPos = -1;
//复用的Task,找个合适的位置插ActivityRecord进去
if (!newTask) {
boolean startIt = true;
for (int i = NH-1; i >= 0; i--) {
ActivityRecord p = mHistory.get(i);
if (p.finishing) {
continue;
}
if (p.task == r.task) {
//TargetActivity要插入mHistory的位置在MainActivity的前一个
addPos = i+1;
if (!startIt) {
//所在的Task不在前台显示着,直接启动要启动的Activity,不走这里,略
...
}
//直接break
break;
}
if (p.fullscreen) {
startIt = false;
}
}
}
//没有可以插入的位置,直接顶上,不走这
if (addPos < 0) {
addPos = NH;
}
if (addPos < NH) {
...
}
...
mHistory.add(addPos, r);
//见后文分析
r.putInHistory();
//frontOfTask表示是否是Task的根Activity,这里是false
r.frontOfTask = newTask;
if (NH > 0) {
// We want to show the starting preview window if we are
// switching to a new task, or the next activity's process is
// not currently running.
//走这里。一些动画相关的操作,可见上面官方注释,还会通知WMS(WindowsManagerService做一些事情),场景无关,不再分析。
...
else {
//不需要动画但是也通知WMS做了一些事情
...
}
...
if (doResume) {
resumeTopActivityLocked(null);
}
com.android.server.am.ActivityRecord#putInHistory:
void putInHistory() {
//新建的ActivityRecord,不在mHistory中,inHistory是false
if (!inHistory) {
inHistory = true;
//当前场景满足条件,把Task中记录的Activity个数加1
if (task != null && !finishing) {
task.numActivities++;
}
}
}
要想resume新的Activity,先pause掉前一个Activity
com.android.server.am.ActivityStack#resumeTopActivityLocked(com.android.server.am.ActivityRecord):
final boolean resumeTopActivityLocked(ActivityRecord prev) {
return resumeTopActivityLocked(prev, null);
}
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
// 找到mHistory中最近的一个没有正在finishing的Activity,因为TargetActivity已经被插入进去了,一次next就是TargetActivity
ActivityRecord next = topRunningActivityLocked(null);
final boolean userLeaving = mUserLeaving;
mUserLeaving = false;
if (next == null) {
//已经没有可以显示的Activity了,直接显示Launcher,也就是桌面进程,不走这
if (mMainStack) {
ActivityOptions.abort(options);
return mService.startHomeActivityLocked(0);
}
}
next.delayedResume = false;
//mResumedActivity表示当前正在resume的Activity,是MainActivity。要启动的Activity已经resume了,直接return,不走这里
if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
...
return false;
}
if ((mService.mSleeping || mService.mShuttingDown)
&& mLastPausedActivity == next
&& (next.state == ActivityState.PAUSED
|| next.state == ActivityState.STOPPED
|| next.state == ActivityState.STOPPING)) {
...
//休眠状态下的情况,mLastPausedActivity保存着Task顶的Activity,如果要启动的就是休眠后的Task顶,直接return,不走这
return false;
}
//都是要resume的Activity了,从这些list中删除了,状态重置了
mStoppingActivities.remove(next);
mGoingToSleepActivities.remove(next);
next.sleeping = false;
mWaitingVisibleActivities.remove(next);
...
//如果有正在pause的Activity,啥也不干,等它暂停完再说,不走这
if (mPausingActivity != null) {
if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
return false;
}
...
//有正在resume的Activity,先把它pause掉,mResumedActivity就是MainActivity
if (mResumedActivity != null) {
if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
startPausingLocked(userLeaving, false);
return true;
}
...
com.android.server.am.ActivityStack#startPausingLocked:
//userLeaving和uiSleeping传入的都是false
private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
//有正在pause的,属于异常情况,不走这
if (mPausingActivity != null) {
RuntimeException e = new RuntimeException();
Slog.e(TAG, "Trying to pause when pause is already pending for "
+ mPausingActivity, e);
}
ActivityRecord prev = mResumedActivity;
//没有可以用来pause的,属于异常情况,不走这里
if (prev == null) {
RuntimeException e = new RuntimeException();
Slog.e(TAG, "Trying to pause when nothing is resumed", e);
resumeTopActivityLocked(null);
return;
}
...
//这一堆,把正在resume的Activity变成正在pause的
mResumedActivity = null;
mPausingActivity = prev;
mLastPausedActivity = prev;
prev.state = ActivityState.PAUSING;
...
if (prev.app != null && prev.app.thread != null) {
if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
try {
...
//通知resume的Activity,也即是MainActivity,pause掉
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags);
...
} catch (Exception e) {
...
}
} else {
...
}
//设置pause超时时间
if (mPausingActivity != null) {
...
Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
msg.obj = prev;
prev.pauseTime = SystemClock.uptimeMillis();
mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
...
} else {
...
}
prev是ActivityRecord也即是MainActivity,prev.app是ProcessRecord实例,prev.app.thread是IApplicationThread类型,schedulePauseActivity的调用会跨进程。跨进程请求方是AMS,接收方是App进程。
分析一下它的参数:
- prev.appToken:com.android.server.am.ActivityRecord#appToken,构造ActivityRecord的时候创建的,用于唯一标识Activity。向AMS发送startActivity跨进程请求时的android.app.Activity#mToken就是它
- prev.finishing:是否正在finishing
- onUserLeaving:传入的false,后续用到再分析
- prev.configChangeFlags:ActivityRecord的一个int属性,当前是0,用到再分析
至此,AMS要向App进程发起第二次握手了,回到App进程继续执行。startActivity还不算完。
总结
AMS要经过一系列的操作如:Activity信息收集、uid和pid获取、权限检查、Task和mHistory的处理等一系列操作,才能确定要启动Activity,尝试启动时又需要把前一个Activity pause掉,因此AMS无可奈何,只能请求App进程把前一个Activity把pause,由此拉开了第二次握手的序幕。