(五)Binder分析·下篇

(五)Binder使用·下篇

通过一个BinderDemo项目,学习binder在java层的使用。



一、获取Service Manager远程接口

Service Manager的Java远程接口是一个ServiceManagerProxy对象的IServiceManager接口,ServiceManagerProxy类实现了IServiceManager接口,IServiceManager提供了getService和addService两个成员函数来管理系统中的Service。

//frameworks/base/core/java/android/os/ServiceManager.java
public final class ServiceManager {  
    ......  
    private static IServiceManager sServiceManager;  
    ......  
    private static IServiceManager getIServiceManager() {  
        if (sServiceManager != null) {  
            return sServiceManager;  
        }  
  
        // Find the service manager  
        //相当于 new ServiceManagerProxy(new BinderProxy);
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());  
        return sServiceManager;  
    }  
    ......  
}  

1.1 BinderInternal.getContextObject()

//frameworks/base/core/java/com/android/internal/os/BinderInternal.java
// 88
public static final native IBinder getContextObject();



//frameworks/base/core/jni/android_util_Binder.cpp
// 899
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
	/* 打开 binder驱动( ProcessState是单例的) , 创建 BpBinder(handle) 对象, 并返回 */
	sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
	return javaObjectForIBinder(env, b);
} 


//frameworks/base/core/jni/android_util_Binder.cpp
// 547
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
// 563 从 BpBinder中查找 BinderProxy对象, 第一次为 null
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
// 576 创建 BinderProxy对象
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
// 580 BinderProxy.mObject成员变量记录 BpBinder对象
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
// 587 将 BinderProxy对象信息添加到 BpBinder的成员变量 mObjects中
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
// 593 BinderProxy.mOrgue成员变量记录死亡通知对象
env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));

1.2 ServiceManagerNative.asInterface

//frameworks/base/core/java/android/os/ServiceManagerNative.java
// 这里的参数obj是一个BinderProxy对象,它的queryLocalInterface函数返回null。因此,最终以这个
//BinderProxy对象为参数创建一个ServiceManagerProxy对象。
static public IServiceManager asInterface(IBinder obj)
	// 38 因为 obj为 BinderProxy, 默认返回 null
	IServiceManager in =
	(IServiceManager)obj.queryLocalInterface(descriptor);
	// 44
	return new ServiceManagerProxy(obj);

1.3 ServiceManagerProxy

class ServiceManagerProxy implements IServiceManager {
    ...
    public IBinder getService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }
    ...
    public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        data.writeStrongBinder(service);
        data.writeInt(allowIsolated ? 1 : 0);
        data.writeInt(dumpPriority);
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }
}
...

在Java层,就有拥有了一个Service Manager远程接口ServiceManagerProxy。

二、AIDL接口定义(一个例子)

服务接口定义在frameworks/base/core/java/android/os/IBinderDemo.aidl文件中:

package android.os;  
  
interface IBinderDemoService  
{  
    void setText(int val);  
    int getText();  
} 

aidl文件,编译后会生成一个IBinderDemo.java文件:

/* 
 * This file is auto-generated.  DO NOT MODIFY. 
 * Original file: frameworks/base/core/java/android/os/IHelloService.aidl 
 */  
package android.os;  
public interface IBinderDemoService  extends android.os.IInterface  
{  
    /** Local-side IPC implementation stub class. */  
    public static abstract class Stub extends android.os.Binder implements android.os.IBinderDemoService  
    {  
        private static final java.lang.String DESCRIPTOR = "android.os.IBinderDemoService  ";  
        /** Construct the stub at attach it to the interface. */  
        public Stub()  
        {  
            this.attachInterface(this, DESCRIPTOR);  
        }  
  
