Activity的創建特點
作為四大組件之一的Activity,它不像普通java對像那樣,可以new出來,然后去使用。而是調用
startActivity()這樣的方式啟動。那么Android系統是如何創建并啟動Activity的呢?本文就來
一探究竟。
NOTE:本文內容就是對老羅《Android系統源代碼情景分析》章節的簡化筆記。
因為涉及到不同進程間的通信,所以分析流程的過程中會在不同的源代碼文件之間跳轉,源碼為Android 2.3版本,下載系統源碼后,可以使用像Everything這樣的軟件根據類名對文件進行快速查找。
Launcher啟動App
任何安裝的應用幾乎都是點擊桌面上的圖標被啟動。
接下來以Launcher程序啟動一個App的過程作為案例。要啟動的App的包名為com.idlestar.bot
,其入口Activity為MainActivity。
Task和Back Stack
即便沒有了解過Activity的啟動過程、ActivityManagerService(簡稱AMS,它是運行在系統進程SystemServer中的系統關鍵服務)這些知識點,對任務(Task)和回退棧(Back Stack)的概念、Activity啟動模式等多少都回了解。接下來可以在源碼級稍微感受到它們的真實表現。
Task
用戶完成一個任務時,可能和若干相關的Activity組件進行交互,這些相關的Activity的集合被稱作一個Task,由TaskRecord對象表示。Task中所有Activity形成一個stack結構,以它們的啟動順序被添加。
ActivityStack
實際上在系統中,每一個Activity組件實例被使用一個ActivityRecord對像表示,所有的Activity組件都保存在一個ActivityStack對象的字段ArrayList mHistory
中。ActivityRecord.task字段表示其所在Task。假設把所有Activities指定編號:a0,a1,a2...an,表示mHistory中從第0,1,2...n個Activity,那么,Task就是從a0到an中連續的一個個“子序列”,一個Task包括1或多個Activity。Task中的Activity的“棧結構”是通過ArrayList間接實現的
命令adb shell dumpsys activity
可以查看當前系統中運行的Activities的信息。在啟動MainActivity的前后,可以運行命令來查看有關的Activities的信息。
啟動MainActivity前,顯示Launcher時:
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Stack #0:
Task id #1
TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
...
ProcessRecord{529e7b24 735:com.android.launcher/u0a8}
Running activities (most recent first):
TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
Run #0: ActivityRecord{529e66bc u0 com.android.launcher/com.android.launcher2.Launcher t1}
...
Recent tasks:
* Recent #0: TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
上面的信息有點像Json那種格式,縮進表示了信息的分組。
先是Stack #0
這種劃分,#跟數字表示序號。Stack #0
是整個ActivityStack中的第一個Task。
此時,只有一個Task——Stack #0
。
其Task id
為#1,即任務id=1。
而Running activities是Task所包含的運行中的Activity的信息,最近使用的排在前面。Run #0
顯示了正在運行的第一個也是唯一一個ActivityRecord,就是Launcher組件。
點擊App圖標,打開MainActivity之后:
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Stack #0:
Task id #1
TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
...
ProcessRecord{529e7b24 735:com.android.launcher/u0a8}
Running activities (most recent first):
TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
Run #0: ActivityRecord{529e66bc u0 com.android.launcher/com.android.launcher2.Launcher t1}
Stack #1:
Task id #2
TaskRecord{52a203f8 #2 A=com.idlestar.bot U=0 sz=1}
...
ProcessRecord{529704e8 3307:com.idlestar.bot/u0a82}
...
Running activities (most recent first):
TaskRecord{52a203f8 #2 A=com.idlestar.bot U=0 sz=1}
Run #0: ActivityRecord{5296eea0 u0 com.idlestar.bot/.MainActivity t2}
...
Recent tasks:
* Recent #0: TaskRecord{52a203f8 #2 A=com.idlestar.bot U=0 sz=1}
* Recent #1: TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
可以看到此時多了一個Task Stack #1
,它在是棧頂位置(#序號最大的),它對應的ActivityRecord為MainActivity,正是當前處在前臺(foreground)被顯示的Activity。
上面啟動MainActivity前后,看到Launcher和MainActivity屬于不同的Task,因為Launcher為啟動的MainActivity指定了NEW_TASK。
啟動過程跟蹤
自己的App會運行在一個包名對應的進程中,這點常識這里不去解釋。
MainActivity是Launcher啟動的,而Launcher是通過AMS來啟動MainActivity的。它們分別運行在不同的進程中,整個過程中它們之間使用Binder完成跨進程通信。
NOTE:源代碼為android系統2.3。
下面是完整的過程,非重要部分會很簡單地描述下,保證流程完整性。
階段1:Launcher通知AMS啟動MainActivity。
Launcher向ActivityManagerService發送一個啟動MainActivity組件的進程間通信請求。
系統啟動時,會啟動PackageManagerService服務,簡稱PMS,通過它安裝系統中的應用程序。
第一個啟動的就是Launcher,Launcher向PMS查詢所有App的AndroidManifest.xml獲得所有App
的圖標,啟動Activity組件(Action為Intent.ACTION_MAIN,Category為Intent.CATEGORY_LAUNCHER)的全名。
用戶點擊桌面App圖標后,Launcher根據對應App的信息,創建一個啟動它的intent,并調用startActivity()來啟動它。
不同android版本中Launcher的代碼會稍有差異,但基本過程是類似的。
方法調用過程,對傳遞調用不加說明,直接繼續給出所調用的方法:
step 1:Launcher.startActivitySafely()
void startActivitySafely(Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
...
默認為intent添加了FLAG_ACTIVITY_NEW_TASK標志。
step 2:Activity.startActivity(intent)
step 3:Activity.startActivityForResult(intent, -1)
參數requestCode = -1表示不處理onActivityResult()
// set by the thread after the constructor and before onCreate(Bundle savedInstanceState) is called.
private Instrumentation mInstrumentation;
void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
...
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
...
}
step 4:Instrumentation.execStartActivity()
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode) {
...
try {
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
null, 0, token, target != null ? target.mEmbeddedID : null,
requestCode, false, false);
...
}
ActivityManagerNative.getDefault()獲得的是AMS的一個代理對像,類型為IActivityManager。
/**
* Retrieve the system's default/global activity manager.
*/
static public IActivityManager getDefault()
{
if (gDefault != null) {
//if (Config.LOGV) Log.v(
// "ActivityManager", "returning cur default = " + gDefault);
return gDefault;
}
IBinder b = ServiceManager.getService("activity");
if (Config.LOGV) Log.v(
"ActivityManager", "default service binder = " + b);
gDefault = asInterface(b);
if (Config.LOGV) Log.v(
"ActivityManager", "default service = " + gDefault);
return gDefault;
}
asInterface(b):
/**
* Cast a Binder object into an activity manager interface, generating
* a proxy if needed.
*/
static public IActivityManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
以上2個方法是典型的Binder通信方式,將一個和遠程進程通信的IBinder轉為通信定義的接口類型。最終getDefault()返回的就是ActivityManagerProxy對像。
step 5:ActivityManagerProxy.startActivity()
public int startActivity(IApplicationThread caller, Intent intent,
String resolvedType, Uri[] grantedUriPermissions, int grantedMode,
IBinder resultTo, String resultWho,
int requestCode, boolean onlyIfNeeded,
boolean debug) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
intent.writeToParcel(data, 0);
data.writeStrongBinder(resultTo);
...
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
上面使用IBinder.transact()對系統進程中的AMS執行遠程調用:START_ACTIVITY_TRANSACTION。
- 參數
caller:指向Launcher組件所在的應用程序進程的ApplicationThread對像。
intent:包含了要啟動的MainActivity組件的信息。
resultTo:指向AMS內部的一個ActivityRecord對像,它保存了Launcher組件的信息。
/**
* An entry in the history stack, representing an activity.
*/
class ActivityRecord extends IApplicationToken.Stub {
}
NOTE:在多進程交互的環境下,IBinder對像可以是一個進程中供其它進程訪問的“可遠程訪問”對像的一個BinderProxy代理。跨進程引用一個對象的作用。
以上step操作發生在Launcher應用中,其方法調用流程圖:
階段2:AMS保存啟動信息,通知caller進入stop
接下來的操作在AMS中進行,處理Launcher發起的START_ACTIVITY_TRANSACTION請求。
AMS首先將要啟動的MainActivity組件的信息保存起來,然后再向Launcher組件發送一個進入中止狀態的進程間通信請求。
step 6:ActivityManagerService.startActivity()
AMS繼承ActivityManagerNative,其onTransact()方法中,對code = START_ACTIVITY_TRANSACTION的處理是調用接口方法IActivityManager.startActivity()
,AMS實現了startActivity():
public ActivityStack mMainStack;
public final int startActivity(IApplicationThread caller,
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo,
String resultWho, int requestCode, boolean onlyIfNeeded,
boolean debug) {
return mMainStack.startActivityMayWait(caller, intent, resolvedType,
grantedUriPermissions, grantedMode, resultTo, resultWho,
requestCode, onlyIfNeeded, debug, null, null);
}
step 7:ActivityStack.startActivityMayWait()
final int startActivityMayWait(IApplicationThread caller,
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo,
String resultWho, int requestCode, boolean onlyIfNeeded,
boolean debug, WaitResult outResult, Configuration config) {
...
// Collect information about the target of the Intent.
ActivityInfo aInfo;
try {
ResolveInfo rInfo =
AppGlobals.getPackageManager().resolveIntent(
intent, resolvedType,
PackageManager.MATCH_DEFAULT_ONLY
| ActivityManagerService.STOCK_PM_FLAGS);
aInfo = rInfo != null ? rInfo.activityInfo : null;
...
int res = startActivityLocked(caller, intent, resolvedType,
grantedUriPermissions, grantedMode, aInfo,
resultTo, resultWho, requestCode, callingPid, callingUid,
onlyIfNeeded, componentSpecified);
...
}
方法先通過PackageManager根據啟動intent獲得關于MainActivity組件的更多信息,保存在變量ActivityInfo aInfo中。繼續調用startActivityLocked()。
step 8:ActivityStack.startActivityLocked()
final ActivityManagerService mService;
/**
* The back history of all previous (and possibly still
* running) activities. It contains HistoryRecord objects.
*/
final ArrayList mHistory = new ArrayList();
...
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType,
Uri[] grantedUriPermissions,
int grantedMode, ActivityInfo aInfo, IBinder resultTo,
String resultWho, int requestCode,
int callingPid, int callingUid, boolean onlyIfNeeded,
boolean componentSpecified) {
...
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
...
ActivityRecord sourceRecord = null;
...
int index = indexOfTokenLocked(resultTo);
...
sourceRecord = (ActivityRecord)mHistory.get(index);
ActivityRecord r = new ActivityRecord(mService, this, callerApp,
callingUid,intent, resolvedType, aInfo, mService.mConfiguration,
resultRecord, resultWho, requestCode, componentSpecified);
...
return startActivityUncheckedLocked(r, sourceRecord,
grantedUriPermissions, grantedMode, onlyIfNeeded, true);
}
AMS內部使用ProcessRecord對象表示每一個應用程序進程,getRecordForAppLocked獲得caller對應的ProcessRecord callerApp,也就是Launcher的進程信息。
mHistory正是用來保存所有已啟動的Activity組件,每個Activity組件使用ActivityRecord表示。sourceRecord就是Launcher組件對應的信息,啟動操作的源組件。
之后創建一個ActivityRecord r變量,它表示要啟動的MainActivity組件的信息,啟動操作的目標組件。
step 9:ActivityStack.startActivityUncheckedLocked()
根據啟動intent獲得launchFlags。
用戶是點擊Launcher中的圖標手動啟動,所以Intent.FLAG_ACTIVITY_NO_USER_ACTION不成立,之后會向源Activity Launcher發送一個“用戶離開”的事件通知。
標志FLAG_ACTIVITY_NEW_TASK說明需要將要啟動的MainActivity放在一個新Task中——就是和當前的Launcher組件不在一個Task中,而在AndroidManifest.xml中可以使用
android:taskAffinity來指定組件所在任務id,所以AMS檢查此Task是否存在,不存在就創建它,把MainActivity放到此Task中。每個新創建的Task有一個int id,是AMS維護的一個自增字段。
最后緊接著執行重載的另一個方法
startActivityLocked(r, newTask, doResume);
如果newTask為true,也就是要啟動的Activity組件在新Task中,那么它會被放在mHistory棧的頂部。
然后doResume = true,就對mHistory最后的Activity執行resume。
這里就是MainActivity被添加到棧頂,然后會被執行resume。
step 10:ActivityStack.resumeTopActivityLocked()
在啟動MainActivity的ActivityRecord之前,會通知MainActivity的上一個prev處在前臺的Activity組件——也就是Launcher用戶離開。
step 11:ActivityStack.startPausingLocked()
ActivityRecord有一個字段ProcessRecord app,表示其Activity組件所在的進程。ProcessRecord有一個字段ApplicationThreadProxy thread,就是另一個應用程序進程中ApplicationThread的Binder代理對象。
startPausingLocked()會執行代表Launcher組件所在進程的ProcessRecord變量的方法app.thread.schedulePauseActivity()來通知Launcher組件進入pause狀態。
ActivityRecord prev = mResumedActivity;
...
prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
prev.configChangeFlags);
上面代碼片段中prev就是Launcher對應的組件信息。它是一個IBinder實例,對應Launcher組件。
因為app.thread.schedulePauseActivity()的執行是一個Binder通信,但指定為FLAG_ONEWAY,所以方法調用會立即返回。當前方法中會使用mHandler發送一個PAUSE_TIMEOUT_MSG的消息:
// Schedule a pause timeout in case the app doesn't respond.
// We don't give it much time because this directly impacts the
// responsiveness seen by the user.
Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
msg.obj = prev;
mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
作為系統進程中的服務,此處AMS沒有以同步的Binder通信方式等待Launcher執行pause完成,而是異步地通知Launcher進入pause,然后,它內部使用Handler發送一個延遲消息,在延遲消息收到前若Launcher沒有通知AMS已經進入pause,那么AMS做其它處理——認為Launcher未響應。
step 12:ApplicationThreadProxy.schedulePauseActivity()
public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
data.writeInt(finished ? 1 : 0);
data.writeInt(userLeaving ? 1 :0);
data.writeInt(configChanges);
mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
它執行了一個Binder-IPC操作,發送命令code = SCHEDULE_PAUSE_ACTIVITY_TRANSACTION。
這個進程間操作是FLAG_ONEWAY的,它會立即返回。
參數token就是AMS中Launcher對應的ActivityRecord對象。
注意Binder的通信默認是同步的,更多為什么可以先了解下Binder通信。
以上操作都是在AMS中執行的,AMS在系統進程SystemServer中。所有方法的調用流程圖:
階段3:Launcher處理SCHEDULE_PAUSE_ACTIVITY_TRANSACTION
接下來地的幾步操作在Launcher中進行,執行處理AMS發送的SCHEDULE_PAUSE_ACTIVITY_TRANSACTION通信請求。
方法調用流程如下:
Step 13:ApplicationThread.schedulePauseActivity()
注意系統源碼在Binder通信的設計,如果了解AIDL生成的通信接口的實現類和Proxy內部類等,這些Binder-IPC相關的類型都很容易理解。
類似AMS和ActivityManagerNative等,ApplicationThreadNative在onTransact()中對code = SCHEDULE_PAUSE_ACTIVITY_TRANSACTION的處理是調用接口方法IApplicationThread.schedulePauseActivity()。
case SCHEDULE_PAUSE_ACTIVITY_TRANSACTION:
{
data.enforceInterface(IApplicationThread.descriptor);
IBinder b = data.readStrongBinder();
boolean finished = data.readInt() != 0;
boolean userLeaving = data.readInt() != 0;
int configChanges = data.readInt();
schedulePauseActivity(b, finished, userLeaving, configChanges);
return true;
}
變量IBinder b就是AMS中Launcher對應的ActivityRecord對象。
ApplicationThread是ActivityThread的內部類,它繼承ApplicationThreadNative,實現了schedulePauseActivity()。
public final class ActivityThread {
...
private final class ApplicationThread extends ApplicationThreadNative {
...
public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges) {
queueOrSendMessage(
finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
token,
(userLeaving ? 1 : 0),
configChanges);
}
}
}
可以看到,方法執行queueOrSendMessage()向應用程序Launcher的主線程的消息隊列發送一個類型為PAUSE_ACTIVITY的消息。
Step 14:ActivityThread.queueOrSendMessage()
public final class ActivityThread {
...
final H mH = new H();
...
private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
synchronized (this) {
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
mH.sendMessage(msg);
}
}
}
ActivityThread的字段mH是在進程主線程中創建的,用來處理應用程序進程中的主線程消息,類H繼承Handler。
因為對Binder方法onTransact()的執行基本是(當跨進程時)在Binder線程池中的線程中執行的,可見這里定義mH就是為了供其它非主線程的操作轉到主線程中執行。
TODO:ActivityThread的創建及其相關知識后面會小結下。
Step 15:H.handleMessage()
/**
* This manages the execution of the main thread in an
* application process, scheduling and executing activities,
* broadcasts, and other operations on it as the activity
* manager requests.
*/
public final class ActivityThread {
...
private final class H extends Handler {
...
public static final int PAUSE_ACTIVITY = 101;
public void handleMessage(Message msg) {
switch (msg.what) {
...
case PAUSE_ACTIVITY:
handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
...
break;
...
}
}
}
msg.obj就是AMS中執行ApplicationThreadProxy.schedulePauseActivity()時傳遞的代表IBinder的ActivityRecord對象。
Step 16:ActivityThread.handlePauseActivity()
應用程序進程中啟動的每一個Activity組件都使用一個ActivityClientRecord對象描述,其對應AMS中的ActivityRecord對象。ActivityThread的字段mActivities就是。
方法中,根據AMS傳遞的表示Launcher組件的token從mActivities獲得Launcher對應的ActivityClientRecord對象,通知它執行onUserLeaveHint(),然后是onPause()。
最后,ActivityManagerNative.getDefault()獲得AMS代理對象,通知AMS已經完成對Launcher的pause。
Step 17:ActivityManagerProxy.activityPaused()
public void activityPaused(IBinder token, Bundle state) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
data.writeBundle(state);
mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
執行Binder通信,通知AMS事件code = ACTIVITY_PAUSED_TRANSACTION。
階段4 AMS處理ACTIVITY_PAUSED_TRANSACTION
接下來的操作又轉到AMS中進行,從響應ACTIVITY_PAUSED_TRANSACTION事件開始。
方法調用時序圖:
Step 18:ActivityManagerService.activityPaused()
在onTransact()中響應ACTIVITY_PAUSED_TRANSACTION執行的方法。
請求轉給ActivityStack:
mMainStack.activityPaused(token, icicle, false);
參數token指向Launcher組件對應的ActivityRecord對象。
Step 19:ActivityStack.activityPaused()
根據token從字段mHistory中找到Launcher的ActivityRecord對象,然后設置其為paused。
繼續啟動MainActivity。
Step 20:ActivityStack.completePauseLocked()
對ActivityRecord prev = mPausingActivity,也就是Launcher的pause完成。
執行resumeTopActivityLocked(prev)。
前面的執行中,mHistory中的topActivity就是MainActivity。
Step 21:ActivityStack.resumeTopActivityLocked()
此時的topActivity就是MainActivity,其ActivityRecord.app字段為null,因為還未為它創建進程。
Step 22:ActivityStack.startSpecificActivityLocked()
在AMS中,每一個Activity組件都有userId和進程名,用戶ID是安裝該Activity組件的App時由PackageManagerService分配的,進程名由該組件的android:process決定的。
方法中,AMS檢查對應用戶ID和進程名的進程是否存在,ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid)
,
若app為null,就先啟動一個App進程,然后通知該進程啟動MainActivity。
Step 23:AMS.startProcessLocked()
AMS用字段mProcessNames記錄已經運行的App進程的信息:
/**
* All of the applications we currently have running organized by name.
* The keys are strings of the application package name (as
* returned by the package manager), and the keys are ApplicationRecord
* objects.
*/
final ProcessMap<ProcessRecord> mProcessNames
= new ProcessMap<ProcessRecord>();
再次檢查對應app進程是否存在:
ProcessRecord app = getProcessRecordLocked(processName, info.uid)
如果app為null:
app = newProcessRecordLocked(null, info, processName);
mProcessNames.put(processName, info.uid, app);
最后,方法調用一個重載版本繼續完成MainActivity的進程的創建。
startProcessLocked(app, hostingType, hostingNameStr);
方法首先得到要創建的進程的用戶ID和用戶組ID,然后執行Process.start()靜態函數啟動一個新的應用程序進程:
int pid = Process.start("android.app.ActivityThread",
mSimpleProcessManagement ? app.processName : null, uid, uid,
gids, debugFlags, null);
得到的返回值pid是對應啟動的App進程的大于0的進程ID。然后將參數app指向的ProcessRecord對象保存在AMS的以pid為key的字典字段mPidsSelfLocked中:
/**
* All of the processes we currently have running organized by pid.
* The keys are the pid running the application.
*
* <p>NOTE: This object is protected by its own lock, NOT the global
* activity manager lock!
*/
final SparseArray<ProcessRecord> mPidsSelfLocked
= new SparseArray<ProcessRecord>();
....
this.mPidsSelfLocked.put(pid, app);
進程的啟動還是異步的,所以這里向AMS使用Handler發送延遲消息PROC_START_TIMEOUT_MSG。
如果延遲時間后新啟動的App進程未通知AMS它啟動完成,否則AMS不再繼續處理MainActivity的啟動。
階段5
接下來就是android應用程序進程啟動的過程。
AMS中執行的Process.start()方法所啟動的新進程的程序入口方法是android.app.ActivityThread的靜態成員函數main()。
接下來的方法執行流程如:
Step 24:ActivityThread.main
public final class ActivityThread {
...
final ApplicationThread mAppThread = new ApplicationThread();
...
private final void attach(boolean system) {
....
mSystemThread = system;
if (!system) {
...
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException e) {
}
}
...
}
...
public static final void main(String[] args) {
..
Looper.prepareMainLooper();
...
ActivityThread thread = new ActivityThread();
thread.attach(this);
...
Looper.loop();
...
}
}
創建一個ActivityThread對象,調用其attach()向AMS發送進程啟動完成通知。
開啟主線程消息循環。
ApplicationThread是一個Binder本地對象,AMS使用它的代理和當前App進程通信。
attachApplication()向AMS通知進程創建完成。
Step 25:ActivityManagerProxy.attachApplication
public void attachApplication(IApplicationThread app) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(app.asBinder());
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
向AMS發送ATTACH_APPLICATION_TRANSACTION事件,IApplicationThread app的Binder代理作為AMS對當前ApplicationThread的標識。
階段6 AMS響應App進程創建完成通知
接下來是AMS處理ATTACH_APPLICATION_TRANSACTION事件。
方法時序圖:
Step 26:AMS.attachApplication
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
callingPid就是為MainActivity創建的新進程的pid。
Step 27:AMS.attachApplicationLocked
根據pid得到mPidsSelfLocked中的ProcessRecord app對象。
得到AMS管理的棧頂topActivity:
ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
將app設置給MainActivity對應的hr。
執行mMainStack.realStartActivityLocked(hr, app, true, true)
繼續啟動MainActivity。
Step 28:ActivityStack.realStartActivityLocked
這時MainActivity的ActivityRecord r的app字段就是設置過的,不為null。
topActivity.app.thread就是所創建MainActivity進程中ApplicationThread mAppThread的Binder代理。
使用topActivity.app.thread.scheduleLaunchActivity()跨進程通知創建的App進程啟動MainActivity組件。
Step 29:ApplicationThreadProxy.scheduleLaunchActivity
使用IBinder向MainActivity對應進程的mAppThread發送SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION通知。
消息中記錄了要啟動的MainActivity的ActivityInfo info。
階段7 ActivityThread處理啟動MainActivity的請求
接下來的操作就在為MainActivity所創建的新的App進程中執行。
前面的ActivityThread.main()的執行使得進程中已經存在mAppThread和創建的ActivityThread thread。
main方法進入Looper循環。
將要執行的方法時序圖:
Step 30:ApplicationThread.scheduleLaunchActivity
ApplicationThreadNative的onTransact()將對SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION的響應轉為ApplicationThread.scheduleLaunchActivity()的調用。
方法繼續使用queueOrSendMessage()將處理打包為msg傳給ActivityThread.mH。
ActivityClientRecord r = new ActivityClientRecord();
...
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
r就是從AMS端傳遞過來的MainActivity的信息。
Step 31:ActivityThread.queueOrSendMessage
handleMessage()中對消息LAUNCH_ACTIVITY的處理:
case LAUNCH_ACTIVITY: {
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo);
handleLaunchActivity(r, null);
Step 32:ActivityThread.handleLaunchActivity
private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
Activity a = performLaunchActivity(r, customIntent);
...
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward);
...
}
啟動MainActivity,然后設置它為resume。
Step 34:ActivityThread.performLaunchActivity
原型:
private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent)
獲得關于MainActivity的組件信息:
ComponentName component = r.intent.getComponent();
然后根據component,使用類加載器實例化Activity對象:
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
r.intent.setExtrasClassLoader(cl);
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
...
然后創建一個ContextImpl appContext,作為activity的運行上下文環境。
ContextImpl appContext = new ContextImpl();
appContext.init(r.packageInfo, r.token, this);
appContext.setOuterContext(activity);
使用appContext和參數r對activity執行初始化:
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstance,
r.lastNonConfigurationChildInstances, config);
然后執行onCreate:
mInstrumentation.callActivityOnCreate(activity, r.state);
callActivityOnCreate()會調用Activity.onCreate(),這時自定義MainActivity中的setContentView()等邏輯就會被調用。
activity創建完畢后,對應記錄被添加到ActivityThread中:
mActivities.put(r.token, r);
ActivityClientRecord r是AMS中對應MainActivity的ActivityRecord對象的Binder代理,它們分別是MainActivity在AMS中和App進程ActivityThread中的描述。
總結
經過以上步驟,從Launcher.startActivitySafely()開始到Activity.onCreate()得以執行,可以認為MainActivity組件及其進程已經啟動完畢。
啟動的各個階段
- Launcher組件向AMS發送啟動MainActivity組件的進程間通信。
- AMS首先保存要啟動的MainActivity的信息,然后向Launcher發送進入pause狀態的進車間通信。
- Launcher進入中止狀態后,向AMS發送已經進入中止狀態的進程間通信請求。這樣AMS就繼續執行啟動MainActivity的操作。
- AMS檢查用來運行MainActivity的進程不存在,創建并啟動一個App進程。
- 新進程啟動完成后,向AMS發送啟動完成的進程間通信請求。
- AMS將保存的MainActivity組件的信息發送給創建的新進程。
- 新進程啟動MainActivity。
ActivityThread.mH
ActivityThread的main方法就是整個App進程的入口函數,它執行結束那么App進程就結束了。
main()中開啟了Looper消息循環。
ActivityThread.mH把很多Binder操作從Binder線程中轉到UI線程中執行。
(本文使用Atom編寫)
文章列表