前言
android应用程序进程的启动介绍完了之后,需要开始学习android应用程序的启动,android的应用程序主要就是包括四大组件:Activity、Service、BroadcastReceiver、ContentProvider,该文主要讲Activity的启动过程,Activity的启动又分为两种:根Activity和普通的Activity,因为根Activity的启动过程是包括普通Activity的,所以我们今天来看下根Activity。
阿简原来有对根Activity过程进行分析过(android 根activity启动源码分析),但是有些东西还是没有很清楚,这次的收获肯定是比上次大的,还是那句话,大家一起学习、一起进步
一:根Activity
根Activity可以理解为:在Launcher界面点击一个APP,此时这个APP进程还不存在,此时AMS通过Soket向Zygote申请创建应用程序的请求,Zygote进程在runSelectLoop方法中监听到AMS发来请求,然后开始fork应用程序进程,成功之后,应用程序启动的第一个Activity。
其原理也是没有很复杂,主要分为三个步骤,我们从这三个大步骤分析就会很清晰:
- 1.Launcher请求ActivityManageService
- 2.ActivityManageService到ApplicationThread的调用流程
- 3.ActivityThread启动Activity的过程
二:框架图
三:Launcher请求ActivityManageService
当我们点击Launcher界面的某个应用时,Launcher界面会调用startActivitySafely方法:
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;
}
会新开启一个任务栈 : intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);然后调用父类Activity的startActivity方法
@Override
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(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
...省略
} else {
...省略
}
}
因为根Activity还没有被创建出来,所以肯定mParent 为null
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
...省略
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;
}
我们抽出重要的部分,可以看到这里调用了ActivityManage的getService方法然后去startActivity
那这个ActivityManager.getService()做了些什么呢
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
我们看下这个IActivityManagerSingleton对象怎么创建的
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;
}
};
看到IActivityManager.Stub.asInterface(b)我们马上就想到了AIDL,AIDL的本质就是Binder机制,记得我们在android 应用程序进程启动过程说过的Zygote进程fork出新的进程后,会调用一个Native方法,把当前线程加入Binder线程池,然后此时新创建的这个应用就可以与SystemServer进程通讯,这里用的原理就是这个
所以ActivityManager其实是AMS的一个代理类,我们可以通过这个类直接调用AMS服务、
这里还需要注意一个点:ActivityManager.getService().startActivity(whoThread,这里传入了一个whoThread对象,这个对象是在Launcher界面的,所以获取到的是Launcher的appThread对象
所以execStartActivity()方法是调用了AMS的startActivity方法
至此,Launcher请求ActivityManageService告一段落
四.ActivityManageService到ApplicationThread的调用流程
这个过程稍显繁琐,阿简认为大致了解过程,记住结论即可
先来说下ApplicationThread,他是ActivityThread类下面的一个内部类,具体后面会说,我们先开始分析,AMS的startActivity做了些什么
如果不是太在意过程的,直接跳到本段最后结论即可
接着上步Instrumentation调用了AMS的startActivity方法,里面又调用了startActivityAsUser,多了一个参数,UserHandle.getCallingUserId(),AMS根据这个可以确定调用者的权限
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
接着调用了ActivityStarter的startActivityMayWait方法
@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);//检查调用者权限
// TODO: Switch to user app stacks here.
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
}
这里没有什么好说的,就是接着往下调用
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,
TaskRecord inTask, String reason) {
...省略
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, inTask,
reason);
...省略
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, TaskRecord inTask, String reason) {
//判断启动的理由不为空
if (TextUtils.isEmpty(reason)) {
throw new IllegalArgumentException("Need to specify a reason.");
}
mLastStartReason = reason;
mLastStartActivityTimeMs = System.currentTimeMillis();
mLastStartActivityRecord[0] = null;
mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
inTask);
if (outActivity != null) {
// mLastStartActivityRecord[0] is set in the call to startActivity above.
outActivity[0] = mLastStartActivityRecord[0];
}
// Aborted results are treated as successes externally, but we must track them internally.
return mLastStartActivityResult != START_ABORTED ? mLastStartActivityResult : START_SUCCESS;
}
然后我们看调用到的startActivity(),这里的caller是从Launcher界面的Instrumation那里一直传过来的,指的是Launcher所在的进程,这里callerApp 指的是Launcher这个界面的Application对象,然后根据各种信息生成了一个ActivityRecord,用于描述一个activity
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, b){
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;
}
//省略...
//ActivityRecord用于描述一个activity
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, options, sourceRecord);
//省略...
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
options, inTask, outActivity);
}
}
接着一路调用到了ActivityStackSupervisor类(frameworks\base\services\core\java\com\android\server\am)的startSpecificActivityLocked方法()
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// 通过activityRecord获取应用程序所在的进程
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
//如果这个进程不为null的话
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) {
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);
}
然后调用了ActivityStackSupervisor类的realStartActivityLocked方法,然后开始进入ActivityThread
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
//这里的app.thread就是ActivityThread类里面的内部类ApplicationThread对象
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
}
AMS-> ApplicationThread这个过程到此结束,是吧,其实也没啥意思,对于我们普通想了解一下的,这个过程过于繁琐,就是一个函数接着调用一个函数,记住的意义不大,记住这个过程做了些什么比较重要
我们直接说结论:
startSpecificActivityLocked方法中获取即将启动的Activity所在的应用程序进程对象ProcessRecord ,scheduleLaunchActivity中的app就是这个对象ProcessRecord ,那么app.thread就是IApplicationThread,其中:
private class ApplicationThread extends IApplicationThread.Stub {
因为刚才又说了ApplicationThread 是ActivityThread的内部类,所以这段代码就是要在目标的应用进程启动Activity的,代码逻辑运行在AMS当中(就是SystemServer进程中)
至此,ActivityManageService到ApplicationThread的调用流程告一段落
五.ActivityThread启动Activity的过程
在上一步中,我们有说过,ApplicationThread在AMS进程当中(就是SystemServer进程),然而ActivityThread在当前应用程序的“主线程”中,我们要通讯的话,肯定是不能直接通讯的,这里是通过handler去实现的,我们接着分析
我们先看下上一步最后调用的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) {
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);
}
这里我们看到创建了一个ActivityClientRecord 对象,然后发送了一个Message,并把ActivityClientRecord 对象传入
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;//1
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);//2
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");//3
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case RELAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
handleRelaunchActivity(r);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
}
PS:这里要说一点很重要的就是:ActivityThread这里有个继承了Handler的H类,AMS和app通讯都是通过发送Handler的形式
private class H extends Handler {
所以我们看下handleLaunchActivity做了些什么:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
Activity a = performLaunchActivity(r, customIntent);//1
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);//1
if (!r.activity.mFinished && r.startsNotResumed) {
performPauseActivityIfNeeded(r, reason);
if (r.isPreHoneycomb()) {
r.state = oldState;
}
}
} else {
try {
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
最先调用了performLaunchActivity方法返回了一个Activity对象
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
ActivityInfo aInfo = r.activityInfo;//1
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
...
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);//2
...
}
} catch (Exception e) {
...
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);//3
...
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
...
}
/**
*7
*/
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);//4
...
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);//5
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
}
return activity;
}
我们来逐步分析下以上注释的的点分别做了些什么:
注释1:用来获取ActivityInfo,用于存储代码以及AndroidMainfests.xml设置的Activity和Receiver节点信息,比如Activity的theme和LauncherMode
注释2:用类加载器创建Activity实例
注释3:创建Applicaiton对象,makeApplication中会调用application的onCreate方法
注释4:调用Activity的attach方法,这个方法主要创建了PhoneWindow
注释5:主要通过mInstrumentation.callActivityOnCreated调用了Activity的onCreate方法
所以这里就有一个顺序:
Application的oncreate()-> Activity的attach()->Activity的onCreate()
至此:ActivityThread启动Activity的过程就告一段落
六.根Activity和普通Activity有什么区别
从以上流程我们其实不难看出,根Activity的启动流程其实涉及4个进程:Zygote进程、Launcher进程、AMS所在的进程(SystemServer进程)、应用程序进程
普通Activity其实只涉及两个进程:AMS所在的进程、应用程序进程
END
最近看到黑泽明先生说的一段话,很有感触、共勉