        /** 
        * Cast an IBinder object into an android.os.IHelloService interface, 
        * generating a proxy if needed. 
        */  
        public static android.os.IBinderDemoService  asInterface(android.os.IBinder obj)  
        {  
            if ((obj==null)) {  
                return null;  
            }  
            android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);  
            if (((iin!=null)&&(iin instanceof android.os.IBinderDemoService  ))) {  
                return ((android.os.IBinderDemoService  )iin);  
            }  
            return new android.os.IBinderDemoService.Stub.Proxy(obj);  
        }  
  
        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_setText:  
                {  
                    data.enforceInterface(DESCRIPTOR);  
                    int _arg0;  
                    _arg0 = data.readInt();  
                    this.setText(_arg0);  
                    reply.writeNoException();  
                    return true;  
                }  
                case TRANSACTION_getText:  
                {  
                    data.enforceInterface(DESCRIPTOR);  
                    int _result = this.getText();  
                    reply.writeNoException();  
                    reply.writeInt(_result);  
                    return true;  
                }  
            }  
            return super.onTransact(code, data, reply, flags);  
        }  
  
        private static class Proxy implements android.os.IBinderDemoService
        {  
            private android.os.IBinder mRemote;  
  
            Proxy(android.os.IBinder remote)  
            {  
                mRemote = remote;  
            }  
  
            public android.os.IBinder asBinder()  
            {  
                return mRemote;  
            }  
  
            public java.lang.String getInterfaceDescriptor()  
            {  
                return DESCRIPTOR;  
            }  
  
            public void setText(int val) 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(val);  
                    mRemote.transact(Stub.TRANSACTION_setText, _data, _reply, 0);  
                    _reply.readException();  
                }  
                finally {  
                    _reply.recycle();  
                    _data.recycle();  
                }  
            }  
  
            public int getText() throws android.os.RemoteException  
            {  
                android.os.Parcel _data = android.os.Parcel.obtain();  
                android.os.Parcel _reply = android.os.Parcel.obtain();  
                int _result;  
                try {  
                    _data.writeInterfaceToken(DESCRIPTOR);  
                    mRemote.transact(Stub.TRANSACTION_getText, _data, _reply, 0);  
                    _reply.readException();  
                    _result = _reply.readInt();  
                }  
                finally {  
                    _reply.recycle();  
                    _data.recycle();  
                }  
                return _result;  
            }  
        }  
  
        static final int TRANSACTION_setText = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);  
        static final int TRANSACTION_getText = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);  
    }  
  
    public void setText(int val) throws android.os.RemoteException;  
    public int getText() throws android.os.RemoteException;  
}  

三、addService注册服务

定义一个Service,frameworks/base/services/java/com/android/server目录下新增了一个BinderDemoService.java文件:

package com.android.server;  
  
import android.content.Context;  
import android.os.IBinderDemoService;  
import android.util.Slog;  
  
public class BinderDemoService extends IBinderDemoService.Stub {  
    private static final String TAG = "BinderDemoService ";  
  
    BinderDemoService() {  
        init_native();  
    }  
  
    public void setText(int val) {  
       setText_native(val);  
    }     
  
    public int getText() {  
        return getText_native();  
    }  
      
    private static native boolean init_native();  
    private static native void setText_native(int val);  
   	private static native int getText_native();  
}  

定义Service完成之后,将BinderDemoService 注册到ServiceManager。

//frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
public class ActivityManagerService extends ...{
 	public void setSystemProcess() {
            ...
        try {
			...
            ServiceManager.addService("binderdemo", new BinderDemoService ());
            ...
            }
            ...
}
public final class ServiceManager {  
    ......  
  
    private static IServiceManager sServiceManager;  
  
    ......  
  
    public static void addService(String name, IBinder service) {  
        try {  
            getIServiceManager().addService(name, service);  
        } catch (RemoteException e) {  
            Log.e(TAG, "error in addService", e);  
        }  
    }  
  
    ......  
  
}  

getIServiceManager()在前面已经分析过了,下面继续分析addService函数调用流程:

class ServiceManagerProxy implements IServiceManager {  
    public ServiceManagerProxy(IBinder remote) {  
        mRemote = remote;  
    }  
  
    ......  
  
    public void addService(String name, IBinder service)  
        throws RemoteException {  
            Parcel data = Parcel.obtain();  
            Parcel reply = Parcel.obtain();  
            data.writeInterfaceToken(IServiceManager.descriptor);  
            data.writeString(name);  
            data.writeStrongBinder(service);  //此处 service == AMS
            mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);  
            reply.recycle();  
            data.recycle();  
    }  
  
