首先感謝:
從AILD與bindService談Binder程序間通信原理(上) 解答了我很多疑惑, 但由于上述文章的源碼是7.0的,Java架構層沒有用AIDL,是以我想根據新的源碼(8.0)來了解Binder的知識。
前幾天在學習一些Binder機制(較淺)後,我就在趁熱打鐵看看AIDL的一些東西,在學習的時候發現了幾點疑問,并且網上鮮有解答:
-
管理的是系統服務,那我們自定義的Service會注冊到ServiceManager中嗎?ServiceManager
- 為什麼AIDL中的跨程序下asInterface()會傳回
?我們在Service的啟動流程沒有留意到這個類呀?BinderProxy
不過最後我一些地方還是有些模糊,如果大神能有幸閱讀我的文章,請麻煩指出我文中的錯誤!我定查閱改正。
1.關于系統Service和自定義Service的差別
這裡是 bindService在應用層 - framwork層的綁定流程,源碼基于8.0:Service的startService和bindService源碼流程 或者閱讀《Android進階解密》第四章
這裡是關于系統服務和ServiceManager在基于Binder角度 注冊、擷取、使用上的流程,源碼基于9.0,也是皇叔寫的:Binder原理
可以大概總結出他們的差別:
-
系統Service
是指在 SystemServer程序開啟後,通過
、startBootstrapServices()
、startCoreServices()
所開啟的服務,他們顯示地通過startOtherServices()
注冊在了add_service()
ServiceManager
中。
之後用戶端程序想要使用系統Service,需要通過 ServiceManager的程序來檢視是否有目标Service,然後再來擷取和使用
-
自定義Service
通過
和startService()
bindService()
兩種方式開啟,在framwork架構層中沒有發現流程中使用add_service方法(甚至都沒出現ServiceManager)。
↑ 這就看出無論自定義Service最後在不在ServiceManager中,Android本身是不希望我們通過ServiceManager的途徑去擷取使用自定義Service的。
上述第二條的結論,原因是什麼?我不是很清楚,但是基于結論來看:
隻要一個程序持有另一程序的BinderProxy類,那我還去找 ServiceManager幹什麼,這不更加省事嗎?
是以,在自定義的流程中把ServiceManager忽略掉,我們就不用考慮Service到底有沒有注冊在ServiceManager中了。
2. 從AIDL上看Binder
AIDL本質上是在Java層對Binder進行了封裝。是以Android8.0前後AMS是否使用了AIDL,本質都是使用Binder + 代理模式,隻是說使用了 AIDL通過編譯時生成代碼,節省了一些代碼的編寫,提高了開發效率。
那麼我們就從編譯時産生的代碼開始,來看看Binder的運作機制,這裡使用的例子是:使用AIDL來進行程序間通信,就是一個 Service遠端服務 + User類 + IUserManager代理類
2.1 用于程序傳輸的Stub類
在編譯檔案産生的 IUserManager中,它是一個接口類,同時它有一個靜态内部類
Stub
:
// IUserManager.java
// 0
public static abstract class Stub extends android.os.Binder implements com.rikkatheworld.aidl_demo.IUserManager {
private static final java.lang.String DESCRIPTOR = "com.rikkatheworld.aidl_demo.IUserManager";
// 1
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
// 2
public static com.rikkatheworld.aidl_demo.IUserManager asInterface(android.os.IBinder obj) {
...
}
// 3
@Override
public android.os.IBinder asBinder() {
return this;
}
// 4
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
...
}
// 5
private static class Proxy implements com.rikkatheworld.aidl_demo.IUserManager {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
...
// 6
@Override
public com.rikkatheworld.aidl_demo.User getUser(java.lang.String name) throws android.os.RemoteException {
....
}
}
}
Stub類分成兩個部分,一個是自己本身的成員方法,另一個是Proxy類,先來看看這些成員。
(1)自身部分
-
注釋0
Stub類繼承自
,說明這個類是用于程序間傳輸的。Binder
- 注釋1
構造方法,把自身和标記自身的descriptor傳入,後者用于表明身份Stub()
- 注釋2
靜态方法, 處理ActivityManagerService丢給我們的 IBinder,将它轉換成 用戶端程序想要的類。asInterface(obj)
- 注釋3:
用于Binder傳輸的過程,需要轉換自身的類型,Stub(A程序)->IBinder(Binder)->Stub(B程序),就用到這個方法,這個例子非常粗糙,可能也有問題,但是這個方法是輔助用的,我們不需要對這個方法深入了解。asBinder()
- 注釋4 :
重寫父類的 onTrancsact,這個方法是用戶端程序在使用Binder進行資料傳輸時需要用到的資料。onTransact()
(2)Proxy代理類
-
注釋5
靜态内部類,實作了 IUserManager接口
内部定義了一個 IBinder類型的 mRemote對象
-
注釋6
實作方法,如果用戶端程序要跨程序調用Server端的方法,就要通過調用這些方法。
我們看看用戶端程序是怎麼使用這個類的:
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 1
IUserManager userManager = IUserManager.Stub.asInterface(service);
try {
User user = userManager.getUser("Rikka");
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
AIDL的用戶端程序,在
onServiceConnected()
中拿到 AMS傳過來的 service,通過
asInterface()
轉化成 IUserManager,然後調用它的方法,就能完成跨程序的方法調用了。
我們來看看
asInterface()
具體實作:
// IUserManager.java
...
public static com.rikkatheworld.aidl_demo.IUserManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.rikkatheworld.aidl_demo.IUserManager))) {
return ((com.rikkatheworld.aidl_demo.IUserManager) iin);
}
return new com.rikkatheworld.aidl_demo.IUserManager.Stub.Proxy(obj);
}
...
可以看出調用了
queryLocalInterface()
獲得一個 IInterface類型的對象iin,如果iin不為空,則傳回iin,如果為空,則 new一個 Proxy類并傳回。
我們知道AMS給我們傳回的一定是Binder的對象,是以我們去 Binder中看看
queryLocalInterface()
:
// Binder.java
public class Binder implements IBinder {
...
// 1
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
if (mDescriptor != null && mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
...
}
// 2
final class BinderProxy implements IBinder {
// 3
public IInterface queryLocalInterface(String descriptor) {
return null;
}
...
}
可以發現Binder檔案中,有兩處實作了這個方法,在Binder類中。
注釋1中 通過 descriptor辨別來傳回,mOwner是Bidner本身。
注釋2、3是
BinderProxy
實作的,直接傳回一個空。
在Stub類的構造方法裡我們就看到了隻要
Stub
被建構就會調用:
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
按理來說,
queryLocalInterface
不可能傳回為空,我們應該都是得到一個正宗的 Stub類才對,但是實際上這裡出現了偏出。
在跨程序服務中,我們通過 asInterface() 傳回的是一個
IUserManager.Stub.Proxy
的對象。這就說明
queryLocalInterface()
傳回了空,隻有一種情況會導緻這種結果, 那就是 ServiceConnection傳回來的值是一個
BinderProxy
類型的對象。
這就是我最開始的疑問點,為什麼
onServiceConnection()
中遠端程序和同程序下傳回的是Binder,而不同程序下傳回的是
BinderProxy
。
2.2 BindService 用戶端程序傳出流程
Binder機制是C/S架構,任意兩個程序,請求方是C端,接收方是S端
C端通過
BpBinder
來通路S端,S端通過
BBinder
來通路C端,而
BpProxy
就是BpBinder的封裝類。他們的具體知識這裡就不再贅述了。詳情請看皇叔的文章。下面以架構層角度畫個圖來看下 用戶端程序的資料傳出經過了什麼方法:

萬物的開端在于BindService,在 Service的startService和bindService源碼流程中,我們知道主程序的最終代碼是到
ContextImpl.bindServiceCommon()
:
// ContextImpl.java
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
IServiceConnection sd;
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
...
try {
IBinder token = getActivityToken();
...
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
...
} ...
}
// ActivityManager
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
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;
}
};
ActivityManager.getService()是
IActivityManager.Stub.asInterface(b)
,這個肯定是Proxy類(套娃了,不過問題不大),我們要來看看bindService做了什麼,由于IActivityManager是編譯産生的,是以我暫時還沒有找到IActivityManager,但是我們知道 它的實作肯定和我們自己所編譯出來的如出一轍,甚至我們自己都可以寫出來:
// 這個地方是照着 IUserManger.Stub.Proxy 仿寫的,也看了開篇Blog的内容
// IActivityManager.Stub.Proxy
@Override
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType, IServiceConnection connection, int flags, int userId) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain(); // 1
android.os.Parcel _reply = android.os.Parcel.obtain(); // 2
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder(caller != null ? caller.asBinder() : null); // 3
_data.writeStrongBinder(token); // 4
service.writeToParcel(data, 0);
_data.writeString(resolvedType);
_data.writeStrongBinder(connection.asBinder()); // 5
_data.writeInt(flags);
_data.writeInt(userId);
mRemote.transact(TRANSACTION_bindService, data, reply, 0); // 6
reply.readException();
_result = reply.readInt(); // 7
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
注釋1:獲得一個傳出去的序列化資料 data
注釋2:獲得一個用于接收的序列化資料 reply
注釋3、4、5: 通過
writeStrongBinder()
把 Binder資料寫入到 data中
注釋6:調用原生層的
transact()
,傳入資料
注釋7:在傳回結果reply讀出資料result
其中,注釋3、4、5、6是這個方法的關鍵。就是參數是這麼從用戶端程序傳出去的。
我們來看看
writeStrongBinder()
,它是一個native方法:
// frameworks/base/core/jni/android_os_Parcel.cpp
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
這裡調用了兩個函數, 一個是調用了
ibindForJavaObject
得到一個IBinder,在傳入到
Parcel->writeStrongBinder()
中:
先來看看前者
// frameworks/base/core/jni/android_os_Parcel.cpp
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
return jbh != NULL ? jbh->get(env, obj) : NULL; // 1
}
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject); // 2
}
return NULL;
}
注釋1:如果傳進來的binder是 gBinderOffsets,則 new一個
JavaBBinder
并傳回。
注釋2:如果傳進來的bind是 gBinderProxyOffsets(代理類),類中的 代理對象。(也就是封裝在裡面了,取出來用)
由于我們是用戶端程序,是以進來的并不是代理類,是以
ibinderForJavaObject()
會傳回一個 JavaBBinder傳回給我們。
再來看看 Parcel.writeStrongBinder():
// frameworks\native\libs\binder\Parcel.cpp
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flatten_binder(ProcessState::self(), val, this);
}
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)
{
...
if (binder != NULL) {
IBinder *local = binder->localBinder(); // 1
if (!local) {
BpBinder *proxy = binder->remoteBinder();
if (proxy == NULL) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
obj.type = BINDER_TYPE_HANDLE;
obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
obj.handle = handle;
obj.cookie = 0;
} else {
obj.type = BINDER_TYPE_BINDER; // 2
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local);
}
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
}
return finish_flatten_binder(binder, obj, out);
}
inline static status_t finish_flatten_binder(
const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out)
{
return out->writeObject(flat, false);
}
在writeStrongBinder中調用了
flatten_binder()
,
注釋1:localBinder()是取出Binder中的資料,用來辨別傳入Binder的程序是否是目前程序,是以local不為null,會走到else中去
注釋2:設定 type為
BIND_TYPE_BINDER
最後把這些資料寫到輸出資料中。也就是一開始我們的 _data。
接下來看下
mRemote.transact()
這個方法,mRemote是
ServiceManager
傳回給我們的,它是一個 BinderProxy對象,是以會調用
BinderProxy.transact()
:
// Binder.java
// BinderProxy ->
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
....
try {
return transactNative(code, data, reply, flags);
} ...
}
調用了 native層的
transactNative()
:
// android_util_Binder.cpp
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
...
Parcel* data = parcelForJavaObject(env, dataObj); // 1
..
Parcel* reply = parcelForJavaObject(env, replyObj); // 2
...
IBinder* target = (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject); // 3
....
status_t err = target->transact(code, *data, reply, flags); // 4
....
}
注釋1、2:通過
parcelForJavaObject()
把 Java層的Parce -> Natve層的Parcel,data是參數資料,reply是結果資料
注釋3:把 java層的 ActivityManagerService的
BinderProxy
轉換成 Native層的
BpBinder
注釋4:調用
BpBinder.transact()
到這裡我就不往下說了,BpBinder會調用
IPCThreadState.transact()
、
writeData()
、
talkWithDriver()
、
waitForResponse()
等方法去深入到 Kernel層的Binder,具體請看: Android Binder原理(三)系統服務的注冊過程,裡面寫了一個系統服務注冊到ServiceManager的過程,其中就有上述接下來的過程。
這樣我們的Binder資料就從用戶端程序傳出去了。
2.3 ActivityManagerService接收資料
如果一個支援Binder通信的程序被建立後,它會開啟一條線程加入到Binder線程池中,并通過
joinThreadPool()
開啟死循環,讀 Binder驅動中的
BR_TRANSACTION
(因為用戶端程序傳入的是
BC_TRANSACTION
)指令,具體可以看 《Android進階解密》第三章 應用程式程序的建立。
// IPCThreadState.cpp
void IPCThreadState::joinThreadPool(bool isMain)
{
...
do {
...
result = getAndExecuteCommand();
...
} while (result != -ECONNREFUSED && result != -EBADF);
...
talkWithDriver(false);
}
可以看到在死循環中不斷調用
getAndExecuteCommand()
:
status_t IPCThreadState::getAndExecuteCommand()
{
...
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) return result;
cmd = mIn.readInt32();
...
result = executeCommand(cmd);
...
}
return result;
}
// IPCThreadState.cpp
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
if (mProcess->mDriverFD <= 0) {
return -EBADF;
}
//和Binder驅動通信的結構體
binder_write_read bwr; //1
//mIn是否有可讀的資料,接收的資料存儲在mIn
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data();//2
//這時doReceive的值為true
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();//3
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
...
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
do {
IF_LOG_COMMANDS() {
alog << "About to read/write, write size = " << mOut.dataSize() << endl;
}
#if defined(__ANDROID__)
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)//4
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
...
} while (err == -EINTR);
...
return err;
}
talkWithDriver()
就是通過
ioctl
讀取有沒有想要的BR資料,有就響應,調用
executeCommand()
:
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch ((uint32_t)cmd) {
....
case BR_TRANSACTION:
{
binder_transaction_data tr; // 1
result = mIn.read(&tr, sizeof(tr)); // 2
....
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), freeBuffer, this); // 3
....
Parcel reply;
status_t error;
if (tr.target.ptr) {
if (....) {
error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
&reply, tr.flags); // 4
}
} ...
....
}
break;
...
return result;
}
這裡隻要截取
BR_TRANSACTION
,因為用戶端程序發的是
BC_TRANSATION
注釋1:建立
binder_transaction_data
結構體的對象tr,它是IPCThread專用的 Parcel包, 在用戶端程序的IPCThreadState調用transact時也是用這個類型
注釋2:mIn是Binder驅動的讀到的Parcel資料,通過 read()方法把這些資料寫入到 tr中
注釋3:通過寫好的資料重新構造一個 Parcel包。(把它修改成AMS用的包)
注釋4:調用
BBinder.transact()
,這裡的 BBinder是指 ActivityManagerService在Service端的對象,也就是自己。最後會調用自己的
onTransact()
,會調用父類也就是
IActivityManager.onTransact()
在
IActivityManager
對 onTransact應該是對
TRANSACTION_bindService()
case處理,雖然我們沒有 IActivityManager這個類,但是我們通過
IUserManager
檔案,可以仿寫一份 IActivityManager的代碼:
// 跟IActivityManager.Stub.Proxy類一樣, 根據 IUserManager 仿寫 IActivityManager.Stub.onTransact(),
// 代碼參照開篇Blog,即Android7.0 的Binder傳回的處理
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
...
case TRANSACTION_bindService: {
data.enforceInterface(descriptor);
IBinder b = data.readStrongBinder(); // 1
IApplicationThread app = ApplicationThreadNative.asInterface(b);
IBinder token = data.readStrongBinder();
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
b = data.readStrongBinder();
IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
int fl = data.readInt();
int userId = data.readInt();
int res = bindService(app, token, service, resolvedType, conn, fl, userId); // 5
reply.writeNoException();
reply.writeInt(res);
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
在拿到 natvie層的Pacel包後,進行拆包。
注釋1-2前:通過readString() 、readInt()、
readStrongBinder()
拆包,怎麼裝包的就怎麼拆包
注釋2:執行
ActivityManagerService.bindService()
,正式開啟 AMS之旅。
我們來看看解包的一個方法
readStrongBinder()
,它和裝包的
writeStrongBinder()
對應:
// Parcel.cpp
status_t Parcel::readStrongBinder(sp<IBinder>* val) const
{
status_t status = readNullableStrongBinder(val);
if (parcel != NULL) {
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return status;
}
status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
{
return unflatten_binder(ProcessState::self(), *this, val);
}
readStrongBinder()調用了
readNullableStrongBinder()
,它裡面調用了
unflatten_binder()
:
// Parcel.cpp
status_t unflatten_binder(const sp<ProcessState>& proc,
const Parcel& in, sp<IBinder>* out)
{
const flat_binder_object* flat = in.readObject(false);
if (flat) {
switch (flat->type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
return finish_unflatten_binder(NULL, *flat, in);
case BINDER_TYPE_HANDLE:
*out = proc->getStrongProxyForHandle(flat->handle); // 1
return finish_unflatten_binder(
static_cast<BpBinder*>(out->get()), *flat, in);
}
}
return BAD_TYPE;
}
我們在用戶端程序傳入進來flat的是
BINDER_TYPE_BINDER
, 但是我跟你講,這裡拿到的是
BINDER_TYPE_HANDLE
,因為
-
如果是非跨程序調用
資料Parcel包在kernel層不會做修改
-
如果是跨程序調用
kernel層的
會修改這個值,即binder_transaction()
->BINDER_TYPE_BINDER
BINDER_TYPE_HANDLE
是以這裡會在注釋1中得到一個
BpBinder
,然後傳回。
也就是說
readStrongBinder(Parcel)
可以拿到 parcel包裡面的 的Binder資料并轉化為 BpBinder, 然後把BpBinder通過
Parcel.javaObjectForIBinder()
轉換成
BinderProxy
。在Android7.0可以找到這個轉換,8.0後我突然找不到了…不知道為什麼。以後找機會再查查吧。
到這裡,就已經明了了,用戶端程序的 Binder 到了 服務端程序後 會包裝成 BinderProxy。
這句話也可以換成:
任意一個程序的IBinder 通過 Binder機制 到達了另外一個程序後,就會包裝成一個 BinderProxy。
這就回到了我最開始的第二點疑問,通過Service -> AMS -> MainActivity.onServiceConnection(IBinder) 中的 IBinder是一個BindProxy類。
3. 總結
從一開始我的兩個問題,到現在也算是解決了。
自定義Service并不需要通過
addService()
來加入到 ServiceManager,因為它隻要别的程序能夠持有它的BinderProxy,就可以調用它的方法。
其次 Binder在跨程序後會轉換成 BindProxy,這也是為什麼AIDL中能夠拿到 Proxy類。
-
的代碼到底時怎麼樣的?IActivityManager
- Android7.0 的
顯示的用了readStrongBinder()
把 unflatten_binder得到 BpBinder轉換成了 BinderProxy,但是Andorid8.0我卻沒有看到這樣的代碼,到了BpBinder就好了…不知道是不是我看漏了,反正查了半天沒查到…javaObjectForIBinder()