Android四大組件

frameworks/base/services/core/java/com/android/server/am/
  - ActivityManagerService.java
  - ProcessRecord
  - ActivityStackSupervisor.java 
  - ActivityStack.java
  - ActiveServices
  - BroadcastQueue

一. 引言

Android系統(tǒng)內(nèi)部非常復(fù)雜,經(jīng)層層封裝后,app只需要簡單的幾行代碼便可完成任一組件的啟動/結(jié)束、 生命周期的操作。然而每一次看似簡單的操作,背后所有的復(fù)雜工作都是交由系統(tǒng)來完成。

組件啟動后,首先需要依賴進(jìn)程,那么就需要先創(chuàng)建進(jìn)程,系統(tǒng)需要記錄每個進(jìn)程,這便產(chǎn)生了ProcessRecord。 Android中,對于進(jìn)程的概念被弱化,通過抽象后的四大組件。讓開發(fā)者幾乎感受不到進(jìn)程的存在。 當(dāng)應(yīng)用退出時,進(jìn)程也并非馬上退出,而是成為cache/empty進(jìn)程,下次該應(yīng)用再啟動的時候,可以不用 再創(chuàng)建進(jìn)程直接初始化組件即可,提高啟動速度。先來說一說進(jìn)程。

二. 進(jìn)程管理

Android系統(tǒng)中用于描述進(jìn)程的數(shù)據(jù)結(jié)構(gòu)是ProcessRecord對象,AMS便是管理進(jìn)程的核心模塊。四大組件 (Activity,Service, BroadcastReceiver, ContentProvider)定義在AndroidManifest.xml文件, 每一項都可以用屬性android:process指定所運行的進(jìn)程。同一個app可以運行在通過一個進(jìn)程,也可以運行在多個進(jìn)程, 甚至多個app可以共享同一個進(jìn)程。例如:AndroidManifest.xml中定義Service:

<service android:name =".GityuanService" android:process =":remote" >  
    <intent-filter>  
       <action android:name ="com.action.gityuan" />  
    </intent-filter>  
</service>

GityuanService這個服務(wù)運行在remote進(jìn)程。

2.1 進(jìn)程關(guān)系圖

以一幅圖來展示AMS管理進(jìn)程的相關(guān)成員變量以及ProcessRecord對象:

點擊查看大圖

[圖片上傳中...(image-dc86ea-1513257973227-2)]

2.2 進(jìn)程與AMS的關(guān)聯(lián)

這里只介紹AMS的進(jìn)程相關(guān)的成員變量:

  1. mProcessNames:數(shù)據(jù)類型為ProcessMap<processrecord style="box-sizing: border-box; user-select: text !important;">,以進(jìn)程名和userId為key來記錄ProcessRecord;</processrecord>
    • 添加進(jìn)程,addProcessNameLocked()
    • 刪除進(jìn)程,removeProcessNameLocked()
  2. mPidsSelfLocked: 數(shù)據(jù)類型為SparseArray<processrecord style="box-sizing: border-box; user-select: text !important;">,以進(jìn)程pid為key來記錄ProcessRecord;</processrecord>
    • startProcessLocked(),移除已存在進(jìn)程,增加新創(chuàng)建進(jìn)程pid信息;
    • removeProcessLocked,processStartTimedOutLocked,cleanUpApplicationRecordLocked移除進(jìn)程;
  3. mLruProcesses:數(shù)據(jù)類型為ArrayList<processrecord style="box-sizing: border-box; user-select: text !important;">,以進(jìn)程最近使用情況來排序記錄ProcessRecord;</processrecord>
    • 其中第一個元素代表的便是最近最少使用的進(jìn)程;
    • updateLruProcessLocked()更新進(jìn)程隊列位置;
  4. mRemovedProcesses:數(shù)據(jù)類型為ArrayList<processrecord style="box-sizing: border-box; user-select: text !important;">,記錄所有需要強制移除的進(jìn)程;</processrecord>
  5. mProcessesToGc:數(shù)據(jù)類型為ArrayList<processrecord style="box-sizing: border-box; user-select: text !important;">,記錄系統(tǒng)進(jìn)入idle狀態(tài)需執(zhí)行g(shù)c操作的進(jìn)程;</processrecord>
  6. mPendingPssProcesses:數(shù)據(jù)類型為ArrayList<processrecord style="box-sizing: border-box; user-select: text !important;">,記錄將要收集內(nèi)存使用數(shù)據(jù)PSS的進(jìn)程;</processrecord>
  7. mProcessesOnHold:數(shù)據(jù)類型為ArrayList<processrecord style="box-sizing: border-box; user-select: text !important;">,記錄剛開機(jī)過程,系統(tǒng)還沒與偶準(zhǔn)備就緒的情況下, 所有需要啟動的進(jìn)程都放入到該隊列;</processrecord>
  8. mPersistentStartingProcesses:數(shù)據(jù)類型ArrayList<processrecord style="box-sizing: border-box; user-select: text !important;">,正在啟動的persistent進(jìn)程;</processrecord>
  9. mHomeProcess: 記錄包含home Activity所在的進(jìn)程;
  10. mPreviousProcess:記錄用戶上一次剛訪問的進(jìn)程;其中mPreviousProcessVisibleTime記錄上一個進(jìn)程的用戶訪問時間;
  11. mProcessList: 數(shù)據(jù)類型ProcessList,用于進(jìn)程管理,Adj常量定義位于該文件;

