概述
當你點選桌面App的圖示到底發生了什麼,上篇文章我們大概簡述了流程
- App發起程式:如果從桌面啟動應用,則發起程式便是
Launcher
所在的程式,當從某App啟動遠端程式,則發起程式是App所在的程式,發起程式首先需要通過Binder
傳送資訊給system_server
程式 - system_server程式:呼叫
Process.start
方法,通過Socket
向Zygote
程式傳送新建程式的請求 - zygote程式:在執行
ZygoteInit.main()
後進入runSelectLoop()
迴圈體,當有客戶端連線時,便會執行ZygoteConnection.runOnce()
方法,再經過層層呼叫後fork
出新的應用程式 - 新程式:執行
handleChildProc
方法,設定程式名,開啟binder驅動,啟動新的binder執行緒,設定art虛擬機器引數,反射目標類的main
方法,即呼叫ActivityThread.main()
方法
這次我們來詳細的分析一下原始碼,基於API 27
1.Launcher
當你點選桌面上的App圖示,Launcher捕獲點選事件,其過程為Launcher#onClick
-> Launcher#onClickAppShortcut
->Launcher#startAppShortcutOrInfoActivity
->Launcher#startActivitySafely
-> Activity#startActivity
最終呼叫了 startActivity(intent, optsBundle);
方法
下面我們從startActivity(intent, optsBundle);
方法開始分析呼叫流程
2.Activity.startActivity
上方我們說到了Activity.startActivity
,點進原始碼發現呼叫的是Activity#startActivityForResult
,其中還呼叫到了Instrumentation#execStartActivity
這個方法,原始碼如下
@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);
}
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
...
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
...
}
複製程式碼
3.Instrumentation.execStartActivity
在Instrumentation.execStartActivity
中,我們發現他呼叫了ActivityManager#getService()#startActivity
,其中ActivityManager#getService()
返回的是IActivityManager
型別的Binder物件,他的具體實現在ActivityManagerService
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, String target,
Intent intent, int requestCode, Bundle options) {
...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target, requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
ActivityManager原始碼
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;
}
};
複製程式碼
4.ActivityManagerService.startActivity
我們檢視ActivityManagerService.startActivity
原始碼,發現他呼叫了ActivityManagerService#startActivityAsUser
,該方法又呼叫了ActivityStarter#startActivityMayWait
原始碼如下
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());
}
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");
}
複製程式碼
5.ActivityStarter.startActivityMayWait
我們檢視ActivityStarter.startActivityMayWait
原始碼發現他呼叫了ActivityStarter#startActivityLocked
,接著是ActivityStarter#startActivity
,然後是ActivityStarter#startActivityUnchecked
,其中呼叫了ActivityStackSupervisor#resumeFocusedStackTopActivityLocked
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) {
...
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) {
...
mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
inTask);
}
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, TaskRecord inTask) {
...
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
options, inTask, outActivity);
}
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
...
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
...
}
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
...
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
...
}
複製程式碼
6.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked
我們檢視ActivityStackSupervisor.resumeFocusedStackTopActivityLocked
他呼叫了ActivityStack#resumeTopActivityUncheckedLocked
,然後是ActivityStack#resumeTopActivityInnerLocked
,接著又回到了ActivityStackSupervisor.java
,呼叫了ActivityStackSupervisor#startSpecificActivityLocked
,這個方法要判斷啟動的App程式是否存在,存在就直接啟動Activity,如果不存在就把程式建立出來
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
...
if (app != null && app.thread != null) {
...
// 如果程式已存在,則通知程式啟動元件
realStartActivityLocked(r, app, andResume, checkConfig);
return;
...
}
// 否則先將程式建立出來
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
...
}
複製程式碼
7.mService.startProcessLocked
我們這裡分析程式不存在的情況,這裡的mService
指的是ActivityManagerService
,我們檢視ActivityManagerService#startProcessLocked
原始碼如下
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
...
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, entryPointArgs);
...
}
複製程式碼
最終呼叫Process.start
來開啟新程式,這個程式的入口就會在android.app.ActivityThread.java
的main
方法,我們下面繼續分析ActivityThread#main
8.ActivityThread#main
ActivityThread#main
方法其中呼叫了ActivityThread#attach
方法,這個方法中的ActivityManager.getService()
返回的是IActivityManager
型別的Binder
物件,其實現類是ActivityManagerService
,原始碼如下
public static void main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
...
Looper.loop();
...
}
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
...
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
...
}
...
}
...
}
複製程式碼
現在我們又回到了ActivityManagerService
中,檢視其attachApplication
方法,發現呼叫了thread#bindApplication
和mStackSupervisor#attachApplicationLocked
,我們一次講解這倆個方法作用
public final void attachApplication(IApplicationThread thread) {
...
attachApplicationLocked(thread, callingPid);
...
}
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
....
thread.bindApplication(processName, appInfo, providers,
app.instr.mClass,
profilerInfo, app.instr.mArguments,
app.instr.mWatcher,
app.instr.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial);
...
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
...
}
}
...
}
複製程式碼
9.thread#bindApplication
上面說到的thread#bindApplication
中的thread
型別是ApplicationThread
,是ActivityThread
的一個內部類,繼承自IApplicationThread.Stub
,我們檢視ApplicationThread#bindApplication
方法,我發現呼叫了ActivityThread#sendMessage
方法,它內部呼叫mH.sendMessage
來傳送訊息,其中mH
是ActivityThread
的一個內部類H
的一個例項
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial) {
...
sendMessage(H.BIND_APPLICATION, data);
}
void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}
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);
}
複製程式碼
10.H.handleMessage
我們來看一下H這個內部類的handleMessage,最終走到了ActivityThread#handleBindApplication方法
public void handleMessage(Message msg) {
...
switch (msg.what) {
...
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
}
複製程式碼
11.ActivityThread#handleBindApplication
從原始碼中我們發現,他首先建立了mInstrumentation
物件,呼叫data#info#makeApplication
來建立Application
物件,其中data#info
代表的是LoadedApk
的一個例項,檢視LoadedApk#makeApplication
方法可以看到,內部呼叫了Instrumentation#newApplication
方法,這個方法內部呼叫Class#newInstance()
來完成對Application
的例項化,然後呼叫Application#attach(context)
來繫結Context
上面建立完Application
後,就呼叫Instrumentation#callApplicationOnCreate
走Application
的onCreate
生命週期,原始碼如下
private void handleBindApplication(AppBindData data) {
...
final InstrumentationInfo ii;
...
// 建立 mInstrumentation 例項
if (ii != null) {
final ApplicationInfo instrApp = new ApplicationInfo();
ii.copyTo(instrApp);
instrApp.initForUser(UserHandle.myUserId());
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
try {
final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
...
}
...
} else {
mInstrumentation = new Instrumentation();
}
...
Application app;
...
// 建立 Application 例項
try {
...
app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
...
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
...
}
} finally {
...
}
...
}
// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/LoadedApk.java#959
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
...
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
...
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {// 傳入為 null 所以不走
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
...
}
}
...
return app;
}
// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/Instrumentation.java#1084
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return newApplication(cl.loadClass(className), context);
}
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}
複製程式碼
12.mStackSupervisor#attachApplicationLocked
上面說完了thread#bindApplication
這個方法,下面我們繼續說mStackSupervisor#attachApplicationLocked
這個方法,其mStackSupervisor
是ActivityStackSupervisor
的一個例項,我們檢視ActivityStackSupervisor#attachApplicationLocked
方法發現其中呼叫了ActivityStackSupervisor#realStartActivityLocked
,這個方法呼叫了app#thread#scheduleLaunchActivity
,原始碼如下
// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#956
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
...
if (realStartActivityLocked(activity, app,
top == activity /* andResume */, true /* checkConfig */)) {
...
}
...
}
// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#1313
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);
...
}
複製程式碼
12.app#thread#scheduleLaunchActivity
上面說到app#thread#scheduleLaunchActivity
,這個裡面的thread
是IApplicationThread
,他的實現類是ActivityThread#ApplicationThread
,我們檢視ActivityThread#ApplicationThread#scheduleLaunchActivity
方法中的程式碼,發現最終是傳送了LAUNCH_ACTIVITY
的訊息,傳送訊息我們再9 ,10步驟中分析過,我們直接檢視處理訊息的程式碼,在 H#handleMessage
方法中,我們可以看到他會接收並處理很多四大元件的相關操作,我們檢視 LAUNCH_ACTIVITY
的處理,發現其處理方法是呼叫了ActivityThread#handleLaunchActivity
,這個方法再次涉及到了Instrumentation類
,之前建立Application
的時候用到了他,如今建立Activity
也用到了他,其中Instrumentation#newActivity
是通過 Class.newInstance()
來例項化Activity
,例項化完成後回到ActivityThread#performLaunchActivity
中,讓Activity
依附到window中,然後callActivityOnCreate走Activity
的onCreate
的生命週期,涉及到的原始碼如下
// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#756
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) {
...
sendMessage(H.LAUNCH_ACTIVITY, r);
}
// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#1580
public void handleMessage(Message msg) {
...
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;
...
}
}
// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#2833
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
Activity a = performLaunchActivity(r, customIntent);
...
}
// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#2644
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
...
} catch (Exception e) {
...
}
try {
// 返回之前建立過的 application 物件
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
...
if (activity != null) {
...
// attach 到 window 上
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()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
}
} catch (Exception e) {
...
}
return activity;
}
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
複製程式碼
總結
概述一下大致流程
- 首先是點選App圖示,此時是執行在
Launcher
程式,通過ActivityManagerService
Binder IPC的形式向system_server
程式發起startActivity
的請求 system_server
程式接收到請求後,通過Process.start
方法向zygote
程式傳送建立程式的請求zygote
程式fork
出新的子程式,即App
程式- 然後進入
ActivityThread.main
方法中,這時執行在App
程式中,通過ActivityManagerService
Binder IPC的形式向system_server
程式發起attachApplication
請求 system_server
接收到請求後,進行一些列準備工作後,再通過Binder IPC向App
程式傳送scheduleLaunchActivity
請求App
程式binder執行緒(ApplicationThread)
收到請求後,通過Handler
向主執行緒傳送LAUNCH_ACTIVITY
訊息- 主執行緒收到Message後,通過反射機制建立目標
Activity
,並回撥Activity
的onCreate