    ......  
  
    private IBinder mRemote;  
}  

writeStrongBinder函数又是一个JNI方法,它定义在frameworks/base/core/jni/android_util_Binder.cpp文件中:


static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object)  
{  
    Parcel* parcel = parcelForJavaObject(env, clazz);  
    if (parcel != NULL) {  
        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));  
        if (err != NO_ERROR) {  
            jniThrowException(env, "java/lang/OutOfMemoryError", NULL);  
        }  
    }  
} 

这里的object参数是一个Java语言实现的Binder对象,在调用C++语言实现的Parcel::writeStrongBinder把这个对象写入到parcel对象时,首先通过ibinderForJavaObject函数把这个Java语言实现的Binder对象转换为C++语言实现的JavaBBinderHolder对象:

frameworks/base/core/jni/android_util_Binder.cpp
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) : NULL;   // 返回 JavaBBinder对象
    }  
  
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {  
        return (IBinder*)  
            env->GetIntField(obj, gBinderProxyOffsets.mObject);  
    }  
  
    LOGW("ibinderForJavaObject: %p is not a Binder object", obj);  
    return NULL;  
}  

ServiceManagerProxy.addService这个函数中,还有一个比较重要的函数transact。 mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0),mRemote成员变量实际上是一个BinderProxy对象,我们再来看看BinderProxy.transact函数的实现:

final class BinderProxy implements IBinder {  
    ......  
  
    public native boolean transact(int code, Parcel data, Parcel reply,  
                                int flags) throws RemoteException;  
  
    ......  
}  
//frameworks/base/core/jni/android_util_Binder.cpp
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,  
                        jint code, jobject dataObj,  
                        jobject replyObj, jint flags)  
{  
    ......  
  
    Parcel* data = parcelForJavaObject(env, dataObj);  
    if (data == NULL) {  
        return JNI_FALSE;  
    }  
    Parcel* reply = parcelForJavaObject(env, replyObj);  
    if (reply == NULL && replyObj != NULL) {  
        return JNI_FALSE;  
    }  
  
    IBinder* target = (IBinder*)  
        env->GetIntField(obj, gBinderProxyOffsets.mObject);  //得到这个BpBinder对象的IBinder接口
    if (target == NULL) {  
        jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");  
        return JNI_FALSE;  
    }  
  
    ......  
  //有了这个IBinder接口后,通过BpBinder::transact函数进入到Binder驱动程序,然后Binder驱动程序唤醒Service Manager响应这个ADD_SERVICE_TRANSACTION
    status_t err = target->transact(code, *data, reply, flags);  
  
    ......  
  
    if (err == NO_ERROR) {  
        return JNI_TRUE;  
    } else if (err == UNKNOWN_TRANSACTION) {  
        return JNI_FALSE;  
    }  
  
    signalExceptionForError(env, obj, err);  
    return JNI_FALSE;  
}  

Service Manager收到这个ADD_SERVICE_TRANSACTION请求时,就会把这个Binder实体纳入到自己内部进行管理。
这样,实现BinderDemoService 的Server的启动过程就完成了。

四、getService获取远程接口

在BinderDemo 这个Activity的onCreate函数,通过IServiceManager.getService函数来获得HelloService的远程接口:

public class BinderDemo extends Activity implements OnClickListener {    
    ......   
  
    private BinderDemoService binderService = null;    
  
    ......  
  
    @Override    
    public void onCreate(Bundle savedInstanceState) {    
  
        binderService = BinderDemoService .Stub.asInterface(    
                            ServiceManager.getService("binderdemo"));  
    }  
  
    ......  
}  

ServiceManager.getService实际上是调用了ServiceManagerProxy.getService函数:


class ServiceManagerProxy implements IServiceManager {  
    public ServiceManagerProxy(IBinder remote) {  
        mRemote = remote;  
    }  
  
    ......  
  
    public IBinder getService(String name) throws RemoteException {  
        Parcel data = Parcel.obtain();  
        Parcel reply = Parcel.obtain();  
        data.writeInterfaceToken(IServiceManager.descriptor);  
        data.writeString(name);  
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);  
        IBinder binder = reply.readStrongBinder();  
        reply.recycle();  
        data.recycle();  
        return binder;  
    }  
  
    ......  
  
    private IBinder mRemote;  
}  

