根Activity的啟動過程
《安卓進階解密》讀書筆記
這裡分析的原始碼基於android-8.0.0_r4.
「根Activity的啟動過程」和「Activity的啟動_5.0」筆記記錄的,有大部分過程是一樣的.
概述
根Activity
啟動過程中設計到的程序及其互動
時序圖如下
這裡將根Activity
的啟動劃分為四部分
- Launcher請求AMS過程
- AMS判斷根
Activity
所需的應用程式程序是否已經存在並啟動,若不存在,則請求Zygote
程序建立應用程式程序,詳情檢視《應用程式程序啟動過程》的筆記。應用程式程序啟動後,則進入下一個步驟 - AMS到ApplicationThread的呼叫過程
- ActivityThread啟動Activity的過程
這裡先看下第2部分,為什麼會存在根Activity
所需的應用程序已經啟動的情況呢?比如現在要寫一個音樂播放器App,第一次開啟這個App,那麼應用程序當然是未啟動的,這時候為了啟動根Activity
,就需要先啟動應用程式程序,再啟動根Activity
,現在它們都啟動完畢,並且運行了一段時間,現在在程式中播放一首歌曲,音樂播放器放在Service中管理,現在按返回鍵,銷燬所有的Activity,銷燬完之後,會發現音樂還在播放,這時候雖然Activity都被銷燬了,但是程序還是存活的,並且Service還是存活的,音樂仍然在播放,那麼這時候,如果點選應用程式的快捷圖示,將會啟動根Activity
Activity
所需的應用程序已經啟動的情況。
另外,好像沒有找到在哪裡判斷的「根
Activity
所需的應用程式程序是否已經存在並啟動」的程式碼,是在ActivityStackSupervisor::startSpecificActivityLocked
當中嗎?
後面會講解其餘的三個部分。
相關類介紹
Instrumentation
:儀表盤,具體到應用程式中是管理Activity
的一個工具類,包括建立和啟動Activity
,Activity
的生命週期方法都是由Instrumentation
來控制的,一個程序只用一個Instrumentation
例項
ActivityManagerService
Android
中最核心的服務,主要負責系統中四大元件的啟動、切換、排程及應用程式的管理和排程等工作
ActivityThread
:管理應用程式程序中主執行緒的執行,根據Activity
管理者的請求排程和執行activities
、broadcasts
及其相關的操作
ApplicationThread
:用來實現ActivityManagerService
和ActivityThread
之間的互動,是ActivityThread
的內部類
ActivityStack
:負責單個Activity
棧的狀態和管理
ActivityStackSupervisor
:負責所有Activity棧的管理
ActivityStarter
:Android 7.0新加入的類,它是載入Activity的控制類
H
:ActivityThread
的內部類,繼承至Handler
,是應用程式程序中主執行緒的訊息管理類
ProcessRecord:用於描述一個應用程式程序
ActivityRecord:用於描述一個Activity,用來記錄一個Activity的所有資訊
TaskRecord:用於描述一個任務棧
LoadedApk:用來描述已載入的APK檔案
Activity
:變數說明
mMainThread
:ActivityThread
mMainThread.getApplicationThread()
:ApplicationThread
ApplicationThread
是ActivityThread
的一個內部類,這兩個類在Activity
啟動的過程中都發揮著重要的作用
IBinder
這裡簡單說明根Activity
啟動時涉及到的Binder
類、Binder
介面,這部分內容在《Activity的啟動_5.0》筆記中有記錄過,但是Android 8.0之前,IActivityManager
以及IApplicationThread
的定義宣告等並沒有採用AIDL的形式,而是一種類似AIDL的形式,在Android 8.0中,採取的是一種AIDL的形式
Android 5.0的筆記
IActivityManager:
//Binder介面
public interface IActivityManager extends IInterface {...}
//Binder類,相當於Stub
public abstract class ActivityManagerNative extends Binder implements IActivityManager{.}
//Binder類的具體實現
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {...}
//Binder類的本地代理,相當於Proxy,定義在ActivityManagerNative裡面,不同程序下,通過 //ActivityManagerNative的asInterface,即可將AMS「繼承至Stub」轉化為ActivityManagerProxy //「Proxy」
class ActivityManagerProxy implements IActivityManager{...}
IApplicationThread:
//Binder介面
public interface IApplicationThread extends IInterface {...}
//Binder類,相當於Stub
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread {}
//繼承至Binder類,也就說這個相當於是Binder類的真正實現,相當於上面AMS的aidl邏輯分析中的Binder_1
private class ApplicationThread extends ApplicationThreadNative {...}
//代理物件如下,定義在ActivityThreadNative裡面
class ApplicationThreadProxy implements IApplicationThread {...}
Android 8.0的變化
原始碼地址:IActivityManager.java.
public interface IActivityManager extends android.os.IInterface{
...
public static abstract class Stub extends android.os.Binder implements
android.app.IActivityManager{
...
private static class Proxy implements android.app.IActivityManager{
...
}
}
}
原始碼地址:ActivityManagerService.java.
public class ActivityManagerService extends IActivityManager.Stub...{
...
}
形式上和《Android 開發藝術探索》介紹的一樣。Android 8.0
去除了ActivityManagerNative
的內部類ActivityManagerProxy
,代替它的是IActivityManager.Stub.Proxy
;ActivityManagerService
繼承至IActivityManager.Stub
IApplicationThread
應該也是這樣。另外,ApplicationThread
是ActivityThread
的內部類
這裡沒有去找原始碼,所以只能說應該,沒找原始碼是因為aidl檔案,是在編譯的時候才轉化為.java檔案,原始碼怎麼找嘛~~
PS:IActivityManager.java是通過程式碼的跳轉連結找到的~~
Launcher請求AMS過程
當我們點選某個應用程式的快捷圖示時,就會通過Launcher請求AMS來啟動該應用程式,也就是啟動根Activity,時序圖如下
首先檢視Launcher
的繼承關係
public class Launcher extends BaseActivity implements ... {...}
public abstract class BaseActivity extends Activity {...}
可以看出,Launcher
就是Activity
的子類.
首先是Launcher
的startActivitySafely
方法
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
...
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//該Flag表明根Activity會在新的任務棧啟動
...
startActivity(intent, optsBundle);
...
}
呼叫父類Activity
的startActivity
方法
public void startActivity(Intent intent, @Nullable Bundle options) {
...
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
這裡出現了startActivityForResult
方法的兩個過載,兩個引數的那個方法,最終會呼叫到三個引數的,如下
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
這裡檢視三個引數的startActivityForResult
方法
# requestCode:如果requestCode >= 0,該Activity銷燬時,requestCode值會返回到
# onActivityResult方法裡
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 {
...
}
}
-
Activity mParent
代表的是ActivityGroup
,ActivityGroup
最開始被用來一個介面中嵌入多個子Activity
,後來在API 13
中被廢棄了,使用Fragment
代替,所以這裡只用看mParent == null
的邏輯 -
這裡傳入的
requestCode
的值為-1,表明Launcher
不需要知道Activity
啟動的結果
接著檢視Instrumentation
的execStartActivity
方法
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...
try {
...
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
的本地代理,遠端呼叫AMS
的startActivity
,首先檢視ActivityManager.getService()
方法
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;
}
};
這裡通過單例類Singleton
獲取AMS的本地代理,Android 8.0之前 是通過ActivityManagerNative
的getDefault
來完成的,Android 8.0則將該邏輯封裝到了ActivityManager
當中
程序切換:Launcher程序 -> AMS所在程序(SystemServer程序)
AMS -> ApplicationThread
接下來的邏輯就進入了AMS所在程序.
時序圖如下
下面只列舉出幾個重要的方法
首先是ActivityStarter
的幾個方法,先說一下ActivityStarter
這個類,Android 7.0新加入的,是載入Activity的控制類,它會收集所有的邏輯,來決定如何將Intent
和Flags
轉換為Activity
,並將Activity
和Task
以及Stack
相關聯.
ActivityStarter::startActivity
,這裡講解的是第一個startActivity
方法
private int startActivity(IApplicationThread caller ...) {
...
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
...
}
...
//建立即將要啟動的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);
//outActivity:ActivityRecord[]型別
if (outActivity != null) {
outActivity[0] = r;
}
}
-
caller:方法呼叫一路傳來,是
Launcher
程序的Instrumentation::execStartActivity
傳來的,指向的是Launcher
程序的ApplicationThread
物件 -
callerApp:代表
Launcher
程序的ProcessRecord
物件
ActivityStarter::startActivityUnchecked
,該方法主要處理與棧管理相關的邏輯
private int startActivityUnchecked(...){
...
//1.
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
//2.
result = setTaskFromReuseOrCreateNewTask(
taskToAffiliate, preferredLaunchStackId, topStack);
}
...
//3.
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
-
註釋1:在
Luncher::startActivitySafely
中,會為根Activity的Intent
設定FLAG_ACTIVITY_NEW_TASK
的Flag
,在註釋1中可以進入If語句 -
註釋2:內部會建立一個新的Activity任務棧,建立一個新的
TaskRecord
-
註釋3:呼叫
ActivityStackSupervisor::resumeFocusedStackTopActivityLocked
ActivityStackSupervisor::startSpecificActivityLocked
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
//1.獲取即將啟動的Activity的所在的應用程式程序
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
//2.
if (app != null && app.thread != null) {
try {
...
//3.
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.
}
// 如果程序不存在,則通過zygote建立應用程序
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
- 註釋2:
app
指的是即將啟動的Activity的所在的應用程式程序;app.thread
的型別是IApplicationThread
,它的實現是要啟動的Activity所在的應用程式程序的ActivityThread
的內部類ApplicationThread
,ApplicationThread
繼承了IApplication.Stub
,這裡app.thread
得到的是ApplicationThread
在SystemServer
程序的代理 - 註釋3:呼叫自身的
realStartActivityLocked
方法
ActivityStackSupervisor::realStartActivityLocked
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,
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.thread
的scheduleLaunchActivity
,也就是呼叫應用程式程序的ApplicationThread
的scheduleLaunchActivity
方法
程序切換:AMS所在程序(SystemServer程序) -> 即將啟動的Activity所在的應用程式程序
ActivityThread啟動Activity的過程
目前程式碼邏輯執行在應用程式程序,時序圖如下
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);
//將啟動Activity的引數封裝成ActivityClientRecord
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
...
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
向H
類傳送型別為H.LAUNCH_ACTIVITY
的訊息,並將ActivityClientRecord
傳遞過去,H
類是ActivityThread
的內部類,繼承至Handler
,是應用程式程序中主執行緒的訊息管理類
ActivityThread::sendMessage
private 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);
}
由於ApplicationThread
是一個Binder
,它的呼叫邏輯執行在Binder
執行緒池中,因此這裡通過H
,將程式碼邏輯切回主執行緒.
執行緒切換:應用程式Binder執行緒 -> 應用程式主執行緒
H::handleMessage
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;
//1.
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
//2.
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
}
...
}
}
- 註釋1:獲取LoadedApk型別的物件賦值給
ActivityClientRecord
的packageInfo
,應用程式程序要啟動Activity時需要將該Activity所屬的APK載入進來,而LoadApk就是用來描述已載入的APK檔案的 - 呼叫
ActivityThread::handleLaunchActivity
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為null,則通知AMS停止啟動Activity
ActivityManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
ActivityThread::performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//1.獲取ActivityInfo類
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
//2.獲取APK檔案的描述類LoadedApk
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
//3.獲取要啟動的Activity的ComponentName
//ComponentName儲存了該Activity的包名和類名
ComponentName component = r.intent.getComponent();
...
//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);
...
} catch (Exception e) {
...
}
try {
//6.嘗試建立Application,makeApplication內部會呼叫Application的onCreate
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
...
if (activity != null) {
...
appContext.setOuterContext(activity);
//7.初始化Activity
//內部包括建立PhoneWindow與Activity自身關聯;關聯ContextImpl...
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()) {
//8.呼叫Instrumentation::callActivityOnCreate啟動Activity
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
...
}
return activity;
}
註釋4:建立Activity
的上下文環境
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
...
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
...
return appContext;
}
在Activity
的attach
中會將ContextImpl
進行關聯
註釋6:嘗試建立Application,r.packageInfo
的型別是LoadedApk
,LoadedApk::makeApplication
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
// 如果Application已經被建立過了,那麼就不會再重複建立了,這意味著一個應用程序只有
// 一個Application物件
if (mApplication != null) {
return mApplication;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
Application app = null;
...
try {
java.lang.ClassLoader cl = getClassLoader();
...
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
// Application物件的建立通過Instrumentation來完成,內部通過類載入器來實現
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
...
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
// 這裡面會呼叫Application的onCreate()方法
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
...
}
}
...
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
return app;
}
回到ActivityThread
的performLaunchActivity
中,呼叫了Instrumentation::callActivityOnCreate
public void callActivityOnCreate(Activity activity, Bundle icicle,
PersistableBundle persistentState) {
prePerformCreate(activity);
activity.performCreate(icicle, persistentState);
postPerformCreate(activity);
}
Activity::performCreate
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle, persistentState);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
Activity::onCreate
public void onCreate(@Nullable Bundle savedInstanceState,
@Nullable PersistableBundle persistentState) {
onCreate(savedInstanceState);
}
呼叫到了void onCreate(@Nullable Bundle savedInstanceState) {...}
,至此,根Activity
就啟動了,即應用程式就啟動了
可以結合《Activity的啟動_5.0》的筆記一起看,那裡關於一些細節記錄得更詳細一些~~
參考
《安卓進階解密》