其中最為常見的是mProcessNames,mPidsSelfLocked,mLruProcesses這3個對象;

2.3 進(jìn)程與組件的關(guān)聯(lián)

系統(tǒng)AMS這邊是由ProcessRecord對象記錄進(jìn)程,進(jìn)程自身比較重要成員變量如下:

  1. processName:記錄進(jìn)程名,默認(rèn)情況下進(jìn)程名和該進(jìn)程運行的第一個apk的包名是相同的,當(dāng)然也可以自定義進(jìn)程名;
  2. pid: 記錄進(jìn)程pid,該值在由進(jìn)程創(chuàng)建時內(nèi)核所分配的。
  3. thread:執(zhí)行完attachApplicationLocked()方法,會把客戶端進(jìn)程ApplicationThread的binder服務(wù)的代理端傳遞到 AMS,并保持到ProcessRecord的成員變量thread;
    • ProcessRecord.makeActive,賦值;
    • ProcessRecord.makeInactive,清空;
  4. info:記錄運行在該進(jìn)程的第一個應(yīng)用;
  5. pkgList: 記錄運行在該進(jìn)程中所有的包名,比如通過addPackage()添加;
  6. pkgDeps:記錄該進(jìn)程所依賴的包名,比如通過addPackageDependency()添加;
  7. lastActivityTime:每次updateLruProcessLocked()過程會更新該值;
  8. killedByAm:當(dāng)值為true,意味著該進(jìn)程是被AMS所殺,而非由于內(nèi)存低而被LMK所殺;
  9. killed:當(dāng)值為true,意味著該進(jìn)程被殺,不論是AMS還是其他方式;
  10. waitingToKill:比如cleanUpRemovedTaskLocked()過程會賦值為”remove task”,當(dāng)該進(jìn)程處于后臺且

任一組件都運行在某個進(jìn)程,再來說說ProcessRecord對象中與組件的關(guān)聯(lián)關(guān)系:

成員變量 說明 對應(yīng)組件
activities 記錄進(jìn)程的ActivityRecord列表 Activity
services 記錄進(jìn)程的ActivityRecord列表 Service
executingServices 記錄進(jìn)程的正在執(zhí)行的ActivityRecord列表 Service
connections 記錄該進(jìn)程bind的ConnectionRecord集合 Service
receivers 動態(tài)注冊的廣播接收者ReceiverList集合 Broadcast
curReceiver 當(dāng)前正在處理的一個廣播BroadcastRecord Broadcast
pubProviders 該進(jìn)程發(fā)布的ContentProviderRecord的map表 ContentProvider
conProviders 該進(jìn)程所請求的ContentProviderConnection列表 ContentProvider

說明:

  • connections:舉例來說,進(jìn)程A調(diào)用bindService()方法去bind遠(yuǎn)程進(jìn)程B的Service。 此時會在進(jìn)程A的ProcessRecord.connections添加一個ConnectionRecord.
  • pubProviders: 該進(jìn)程所有對外發(fā)布的ContentProvider信息,這是是以ArrayMap形式保存,即 以provider的name為key,以ContentProviderRecord為value的鍵值對結(jié)構(gòu)體。
  • conProviders: 當(dāng)進(jìn)程A調(diào)用query()的過程,會執(zhí)行g(shù)etContentProvider()方法去向進(jìn)程B請求 provider的代理。此時會在進(jìn)程A的ProcessRecord.conProviders添加一個ContentProviderConnection。

三. AMS的組件管理

組件啟動,先填充完進(jìn)程信息,接下來還需要完善組件本身的信息,各個組件在system_server的核心信息記錄如下:

  • Service的信息記錄在ActiveServices和AMS
  • Broadcast信息記錄在BroadcastQueue和AMS
  • Activity信息記錄在ActivityStack,ActivityStackSupervisor,以及AMS;
  • Provider信息記錄在ProviderMap和AMS;

可見,AMS是整個四大組件最為核心的對象,所有組件都或多或少依賴該對象的數(shù)據(jù)結(jié)構(gòu)信息。 關(guān)系圖如下:點擊查看大圖

[圖片上傳中...(image-5a3c91-1513257973227-1)]

3.1 Activity

AMS對象

public final class ActivityManagerService extends ...{
    //當(dāng)前聚焦的Activity
    ActivityRecord mFocusedActivity = null;
    //用于管理各個Activity棧
    final ActivityStackSupervisor mStackSupervisor;
}

ASS對象

public final class ActivityStackSupervisor implements DisplayListener {
    //桌面app所在棧
    ActivityStack mHomeStack;

    //當(dāng)前可以接受Input事件,或許啟動下一個Activity的棧
    ActivityStack mFocusedStack;

