目錄
- 概述
- 總結(jié)
- 詳細(xì)過程
- 重要類說明
概述
在冷啟動過程中,“當(dāng)為App創(chuàng)建完進程”之后,就需要“激活處于焦點棧棧頂?shù)拇龁覣ctivity”。關(guān)于冷啟動過程的前兩步操作,《為目標(biāo)App啟動做準(zhǔn)備》、《啟動App進程》 的流程請點擊查看。
由于“App進程內(nèi)部操作”部分內(nèi)容比較多一些,所以這部分的內(nèi)容被分成了2個小章節(jié)來分析。
第一節(jié):也就是本節(jié)是從“App進程啟動完畢之后,從ActivityThread.main()開始” 至 “App進程接收到AMS通過scheduleLaunchActivity()發(fā)起的 LAUNCH_ACTIVITY 消息”為止。
第二節(jié):《App啟動流程:App進程內(nèi)部操作-2》,則從“App接收到LAUNCH_ACTIVITY開始” 至 “通過Activity.handleResumeActivity()真正完成待啟動Activity的實例化并執(zhí)行其View樹的繪制”為止。
當(dāng)前源碼的分析是基于 Android8.0。
總結(jié)
1:當(dāng)Zygote進程創(chuàng)建并初始化完App進程后,就會通過反射執(zhí)行ActivityThread.main()對main線程進行初始化。
2:通過ActivityManager.getService()獲取AMS服務(wù)在本進程的BInder 代理,而后通過這個代理對象通知AMS執(zhí)行attachApplication()操作。
這是一次IPC操作,從App進程切換至system_server進程
3:AMS接收到App進程發(fā)起的“attachApplication()操作”操作后會執(zhí)行如下操作:
3.1:根據(jù) 調(diào)用者進程的pid,獲取記錄此進程信息的ProcessRecord。
3.2:注冊“Binder服務(wù)死亡通知”,App進程掛掉之后其Binder服務(wù)也會隨之停止掉,此時AMS需要接收到這個通知,然后去回收一些此進程使用的資源。
3.3:把當(dāng)前App進程的ApplicationThread賦值給ProcessRecord中的thread。并重置此ProcessRecord中一些參數(shù)。
3.4:通過App進程的ApplicationThread服務(wù)在system_server進程的Binder代理對象,執(zhí)行bindApplication()來通知App進程繼續(xù)后續(xù)“綁定”操作。
這是一次IPC操作,從system_server進程切換至App進程
4:App進程接收到AMS發(fā)起的bindApplication()操作后會執(zhí)行如下操作:
4.1:通過 ServiceManager.initServiceCache()更新系統(tǒng)服務(wù)在App進程的Binder緩存。
4.2:通過Handler消息機制,向App進程的主線程發(fā)一個“BIND_APPLICATION”消息,使操作切換至主線程繼續(xù)后續(xù)執(zhí)行。
5:App進程會通過handleBindApplication()處理bindApplication()操作。 具體所做的事情如下:
5.1:設(shè)置App進程名、為低內(nèi)存設(shè)備關(guān)閉硬件加速功能、如果系統(tǒng)的版本號低于3.1,則更換AsyncTask的內(nèi)部的線程池實現(xiàn)方法、系統(tǒng)版本號大于等于 3.0 的話,則開啟嚴(yán)格模式來檢查“是否在主線程開啟了網(wǎng)絡(luò)請求、初始化http代理、創(chuàng)建全局唯一Instrumentation實例 等。
5.2:通過LoadedApk.makeApplication()創(chuàng)建App進程的唯一Application實例,回調(diào)Application的attachBaseContext()、onCreate()。
App進程執(zhí)行完bindApplication()操作后,又會回到system_server進程繼續(xù)后續(xù)操作。
這些操作包括如下部分:
6.1:從“焦點?!敝蝎@取“處于棧頂?shù)拇龁覣ctivity對應(yīng)的ActivityRecord”。
6.2:通知App進程執(zhí)行“scheduleLaunchActivity()”操作,在App進程進行待啟動Activity的實例化、各種生命周期方法的執(zhí)行、相應(yīng)PhoneWindow維護的View樹的繪制等操作。
這是一次IPC操作,從system_server進程切換至App進程
7:App 進程接收到LLAUNCH_ACTIVITY消息之后,會在App進程內(nèi)部的handleLaunchActivity()對待啟動Activity進行激活等初始化操作。 具體操作如下:
7.1:從空閑消息處理器列表中 移除 “在主線程空閑時,執(zhí)行強制GC操作的空閑消息處理器” 。
7.2:在創(chuàng)建待啟動Activity之前,先獲取WMS服務(wù)在本進程的Binder代理并保存至WindowManagerGlobal。
7.3:通過performLaunchActivity()初始化ContextImpl實例、對目標(biāo)Activity進行初始化、執(zhí)行Activity的綁定操作、執(zhí)行Activity的相應(yīng)生命周期方法、等Activity執(zhí)行完Resume之后,才開始對Activity的View樹進行App進程內(nèi)部的測量、擺放、繪制等操作。并通過ViewRootImpl內(nèi)部的“編舞者來接收IO硬件產(chǎn)生的“Vsync”刷新信號,進而對PhoneView維護的視圖樹進行周期性的刷新操作。
7.4:根據(jù)AMS傳遞給App 進程的startsNotResumed,來決定是否需要“禁止Resume待啟動Activity,如果禁止就會執(zhí)行該Activity的pasue操作”。
7.5:如果初始化Activity實例失敗,告訴AMS需要 “移除” 此Activity對應(yīng)保存在AMS 服務(wù)中的Activity棧中的ActivityRecord。
詳細(xì)過程
當(dāng)Zygote進程創(chuàng)建并初始化完App進程后,就會通過反射執(zhí)行ActivityThread.main()對main線程進行初始化。
1.1.ActivityThread.main()
main()方法是子進程執(zhí)行其主線程初始化的唯一入口。
源碼
public static void main(String[] args) {
//開始記錄ActivityThread的初始化事件
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
......
//為主線程創(chuàng)建Looper
Looper.prepareMainLooper();
//初始化App進程內(nèi)的ActivityThread唯一實例
ActivityThread thread = new ActivityThread();
//見小節(jié)[1.2]
thread.attach(false);
//sMainThreadHandler就是ActivityThead.H類的實例
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
//ActivityThread初始化完畢之后,結(jié)束記錄該事件的耗時
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//啟動主線程Looper,開始處理消息
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
1.2.ActivityThread.attach()
總結(jié)
1:通過ViewRootImpl.addFirstDrawHandler()注冊“View樹的首次繪制完畢回調(diào)事件”。
2:通過ViewRootImpl.addConfigCallback()注冊“手機配置信息發(fā)生更改之后的回調(diào)事件?!?br> 3:通過ActivityManager.getService()獲取AMS服務(wù)在本進程的BInder 代理,而后通過這個代理對象通知AMS執(zhí)行attachApplication()操作。
源碼
private void attach(boolean system) {
//把當(dāng)前ActivityThread實例對象賦值給sCurrentActivityThread 屬性。使用的時候方便通過currentActivityThread()獲取。
sCurrentActivityThread = this;
//用于區(qū)分“當(dāng)前進程是否是系統(tǒng)進程”。
mSystemThread = system;
if (!system) {
//見小節(jié)[1.2.1]
ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {
ensureJitEnabled();
}
});
......
//見小節(jié)[1.3]
final IActivityManager mgr = ActivityManager.getService();
try {
//見小節(jié)[2.1]
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
......
} else {
//是系統(tǒng)進程的話,設(shè)置該進程的name為“system_process”。
//可以啟動一個模擬器或者刷root之后,打開可debug的進程之后,顯示的那個“system_process”。如果要調(diào)試FrameWorker層的代碼的話,那么此進程就是要debug的那個進程。
android.ddm.DdmHandleAppName.setAppName("system_process",
UserHandle.myUserId());
......
}
......
//見小節(jié)[1.2.2]
ViewRootImpl.ConfigChangedCallback configChangedCallback
= (Configuration globalConfig) -> {
synchronized (mResourcesManager) {
// We need to apply this change to the resources immediately, because upon returning
// the view hierarchy will be informed about it.
if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
null /* compat */)) {
updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
mResourcesManager.getConfiguration().getLocales());
// This actually changed the resources! Tell everyone about it.
if (mPendingConfiguration == null
|| mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
mPendingConfiguration = globalConfig;
sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
}
}
}
};
ViewRootImpl.addConfigCallback(configChangedCallback);
}
1.2.1.ViewRootImpl.addFirstDrawHandler():
總結(jié):
1:注冊“View樹繪制第一幀時的回調(diào)事件”。
2:在View樹繪制第一幀時,用于通知注冊了此事件的被觀察者,View開始繪制第一幀了。
源碼
public static void addFirstDrawHandler(Runnable callback) {
synchronized (sFirstDrawHandlers) {
if (!sFirstDrawComplete) {
sFirstDrawHandlers.add(callback);
}
}
}
private void draw(boolean fullRedrawNeeded) {
......
//通知那些注冊了“繪制第一幀”事件的被觀察者,開始繪制第一幀了
if (!sFirstDrawComplete) {
synchronized (sFirstDrawHandlers) {
sFirstDrawComplete = true;
final int count = sFirstDrawHandlers.size();
for (int i = 0; i< count; i++) {
mHandler.post(sFirstDrawHandlers.get(i));
}
}
}
......
}
1.2.2.ViewRootImpl.addConfigCallback():添加當(dāng)手機自身的配置信息發(fā)生改變之后(橫豎屏切換、字體大小發(fā)生了更改等等)的回調(diào)事件。
Configuration:該類表示的是“設(shè)備的配置信息”。該類定義了許多與手機本身相關(guān)的配置信息。
1.orientation:表示當(dāng)前手機的屏幕狀態(tài)(橫豎屏就是用這個來判斷)。
2.densityDpi:屏幕密度(eg:440dpi)。
3.appBounds:屏幕大小。
4.screenLayout:該參數(shù)是一個“復(fù)合值”。具體的存儲的信息如下:
4.1.屏幕整體大?。?/strong>可通過該值與相應(yīng)的mask進行位運算獲得當(dāng)前屏幕是“SMALL”、“NORMAL”、“LARGE”、“XLARGE”。
4.2.屏幕布局:表示當(dāng)前屏幕中的元素是“從左往右布局”還是“從右往左布局”。取值范圍為:“SCREENLAYOUT_LAYOUTDIR_LTR”、“SCREENLAYOUT_LAYOUTDIR_RTL”。
4.3.屏幕是否是圓形。
5.fontScale:字體的縮放比率。
源碼
public static void addConfigCallback(ConfigChangedCallback callback) {
synchronized (sConfigCallbacks) {
sConfigCallbacks.add(callback);
}
}
1.3.ActivityManager.getService():獲取AMS服務(wù)在本進程的Binder代理。
源碼
public static IActivityManager getService() {
//調(diào)用IActivityManagerSingleton.get()會觸發(fā)IActivityManagerSingleton中聲明的create()。
//見小節(jié)[1.3.1]
return IActivityManagerSingleton.get();
}
1.3.1.Singleton.create()
源碼
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
//見小節(jié)[1.3.2]
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
//見小節(jié)[1.3.7]
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
1.3.2.ServiceManager.getService():獲得相應(yīng)系統(tǒng)服務(wù)在本進程的 IBinder 引用。
總結(jié):
1:如果ServiceManager內(nèi)部的HashMap緩存了此Binder服務(wù)的話,則返回。
2:如果沒有,則通過getIServiceManager().getService()重新與system_server進程建立連接,獲取相應(yīng)服務(wù)在本進程的Binder代理。
3:這個Binder代理對象與系統(tǒng)服務(wù)對象不是一個。因為AMS運行在system_server進程,此對象運行在 App進程。采用“進程隔離”的方式,每個進程都有自己的 虛擬內(nèi)存地址空間,且每個進程被分配的虛擬內(nèi)存地址都不一樣,這就導(dǎo)致每個進程可訪問的內(nèi)存區(qū)域是不一樣的,進程之間沒有交集,這就避免了 “修改進程A內(nèi)存區(qū)域會影響到進程B內(nèi)存中的數(shù)據(jù)”。
源碼
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
//此時,從本地服務(wù)緩存中獲取的AMS服務(wù)的本地代理肯定為 null。
//因為這些系統(tǒng)服務(wù)的本地代理還沒有通過 initSerivceCache()緩存起來。
if (service != null) {
return service;
} else {
//見小節(jié)[1.3.3]、[1.3.6]
return Binder.allowBlocking(getIServiceManager().getService(name));
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
1.3.3.ServiceManager.getIServiceManager():獲取ServiceManager內(nèi)部保存的IServiceManager實例。
總結(jié):
1:如果IServiceManager實例已經(jīng)初始化過了,則直接返回此實例。
2:如果還沒初始化過,則需要先初始化然后返回此類實例。
源碼
private static IServiceManager getIServiceManager() {
//非首次調(diào)用,則返回此類實例
if (sServiceManager != null) {
return sServiceManager;
}
// 初始化IServiceManager類實例
//見小節(jié)[1.3.4]、[1.3.5]
sServiceManager = ServiceManagerNative
.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
return sServiceManager;
}
1.3.4.BinderInternal.getContextObject():獲取一個IServiceManager,通過它可以獲取到一些其它系統(tǒng)服務(wù)。
總結(jié):
1:該方法是一個native方法,用于獲取“IServiceManager類型的實例”。
2:該IServiceManager接口的實例可以用來“查詢其它服務(wù)”。
源碼
/**
* Return the global "context object" of the system. This is usually
* an implementation of IServiceManager, which you can use to find
* other services.
*/
public static final native IBinder getContextObject();
1.3.5.ServiceManagerNative.asInterface():獲取一個IServiceManager類型的IBinder服務(wù)。
Binder使用上的簡單介紹
1:Binder這種IPC方式采用的是CS架構(gòu)。
2:IBinder表示“此類是可以用來進行IPC通信的,它提供了IPC通信的能力”。
2.1:Binder類實現(xiàn)了IBidner接口,實現(xiàn)了 “onTransact()”。
2.2:通常我們所提供的服務(wù)類要繼承Binder,重寫 OnTransact() 方法用于根據(jù)自己的業(yè)務(wù)處理來自Client端的請求。
總結(jié)
1:首先,判斷通過“BinderInternal.getContextObject()”獲得的IBinder服務(wù)是否是當(dāng)前進程所創(chuàng)建,如果是直接返回此IBInder 服務(wù)。
2:如果不是,則返回一個 ServiceManagerProxy,把服務(wù)端在本進程的IBinder服務(wù)實例保存到這個代理對象中。這樣做是為了 方便以后通過此IBinder實例與服務(wù)的所屬進程進行通信。
源碼
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
//根據(jù)“descriptor”從本進程中查找該Binder服務(wù)。
//1:如果此IBinder服務(wù)所屬者是當(dāng)前進程的話,則返回該服務(wù)。
//2:如果不是,則返回ServiceManagerProxy。其中“obj”是服務(wù)端進程的IBinder服務(wù)在本進程的一個實例。
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
//把IBinder服務(wù)在本進程的一個實例保存至ServiceManagerProxy中。
//方便以后通過此IBinder實例與服務(wù)的所屬進程進行通信。
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
1.3.6.IServiceManager.getService():通過Binder IPC方式,根據(jù)name從system_server進程獲取系統(tǒng)服務(wù)在本地進程的Binder代理對象。
源碼
/**
* Retrieve an existing service called @a name from the
* service manager. Blocks for a few seconds waiting for it to be
* published if it does not already exist.
*/
public IBinder getService(String name) throws RemoteException;
1.3.7.IActivityManager.Stub.asInterface():
總結(jié):
1:把獲取的IBinder對象封裝到AMS服務(wù)在子進程的Binder代理對象中。
2:此代理對象的實際類型為 IActivity.Stub.Proxy。
3:此代理對象與AMS對象一樣都實現(xiàn)了IActivityManager接口,此接口定了AMS向外提供了哪些操作。這樣做的好處是“在使用的時候,就可以直接知道可以使用AMS提供的哪些方法了”。
說明:
1:從8.0開始,AMS這種用于IPC通信的系統(tǒng)服務(wù)的實現(xiàn)方式改為AIDL 來實現(xiàn)。
2:8.0之前AMS內(nèi)提供的 用于處理進程間操作的業(yè)務(wù) 全部是在ActivityManagerNative內(nèi)部來實現(xiàn),而從8.0開始采用AIDL之后,AMS直接繼承自IActivityService.Stub原來處理進程間操作的業(yè)務(wù)全部挪到AMS來中完成。
因為看不到IActivityService.Stub的內(nèi)部實現(xiàn),所以以下代碼就摘抄了一個AS編譯的AIDL文件生成的的asInterface()實現(xiàn)(通過AIDL方式編譯的此方法的實現(xiàn)格式是一樣)。
public static sj.IMyAidlInterface asInterface(android.os.IBinder obj) {
//判斷IBinder服務(wù)是否為空
if ((obj==null)) {
return null;
}
//查詢此服務(wù)是否是本進程創(chuàng)建的
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof sj.IMyAidlInterface))) {
return ((sj.IMyAidlInterface)iin);
}
//此服務(wù)不是本進程創(chuàng)建的話,則返回與之對應(yīng)的Proxy對象。
return new sj.IMyAidlInterface.Stub.Proxy(obj);
}
......
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
2.1.ActivityManagerService.attachApplication()
總結(jié):
1:通過ActivityManager.getService()獲取AMS服務(wù)在本進程的Binder代理對象后,調(diào)用該代理對象的attachApplication()就會進行一次進程切換。
2:App進程會被阻塞住,一直等到system_server進程內(nèi)部的AMS.attachApplication()執(zhí)行完畢為止。
參數(shù)說明:
IApplicationThread threa:App進程的ApplicationThread唯一實例。關(guān)于ApplicationThread的介紹請查看本章-重要類說明。
源碼
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
//獲取調(diào)用者進程的pid(已經(jīng)啟動的App進程的id)。
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
//見小節(jié)[2.2]
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
2.2.ActivityManagerService.attachApplicationLocked()
總結(jié):
1:根據(jù) 調(diào)用者進程的pid,獲取記錄此進程信息的ProcessRecord。如果獲取的ProcessRecord為null的話,則表示“之前創(chuàng)建App進程那步出現(xiàn)了問題(ProcessRecord用于記錄App運行在的進程信息)”,這種情況直接返回不再繼續(xù)后續(xù)操作。
2:注冊“Binder服務(wù)死亡通知”。這里的“服務(wù)端”指的是App進程的ApplicationThread實例(ApplicationThread繼承IApplicationThread.Stub,它是在此Binder IPC通信中扮演的是服務(wù)端角色)。App進程掛掉之后其Binder服務(wù)也會隨之停止掉,此時AMS需要接收到這個通知,然后去回收一些此進程使用的資源(eg:重置此進程對應(yīng)的ProcessRecord中的數(shù)據(jù),進程被kill掉之后其ProcessRecord并不會從mPidsSelfLocked緩存中移除)。
3:把當(dāng)前App進程的ApplicationThread賦值給ProcessRecord中的thread。并重置此ProcessRecord中一些參數(shù)。
4:通過App進程的ApplicationThread服務(wù)在system_server進程的Binder代理對象,執(zhí)行bindApplication()來通知App進程繼續(xù)后續(xù)“綁定”操作。
4.1:如果執(zhí)行“bindApplication()”之后的綁定操作失敗了則:取消掉已經(jīng)注冊的 Binder服務(wù)死亡通知。調(diào)用startProcessLocked()再通知Zygote進程重新走一遍fork子進程流程。
源碼
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
// 根據(jù)調(diào)用者進程的pid,獲取記錄此進程信息的ProcessRecord.
ProcessRecord app;
long startTime = SystemClock.uptimeMillis();
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
if (app == null) {
......
//如果獲取的ProcessRecord為null的話,則表示“之前創(chuàng)建App進程那步出現(xiàn)了問題(ProcessRecord用于記錄App運行在的進程信息)”,這種情況直接返回不再繼續(xù)后續(xù)操作。
return false;
}
......
try {
//注冊“Binder服務(wù)死亡通知”。
//這里的“服務(wù)端”指的是App進程的ApplicationThread實例(ApplicationThread繼承IApplicationThread.Stub,它是在此Binder IPC通信中扮演的是服務(wù)端角色。App進程掛掉之后其Binder服務(wù)也會隨之停止掉,此時AMS需要接收到這個通知,然后去回收一些此進程使用的資源(eg:重置此進程對應(yīng)的ProcessRecord中的數(shù)據(jù),進程被kill掉之后其ProcessRecord并不會從mPidsSelfLocked緩存中移除)。)
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
app.deathRecipient = adr;
} catch (RemoteException e) {
......
return false;
}
......
//把當(dāng)前App進程的ApplicationThread賦值給ProcessRecord中的thread。
app.makeActive(thread, mProcessStats);
//ProcessRecord一些參數(shù)的重置操作。
app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.forcingToImportant = null;
updateProcessForegroundLocked(app, false, false);
app.hasShownUi = false;
app.debugging = false;
app.cached = false;
app.killedByAm = false;
app.killed = false;
......
try {
......
//不清楚ProcessRecord中ActiveInstrumentation類型的 instr是做什么的。
//但是無論此屬性是否為null,AMS服務(wù)都會通過App進程的ApplicationThread服務(wù)在system_server進程的Binder代理對象執(zhí)行bindApplication()來通知App進程繼續(xù)后續(xù)操作。
if (app.instr != null) {
//見小節(jié)[2.4]
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), //見小節(jié)[2.3]
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial);
} else {
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated), //見小節(jié)[2.3]
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial);
}
......
} catch (Exception e) {
//如果此操作出現(xiàn)了問題導(dǎo)致拋出了異常情況。
app.resetPackageList(mProcessStats);
//取消掉已經(jīng)注冊的 Binder服務(wù)死亡通知。
app.unlinkDeathRecipient();
//調(diào)用startProcessLocked()再通知Zygote進程重新fork一個新的子進程。
startProcessLocked(app, "bind fail", processName);
return false;
}
boolean badApp = false;
boolean didSomething = false;
//See if the top visible activity is waiting to run in this process...
//激活處于“焦點棧棧頂?shù)拇龁覣ctivity”
//見小節(jié)[3.1]
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
......
}
}
......
return true;
}
2.3.getCommonServicesLocked.getCommonServicesLocked():獲得一些公共的系統(tǒng)服務(wù)。
總結(jié):
1:獲得一些公共的系統(tǒng)Binder服務(wù)。
1.1:如果isolated為true的話,則只把PMS服務(wù)的IBinder對象回傳給App進程。
1.2:如果isolated為fasle的話,則把PMS、WMS、AlarmManagerService(鬧鐘服務(wù))的IBinder對象回傳給App進程。
2:獲得的這些服務(wù),會通過Binder這種IPC方式回傳給App進程,App進程接收到AMS發(fā)起的binderApplication()請求后,會首先通過 ServiceManager.initServiceCache()更新系統(tǒng)服務(wù)在App進程的Binder緩存。
源碼
private HashMap<String, IBinder> getCommonServicesLocked(boolean isolated) {
//如果 isolated為true的話,則只把系統(tǒng)服務(wù)中的“PMS”對應(yīng)的Binder對象存儲到Map中。
if (isolated) {
if (mIsolatedAppBindArgs == null) {
mIsolatedAppBindArgs = new HashMap<>();
mIsolatedAppBindArgs.put("package", ServiceManager.getService("package"));
}
return mIsolatedAppBindArgs;
}
if (mAppBindArgs == null) {
mAppBindArgs = new HashMap<>();
//如果 isolated為false的話,則把系統(tǒng)服務(wù)中的“PMS、WMS、AlarmManagerService”對應(yīng)的Binder對象存儲到Map中。
mAppBindArgs.put("package", ServiceManager.getService("package"));
mAppBindArgs.put("window", ServiceManager.getService("window"));
mAppBindArgs.put(Context.ALARM_SERVICE,
ServiceManager.getService(Context.ALARM_SERVICE));
}
return mAppBindArgs;
}
2.4.ApplicationThread.bindApplication()
總結(jié):
1:通過 ServiceManager.initServiceCache()更新系統(tǒng)服務(wù)在App進程的Binder緩存。
2:通過Handler消息機制,向App進程的主線程發(fā)一個“BIND_APPLICATION”消息,使操作切換至主線程繼續(xù)后續(xù)執(zhí)行。
3:該操作是一次IPC過程,涉及到進程切換,從AMS所在的system_server進程切換至App進程。AMS要想主動發(fā)起與App進程的通信,就得借助于Binder這種IPC方式,因為ApplicationThread承擔(dān)的是服務(wù)端的角色,客戶端發(fā)起的請求,服務(wù)端接收后都會把這些操作扔到Bidner線程池中執(zhí)行,這樣做的好處是提高了服務(wù)端的“并發(fā)”性能。
源碼
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) {
if (services != null) {
//通過 ServiceManager.initServiceCache()更新系統(tǒng)服務(wù)在App進程的Binder緩存。
//見小節(jié)[2.5]
ServiceManager.initServiceCache(services);
}
AppBindData data = new AppBindData();
......
//見小節(jié)[2.6]
sendMessage(H.BIND_APPLICATION, data);
}
2.5.ServiceManager.initServiceCache():更新系統(tǒng)服務(wù)在App進程的Binder緩存。
源碼
public static void initServiceCache(Map<String, IBinder> cache) {
if (sCache.size() != 0) {
throw new IllegalStateException("setServiceCache may only be called once");
}
sCache.putAll(cache);
}
2.6.ActivityThread.handleBindApplication()
總結(jié):
1:做一些準(zhǔn)備操作。 記錄進程的開始時間、設(shè)置App進程名、為低內(nèi)存設(shè)備關(guān)閉硬件加速功能、如果系統(tǒng)的版本號低于3.1,則更換AsyncTask的內(nèi)部的線程池實現(xiàn)方法、系統(tǒng)版本號大于等于 3.0 的話,則開啟嚴(yán)格模式來檢查“是否在主線程開啟了網(wǎng)絡(luò)請求、初始化http代理、創(chuàng)建全局唯一Instrumentation實例 等。
2:通過LoadedApk.makeApplication()創(chuàng)建App進程的唯一Application實例。
源碼
private void handleBindApplication(AppBindData data) {
......
//記錄進程的開始時間。
Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
......
//設(shè)置App進程名
Process.setArgV0(data.processName);
//設(shè)置App進程在ddms模塊顯示的進程名
android.ddm.DdmHandleAppName.setAppName(data.processName,
UserHandle.myUserId());
if (data.persistent) {
//為 低內(nèi)存設(shè)備關(guān)閉硬件加速功能,這是為了節(jié)省資源開銷。
if (!ActivityManager.isHighEndGfx()) {
ThreadedRenderer.disable(false);
}
}
......
// 如果系統(tǒng)的版本號低于3.1,則設(shè)置AsyncTask的內(nèi)部的線程池實現(xiàn)方法。
if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
......
//系統(tǒng)版本號大于等于 3.0 的話,則開啟嚴(yán)格模式來檢查“是否在主線程開啟了網(wǎng)絡(luò)請求,如果開始了會拋出NetworkOnMainThreadException”。
if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
StrictMode.enableDeathOnNetwork();
}
//??
if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
StrictMode.enableDeathOnFileUriExposure();
}
......
//如果App可debug調(diào)試的話,則進行debug調(diào)試的相關(guān)設(shè)置
if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {
......
}
// 根據(jù)App是否可debug調(diào)試,來設(shè)置是否可以trace進程信息。
boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
Trace.setAppTracingAllowed(isAppDebuggable);
if (isAppDebuggable && data.enableBinderTracking) {
Binder.enableTracing();
}
//初始化http代理
final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
if (b != null) {
// In pre-boot mode (doing initial launch to collect password), not
// all system is up. This includes the connectivity service, so don't
// crash if we can't get it.
final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
try {
final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
Proxy.setHttpProxySystemProperty(proxyInfo);
} catch (RemoteException e) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw e.rethrowFromSystemServer();
}
}
......
// 創(chuàng)建全局唯一Instrumentation實例,該mInstrumentation會在Activity創(chuàng)建完畢執(zhí)行其attach()時保存至Activity內(nèi)部。
if (ii != null) {
try {
//創(chuàng)建Instrumentation實例
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {}
......
mInstrumentation.init(this, instrContext, appContext, component,
data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
......
} else {
mInstrumentation = new Instrumentation();
}
......
try {
//創(chuàng)建App進程的唯一Application實例
//見小節(jié)[2.7]
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
//回調(diào)Instrumentation.onCreate()
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
......
//回調(diào)Application的onCreate()生命周期方法
try {
//見小節(jié)[2.8]
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
......
}
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
......
}
2.7.LoadedApk.makeApplication()
總結(jié):
1:該方法做事是:創(chuàng)建Applicaton實例并執(zhí)行該實例的attachBaseContext()與onCreate()生命周期方法。
2:判斷App進程的Application是否實例化了,如果已經(jīng)創(chuàng)建了則返回該Application。
3:系統(tǒng)采用反射的方式實例化Applation實例,第一步就是先指定“實例化Application的類的全限定名”。
4:通過Instrumentation.newApplication()初始化Application實例并回調(diào)其attachBaseContext()。
5:保存創(chuàng)建完畢的Application實例。
6:通過Instrumentation.callApplicationOnCreate()回調(diào)Application的onCreate()。
源碼
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
//判斷App進程的唯一Application是否創(chuàng)建了,如果創(chuàng)建則直接返回。
//一個進程只有一個Application實例。
if (mApplication != null) {
return mApplication;
}
//記錄 創(chuàng)建Application花費的時間
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
Application app = null;
//指定“實例化Application的類的全限定名”。
//ApplicationInfo記錄的是Manifest文件中<application>中的屬性信息。
//如果“<application>未指定自定義Applcation”或者 “強制使用默認(rèn)的Application”來初始化Application實例的話,則使用默認(rèn)Application來
初始化
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"initializeJavaContextClassLoader");
initializeJavaContextClassLoader();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
//創(chuàng)建ContextImpl實例。
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
//見小節(jié)[2.7.1]
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
......
}
mActivityThread.mAllApplications.add(app);
//保存創(chuàng)建完畢的Application實例
mApplication = app;
//傳入的instrumentation為null,不走這里
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
......
}
}
......
return app;
}
2.7.1.Instrumentation.newApplication()
總結(jié):實例化Application實例并回調(diào)Application的attachBaseContext()生命周期方法。
源碼
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;
}
/* package */ final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
2.8.Instrumentation.callApplicationOnCreate()
總結(jié):實例化Application實例并回調(diào)Application的attachBaseContext()生命周期方法。
源碼
public void callApplicationOnCreate(Application app) {
app.onCreate();
}
3.1.ActivityStackSupervisor.attachApplicationLocked()
總結(jié):從“焦點?!敝蝎@取“處于棧頂?shù)拇龁覣ctivity對應(yīng)的ActivityRecord”并激活此ActivityRecord描述的App進程的Activity。
1:一個ActivityDisplay實例表示一塊屏幕,一個ActivityDisplay實例中存儲了多個ActivityStack實例。
2:遍歷每個ActivityDisplay中的ActivityStack集合,找到ActivityDisplay中的那個“焦點棧(ActivityStackSupervisor.mFocusedStack)”。
3:找到“焦點?!敝?,調(diào)用其topRunningActivityLocked()從其內(nèi)部保存TaskRecord列表中找到“處于棧頂?shù)拇龁覣ctivity對應(yīng)的ActivityRecord”。
4:調(diào)用ActivityStackSupervisor.realStartActivityLocked()激活處于焦點棧的待啟動Activity。
源碼
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
//獲取App進程名
final String processName = app.processName;
boolean didSomething = false;
//遍歷ActivityDisplay集合。
//一個ActivityDisplay實例表示一塊屏幕,一個ActivityDisplay實例中存儲了多個ActivityStack實例。
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
//遍歷每個ActivityDisplay中的ActivityStack集合。
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
//找到ActivityDisplay中的那個“焦點?!?。
if (!isFocusedStack(stack)) {
continue;
}
//從“焦點?!敝蝎@取“處于棧頂?shù)拇龁覣ctivity”。
ActivityRecord hr = stack.topRunningActivityLocked();
if (hr != null) {
//待啟動Activity對應(yīng)的ActivityRecord信息只是添加到了AMS中的“Activity?!敝?具體是保存到ActivityTask中的TaskRecord列表中)。
//該Activity實例還沒有在App進程進行實例化,此時“ActivityRecord中保存的用于描述其所屬進程的ProcessRecord還未被賦值”。所以ActivityRecord.app為null。
//檢查“待啟動Activity是否未被添加到所屬進程”、“App進程的uid與待啟動Activity在Manifest中聲明的uid一致”、“App進程名與從Manifest文件中解析出的進程名一致”這3個條件是否都滿足。
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
//見小節(jié)[3.2]
if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ hr.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
}
if (!didSomething) {
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
return didSomething;
}
3.2.ActivityStackSupervisor.realStartActivityLocked()
總結(jié):
1:檢查是否“所有的ActivityStack中的mPausingActivity表示的正在處于暫停狀態(tài)的Activity執(zhí)行完畢暫停操作了”。如果還有ActivityStack種的Activity正在執(zhí)行暫停操作的話,則先不會執(zhí)行待啟動 Activity 的激活操作。
2:把描述App進程信息的ProcessRecord對象保存至ActivityRecord中。
3:通知App進程執(zhí)行“ scheduleLaunchActivity()”操作,在App進程進行待啟動Activity的實例化、各種生命周期方法的執(zhí)行、相應(yīng)PhoneWindow維護的View樹的繪制等操作。**
源碼
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
//檢查是否“所有的ActivityStack中的mPausingActivity表示的正在處于暫停狀態(tài)的Activity執(zhí)行完畢暫停操作了”
if (!allPausedActivitiesComplete()) {
......
return false;
}
......
//把描述App進程信息的ProcessRecord對象保存至ActivityRecord中。
r.app = app;
......
try {
......
//見小節(jié)[3.3]
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);
......
} catch (RemoteException e) {
......
}
......
//andResume為true,走這里
//見小節(jié)[4.1]
if (andResume) {
stack.minimalResumeActivityLocked(r);
} else {
......
r.state = PAUSED;
}
......
return true;
}
3.3.ApplicationThread.scheduleLaunchActivity()
總結(jié):通過Binder IPC方式,通知App進程執(zhí)行待啟動Activity的啟動操作。
1:緩存AMS傳遞給App進程的參數(shù)信息(eg:startsNotResumed被賦值為了false,該值表示“是否需要禁止Resume待啟動Activity”。如果禁止就會執(zhí)行該Activity的pasue操作。true:禁止,false:不禁止)。
1:ApplicationThread作為Binder通信的服務(wù)端,其內(nèi)部操作是通過Handler消息機制,向App進程的主線程發(fā)一個“LAUNCH_ACTIVITY”消息,使操作切換至主線程繼續(xù)后續(xù)執(zhí)行。
2:該操作是一次IPC過程,涉及到進程切換,從AMS所在的system_server進程切換至App進程。AMS要想主動發(fā)起與App進程的通信,就得借助于Binder這種IPC方式,因為ApplicationThread承擔(dān)的是服務(wù)端的角色,客戶端發(fā)起的請求,服務(wù)端接收后都會把這些操作扔到Bidner線程池中執(zhí)行,這樣做的好處是提高了服務(wù)端的“并發(fā)”性能。
源碼
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) {
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;
//該值為false,在AMS所在的system_server通過Binder請求App進程的時候,notResumed為賦值為了“!andResume”,而andResume為true。
//該值表示“是否禁止Resume待啟動Activity”,如果禁止就會執(zhí)行該Activity的pasue操作。true:禁止,false:不禁止。
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
由于文章字?jǐn)?shù)過長,請查看App啟動流程:App進程內(nèi)部操作-2。
重要類說明
ApplicationThread
- 從Android8.0開始,很多用于Binder IPC的類改用AIDL的方式實現(xiàn),其中ApplicationThread的實現(xiàn)也發(fā)生了改變。
- 該類由原來繼承自
ApplicationThreadNative改為在8.0版本繼承自IApplicationThread.Stub。但是不管怎么變,我們可以知道 ApplicationThread還是用來做IPC通信的,且它在Binder這種CS架構(gòu)中擔(dān)任的是 服務(wù)端角色。
ServiceManager
- IServiceManager sServiceManager:該IServiceManager接口的實例可以用來“查詢其它服務(wù)”(eg:從system_server進程獲取AMS服務(wù)的本進程代理)。
- HashMap<String, IBinder> sCache:用于緩存系統(tǒng)服務(wù)在本進程的Binder代理對象。
- initServiceCache():緩存系統(tǒng)服務(wù)在App進程的Binder服務(wù)。當(dāng)App冷啟動完畢后,會執(zhí)行“AMS.attachApplication()”,在該方法內(nèi)部經(jīng)過層層調(diào)用,會通過傳入的App進程內(nèi)唯一的ApplicationThread實例通過Binder這種IPC方式,回調(diào)執(zhí)行子進程的 bindApplication() 用于“初始化App進程的唯一Application實例”。在初始化之前,會首先執(zhí)行 SystemService.initServiceCache()緩存系統(tǒng)服務(wù)在App進程的Binder服務(wù)”。
-
getService():獲取系統(tǒng)服務(wù)在本進程的Binder代理對象。
1:如果ServiceManager內(nèi)部的HashMap緩存了此Binder服務(wù)的話,則返回。
2:如果沒有,則通過getIServiceManager().getService()通過Binder驅(qū)動獲取Native層ServiceManager的Binder服務(wù)后,再通過ServiceManager獲取已向其注冊的相應(yīng)Binder服務(wù)在本進程的Binder代理對象。
3:這個Binder代理對象與系統(tǒng)服務(wù)對象不是一個。因為AMS運行在system_server進程,此對象運行在 App進程。采用“進程隔離”的方式,每個進程都有自己的 虛擬內(nèi)存地址空間,且每個進程被分配的虛擬內(nèi)存地址都不一樣,這就導(dǎo)致每個進程可訪問的內(nèi)存區(qū)域是不一樣的,進程之間沒有交集,這就避免了 “修改進程A內(nèi)存區(qū)域會影響到進程B內(nèi)存中的數(shù)據(jù)”。
Instrumentation
作用:
1:用于檢測,Application、Activity各個生命周期方法的執(zhí)行。
之所以能檢測,是因為在Instrumentation內(nèi)部的相應(yīng)方法內(nèi)部,會執(zhí)行Application、Activity相應(yīng)生命周期方法的執(zhí)行。
也可以說“Application、Activity各個生命周期方法的執(zhí)行是通過Instrumentation中的相應(yīng)方法來觸發(fā)的”。
2:用于檢測,Activity啟動結(jié)果是否成功。
Activity 通過Intent進行跳轉(zhuǎn)的操作,被封裝到該類的execStartActivity()中去進一步執(zhí)行。
2.1:在啟動目標(biāo)Activity時會通過執(zhí)行該類的execStartActivity()。
2.2:首先,通過AMS.startActivity()啟動目標(biāo)Activity。不論啟動是否成功,都會返回一個int類型的result。
2.3:其次,會通過checkStartActivityResult()來檢查Activity啟動結(jié)果。
返回的啟動結(jié)果在[-100,-1]范圍的話,則會根據(jù)實際的res值拋出相應(yīng)的異常,用于提示此次啟動Activity具體是因為什么問題而導(dǎo)致啟動失敗了。
(像是常見的,Activity沒有在manifest文件注冊導(dǎo)致的拋出ActivityNotFoundException的原因等)。
3:其他使用場景:
3.1:自定義檢測器(這個好像是用于Android 測試的),可以監(jiān)聽Application、Activity的各個生命周期方法調(diào)用。
就像該類的說明一下,此類是“實現(xiàn)應(yīng)用程序檢測代碼的基類”。
要想自定義“檢測器的話”,可以在Manifest文件中通過<instrumentation>指定具體的自定義檢測器。
3.2:可以Hook Instrumentation來達(dá)到監(jiān)聽Application、Activity 的目的。因為它在App進程中是唯一的,Application、Activity各個生命周期方法的執(zhí)行是通過Instrumentation中的相應(yīng)方法來觸發(fā)的。所以說Instrumentation作為Hook點來說是比較“穩(wěn)定”的,因為它在App進程中只有一個實例。
ActivityClientRecord :
- 在App進程每個Acticity組件都有一個該類的對象來對已啟動Activity組件進行描述。
- 該類與ActivityRecord相對應(yīng)。
- 該類存儲在App進程,而ActivityRecord則存儲在SystemServer進程中的AMS中的Activity棧結(jié)構(gòu)中。
Activity
重要屬性:
1:mStartedActivity
作用:該屬性表示“是否啟動了其他Activity”。該屬性只有在Activity的幾個startXX()(
startActivityForResult()、startActivityIfNeeded()、startActivityForResultAsUser()等等)方法被重置為true,默認(rèn)值為false。
1:如果mStartedActivity為true,則表示啟動了其他Activity,進一步則會使當(dāng)前Activity不可見。
2:如果為false,則表示可見。