Activity的启动过程
Android组件有四个,Activity、Service、ContentProvider、BroadcastReceiver。首先来学习activity的启动过程,Activity有两种类型,一个是根Activity,即应用程序的第一个Activity,一个是普通的Activity,启动根Activity即是启动该应用程序。首先来看一下如何去启动根Activity,从之前的学习知道,系统第一个应用程序是Laucnher,用于显示各种应用程序图标,之后再通过点击应用程序图标的方式去启动第三方应用程序,所以可知,应用程序的启动入口应该就在Launcher,事实上,应用程序的启动过程大概分为以下三步:
- Launcher请求AMS启动指定应用程序过程
- AMS调用ApplicationThread的过程
- ActivityThread启动指定根Activity
步骤一: Launcher请求AMS启动指定应用程序过程
首先来看一下大致的时序图:
1.点击应用程序图标,会调用Launcher的startActivitySafely方法:
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
...
// 1. 设置intent的flag为FLAG_ACTIVITY_NEW_TASK,那么该Activity会在一个新的栈中启动。
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (v != null) {
intent.setSourceBounds(getViewBounds(v));
}
try {
if (Utilities.ATLEAST_MARSHMALLOW
&& (item instanceof ShortcutInfo)
&& (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
|| item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
&& !((ShortcutInfo) item).isPromise()) {
// Shortcuts need some special checks due to legacy reasons.
startShortcutIntentSafely(intent, optsBundle, item);
} else if (user == null || user.equals(Process.myUserHandle())) {
//2. 调用startActivity去启动activity,这个startActivity在Activity中实现,那么去Activity中看一下这个实现:
startActivity(intent, optsBundle);
} else {
LauncherAppsCompat.getInstance(this).startActivityForProfile(
intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
}
return true;
} catch (ActivityNotFoundException|SecurityException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
}
return false;
}
2.Activity.startActivityForResult()
startActivity()内部调用了startActivityForResult():
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,@Nullable Bundle options) {
//1. mParent表示要创建的Activity的父类,由于根Activity还没有创建出来,所以这里符合mParent == null
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
//2.接下来调用了 Instrumentation的execStartActivity()方法,Instrumentation主要用来监控应用程序和系统的交互,那么再来看下Instrumentation的execStartActivity()方法:
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
...
}
}
3. Instrumentation的execStartActivity()
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {
...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
//1. 这里主要工作就是获取AMS,然后调用AMS的tartActivity()方法,那么如何获取到AMS?
int result = ActivityManager.getService()
.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) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
4.通过ActivityManager.getService()获取AMS
public static IActivityManager getService() {
return IActivityManagerSingleton.get(); //1. 调用IActivityManagerSingleton.get()
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
//2.这里通过ServiceManager的getService()获取名为“activity”的service引用,即是IBinder类型的AMS引用,由于SystemServer启动时会创建各种service包括AMS,并都注册到
// ServiceManager中,所以这里可以通过ServiceManager去获取各种Service。
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
//3. 这里将这个引用转成IActivityManager 类型,这里采用了AIDL实现进程间通信,服务端即AMS继承IActivityManager.Stub类并实现相应的方法即可。
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return Binder.allowBlocking(getIServiceManager().getService(name));
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
从上面步骤可知,从桌面点击应用程序图标会经历Launcher.startActivitySafely() -> Activity.startActivityForResult() -> Instrumentation的execStartActivity() -> AMS.startActivity(),即最终进入到AMS的StartActivity(),那么现在整个Activity的启动流程就进入了AMS,即已经跨入了另一进程了,那么再来看下第二个详细的步骤:
步骤二:AMS调用ApplicationThread的过程
1.首先来看AMS的startActivity()过程
AMS内部startActivity()会调用startActivityAsUser()方法,代码如下:
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
//1. 判断调用者是否被隔离 ,如果被隔离则抛出SecurityException()
enforceNotIsolatedCaller("startActivity");
//2. 检查调用者是否有权限
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startActivity", null);
//3. 最后一步调用ActivityStarter.startActivityMayWait()
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null,
"startActivityAsUser");
}
2. ActivityStarter.startActivityMayWait()
ActivityStarter是加载Activity的控制类,收集所有的逻辑来判断该如何将Intent和flags转换成Activity,并将Activity和Task以及Stack相关联。
final int startActivityMayWait(IApplicationThread caller, int callingUid,...IActivityContainer iContainer, TaskRecord inTask, String reason) {
...
final ActivityRecord[] outRecord = new ActivityRecord[1];
//1. 内部调用了启动reason是否为空,为空则抛出异常,否则就跳转的StartActivity()
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, reason);
...
return res;
}
}
3.ActivityStarter.startActivity()
private int startActivity(IApplicationThread caller, Intent intent, ...TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
final Bundle verificationBundle = options != null ? options.popAppVerificationBundle() : null;
ProcessRecord callerApp = null;
//1 .判断caller是否为空,它是从开始一路传进来的,即调用者Launcher所在的应用程序进程的ApplicationThread对象
if (caller != null) {
//2. 调用AMS去获取Launcher进程的callerApp对象,这是一个ProcessRecord,记录了进程所有相关的消息。
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
//获取Launcher进程的pid、uid
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;
}
}
...
//2. 创建即将要启动的Activity的描述类ActivityRecord,ActivityRecord是用来记录一个Activity所有的信息。
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, container, options, sourceRecord);
if (outActivity != null) {
outActivity[0] = r; //3.
}
doPendingActivityLaunchesLocked(false);
//3. 再次调用了startActivity(),内部调用了startActivityUnchecked()
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask, outActivity);
4.ActivityStarter.startActivityUnchecked()
startActivityUnchecked()主要处理与栈管理相关的逻辑:
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) {
//1. 前面Launcher入口时就设置了Intent为 FLAG_ACTIVITY_NEW_TASK,所以这里的条件会满足
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
//2. 这里内部会创建一个新的TaskRecord,用于描述Activity的任务栈。
result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, preferredLaunchStackId, topStack);
} else if (mSourceRecord != null) {
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
result = setTaskFromInTask();
} else {
setTaskToCurrentTopOrCreateNewTask();
}
...
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mWindowManager.executeAppTransition();
} else {
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
//3. 最后这里会调用ActivityStackSupervisor的resumeFocusedStackTopActivityLocked()方法,那么这个方法又做了什么?
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
preferredLaunchDisplayId, mTargetStack.mStackId);
return START_SUCCESS;
5. ActivityStackSupervisor.resumeFocusedStackTopActivityLocked()
boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
//1.获取当前要启动的Activity的栈顶处于running状态的Activity的ActivityRecord
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
//2.若r == null 或者要启动的Activity不是resumed状态,则调用下面的mFocusedStack.resumeTopActivityUncheckedLocked,由于Activity还没启动。所以这里条件满足
if (r == null || r.state != RESUMED) {
//3.这个resumeTopActivityUncheckedLocked()又做了什么?
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.state == RESUMED) {
// Kick off any lingering app transitions form the MoveTaskToFront operation.
mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}
6. ActivityStack.resumeTopActivityUncheckedLocked()
resumeTopActivityUncheckedLocked()内部经过跳转,会调用startSpecificActivityLocked()方法:
void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {
// 1. 获取即将要启动的ACtivity所在进程,判断该Activity所在进程是否已经running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) {
//给app添加包信息
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,mService.mProcessStats);
}
//2. 判断app != null &&该应用程序进程已经运行时,执行下面方法,这个方法又做了什么?
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
7. realStartActivityLocked()
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
...
/**
* 这个方法的核心代码在这里, app.thread值得是IApplicationThread,它的实现类是ActivityThread的内部类ApplicationThread,继承自IApplicationThread.Stub
* app就是待启动Activity的ProcessRecord,所以这里就是要在目标应用程序的进程里面启动Activity,上面的代码是运行在AMS进程中,现通过应用程序的ActivityThread的ApplicationThread就切换
* 回到了应用程序进程,通过Binder进行通信。
**/
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global and
// override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
...
return true;
}
AMS和应用程序进程通信过程:
中间的这个流程都会在AMS进程中进行的,由一开始Launcher进程接收点击图标事件,先后经历了Launcher进程 -> AMS进程,最后进入了待启动应用程序进程,现在已经进入了第三个步骤,在目标应用程序进程中启动Activity。
步骤三:ActivityThread启动指定根Activity
上面步骤最后一个入口是app.thread.scheduleLaunchActivity(),那么就来看一下app.thread.scheduleLaunchActivity()
1.app.thread.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) {
updateProcessState(procState, false);
//1. 将Activity的启动参数全部封装给Activity。
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
...
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
//2. 然后调用sendMessage()向H发送一个H.LAUNCH_ACTIVITY消息,并将ActivityClientRecord传递过去
sendMessage(H.LAUNCH_ACTIVITY, r);
}
2.sendMessage()
H 是ActivityThread的一个内部类,继承自Handler,用于处理ActivityThread的消息,由于ApplicationThread是一个Binder,运行在Binder线程池中,所以需要通过H将代码逻辑切换到主线程。
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
3.看主线程如何处理H.LAUNCH_ACTIVITY消息
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
//1. 首先将Activity的启动参数封装类ActivityClientRecord取出来
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
//2. 获取LoadApk类型的对象并赋值给ActivityClientRecord的成员变量r.packageInfo,应用程序进程要启动Activity时需要将该Activity所属的Apk加载进来。
r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
//3. 调用handleLaunchActivity()去启动Activity
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
....
4. handleLaunchActivity()
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
WindowManagerGlobal.initialize();
// 1. 启动Activity
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
//2 .将Activity的状态设置为Resume
handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
if (!r.activity.mFinished && r.startsNotResumed) {
performPauseActivityIfNeeded(r, reason);
if (r.isPreHoneycomb()) {
r.state = oldState;
}
}
} else {
// 发生异常,则调用AMS去finish这个Activity
try {
ActivityManager.getService().finishActivity(r.token, Activity.RESULT_CANCELED, null,Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
5. performLaunchActivity()
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//获取ActivityInfo类,用于存储代码以及AndroidManifest.xml设置的Activity和Receiver节点信息,例如Activity的theme和launchMode
ActivityInfo aInfo = r.activityInfo;
//2.获取packageInfo
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,Context.CONTEXT_INCLUDE_CODE);
}
//3.获取ComponentName,保存了Activity的包名和类名
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName, r.activityInfo.targetActivity);
}
//4. 创建要启动Activity的上下文环境
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
//5. 用类加载器来创建Activity的实例
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 {
//6.创建Application,内部会调用Application的onCreate()方法
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
...
appContext.setOuterContext(activity);
//7.初始化Activity,创建Window对象,并且与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, r.configCallback);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
//8.调用mInstrumentation.callActivityOnCreate()来启动Activity
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
return activity;
}
6. mInstrumentation.callActivityOnCreate()
public void callActivityOnCreate(Activity activity, Bundle icicle,PersistableBundle persistentState) {
prePerformCreate(activity);
activity.performCreate(icicle, persistentState); //这里调用了activity的onCreate()方法
postPerformCreate(activity);
}
7.Activity的生命周期函数onCreate()调用入口
final void performCreate(Bundle icicle) {
restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle); //这里调用了Activity的onCreate(),开始了Activity的生命周期,应用程序也因此启动了。
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
总结:
从上面的步骤来看,Activity的启动过程涉及到多个进程,分别是Zygote进程、SystemServer进程、Launcher进程、应用程序进程,如图所示:
那么如果是普通的Activity启动涉及多少进程呢?明显是2个,因为不需要接触到Launcher和zygote