一.背景
Activiy的启动流程分为两种:1.是根Activity的启动流程;2.是普通Activity的启动流程。根Activity是指应用程序启动的第一个Activity,也可以把它理解成应用程序的启动流程。
这里所说的Activity启动流程指的是根Activity的启动流程。根Activity的启动流程笔比较复杂,大概可以分为3个部分,分别是Launcher请求AMS过程、AMS到ApplicationThread的调用过程和ActivityThread启动Activity的过程。
二.Launcher请求AMS过程
SystemServer进程启动完成以后,就会启动Launcher,它启动后会将已经安装的应用程序的快捷图标通过列表显示到桌面上,这些快捷图标就是启动根Activity的入口。当我们点击应用程序的快捷图标时就会调用Launcher的startActivitySafely
方法,下面看一下该方法的具体实现:
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
public class Launcher extends BaseActivity implements ......{
......
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
......
//在新的任务栈中启动
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())) {
//调用startActivity
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;
}
......
}
startActivitySafely方法
中会调用startActivity方法
,该方法是在其父类Activity中实现的,下面就看一下Activity中的startActivity方法
:
frameworks/base/core/java/android/app/Activity.java
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
在startActivity方法
中会调用startActivityForResult方法
,注意第二个参数传递的是-1,表示Launcher不需要知道Activity的启动结果。
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
......
} else {
......
}
}
mParent
表示当前Activity的父类(Activity类型),因为这里说的是根Activity的启动,所以此时mParent == null
条件成立,那么就会调用Instrumentation的execStartActivity方法
,Instrumentation主要用来监控应用程序和系统的交互,下面就看一下它的execStartActivity方法
的实现:
frameworks/base/core/java/android/app/Instrumentation.java
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
......
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
//获取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;
}
在该方法中主要是通过ActivityManager的getService方法
来获取AMS的代理对象,然后再调用它的startActivity方法
。先看一下getService方法
的实现:
frameworks/base/core/java/android/app/ActivityManager.java
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
在Android系统启动过程分析我们知道SystemServer进程以后就会启动各种服务,用于进程间通讯的服务创建后会被添加到ServiceManager中,其中ActivityManagerService对应的key为Context.ACTIVITY_SERVICE
,这样就获取了IBinder类型的AMS的引用,然后将它转换成IActivityManager类型的对象。使用的是AIDL的形式。这样就实现跨进程的通信了:从Launcher进程到AMS所在的进程(SystemServer进程)。
通过上面的分析,最终调用的是AMS的startActivity方法
。
三.AMS到ApplicationThread的调用过程
Launcher请求AMS后,代码逻辑就进入了AMS中,调用了它的startActivity方法
,在该方法中又会调用startActivityAsUser方法
,下面就从该方法开始:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@Override
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) {
//判断调用者进程是否被隔离
enforceNotIsolatedCaller("startActivity");
//检查调用者权限
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startActivity", null);
// 调用startActivityMayWait方法
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null,
"startActivityAsUser");
}
在该方法中会先判断调用者所在的进程是否被隔离已经是否有权限,否则会抛出SecurityException异常,如果没有问题就会调用ActivityStarter的startActivityMayWait方法
,ActivityStarter是Aandroid7.0中新加入的类,它是加载Activity的控制类,会将决定如何将Intent和Flags转换为Activity,并将Activity和Task以及Stack关联。下面就看一下它的startActivityMayWait方法
:
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
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 globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask, String reason) {
......
//inTask : TaskRecord类型的
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);
......
}
int startActivityLocked(......) {
if (TextUtils.isEmpty(reason)) {
throw new IllegalArgumentException("Need to specify a reason.");
}
mLastStartReason = reason;
mLastStartActivityTimeMs = System.currentTimeMillis();
mLastStartActivityRecord[0] = null;
//调用startActivity方法
mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
container, inTask);
if (outActivity != null) {
// mLastStartActivityRecord[0] is set in the call to startActivity above.
outActivity[0] = mLastStartActivityRecord[0];
}
return mLastStartActivityResult;
}
在startActivityMayWait方法
中会调用startActivityLocked方法
,在该方法先判断启动的理由不为空,最后调用的是startActivity方法
:
private int startActivity(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;
// Pull the optional Ephemeral Installer-only bundle out of the options early.
final Bundle verificationBundle
= options != null ? options.popAppVerificationBundle() : null;
ProcessRecord callerApp = null;
//获取Launcher进程
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
//获取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;
}
}
......
//创建即将要启动Activity的描述类ActivityRecord
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;
}
......
doPendingActivityLaunchesLocked(false);
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
options, inTask, outActivity);
}
在该方法中的caller是方法调用一路传递过来的,指向的是Launcher所在的应用程序进程的ApplicationThread对象,先判断该对象是否为空,如果不为空,就会调用AMS的getRecordForAppLocked方法
得到代表Launcher进程的callerApp
对象,它是ProcessRecord类型的,该类型用于描述一个应用程序进程,同样的,ActivityRecord用于描述一个Activity,用来记录一个Activity的所有信息。通过方法传入的各种参数创建用于描述要启动Activity的ActivityRecord类型的对象,然后添加到数组中outActivity
,并将该数组作为参数传递给下面要调用的startActivity方法
,在该方法中会调用startActivityUnchecked方法
,下面就看一下该方法的实现:
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
......
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
//创建新的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)) {
mWindowManager.executeAppTransition();
} else {
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
......
return START_SUCCESS;
}
该方法主要处理与栈管理相关的逻辑,从上面的分析我们知道启动根Activity时会将Intent的Flag设置为FLAG_ACTIVITY_NEW_TASK
,这样方法中的条件就会成立,就会创建新的TaskRecord,是通过setTaskFromReuseOrCreateNewTask方法
来创建的。然后调用ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法
:
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
//获取要启动Activity所在栈的栈顶不是停止状态的ActivityRecord
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
//为空或者不是RESUMED状态
if (r == null || r.state != RESUMED) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.state == RESUMED) {
// Kick off any lingering app transitions form the MoveTaskToFront operation.
mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}
在该方法中,对于即将启动的Activity,条件肯定是满足的,所以就会调用ActivityStack的resumeTopActivityUncheckedLocked方法
,在这个方法中又会调用resumeTopActivityInnerLocked方法
,在这个方法中又会调用ActivityStackSupervisor的startSpecificActivityLocked方法
,下面看一下该方法的实现:
void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {
//获取要启动Activity所在的应用进程
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
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
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);
}
在该方法中,先获取即将启动Activity所在的应用程序进程,如果该应用程序进程(app)已经运行的话,就会调用realStartActivityLocked方法
,该方法传入的第二个参数就是app,看一下该方法的实现:
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,
// 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;
}
app
指的是要启动Activity所在的应用程序进程;app.thread
指的是IApplicationThread,它的实现是ActivityThread的内部类ApplicationThread,该类继承了IApplicationThread.Stub
,然后调用它的
scheduleLaunchActivity方法
,这样代码逻辑就从AMS所在的进程(SystemServer进程)切换到了目标应用程序进程。这个过程使用的是Binder通信。
四.ActivityThread启动Activity的过程
在应用程序进程启动过程分析中我们知道应用程序进程创建后会运行代表主线程的实例ActivityThread,它管理着当前应用程序进程的主线程。下面看一下ApplicationThread的scheduleLaunchActivity方法:
frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread{
......
private class ApplicationThread extends IApplicationThread.Stub {
......
@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);
}
......
}
......
}
在该方法中将要启动Activity的参数封装成ActivityClientRecord,然后调用sendMessage方法
向Handler发送类型为LAUNCH_ACTIVITY
的消息,并将ActivityClientRecord对象传递过去。sendMessage方法
有多个重载,最终调用的sendMessage方法
如下:
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
该方法最终调用的是mH的sendMessage方法
,其中mH指的是H类,它是ActivityThread的内部类并继承自Handler,是应用程序进程中主线程的消息管理类。因为ApplicationThread是一个Binder,它的调用逻辑是在Binder线程池中,所以这里需要用Handler将代码的逻辑切换到主线程中。处理消息的代码逻辑如下:
private class H extends Handler {
......
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;
......
}
......
}
......
}
该消息的处理逻辑主要是:通过getPackageInfoNoCheck方法
获得LoadedApk类型的对象并赋值给ActivityClientRecord的成员变量packageInfo
。应用程序进程要启动Activity时需要将该Activity所属的APK加载进来,而LoadedApk就是用来描述已加载的APK文件。最后调用ActivityThread的handleLaunchActivity方法
。下面看一下该方法的具体实现:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
......
//启动Activity
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
//将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 {
try {
//停止启动Activity
ActivityManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
在该方法中调用ActivityThread的performLaunchActivity方法
来启动Activity,启动成功后将其状态设置为Resume状态,否则调用AMS的finishActivity方法
来停止启动Activity。下面就看一下performLaunchActivity方法
的实现:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
//获取APK文件的描述类LoadedApk
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
......
//获取要启动Activity的上下文环境
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
//用类加载器来创建要启动Activity的实例
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
......
} catch (Exception e) {
......
}
try {
//创建Application
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
......
if (activity != null) {
//初始化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 (r.isPersistable()) {
//启动Activity
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
......
}
r.paused = true;
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
......
}
return activity;
}
该方法主要做了如下几件事情:
- 1.获取ActivityInfo,用于存储代码以及
AndroidManifes
设置的Activity和Receiver等节点信息。 - 2.获取APK文件的描述类LoadedApk。
- 3.获取要启动Activity的ComponentName类,该类中保存类Activity的包名和类名。
- 4.通过类加载器来创建要启动Activity的实例。
- 5.创建Application对象,
makeApplication方法
内部会调用Application的onCreate方法
。 - 6.创建实例后调用Activity的
attach方法
进行初始化。在attach方法
内部会创建Window对象(PhoneWindow)并与自身关联。 - 7.最后调用Instrumentation的
callActivityOnCreate方法
来启动Activity。
下面看一下Instrumentation的callActivityOnCreate方法
代码实现:
frameworks/base/core/java/android/app/Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle,
PersistableBundle persistentState) {
prePerformCreate(activity);
activity.performCreate(icicle, persistentState);
postPerformCreate(activity);
}
可以看出在该方法中调用了activity.performCreate方法
:
frameworks/base/core/java/android/app/Activity.java
final void performCreate(Bundle icicle) {
restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
在该方法中看到了我们最熟悉的方法onCreate方法
,到此根Activity就启动了,也就是应用程序启动了。
五.总结
在上面的分析过程中根Activity的启动过程中会涉及到4个进程,分别是:Zygote进程、Launcher进程、AMS所在进程(SystemServer进程)、应用程序进程。它们的关系如下所示:
网友评论