前言
最近重溫了Binder機制,在此把看到的一些心得,寫一寫。
正文
在這裏需要先說明的一點是Client端和Server端以及後面提到的ServiceManager都處於用戶空間、Binder驅動處於內核空間。
Binder是進程間通訊的一種方式。進程間的通訊方式有很多,比如Socket、管道。而Socket、管道這些需要數據的兩次拷貝(Client把數據從自己的進程空間拷貝到內核空間,然後再從內核空間拷貝到Server端的進程空間,這樣Server就能客戶端傳遞的數據,這個過程經歷過了兩次數據拷貝)。而Binder方式只需要一次數據拷貝:只需要Client把數據拷貝到內核空間,然後將拷貝到內核空間的數據同時映射到Server進程虛擬地址空間和內核虛擬地址空間,這樣經過一次數據拷貝,客戶端和服務端就能進行通訊了。
注意:並不是所有的Binder服務都會註冊到ServiceManager中的,像AMS、WMS、PMS這些系統的Binder服務是會註冊到SM中並受SM管理的,而像bindService方式創建的Binder服務不會註冊到ServiceManager中,這些註冊到SM中的Binder服務稱爲實名Binder,不需要註冊到ServiceManager中的Binder服務稱之爲匿名Binder,匿名Binder的傳遞和使用需要依賴於實名Binder。
借用網上某位大佬一張圖,如圖所示:
Android啓動的時候會啓動SystemServer進程,SystemServer進程的入口是裏面的main方法:
public static void main(String[] args) {
new SystemServer().run();
}
這裏又調用了SystemServer裏面的run方法:
private void run() {
...
// Start services.
try {
traceBeginAndSlog("StartServices");
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
...
}
我們看這裏面的startBootstrapServices()方法:
private void startBootstrapServices() {
....
// Activity manager runs the show.
traceBeginAndSlog("StartActivityManager");
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
traceEnd();
...
traceBeginAndSlog("SetSystemProcess");
mActivityManagerService.setSystemProcess();
traceEnd();
...
}
在這裏,我們看到創建了ActivityManagerService對象,並通過下面的mActivityManagerService.setSystemProcess();啓動了這個ActivityManagerService。
看下ActivityManagerService中的setSystemProcess()這個方法:
public void setSystemProcess() {
...
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
...
}
在這裏也就是執行了ServiceManager把創建的這個ActivityManagerService對象加入了ServiceManager中創建的映射表裏。
Context.ACTIVITY_SERVICE其實就是“activity”字符串。到時候我們可以通過getService(Context.ACTIVITY_SERVICE),通過這個獲取到存儲在映射表裏面的ActivityManagerService變量。例如:
ActivityManager activityManager = (android.app.ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager就是一個殼,它的存在避免了AMS直接暴露給應用程序,而是通過對外提供的ActivityManager來操作AMS,這樣更安全,下面我們看一下ActivityManger裏面的getService方法:
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
看到這裏面調用了IActivityManagerSingleton的get方法,看一下IActivityManagerSingleton:
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
首先看下Singleton類的定義:
package android.util;
/**
* Singleton helper class for lazily initialization.
*
* Modeled after frameworks/base/include/utils/Singleton.h
*
* @hide
*/
public abstract class Singleton<T> {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
其中get是final的方法,不可以覆蓋,create是可以覆蓋的。
主要看這裏的兩行代碼:
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
這個地方是使用了AIDL的方式(Android7.0及之前,AMS通過代理模式來完成Binder通信,8.0之後,AMS通過AIDL完成Binder通信。),通過調用ServiceManager的getService方法查詢出AMS的信息並轉換爲代理對象am。這個am對象是IActivityManager類型的,而IActivityManager是個aidl,根據aidl的規則和原理,可以知道遠程服務的具體實現一定是IActivityManager.Stub的實現類,而AMS實現了IActivityManager.Stub,所以AMS是遠程服務的具體實現。