reply它是一个Parcel对象,从下面语句返回:

mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);  


//引用reply
IBinder binder = reply.readStrongBinder(); 
//frameworks/base/core/jni/android_util_Binder.cpp
//把Java语言实现的Parcel对象class转换成C++语言实现的Parcel对象parcel,接着
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)  
{  
    Parcel* parcel = parcelForJavaObject(env, clazz);  
    if (parcel != NULL) {  
        //相当于return javaObjectForIBinder(env, new BpBinder(handle));  
        return javaObjectForIBinder(env, parcel->readStrongBinder());  
    }  
    return NULL;  
} 

javaObjectForIBinder这个函数,主要作用就是创建一个BinderProxy对象,并且把刚才获得的BpBinder对象的地址保存在这个BinderProxy对象的mObject成员变量中。

回到onCreate()函数:

helloService = IHelloService.Stub.asInterface(    
                    ServiceManager.getService("hello"))

相当于:

helloService = IHelloService.Stub.asInterface(new BinderProxy()));

具体定义:


public interface IBinderDemoService  extends android.os.IInterface  
{  
    /** Local-side IPC implementation stub class. */  
    public static abstract class Stub extends android.os.Binder implements android.os.IBinderDemoService  
    {  
        ......  
  
        public static android.os.IBinderDemoService asInterface(android.os.IBinder obj)  
        {  
            if ((obj==null)) {  
                return null;  
            }  
            android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);  
            if (((iin!=null)&&(iin instanceof android.os.IHelloService))) {  
                return ((android.os.IBinderDemoService )iin);  
            }  
            //相当于return new android.os.IHelloService.Stub.Proxy(new BinderProxy());  
            return new android.os.IBinderDemoService .Stub.Proxy(obj);  
        }  
  
        ......  
    }  
}  

这样,就获得了BinderDemoService 的远程接口了,其实就是一个实现了IBinderDemoService 接口的IBinderDemoService .Stub.Proxy对象。

五、Client通过远程接口使用BinderDemoService提供的服务

上面获得远程接口后,就可以使用接口了:

public class BinderDemoextends Activity implements OnClickListener {  
    ......  
    @Override  
    public void onClick(View v) {  
        if(v.equals(readButton)) {  
            int val = binderService.getVal();    
            ......  
        }  
    }  
    ......  
}  

binderService接口实际上是一个IBinderDemoService.Stub.Proxy对象,因此,我们进入到IBinderDemoService.Stub.Proxy类的getText函数中:

public interface BinderDemoService extends android.os.IInterface  
{  
    /** Local-side IPC implementation stub class. */  
    public static abstract class Stub extends android.os.Binder implements android.os.IBinderDemoService  
    {  
        ......  
  
        private static class Proxy implements android.os.IBinderDemoService   
        {  
            private android.os.IBinder mRemote;  
  
            ......  
  
            public int getText() throws android.os.RemoteException  
            {  
                android.os.Parcel _data = android.os.Parcel.obtain();  
                android.os.Parcel _reply = android.os.Parcel.obtain();  
                int _result;  
                try {  
                    _data.writeInterfaceToken(DESCRIPTOR);  
                    mRemote.transact(Stub.TRANSACTION_getText, _data, _reply, 0);  
                    _reply.readException();  
                    _result = _reply.readInt();  
                }  
                finally {  
                    _reply.recycle();  
                    _data.recycle();  
                }  
                return _result;  
            }  
        }  
  
        ......  
        static final int TRANSACTION_getText = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);  
    }  
  
    ......  
}  

最终,经过层层返回,就回到IBinderDemoService.Stub.Proxy.getVal函数中来了,从下面语句返回:

mRemote.transact(Stub.TRANSACTION_getText, _data, _reply, 0);  

并将结果读出来:

_result = _reply.readInt();  

总结

以上通过一个BinderDemo例子详细讲解了binder的使用,本文仅仅简单介绍了binder的使用,而binder具体详细调用流程还得去阅读Android源代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值