一、前言
我們在許多和Framework
解析相關的文章中,都會看到ActivityManagerService
這個類,但是在上層的應用開發中,卻很少直接會使用到他。
那么我們為什么要學習它的呢,一個最直接的好處就是它是我們理解應用程序啟動過程的基礎,只有把和ActivityManagerService
以及和它相關的類的關系都理解透了,我們才能理清應用程序啟動的過程。
今天這篇文章,我們就來對ActivityManagerService
與應用進程之間的通信方式做一個簡單的總結,這里我們根據進程之間的通信方向,分為兩個部分來討論:
-
從應用程序進程到管理者進程
(a) IActivityManager
(b) ActivityManagerNative
(c) ActivityManagerProxy
(d) ActivityManagerService -
從管理者進程到應用程序進程
(a) IApplicationThread
(b) ApplicationThreadNative
(c) ApplicationThreadProxy
(d) ApplicationThread
二、從應用程序進程到管理者進程
在這一方向上的通信,應用程序進程作為客戶端,而管理者進程則作為服務端。舉一個最簡單的例子,當我們啟動一個Activity
,就需要通知全局的管理者,讓它去負責啟動,這個全局的管理者就運行在另外一個進程,這里就涉及到了從應用程序進程到管理者進程的通信。
這一個方向上通信過程所涉及到的類包括:
2.1 應用程序進程向管理者進程發送消息
當我們想要啟動一個Activity
,會首先調用到Activity
的:
@Override
public void startActivityForResult(
String who, Intent intent, int requestCode, @Nullable Bundle options) {
//...
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, who,
intent, requestCode, options);
//...
}
之后調用到Instrumentation
的:
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
//....
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
//...
}
這里我們看到了上面UML
圖中ActivityManagerNative
,它的getDefault()
方法返回的是一個IActivityManager
的實現類:
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
//1.得到一個代理對象
IBinder b = ServiceManager.getService("activity");
//2.將這個代理對象再經過一層封裝
IActivityManager am = asInterface(b);
return am;
}
};
static public IActivityManager getDefault() {
return gDefault.get();
}
這里,對于gDefault
變量有兩點說明:
- 這是一個
static
類型的變量,因此在程序中的任何地方調用getDefault()
方法訪問的是內存中的同一個對象 - 這里采用了
Singleton
模式,也就是懶漢模式的單例,只有第一次調用get()
方法時,才會通過create()
方法來創建一個對象
create()
做了兩件事:
- 通過
ServieManager
得到IBinder
,這個IBinder
是管理進程在應用程序進程的代理對象,通過IBinder
的transact
方法,我們就可以向管理進程發送消息:
public boolean transact(int code, Parcel data, Parcel reply, int flags)
- 將
IBinder
傳入asInterface(IBinder b)
構建一個IActivityManager
的實現類,可以看到,這里返回的是一個ActivityManagerProxy
對象:
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);
}
下面,我們在來看一下這個ActivityManagerProxy
,它實現了IActivityManager
接口,我們可以看到它所實現的IActivityManager
接口方法都是通過構造這個對象時所傳入的IBinder.transact(xxxx)
來調用的,這些方法之間的區別就在于消息的類型以及參數。
class ActivityManagerProxy implements IActivityManager {
public ActivityManagerProxy(IBinder remote) {
mRemote = remote;
}
public IBinder asBinder() {
return mRemote;
}
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
//這個也很重要,我們之后分析..
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
//發送消息到管理者進程...
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
}
經過上面的分析,我們用一句話總結:
應用程序進程通過
ActivityManagerProxy
內部的IBinder.transact(...)
向管理者進程發送消息,這個IBinder
是管理者進程在應用程序進程的一個代理對象,它是通過ServieManager
獲得的。
2.2 管理者進程處理消息
下面,我們看一下管理者進程對于消息的處理,在管理者進程中,最終是通過ActivityManagerService
對各個應用程序進行管理的。
它繼承了ActivityManagerNative
類,并重寫了Binder
類的onTransact(...)
方法,我們前面通過ActivityManagerProxy
的IBinder
對象發送的消息最終會調用到管理者進程中的這個函數當中,ActivityManagerNative
對該方法進行了重寫:
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code) {
case START_ACTIVITY_TRANSACTION:
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
String callingPackage = data.readString();
Intent intent = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
IBinder resultTo = data.readStrongBinder();
String resultWho = data.readString();
int requestCode = data.readInt();
int startFlags = data.readInt();
ProfilerInfo profilerInfo = data.readInt() != 0
? ProfilerInfo.CREATOR.createFromParcel(data) : null;
Bundle options = data.readInt() != 0
? Bundle.CREATOR.createFromParcel(data) : null;
//這里在管理者進程進行處理操作....
int result = startActivity(app, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
reply.writeNoException();
reply.writeInt(result);
return true;
//...
}
在onTransact(xxx)
方法中,會根據收到的消息類型,調用IActivityManager
接口中所定義的不同接口,而ActivityManagerNative
是沒有實現這些接口的,真正的處理在ActivityManagerService
中,ActivityManagerService
開始進行一系列復雜的操作,這里之后我們介紹應用程序啟動過程的時候再詳細分析。
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
同樣的,我們也用一句話總結:
管理者進程通過
onTransact(xxxx)
處理應用程序發送過來的消息
三、從管理者進程到應用程序進程
接著,我們考慮另一個方向上的通信方式,從管理者進程到應用程序進程,這一方向上的通信過程涉及到下面的類:
可以看到,
ApplicationThread
的整個框架和上面很類似,只不過在這一個方向上,管理者進程作為客戶端,而應用程序進行則作為服務端。
3.1 管理者進程向應用程序進程發送消息
前面我們分析的時候,應用程序進程向管理者進程發送消息的時候,是通過IBinder
這個管理者進程在應用程序進程中的代理對象來實現的,而這個IBinder
則是通過ServiceManager
獲取的:
IBinder b = ServiceManager.getService("activity");
同理,如果管理者進程希望向應用程序進程發送消息,那么它也必須設法得到一個應用程序進程在它這邊的代理對象。
我們回憶一下,在第二節的分析中,應用者進程向管理者進程發送消息的同時,通過writeStringBinder
,放入了下面這個對象:
public int startActivity(IApplicationThread caller, ...) {
//...
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
//...
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
}
這個caller
是在最開始調用startActivityForResult
時傳入的:
ActivityThread mMainThread;
@Override
public void startActivityForResult(
String who, Intent intent, int requestCode, @Nullable Bundle options) {
//...
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, who,
intent, requestCode, options);
//...
}
通過查看ActivityThread
的代碼,我們可以看到它其實是一個定義在ApplicationThread
中的ApplicationThread
對象,它的asBinder
實現是在ApplicationThreadNative
當中:
public IBinder asBinder() {
return this;
}
在管理者進程接收消息的時候,就可以通過readStrongBinder
獲得這個ApplicationThread
對象在管理者進程的代理對象IBinder
:
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case START_ACTIVITY_TRANSACTION:
//取出傳入的ApplicationThread對象,之后調用asInterface方法..
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
//...
int result = startActivity(app, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
return true;
}
}
接著,它再通過asInterface(IBinder xx)
方法把傳入的代理對象通過ApplicationThreadProxy
進行了一層封裝:
static public IApplicationThread asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IApplicationThread in = (IApplicationThread) obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ApplicationThreadProxy(obj);
}
之后,管理者進程就可以通過這個代理對象的transact(xxxx)
方法向應用程序進程發送消息了:
class ApplicationThreadProxy implements IApplicationThread {
private final IBinder mRemote;
public ApplicationThreadProxy(IBinder remote) {
mRemote = remote;
}
public final IBinder asBinder() {
return mRemote;
}
public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException {
//....
mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
//...
}
這一個過程可以總結為:
管理者進程通過
ApplicationThreadProxy
內部的IBinder
向應用程序進程發送消息,這個IBinder
是應用程序進程在管理者進程的代理對象,它是在管理者進程接收應用程序進程發送過來的消息中獲得的。
3.2 用戶進程接收消息
在用戶程序進程中,ApplicationThread
的onTransact(....)
就可以收到管理者進程發送的消息,之后再調用ApplicationThread
所實現的IApplicationThread
的接口方法進行消息的處理:
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
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();
boolean dontReport = data.readInt() != 0;
schedulePauseActivity(b, finished, userLeaving, configChanges, dontReport);
return true;
}
三、小結
以上就是應用程序進程和管理者進程之間的通信方式,究其根本,都是通過獲取對方進程的代理對象的transact(xxxx)
方法發送消息,而對方進程則在onTransact(xxxx)
方法中進行消息的處理,從而實現了進程之間的通信。
更多文章,歡迎訪問我的 Android 知識梳理系列:
- Android 知識梳理目錄:http://www.lxweimin.com/p/fd82d18994ce
- 個人主頁:http://lizejun.cn
- 個人知識總結目錄:http://lizejun.cn/categories/