    //當(dāng)該值等于mFocusedStack,代表當(dāng)前棧頂?shù)腁ctivity已進(jìn)入resumed狀態(tài);
    //當(dāng)該值等于上一個舊棧時,代表正處理activity切換狀態(tài);
    private ActivityStack mLastFocusedStack;

    //在完成相應(yīng)目標(biāo)前,等待新的Activity成為可見的Activity列表
    final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<>();

    //等待找到下一個可見Activity的等待列表
    final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible = new ArrayList<>();

    //等待找到下一個已啟動Activity的等待列表
    final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched = new ArrayList<>();

    //等待上一個activity安置完成,則即將進(jìn)入被stopped的Activity列表
    final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<>();

    //等待上一個activity安置完成,則即將進(jìn)入被finished的Activity列表
    final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<>();

    //即將進(jìn)入sleep狀態(tài)的進(jìn)程所對應(yīng)的Activity列表
    final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<>();
}

AS對象

final class ActivityStack{
    //記錄該棧中所有的task
    private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();

    //按LRU方式排序的Activity列表,隊尾成員是最新活動的Activity
    final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();

    //正在執(zhí)行pausing過程的Activity
    ActivityRecord mPausingActivity = null;

    //已處于paused狀態(tài)的Activity
    ActivityRecord mLastPausedActivity = null;

    //已處于Resumed狀態(tài)的Activity
    ActivityRecord mResumedActivity = null;
}

3.2 Service

[-> ActiveServices.java]

public final class ActiveServices {
    //記錄不同User下所有的Service信息
    final SparseArray<ServiceMap> mServiceMap = new SparseArray<>();

    //bind service的連接信息,以IServiceConnection的Bp端作為Keys
    final ArrayMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections = new ArrayMap<>();

    //已請求啟動但尚未啟動的Service列表
    final ArrayList<ServiceRecord> mPendingServices = new ArrayList<>();

    //crash后需要計劃重啟的Service列表
    final ArrayList<ServiceRecord> mRestartingServices = new ArrayList<>();

    //正在執(zhí)行destroyed的service列表
    final ArrayList<ServiceRecord> mDestroyingServices = new ArrayList<>();
}

3.3 Broadcast

[-> ActivityManagerService.java]

public final class ActivityManagerService extends ...{
    //前臺廣播隊列
    BroadcastQueue mFgBroadcastQueue;
    //后臺廣播隊列
    BroadcastQueue mBgBroadcastQueue;
    //廣播隊列數(shù)組,也就是前臺和后臺廣播隊列
    final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[2];

    //粘性廣播,[userId,action,ArrayList<Intent>]
    final SparseArray<ArrayMap<String, ArrayList<Intent>>> mStickyBroadcasts;

    //動態(tài)注冊的廣播接收者,其中key為客戶端InnerReceiver的Bp端,value為ReceiverList
    final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();

    //從廣播intent到已注冊接收者的解析器
    final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver;
}

[-> BroadcastQueue.java]

public final class BroadcastQueue{
    //并行廣播列表
    final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();
    //串行廣播列表
    final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<>();

    //即將要處理的串行廣播,等待目標(biāo)進(jìn)程創(chuàng)建完成。每個廣播隊列只有一個,其他必須等待該廣播完成。
    BroadcastRecord mPendingBroadcast = null;
}

3.4 Provider

[-> ActivityManagerService.java]

public final class ActivityManagerService extends ...{
    //記錄系統(tǒng)所有的provider信息
    final ProviderMap mProviderMap;

    //記錄有client正在等待的provider列表,當(dāng)provider發(fā)布完成則從該隊列移除
    final ArrayList<ContentProviderRecord> mLaunchingProviders;
}

[-> ProviderMap.java]

public final class ProviderMap {
    //以provider名字(auth)為key的方式所記錄的provider信息
    private final HashMap<String, ContentProviderRecord> mSingletonByName;
    //以provider組件名(ComponentName)為key的方式所記錄的provider信息
    private final HashMap<ComponentName, ContentProviderRecord> mSingletonByClass;

    //記錄不同UserId下的,以auth為key的方式所記錄的provider信息
    private final SparseArray<HashMap<String, ContentProviderRecord>> mProvidersByNamePerUser;
    //記錄不同UserId下的,以ComponentName為key的方式所記錄的provider信息
    private final SparseArray<HashMap<ComponentName, ContentProviderRecord>> mProvidersByClassPerUser;
}

同一個provider組件名,可能對應(yīng)多個provider名。

四. App端的組件信息

關(guān)系圖如下:點擊查看大圖

[圖片上傳中...(image-6b8d58-1513257973227-0)]

App端的組件信息,都保存在ActivityThread和LoadedApk這兩個對象,主要保存信息:

  • ActivityThread:記錄provider, activity, service在客戶端的相關(guān)信息;
  • LoadedApk: 記錄動態(tài)注冊的廣播接收器,以及bind方式啟動service在客戶端的相關(guān)信息;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容