很多文章將Binder框架定義了四個(gè)角色:Server,Client,ServiceManager、以及Binder驅(qū)動(dòng),但這容易將人引導(dǎo)到歧途:好像所有的Binder服務(wù)都需要去ServiceManager去注冊(cè)才能使用,其實(shí)不是這樣。例如,平時(shí)APP開(kāi)發(fā)通過(guò)bindService啟動(dòng)的服務(wù),以及有些自己定義的AIDL遠(yuǎn)程調(diào)用,都不一定都ServiceManager注冊(cè)這條路,個(gè)人理解:ServiceManager主要功能是:管理系統(tǒng)服務(wù),比如AMS、WMS、PKMS服務(wù)等,而APP通過(guò)的bindService啟動(dòng)的Binder服務(wù)其實(shí)是由SystemServer的ActivityManagerService負(fù)責(zé)管理。這篇主要關(guān)注Android APP Java層Binder通信一些奇葩點(diǎn):
聽(tīng)說(shuō)你Binder機(jī)制學(xué)的不錯(cuò),來(lái)解決下這幾個(gè)問(wèn)題(一)
聽(tīng)說(shuō)你Binder機(jī)制學(xué)的不錯(cuò),來(lái)看看這幾個(gè)問(wèn)題(二)
聽(tīng)說(shuō)你Binder機(jī)制學(xué)的不錯(cuò),來(lái)看看這幾個(gè)問(wèn)題(三)
- ServiceManager addService的限制(并非服務(wù)都能使用ServiceManager的addService)
- bindService啟動(dòng)Service與Binder服務(wù)實(shí)體的流程
- Java層Binder實(shí)體與與BinderProxy是如何實(shí)例化及使用的,與Native層的關(guān)系是怎樣的
- Parcel readStrongBinder與writeStrongBinder的原理(首先兩端知曉)
ServiceManager addService的限制--并非所有服務(wù)都能通過(guò)addService添加到ServiceManager
ServiceManager其實(shí)主要的面向?qū)ο笫窍到y(tǒng)服務(wù),大部分系統(tǒng)服務(wù)都是由SystemServer進(jìn)程總添加到ServiceManager中去的,在通過(guò)ServiceManager添加服務(wù)的時(shí)候,是有些權(quán)限校驗(yàn)的,源碼如下:
int svc_can_register(unsigned uid, uint16_t *name)
{
unsigned n;
// 誰(shuí)有權(quán)限add_service 0進(jìn)程,或者 AID_SYSTEM進(jìn)程
if ((uid == 0) || (uid == AID_SYSTEM))
return 1;
for (n = 0; n < sizeof(allowed) / sizeof(allowed[0]); n++)
if ((uid == allowed[n].uid) && str16eq(name, allowed[n].name))
return 1;
return 0;
}
可以看到 (uid == 0) 或者 (uid == AID_SYSTEM)的進(jìn)程都是可以添加服務(wù)的,uid=0,代表root用戶(hù),而uid=AID_SYSTEM,代表系統(tǒng)用戶(hù) 。或者是一些特殊的配置進(jìn)程。SystemServer進(jìn)程在被Zygote創(chuàng)建的時(shí)候,就被分配了UID 是AID_SYSTEM(1000),
private static boolean startSystemServer()
throws MethodAndArgsCaller, RuntimeException {
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007",
"--capabilities=130104352,130104352",
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
Android每個(gè)APP的UID,都是不同的,用了Linux的UID那一套,但是沒(méi)完全沿用,這里不探討,總之,普通的進(jìn)程是沒(méi)有權(quán)限注冊(cè)到ServiceManager中的,那么APP平時(shí)通過(guò)bindService啟動(dòng)的服務(wù)怎么注冊(cè)于查詢(xún)的呢?接管這個(gè)任務(wù)的就是SystemServer的ActivityManagerService。
bindService啟動(dòng)Service與Binder服務(wù)實(shí)體的流程 (ActivityManagerService)
- bindService的框架
- binder服務(wù)實(shí)例化與轉(zhuǎn)化
- 業(yè)務(wù)邏輯的喚醒
- 請(qǐng)求代理的轉(zhuǎn)化與喚醒
bindService比startService多了一套Binder通信,其余的流程基本相同,而startService的流程,同startActivity差不多,四大組件的啟動(dòng)流程這里不做分析點(diǎn),主要看bindService中C/S通信的建立流程,在這個(gè)流程里面,APP與服務(wù)端互為C/S的特性更明顯,在A(yíng)PP開(kāi)發(fā)的時(shí)候,binder服務(wù)是通過(guò)Service來(lái)啟動(dòng)的。Service的啟動(dòng)方式有兩種startService,與bindService,這里只考慮后者,另外啟動(dòng)的binder服務(wù)也分為兩種情況:第一種,client同server位于同一進(jìn)程,可以看做內(nèi)部服務(wù),第二種,Client與Server跨進(jìn)程,即使是位于同一個(gè)APP,第一桶可以不用AIDL來(lái)編寫(xiě),但是第二種必須通過(guò)AIDL實(shí)現(xiàn)跨進(jìn)程通信,看一個(gè)最簡(jiǎn)單的AIDL例子,首先在定義一個(gè)aidl接口:
IMyAidlInterface.aidl
interface IMyAidlInterface {
void communicate(int count);
}
IMyAidlInterface.aidl定義了通信的借口,通過(guò)build之后,構(gòu)建工具會(huì)自動(dòng)為IMyAidlInterface.aidl生成一些輔助類(lèi),這些輔助類(lèi)主要作用是生成Binder通信協(xié)議框架,必須保證兩方通信需要指令相同,才能解析通信內(nèi)容。天王蓋地虎,寶塔鎮(zhèn)河妖。Java層Binder的對(duì)應(yīng)關(guān)系Binder與BinderProxy從這里可以看出,binder采用了代理模式 stub與proxy對(duì)應(yīng),使用aidl實(shí)現(xiàn)的服務(wù)時(shí)候,Client如果想要獲得Binder實(shí)體的代理可以通過(guò)asInterface來(lái)處理,比如如果在同一進(jìn)程就是實(shí)體,不在就新建代理對(duì)象
public interface IMyAidlInterface extends android.os.IInterface {
public static abstract class Stub extends android.os.Binder implements com.snail.labaffinity.IMyAidlInterface {
private static final java.lang.String DESCRIPTOR = "com.snail.labaffinity.IMyAidlInterface";
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public static com.snail.labaffinity.IMyAidlInterface asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.snail.labaffinity.IMyAidlInterface))) {
return ((com.snail.labaffinity.IMyAidlInterface) iin);
}
return new com.snail.labaffinity.IMyAidlInterface.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_communicate: {
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
this.communicate(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.snail.labaffinity.IMyAidlInterface {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public void communicate(int count) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(count);
mRemote.transact(Stub.TRANSACTION_communicate, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_communicate = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public void communicate(int count) throws android.os.RemoteException;
}
啟動(dòng)Binder服務(wù)端封裝Service,之所以成為封裝Service,是因?yàn)镾ervice對(duì)于Binder實(shí)體的最大作用是個(gè)作為新建服務(wù)的入口:
public class AidlService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new BBinderService();
}
public class BBinderService extends IMyAidlInterface.Stub {
@Override
public void communicate(int count) throws RemoteException {
}
}
}
而啟動(dòng)的入口:
public class MainActivity extends AppCompatActivity {
...
void bind(){
Intent intent = createExplicitFromImplicitIntent(MainActivity.this, new Intent("com.snail.labaffinity.service.AidlService"));
bindService(intent, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
IMyAidlInterface iMyAidlInterface = IMyAidlInterface.Stub.asInterface(iBinder);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
}, Context.BIND_AUTO_CREATE);
}
}
以上四個(gè)部分就組成了AIDL跨進(jìn)程服務(wù)的基本組件,現(xiàn)在從ActivitybindService入口開(kāi)始分析:bindService大部分的流程與startActivity類(lèi)似,其實(shí)都是通過(guò)AMS啟動(dòng)組件,這里只將一些不同的地方,Activity啟動(dòng)只需要Intent就可以了,而Service的bind需要一個(gè)ServiceConnection對(duì)象,這個(gè)對(duì)象其實(shí)是為了AMS端在啟動(dòng)Service后回調(diào)用的,ServiceConnection是個(gè)接口,其實(shí)例在ContextImpl的:
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
IBinder token = getActivityToken();
if (token == null && (flags & BIND_AUTO_CREATE) == 0 && mPackageInfo != null
&& mPackageInfo.getApplicationInfo().targetSdkVersion
< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
service.prepareToLeaveProcess();
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
}
mPackageInfo是一個(gè)LoadApk類(lèi),通過(guò)它的getServiceDispatcher獲得一個(gè)IServiceConnection對(duì)象,這個(gè)對(duì)象一個(gè)Binder實(shí)體,看一下具體原理
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
sd = map.get(c);
}
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}
在LoadApk中IServiceConnection對(duì)象是通過(guò)context鍵值來(lái)存儲(chǔ)ServiceDispatcher對(duì)象,而ServiceDispatcher對(duì)象內(nèi)存會(huì)有個(gè)InnerConnection對(duì)象,該對(duì)象就是getServiceDispatcher的返回對(duì)象。因此bindServiceCommon最終調(diào)用
ActivityManagerNative.getDefault().bindService(x,x,x,x,x sd, x, x, x) 的時(shí)候,傳遞的參數(shù)sd其實(shí)就是一個(gè)InnerConnection對(duì)象,這是個(gè)Binder實(shí)體。但是,Binder.java中的Binder只是對(duì)native層BBinder的一個(gè)簡(jiǎn)單封裝,真正的實(shí)例化還是通過(guò)JNI到native層去創(chuàng)建一個(gè)JavaBBinderHolder對(duì)象,并初始化gBinderOffsets,讓其能映射Java層Binder對(duì)象,而JavaBBinderHolder中又可以實(shí)例化BBinder的實(shí)例JavaBBinder,不過(guò)BBinder的實(shí)例化時(shí)機(jī)并不在這里,而是在Parcel對(duì)象writeStrongBinder的時(shí)候,
static struct bindernative_offsets_t
{
// Class state.
jclass mClass;
jmethodID mExecTransact;
// Object state.
jfieldID mObject;
} gBinderOffsets;
static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
JavaBBinderHolder* jbh = new JavaBBinderHolder();
jbh->incStrong((void*)android_os_Binder_init);
env->SetIntField(obj, gBinderOffsets.mObject, (int)jbh);
}
繼續(xù)往下看bindService,會(huì)調(diào)用到ActivityManagerProxy的bindService
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType, IServiceConnection connection,
int flags, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeStrongBinder(token);
service.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(connection.asBinder());
data.writeInt(flags);
data.writeInt(userId);
mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
data.recycle();
reply.recycle();
return res;
}
利用Parcel的writeStrongBinder會(huì)將Binder實(shí)體寫(xiě)入到Parcel中去,這里首先看一下 Parcel data = Parcel.obtain();在java層Parcel只是一個(gè)容器,具體Parcel相關(guān)的操作都在Native層
static jint android_os_Parcel_create(JNIEnv* env, jclass clazz)
{
Parcel* parcel = new Parcel();
return reinterpret_cast<jint>(parcel);
}
這里的返回值,其實(shí)就是Parcel對(duì)象的地址,被賦值給了Parcel.java的mNativePtr成員變量,方便Native調(diào)用,接著看writeStrongBinder的實(shí)現(xiàn),其實(shí)就是調(diào)用Parcel.cpp中的對(duì)應(yīng)方法,通過(guò)flatten_binder將Binder實(shí)體對(duì)象打扁,創(chuàng)建flat_binder_object寫(xiě)入Parcel中,
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jint 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);
}
}
}
ibinderForJavaObject主要為Java層Binder實(shí)例化native binder對(duì)象:
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetIntField(obj, gBinderOffsets.mObject);
return jbh != NULL ? jbh->get(env, obj) : NULL;
}
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return (IBinder*)
env->GetIntField(obj, gBinderProxyOffsets.mObject);
}
return NULL;
}
如果BBinder還沒(méi)實(shí)例化,要通過(guò)JavaBBinderHolder的get函數(shù)實(shí)例化一個(gè)BBinder對(duì)象,這里就是JavaBBinder對(duì)象,綜上分析Java層與Native的Binder其對(duì)應(yīng)關(guān)系如下:
BBinder對(duì)象被Parcel轉(zhuǎn)換成flat_binder_object,經(jīng)過(guò)一次拷貝寫(xiě)入目標(biāo)進(jìn)程,并執(zhí)行BINDER_TYPE_BINDER與BINDER_TYPE_HANDLE的轉(zhuǎn)換,如下:
static void
binder_transaction(struct binder_proc *proc, struct binder_thread *thread,
struct binder_transaction_data *tr, int reply)
...
fp = (struct flat_binder_object *)(t->buffer->data + *offp);
switch (fp->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER: {..
if (fp->type == BINDER_TYPE_BINDER)
fp->type = BINDER_TYPE_HANDLE;
else
fp->type = BINDER_TYPE_WEAK_HANDLE;
fp->handle = ref->desc;
} break;
case BINDER_TYPE_HANDLE:
case BINDER_TYPE_WEAK_HANDLE: {..
struct binder_ref *ref = binder_get_ref(proc, fp->handle);
if (ref->node->proc == target_proc) {
if (fp->type == BINDER_TYPE_HANDLE)
fp->type = BINDER_TYPE_BINDER;
else
fp->type = BINDER_TYPE_WEAK_BINDER;
fp->binder = ref->node->ptr;
fp->cookie = ref->node->cookie;
} else {
struct binder_ref *new_ref;
new_ref = binder_get_ref_for_node(target_proc, ref->node);
fp->handle = new_ref->desc;
}
} break;
}
在內(nèi)核中,bindService中的InnerConnection會(huì)由BINDER_TYPE_BINDER轉(zhuǎn)換成BINDER_TYPE_HANDLE,之后,AMS線(xiàn)程被喚醒后,執(zhí)行后面的流程,在前文分析Parcel數(shù)據(jù)轉(zhuǎn)換的時(shí)候,在Binder線(xiàn)程被喚醒繼續(xù)執(zhí)行的時(shí)候,會(huì)將數(shù)據(jù)映射到一個(gè)natvie Parcel對(duì)象中
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
switch (cmd) {
..
// read到了數(shù)據(jù)請(qǐng)求,這里是需要處理的邏輯 ,處理完畢,
case BR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));
Parcel buffer;
<!--關(guān)鍵點(diǎn)1 -->
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t), freeBuffer, this);
...
<!--關(guān)鍵點(diǎn)2 -->
if (tr.target.ptr) {
sp<BBinder> b((BBinder*)tr.cookie);
const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
if (error < NO_ERROR) reply.setError(error);
}
..
}
}
首先看一下關(guān)鍵點(diǎn)1 ,這里將內(nèi)核數(shù)據(jù)映射到一個(gè)用戶(hù)空間的Parcel對(duì)象中去,之后在調(diào)用目標(biāo)Service的transact函數(shù),進(jìn)而調(diào)用他的onTrasanct函數(shù) , 通過(guò)前面的分析知道,Java層Binder在注冊(cè)時(shí)候,最終注冊(cè)的是JavaBBinder對(duì)象,看一下它的onTrasanct函數(shù):
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
JNIEnv* env = javavm_to_jnienv(mVM);
IPCThreadState* thread_state = IPCThreadState::self();
const int strict_policy_before = thread_state->getStrictModePolicy();
thread_state->setLastTransactionBinderFlags(flags);
..
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, (int32_t)&data, (int32_t)reply, flags);
..
return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
}
關(guān)鍵代碼只有一句:env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, code, (int32_t)&data, (int32_t)reply, flags),其實(shí)就是調(diào)用Binder.java的execTransact函數(shù),該函數(shù)首先將Native的Parcel映射成Jave層Parcel,之后調(diào)用BBinder子類(lèi)的onTransact函數(shù)執(zhí)行對(duì)應(yīng)的業(yè)務(wù)邏輯,最后會(huì)通過(guò)data.recycle通知釋放內(nèi)存:
private boolean execTransact(int code, int dataObj, int replyObj,
int flags) {
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
boolean res;
try {
res = onTransact(code, data, reply, flags);
} ...
reply.recycle();
data.recycle();
return res;
}}
對(duì)于A(yíng)MS而bindService對(duì)應(yīng)的操作如下
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
。。
case BIND_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
IBinder token = data.readStrongBinder();
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
b = data.readStrongBinder();
int fl = data.readInt();
int userId = data.readInt();
IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
int res = bindService(app, token, service, resolvedType, conn, fl, userId);
reply.writeNoException();
reply.writeInt(res);
return true;
}
b = data.readStrongBinder()會(huì)先讀取Binder對(duì)象,這里會(huì)調(diào)用本地函數(shù)nativeReadStrongBinder(mNativePtr),mNativePtr就是Native層Parcel的首地址:
public final IBinder readStrongBinder() {
return nativeReadStrongBinder(mNativePtr);
}
nativeReadStrongBinder(mNativePtr)會(huì)將本地Binder對(duì)象轉(zhuǎn)化成Java層對(duì)象,其實(shí)就是將傳輸?shù)腎nnerConnection讀取出來(lái),不過(guò)由于Binder驅(qū)動(dòng)將BINDER_TYPE_BINDER轉(zhuǎn)換成了BINDER_TYPE_HANDLE,對(duì)于A(yíng)MS其實(shí)是實(shí)例化BinderProxy
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jint nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
// /parcel->readStrongBinder() 其實(shí)就會(huì)創(chuàng)建BpBInder、
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return NULL;
}
首先會(huì)利用Parcel.cpp的parcel->readStrongBinder(),讀取binder對(duì)象,這里會(huì)根據(jù)flat_binder_object的類(lèi)型,分別進(jìn)行BBinder與BpBinder映射,如果是Binder實(shí)體直接將指針賦值out,如果不是,則根據(jù)handle獲取或者新建BpBinder返回給out。
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 = static_cast<IBinder*>(flat->cookie);
return finish_unflatten_binder(NULL, *flat, in);
case BINDER_TYPE_HANDLE:
*out = proc->getStrongProxyForHandle(flat->handle);
return finish_unflatten_binder(
static_cast<BpBinder*>(out->get()), *flat, in);
}
}
return BAD_TYPE;
}
之后會(huì)牽扯一個(gè)將native binder轉(zhuǎn)換成java層Binder的操作,javaObjectForIBinder,這個(gè)函數(shù)很關(guān)鍵,是理解Java層BinderProxy或者BBinder實(shí)體的關(guān)鍵:
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
if (val == NULL) return NULL;
<!--關(guān)鍵點(diǎn)1-->
if (val->checkSubclass(&gBinderOffsets)) {
jobject object = static_cast<JavaBBinder*>(val.get())->object();
return object;
}
AutoMutex _l(mProxyLock);
<!--關(guān)鍵點(diǎn)2-->
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
if (object != NULL) {
android_atomic_dec(&gNumProxyRefs);
val->detachObject(&gBinderProxyOffsets);
env->DeleteGlobalRef(object);
}
<!--關(guān)鍵點(diǎn)3-->
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {
env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get());
val->incStrong((void*)javaObjectForIBinder);
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
sp<DeathRecipientList> drl = new DeathRecipientList;
drl->incStrong((void*)javaObjectForIBinder);
env->SetIntField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jint>(drl.get()));
android_atomic_inc(&gNumProxyRefs);
incRefsCreated(env);
}
return object;
}
先看關(guān)鍵點(diǎn)1, checkSubclass默認(rèn)返回false,但是JavaBBinder,該類(lèi)對(duì)此函數(shù)進(jìn)行了覆蓋,如果是JavaBBinder,就會(huì)返回true,但入股是BpBinder,則會(huì)返回false,
bool checkSubclass(const void* subclassID) const
{
return subclassID == &gBinderOffsets;
}
再看關(guān)鍵點(diǎn)2,如果是BpBinder,則需要首先在gBinderProxyOffsets中查找,是不是已經(jīng)新建了Java層代理BinderProxy對(duì)象,如果沒(méi)有,則新建即可,如果新建就看是否還存在緩存有效的BinderProxy。最后看關(guān)鍵點(diǎn)3 :
env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor)
其實(shí)就是新建BinderProxy對(duì)象,Java層的BinderProxy都是Native新建的,Java層并沒(méi)有BinderProxy的新建入口,之后,再通過(guò)IServiceConnection.Stub.asInterface(b)進(jìn)行轉(zhuǎn)換,實(shí)例化一個(gè)IServiceConnection.Proxy代理對(duì),該對(duì)象在Binder通信的基礎(chǔ)上封裝了業(yè)務(wù)邏輯,其實(shí)就是一些具體的操作。
public static XXXAidlInterface asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof XXXAidlInterface))) {
return ((XXXAidlInterface) iin);
}
return new XXXAidlInterface.Stub.Proxy(obj);
}
這里注意一點(diǎn)杜宇BinderProxy,obj.queryLocalInterface(DESCRIPTOR)返回為null,對(duì)于Binder實(shí)體,返回的是Binder自身,這樣就能為上層區(qū)分出是生成代理還是存根自身,整體對(duì)象轉(zhuǎn)換流程如下:
到這里分析了一半,Java層命令及回調(diào)Binder入口已經(jīng)被傳遞給AMS,AMS之后需要負(fù)責(zé)啟動(dòng)Service,并通過(guò)回調(diào)入口為Client綁定服務(wù),跟蹤到AMS源碼
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType,
IServiceConnection connection, int flags, int userId) {
...
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service, resolvedType,
connection, flags, userId);
}
}
最后調(diào)用ActiveService的bindServiceLocked,這里會(huì)分三中情況,
- Service已經(jīng)經(jīng)啟動(dòng)
- Service未啟動(dòng),但是進(jìn)程已經(jīng)啟動(dòng)
- Service與進(jìn)程君未啟動(dòng)
不過(guò)這里只討論“ Service未啟動(dòng),但是進(jìn)程已經(jīng)啟動(dòng)的情況”,關(guān)鍵代碼如下
int bindServiceLocked(IApplicationThread caller, IBinder token,
Intent service, String resolvedType,
IServiceConnection connection, int flags, int userId) {
try {
.。。
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
<!--關(guān)鍵點(diǎn)1-->
if (bringUpServiceLocked(s, service.getFlags(), false) != null) {
return 0;
}
}
<!--關(guān)鍵點(diǎn)2-->
..
requestServiceBindingLocked(s, b.intent, false);
..
}
}
關(guān)鍵點(diǎn)1其實(shí)就是啟動(dòng)Service,主要是通過(guò)ApplicationThread的binder通信通知App端啟動(dòng)Service,這個(gè)流程同Activity啟動(dòng)一樣。關(guān)鍵點(diǎn)2是Service特有的:requestServiceBindingLocked,這個(gè)命令是告訴APP端:“在Service啟動(dòng)后需要向AMS發(fā)消息,之后AMS才能向其他需要綁定該Service的Client發(fā)送反饋”。
AMS端
private final boolean requestServiceBindingLocked(ServiceRecord r,
IntentBindRecord i, boolean rebind) {
if ((!i.requested || rebind) && i.apps.size() > 0) {
..
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
..
} }
return true;
}
APP端
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
...
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
}
}
ActivityManagerNative.getDefault().publishService會(huì)將啟動(dòng)的Binder服務(wù)實(shí)體傳遞給AMS,上面分析過(guò)Binder實(shí)體傳輸,這里的原理是一樣的,AMS端在傳輸結(jié)束后,會(huì)獲得Service端服務(wù)實(shí)體的引用,這個(gè)時(shí)候,就能通過(guò)最初的InnerConnection的回調(diào)將這個(gè)服務(wù)傳遞給Client端。Binder實(shí)體與引用的整體流程圖如下:
如果要深究Activity的bindService流程,可以按以下幾步來(lái)分析
- 1、Activity調(diào)用bindService:通過(guò)Binder通知ActivityManagerService,要啟動(dòng)哪個(gè)Service
- 2、ActivityManagerService創(chuàng)建ServiceRecord,并利用ApplicationThreadProxy回調(diào),通知APP新建并啟動(dòng)Service啟動(dòng)起來(lái)
- 3、ActivityManagerService把Service啟動(dòng)起來(lái)后,繼續(xù)通過(guò)ApplicationThreadProxy,通知APP,bindService,其實(shí)就是讓Service返回一個(gè)Binder對(duì)象給ActivityManagerService,以便AMS傳遞給Client
- 4、ActivityManagerService把從Service處得到這個(gè)Binder對(duì)象傳給Activity,這里是通過(guò)IServiceConnection binder實(shí)現(xiàn)。
- 5、Activity被喚醒后通過(guò)Binder Stub的asInterface函數(shù)將Binder轉(zhuǎn)換為代理Proxy,完成業(yè)務(wù)代理的轉(zhuǎn)換,之后就能利用Proxy進(jìn)行通信了。
聽(tīng)說(shuō)你Binder機(jī)制學(xué)的不錯(cuò),來(lái)解決下這幾個(gè)問(wèn)題(一)
聽(tīng)說(shuō)你Binder機(jī)制學(xué)的不錯(cuò),來(lái)看看這幾個(gè)問(wèn)題(二)
聽(tīng)說(shuō)你Binder機(jī)制學(xué)的不錯(cuò),來(lái)看看這幾個(gè)問(wèn)題(三)
作者:看書(shū)的小蝸牛
原文鏈接: 聽(tīng)說(shuō)你Binder機(jī)制學(xué)的不錯(cuò),來(lái)面試下這幾個(gè)問(wèn)題(三)
僅供參考,歡迎指正