这次我们讲下AMS的Activity管理,我们先从如何启动Activity说起。
一、应用startActivity函数
先来看看Activity的startActivity函数:
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);
}
}
再来看下startActivityForResult函数
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
......
调用了Instrumentation的execStartActivity函数。
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
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);
} catch (RemoteException e) {
}
return null;
}
而在Instrumentation的execStartActivity函数中调用了AMS的startActivity函数。至于AMS的startActivity函数我们后续再分析。
有时候我们调用的是context的startActivity函数,最后的是contextImpl的startActivity函数:
public void startActivity(Intent intent, Bundle options) {
warnIfCallingFromSystemProcess();
if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
throw new AndroidRuntimeException(
"Calling startActivity() from outside of an Activity "
+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."
+ " Is this really what you want?");
}
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null,
(Activity)null, intent, -1, options);
}
在contextImpl中的startActivity函数最后也是调用了Instrumentation的execStartActivity函数。
而最终都是通过binder调用AMS的startActivity函数。下面我们看下AMS的startActivity函数:
二、AMS的startActivity函数
下面我们看看AMS的startActivity函数
public int startActivity(IBinder whoThread, String callingPackage,
Intent intent, String resolvedType, Bundle options) {
checkCaller();
int callingUser = UserHandle.getCallingUserId();
TaskRecord tr;
IApplicationThread appThread;
synchronized (ActivityManagerService.this) {
tr = recentTaskForIdLocked(mTaskId);
if (tr == null) {
throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
}
appThread = ApplicationThreadNative.asInterface(whoThread);
if (appThread == null) {
throw new IllegalArgumentException("Bad app thread " + appThread);
}
}
return mStackSupervisor.startActivityMayWait(appThread, -1, callingPackage, intent,
resolvedType, null, null, null, null, 0, 0, null, null,
null, options, callingUser, null, tr);
}
startActivity方法中调用了ActivityStackSupervisor的startActivityMayWait函数,而在startActivityMayWait又调用了startActivityLocked函数,节选了重要代码:
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,//新建ActivityRecord
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, this, container, options);
if (outActivity != null) {
outActivity[0] = r;
}
final ActivityStack stack = getFocusedStack();
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);
mPendingActivityLaunches.add(pal);//不Activity信息放在mPendingActivityLaunches
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);//启动挂起等待的Activity
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, true, options, inTask);//继续启动当前Activity
startActivityUncheckedLocked函数比较长,主要是通过Intent的标志和Activity的属性来确定Activity的Task。
找到Activity的Task后,调用ActivityStack的startActivityLocked方法继续启动。
final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
TaskRecord rTask = r.task;
final int taskId = rTask.taskId;
if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
// Last activity in task had been removed or ActivityManagerService is reusing task.
// Insert or replace.
// Might not even be in.
insertTaskAtTop(rTask);
mWindowManager.moveTaskToTop(taskId);//如果是新的Task,把它放在顶部
}
TaskRecord task = null;
if (!newTask) {
// If starting in an existing task, find where that is...
boolean startIt = true;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
task = mTaskHistory.get(taskNdx);
if (task.getTopActivity() == null) {
// All activities in task are finishing.
continue;
}
if (task == r.task) {
if (!startIt) {
task.addActivityToTop(r);
r.putInHistory();
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
r.userId, r.info.configChanges, task.voiceSession != null,
r.mLaunchTaskBehind);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
ActivityOptions.abort(options);
return;
}
break;
} else if (task.numFullscreen > 0) {
startIt = false;
}
}
}
if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
mStackSupervisor.mUserLeaving = false;
}
task = r.task;
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
new RuntimeException("here").fillInStackTrace());
task.addActivityToTop(r);//把Activity放在Task的顶部
task.setFrontOfTask();
r.putInHistory();
if (!isHomeStack() || numActivities() > 0) {
............//如果不是Home应用的Stack,WMS准备绘制Activity以及动画
} else {
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,
r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
ActivityOptions.abort(options);
options = null;
}
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
if (doResume) {
mStackSupervisor.resumeTopActivitiesLocked(this, r, options);//启动Activity
}
}
看下上面的注释,最后是调用了ActivityStackSupervisor的resumeTopActivitiesLocked函数,这个函数主要是将位于栈顶的Activity显示出来。最后会调用resumeTopActivityInnerLocked函数:
final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
.............
if (next == null) {//如果当前没有Activity,显示Home Activity
// There are no more activities! Let's just start up the
// Launcher...
ActivityOptions.abort(options);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "noMoreActivities");
}
next.delayedResume = false;
if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
mStackSupervisor.allResumedActivitiesComplete()) {
//如果当前Activity就是要启动的Activity,直接返回
return false;
}
..............
boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
if (mResumedActivity != null) {
//暂停当前Activity
pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
}
if (pausing) {
.........//如果系统正在暂停Activity,先退出
return true;
}
boolean anim = true;
......//调用WMS的方法处理Activity的显示
ActivityStack lastStack = mStackSupervisor.getLastStack();
if (next.app != null && next.app.thread != null) {
//如果Activity所在的应用已经存在,把Activity显示出来
// This activity is now becoming visible.
mWindowManager.setAppVisibility(next.appToken, 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, "Delivering results to " + next
+ ": " + a);
next.app.thread.scheduleSendResult(next.appToken, a);
}
}
if (next.newIntents != null) {
next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
}
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
System.identityHashCode(next), next.task.taskId, next.shortComponentName);
next.sleeping = false;
mService.showAskCompatModeDialogLocked(next);
next.app.pendingUiClean = true;
next.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
next.clearOptionsLocked();
//调用onResume方法
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
mService.isNextTransitionForward(), resumeAnimOptions);
mStackSupervisor.checkReadyForSleepLocked();
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Resumed " + next);
} catch (Exception e) {
.........
return true;
}
else {
.........//Activity应用进程没有,先启动进程
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
return true;
}
resumeTopActivitiesLocked,如果Activity的应用已经启动,就调用应用进程的scheduleResumeActivity方法,最终到应用的onResume方法,如果应用还没启动调用startSpecificActivityLocked方法。
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {.....
}
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
startSpecificActivityLocked方法中,如果发现没有启动应用,就调用mService.startProcessLocked。在startProcessLocked会新建一个ProcessRecord保存下来,最终会调用Process.start方法启动新进程。
而如果进程已经启动会调用realStartActivityLocked方法,这个方法中会调用app.thread.scheduleLaunchActivity函数,最终调用应用的onCreate方法。
三、ActivityThread的启动
启动应用的进程的话,会调用ActivityThread的main方法:
public static void main(String[] args) {
SamplingProfilerIntegration.start();
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
EventLogger.setReporter(new EventLoggingReporter());
Security.addProvider(new AndroidKeyStoreProvider());
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();//进去消息循环
throw new RuntimeException("Main thread loop unexpectedly exited");
}
上面调用了ActivityThread的attach方法:
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {//非系统应用
ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);//调用AMS的attachApplication
......
在ActivityThread中,把ApplicationThread这个Binder服务端传给AMS。
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
............
ProfilerInfo profilerInfo = profileFile == null ? null
: new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop);
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,//调用应用的bindApplication接口
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, null);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
..........
return false;
}
......
boolean badApp = false;
boolean didSomething = false;
if (normalMode) {
try {//处理挂起的Activity
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) { badApp = true;}
}
// Find any services that should be running in this process...
if (!badApp) {
try {//处理挂起的Service
didSomething |= mServices.attachApplicationLocked(app, processName);
} catch (Exception e) {badApp = true;}
}
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {//发起挂起的广播
didSomething |= sendPendingBroadcastsLocked(app);
} catch (Exception e) {badApp = true;}
}
...........
return true;
}
attachApplicationLocked方法,先调用了ApplicationThread的接口bindApplication,这样就到应用ActivityThread中了,在ActivityThread在handleBindApplication中主要是初始化应用的数据。
调用完这个方法后,还会调用mStackSupervisor.attachApplicationLocked,这个方法主要调用了realStartActivityLocked,这个方法前面分析过了。这边进程已经启动,就调用
app.thread.scheduleLaunchActivity,在这个方法中创建了ActivityClientRecord。然后发送了一个消息。
@Override
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);
}
消息处理会执行到handleLaunchActivity函数,在performLaunchActivity函数中会创建Activity,并且调用Activity的attach方法创建PhoneWindow等,在performActivity方法中会把这个ActivityClientRecord对象放到mActivities中去。我们来看下代码:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(//创建Activity
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
activity.attach(appContext, this, getInstrumentation(), r.token,//Activity的attach方法
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);//调用Activity的onCreate函数
}
......
mActivities.put(r.token, r);//将ActivityClientRecord放入mActivities中
......