關於作者
郭孝星,程式設計師,吉他手,主要從事Android平臺基礎架構方面的工作,歡迎交流技術方面的問題,可以去我的Github提issue或者發郵件至guoxiaoxingse@163.com與我交流。
文章目錄
- 一 元件管家ActivityManagerService
- 1.1 ActivityManagerService啟動流程
- 1.1 ActivityManagerService工作流程
- 二 應用主執行緒ActivityThread
- 2.1 ActivityThread啟動流程
- 2.2 ActivityThread工作
ActivityManagerService是貫穿Android系統元件的核心服務,在ServiceServer執行run()方法的時候被建立,執行在獨立的執行緒中,負責Activity、Service、BroadcastReceiver的啟動、切換、排程以及應用程式的管理和排程工作。
Activity、Service、BroadcastReceiver的啟動、切換、排程都有著相似的流程,我們來看一下。
Activity的啟動流程圖(放大可檢視)如下所示:
![Android元件框架:Android元件管理者ActivityManager](https://i.iter01.com/images/b0f7a5a72a3bc9a372b52e350b852cdfa90a40a780d386512866893d774c8e07.png)
主要角色有:
- Instrumentation: 監控應用與系統相關的互動行為。
- AMS:元件管理排程中心,什麼都不幹,但是什麼都管。
- ActivityStarter:處理Activity什麼時候啟動,怎麼樣啟動相關問題,也就是處理Intent與Flag相關問題,平時提到的啟動模式都可以在這裡找到實現。
- ActivityStackSupervisior:這個類的作用你從它的名字就可以看出來,它用來管理Stack和Task。
- ActivityStack:用來管理棧裡的Activity。
- ActivityThread:最終幹活的人,是ActivityThread的內部類,Activity、Service、BroadcastReceiver的啟動、切換、排程等各種操作都在這個類裡完成。
Service的啟動流程圖(放大可檢視)如下所示:
![Android元件框架:Android元件管理者ActivityManager](https://i.iter01.com/images/2145343805a3cf44f97ca46fe94a1adff3c7462d2da6c8249fb857d5e07f5bf1.png)
主要角色有:
- AMS:元件管理排程中心,什麼都不幹,但是什麼都管。
- ApplicationThread:最終幹活的人,是ActivityThread的內部類,Activity、Service、BroadcastReceiver的啟動、切換、排程等各種操作都在這個類裡完成。
- ActiveServices:主要用來管理Service,內部維護了三份列表:將啟動Service列表、重啟Service列表以及以銷燬Service列表。
BroadcastReceiver的啟動流程圖(放大可檢視)如下所示:
![Android元件框架:Android元件管理者ActivityManager](https://i.iter01.com/images/c4b0ed38408de4dadab7347f2515d881e7b8653b28bdc9f47abddc59a35379e5.png)
主要角色有:
- AMS:元件管理排程中心,什麼都不幹,但是什麼都管。
- BroadcastQueue:廣播佇列,根據廣播的優先順序來管理廣播。
- ApplicationThread:最終幹活的人,是ActivityThread的內部類,Activity、Service、BroadcastReceiver的啟動、切換、排程等各種操作都在這個類裡完成。
- ReceiverDispatcher:廣播排程中心,採用反射的方式獲取BroadcastReceiver的例項,然後呼叫它的onReceive()方法。
可以發現,除了一些輔助類外,最主要的元件管家AMS和應用主執行緒ActivityThread。本篇文章重點分析這兩個類的實現,至於其他類會在 Activity、Service與BroadcastReceiver啟動流程的文章中一一分析。
通過上面的分析,AMS的整個排程流程就非常明朗了。
ActivityManager相當於前臺接待,她將客戶的各種需求傳達給大總管ActivityMangerService,但是大總管自己不幹活,他招來了很多小弟,他最信賴的小弟ActivityThread 替他完成真正的啟動、切換、以及退出操作,至於其他的中間環節就交給ActivityStack、ActivityStarter等其他小弟來完成。
一 元件管家ActivityManagerService
1.1 ActivityManagerService啟動流程
我們知道所有的系統服務都是在SystemServer的run()方法裡啟動的,SystemServer 將系統服務分為了三類:
- 引導服務
- 核心服務
- 其他服務
ActivityManagerService屬於引導服務,在startBootstrapServices()方法裡被建立,如下所示:
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
複製程式碼
SystemServiceManager的startService()方法利用反射來建立物件,Lifecycle是ActivityManagerService裡的靜態內部類,它繼承於SystemService,在它的構造方法裡 它會呼叫ActivityManagerService的構造方法建立ActivityManagerService物件。
public static final class Lifecycle extends SystemService {
private final ActivityManagerService mService;
public Lifecycle(Context context) {
super(context);
mService = new ActivityManagerService(context);
}
@Override
public void onStart() {
mService.start();
}
public ActivityManagerService getService() {
return mService;
}
}
複製程式碼
ActivityManagerService的構造方法如下所示:
public ActivityManagerService(Context systemContext) {
mContext = systemContext;
mFactoryTest = FactoryTest.getMode();
mSystemThread = ActivityThread.currentActivityThread();
Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
//建立並啟動系統執行緒以及相關Handler
mHandlerThread = new ServiceThread(TAG,
android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
mHandlerThread.start();
mHandler = new MainHandler(mHandlerThread.getLooper());
mUiHandler = new UiHandler();
/* static; one-time init here */
if (sKillHandler == null) {
sKillThread = new ServiceThread(TAG + ":kill",
android.os.Process.THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
sKillThread.start();
sKillHandler = new KillHandler(sKillThread.getLooper());
}
//建立用來儲存各種元件Activity、Broadcast的資料結構
mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
"foreground", BROADCAST_FG_TIMEOUT, false);
mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
"background", BROADCAST_BG_TIMEOUT, true);
mBroadcastQueues[0] = mFgBroadcastQueue;
mBroadcastQueues[1] = mBgBroadcastQueue;
mServices = new ActiveServices(this);
mProviderMap = new ProviderMap(this);
mAppErrors = new AppErrors(mContext, this);
//建立system等各種資料夾,用來記錄系統的一些事件
...
//初始化一些記錄工具
...
}
複製程式碼
可以發現,ActivityManagerService的構造方法主要做了兩個事情:
- 建立並啟動系統執行緒以及相關Handler。
- 建立用來儲存各種元件Activity、Broadcast的資料結構。
這裡有個問題,這裡建立了兩個Hanlder(sKillHandler暫時忽略,它是用來kill程式的)分別是MainHandler與UiHandler,它們有什麼區別呢??
我們知道Handler是用來向所線上程傳送訊息的,也就是說決定Handler定位的是它構造方法裡的Looper,我們分別來看下。
MainHandler裡的Looper來源於執行緒ServiceThread,它的執行緒名是"ActivityManagerService",該Handler主要用來處理元件排程相關操作。
mHandlerThread = new ServiceThread(TAG,
android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
mHandlerThread.start();
mHandler = new MainHandler(mHandlerThread.getLooper());
複製程式碼
UiHandler裡的Looper來源於執行緒UiThread(繼承於ServiceThread),它的執行緒名"android.ui",該Handler主要用來處理UI相關操作。
private UiThread() {
super("android.ui", Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
// Make sure UiThread is in the fg stune boost group
Process.setThreadGroup(Process.myTid(), Process.THREAD_GROUP_TOP_APP);
}
public UiHandler() {
super(com.android.server.UiThread.get().getLooper(), null, true);
}
複製程式碼
以上便是整個ActivityManagerService的啟動流程,還是比較簡單的。
1.2 ActivityManagerService工作流程
ActivityManagerService就是ActivityManager家族 的核心類了,四大元件的啟動、切換、排程都是在ActivityManagerService裡完成的。
ActivityManagerService類圖如下所示:
![Android元件框架:Android元件管理者ActivityManager](https://i.iter01.com/images/fbec633ec2b70207d2df833ae773cd160b97073caa8473a4da4ce8f8bbed310e.png)
- ActivityManager:AMS給客戶端呼叫的介面。
- ActivityManagerNative:該類是ActivityManagerService的父類,繼承與Binder,主要用來負責程式通訊,接收ActivityManager傳遞過來的資訊,這麼寫可以將通訊部分分離在ActivityManagerNative,使得 ActivityManagerService可以專注元件的排程,減小了類的體積。
- ActivityManagerProxy:該類定義在ActivityManagerNative內部,正如它的名字那樣,它是ActivityManagerService的代理類,
關於ActivityManager
ActivityManager是提供給客戶端呼叫的介面,日常開發中我們可以利用 ActivityManager來獲取系統中正在執行的元件(Activity、Service)、程式(Process)、任務(Task)等資訊,ActivityManager定義了相應的方法來獲取和操作這些資訊。
ActivityManager定義了很多靜態內部類來描述這些資訊,具體說來:
- ActivityManager.StackId: 描述元件棧ID資訊
- ActivityManager.StackInfo: 描述元件棧資訊,可以利用StackInfo去系統中檢索某個棧。
- ActivityManager.MemoryInfo: 系統可用記憶體資訊
- ActivityManager.RecentTaskInfo: 最近的任務資訊
- ActivityManager.RunningAppProcessInfo: 正在執行的程式資訊
- ActivityManager.RunningServiceInfo: 正在執行的服務資訊
- ActivityManager.RunningTaskInfo: 正在執行的任務資訊
- ActivityManager.AppTask: 描述應用任務資訊
說道這裡,我們有必要區分一些概念,以免以後混淆。
- 程式(Process):Android系統進行資源排程和分配的基本單位,需要注意的是同一個棧的Activity可以執行在不同的程式裡。
- 任務(Task):Task是一組以棧的形式聚集在一起的Activity的集合,這個任務棧就是一個Task。
在日常開發中,我們一般是不需要直接操作ActivityManager這個類,只有在一些特殊的開發場景才用的到。
- isLowRamDevice():判斷應用是否執行在一個低記憶體的Android裝置上。
- clearApplicationUserData():重置app裡的使用者資料。
- ActivityManager.AppTask/ActivityManager.RecentTaskInfo:我們如何需要操作Activity的棧資訊也可以通過ActivityManager來做。
關於ActivityManagerNative與ActivityManagerProxy
這兩個類其實涉及的是Android的Binder通訊原理,後面我們會有專門的文章來分析Binder相關實現。
二 應用主執行緒ActivityThread
ActivityThread管理著應用程式裡的主執行緒,負責Activity、Service、BroadcastReceiver的啟動、切換、 以及銷燬等操作。
2.1 ActivityThread啟動流程
先來聊聊ActivityThread,這個類也厲害了?,它就是我們app的入口,寫過Java程式的同學都知道,Java程式的入口類都會有一個main()方法,ActivityThread也是這樣,它的main()方法在新的應用 程式被建立後就會被呼叫,我們來看看這個main()方法實現了什麼東西。
public final class ActivityThread {
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
//主執行緒的looper
Looper.prepareMainLooper();
//建立ActivityThread例項
ActivityThread thread = new ActivityThread();
//呼叫attach()方法將ApplicationThread物件關聯給AMS,以便AMS呼叫ApplicationThread裡的方法,這同樣也是一個IPC的過程。
thread.attach(false);
//主執行緒的Handler
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//開始訊息迴圈
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
複製程式碼
這裡面還有關鍵的attach()方法,我們來看一下。
public final class ActivityThread {
private void attach(boolean system) {
sCurrentActivityThread = this;
//判斷是否為系統程式,上面傳過來的為false,表明它不是一個系統程式
mSystemThread = system;
//應用程式的處理流程
if (!system) {
ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
//將ApplicationThread物件關聯給AMS,以便AMS呼叫ApplicationThread裡的方法,這
//同樣也是一個IPC的過程。
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
// Watch for getting close to heap limit.
BinderInternal.addGcWatcher(new Runnable() {
@Override public void run() {
if (!mSomeActivitiesChanged) {
return;
}
Runtime runtime = Runtime.getRuntime();
long dalvikMax = runtime.maxMemory();
long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
if (dalvikUsed > ((3*dalvikMax)/4)) {
if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
+ " total=" + (runtime.totalMemory()/1024)
+ " used=" + (dalvikUsed/1024));
mSomeActivitiesChanged = false;
try {
mgr.releaseSomeActivities(mAppThread);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
});
}
//系統程式的處理流程
else {
//初始化系統元件,例如:Instrumentation、ContextImpl、Application
//系統程式的名稱為system_process
android.ddm.DdmHandleAppName.setAppName("system_process",
UserHandle.myUserId());
try {
//建立Instrumentation物件
mInstrumentation = new Instrumentation();
//建立ContextImpl物件
ContextImpl context = ContextImpl.createAppContext(
this, getSystemContext().mPackageInfo);
//建立Application物件
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
//呼叫Application.onCreate()方法,這個方法我們非常熟悉了,我們經常在這裡做一些初始化庫的工作。
mInitialApplication.onCreate();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate Application():" + e.toString(), e);
}
}
// add dropbox logging to libcore
DropBox.setReporter(new DropBoxReporter());
//註冊Configuration變化後的回撥通知,當系統配置發生變化時,例如:語言切換,觸發該回撥。
ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
//配置發生變化
@Override
public void onConfigurationChanged(Configuration newConfig) {
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(newConfig, null)) {
updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
mResourcesManager.getConfiguration().getLocales());
// This actually changed the resources! Tell
// everyone about it.
if (mPendingConfiguration == null ||
mPendingConfiguration.isOtherSeqNewer(newConfig)) {
mPendingConfiguration = newConfig;
sendMessage(H.CONFIGURATION_CHANGED, newConfig);
}
}
}
}
//低記憶體
@Override
public void onLowMemory() {
}
@Override
public void onTrimMemory(int level) {
}
});
}
}
複製程式碼
從上面這兩個方法我們可以看出ActivityThread主要做了兩件事情:
- 建立並開啟主執行緒的訊息迴圈。
- 將ApplicationThread物件(Binder物件)關聯給AMS,以便AMS呼叫ApplicationThread裡的方法,這同樣也是一個IPC的過程。
2.2 ActivityThread工作流程
ActivityThread工作流程圖如下所示:
![Android元件框架:Android元件管理者ActivityManager](https://i.iter01.com/images/e5fcf0fc3adc6704cfd24332ecfd2d279039d78633c0ab9302c5a65082e428a8.png)
通過前面的分析,ActivityThread的整個工作流程就非常明朗了。ActivityThread內部有個Binder物件ApplicationThread,AMS可以呼叫ApplicationThread裡的方法,而 ApplicationThread裡的方法利用mH(Handler)傳送訊息給ActivityThread裡的訊息佇列,ActivityThread再去處理這些訊息,進而完成諸如Activity啟動等各種操作。
到這裡我們已經把ActivityManager家族的主要框架都梳理完了,本篇文章並沒有大篇幅的去分析原始碼,我們的重點是梳理整體框架,讓大家有整體上的認識,至於具體的細節,可以根據自己的需要有的 放矢的去研究。這也是我們提倡的閱讀Android原始碼的方法:不要揪著細節不放,要有整體意識。
理解了AMS的內容,後續就接著來分析Activity、Service、BroadcastReceiver的啟動、切換和銷燬等流程,分析的過程中也會結合著日常開發中經常遇到的一些問題,帶著這些問題,我們去看看源 碼裡怎麼寫的,為什麼會出現這些問題。應該如何去解決。