码迷,mamicode.com
首页 > 移动开发 > 详细

android分析之Binder 02

时间:2014-10-01 20:54:11      阅读:269      评论:0      收藏:0      [点我收藏+]

标签:des   android   blog   io   os   使用   ar   java   for   

分析Java层的ServiceManager,看看Binder在Java层是如何实现的。

public final class ServiceManager {
    private static final String TAG = "ServiceManager";

    private static IServiceManager sServiceManager;//IserviceManager是一个接口,定义了通用(公共)方法。
    private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();//缓存,其值是IBinder

...

    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);//先从缓存中查找
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().getService(name);//生成新的IBinder
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }
...

  这里的ServiceManager仅仅是一种封装,其成员变量和方法都是static。从上面的sCache保存的键值对和getService的返回值类型为IBinder(与C++层的IBinder不同)可以看出,通过ServiceManager得到的是一个IBinder类型对象,通过后面的分析,实际可以看出它是BpBinder对象。

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());//找到IServiceManager对象,并返回
        return sServiceManager;
    }

...

    /**
     * Return the global "context object" of the system.  This is usually
     * an implementation of IServiceManager, which you can use to find
     * other services.
     */
    public static final native IBinder getContextObject();//BinderInternale:调用native函数,返回IBinder对象

...

    static public IServiceManager asInterface(IBinder obj)//传入的就是上面的那个IBinder对象,记住这是Java对象
    {
        if (obj == null) {
            return null;
        }
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);//从IBinder对象里查找,并转换为IServiceManager对象
        if (in != null) {
            return in;
        }
        
        return new ServiceManagerProxy(obj);//如果找不到,则使用传入的IBinder对象生成一个ServiceManagePorxy对象
    }

  上面绕了一圈,直接从ServiceManagerProxy来看,有两方面:1,得到native层的一个某对象,并转换为IBinder,即上面的native IBinder getContextObject();2,使用获得的IBinder来生成一个ServiceManagerProxy对象。下面来看看ServiceManagerProxy的构造方法:

    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;//mRemote是IBinder类型,这里将传入的IBinder对象保存在mRemote
    }
    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的transact来传送数据
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }

  小结:调用ServiceManager的getService(),会生成一个ServiceManagerProxy对象,该对象持有一个mRemote(IBinder),通过该mRemote(它是BpBinder在Java层的代表)可以向下层发送数据。

 

getContextObject分析:

public static final native IBinder getContextObject();//BinderInternale:调用native函数,返回IBinder对象——对应为下面这个函数:

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);//走到这里:b为一个BpBinder
    return javaObjectForIBinder(env, b);//返回一个Java层的BinderProxy

  到这里明白了,上面的mRemote持有的就是BinderProxy对象。而上面调用mRemote对象的transact()方法就是调用BinderProxy的transact方法:

    public native boolean transact(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException;
...
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
    if (dataObj == NULL) {
        jniThrowNullPointerException(env, NULL);
        return JNI_FALSE;
    }

    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*)//将BinderProxy转换为BpBinder
        env->GetIntField(obj, gBinderProxyOffsets.mObject);
...
  status_t err = target->transact(code, *data, reply, flags);//调用BpBinder来与更下层通信 ...

  走到这里:Java层主要就是获取Native层的BpBinder,并使用它来与下层通信。

 

android分析之Binder 02

标签:des   android   blog   io   os   使用   ar   java   for   

原文地址:http://www.cnblogs.com/littlefishxu/p/4003445.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!