读书笔记 《深入理解安卓内核设计思想》获取ServiceManager服务 一

1,应用程序只需要调用ServiceManager.getService(name)就可以获取到获取到相应的服务

    /**
     * Returns a reference to a service with the given name.
     * 
     * @param name the name of the service to get
     * @return a reference to the service, or <code>null</code> if the service doesn't exist
     */
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return Binder.allowBlocking(getIServiceManager().getService(name));
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

先从缓存中去翻阅历史记录,如果缓存中有就直接返回,如果没有就调用getIServiceManager().getService(name)发起一条查询请求。

2,getIServiceManager()会获取到一个IServiceManager的接口对象

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

        // Find the service manager
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
    }

为了防止多次创建IServiceManager对象,会做一个非空判断,如果为空才会调用ServiceManagerNative的asInterface获取一个IServiceManager对象.传入的参数是个binder对象。

3,接着看asInterface的实现

    /**
     * Cast a Binder object into a service manager interface, generating
     * a proxy if needed.
     */
    static public IServiceManager asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
        
        return new ServiceManagerProxy(obj);
    }

可以J看到方法上面有一行注释,意思是将Binder对象转换为服务管理器接口,生成
      *代理(如果需要)。也就是将BInder对象转化为IServiceManager对象。

该方法首先会调用queryLocalInterface去查询本地是否已经有IServiceManager,如果没有也就是返回值为null就会创建一个

ServiceManagerProxy 对象,可以肯定ServiceManagerProxy 肯定实现了IServiceManager这个接口。

4,接着看ServiceManagerProxy的构造方法是如何实现的

    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
    

可以看到,ServiceManagerProxy没有做任何事情,只是将这个Binder对象保存起来了。

如果客户端想要获取各种服务端的binder,只需要调用ServiceManagerProxy中的getService就可以获取到各种服务端的biner句柄,然后就可以操作服务端的相关业务了,如下:

    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;
    }

可以看到getService主要做了如下事情:

a,使用Parcel对象打包数据

b,调用Binder的transact方法发送数据

c,获取返回结果

整个过程最重要的一个方法就是transact方法,启动里面有一个参数GET_SERVICE_TRANSACTION

在Ibinder中定义:

  /**
     * The first transaction code available for user commands.
     */
    int FIRST_CALL_TRANSACTION  = 0x00000001;

业务代码是1,在服务端定义的业务代码也是1这样服务端和客户端就对应起来了

enum {
    /* Must match definitions in IBinder.h and IServiceManager.h */
    PING_TRANSACTION  = B_PACK_CHARS('_','P','N','G'),
    SVC_MGR_GET_SERVICE = 1,
    SVC_MGR_CHECK_SERVICE,
    SVC_MGR_ADD_SERVICE,
    SVC_MGR_LIST_SERVICES,
};

5,最开始我们获取getService的时候然后一直到创建ServiceManagerProxy对象的时候一直有个Biner对象贯穿其中,这样我们才能最终调用transact方法与服务端进行通信,那么这个Biner是怎么来的呢?

可以看到最开始是调用BinderInternal.getContextObject() 传入了asInterface接口。

6,继续分析这个方法

,

    /**
     * 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();

跟踪代码发现这是一个native方法

而切注释是这样说的:

返回系统的全局“上下文对象”。 通常是IserviceManager的实现,可用于查找其他服务.

7,接着看改方法的native层实现

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    return javaObjectForIBinder(env, b);
}

可以看到使用ProcessState实现的

其中ProcessState::self()->getContextObject 返回的是一个native层的biner对象,也就是BpBinder,而BpBiner实现了native层IBiner接口 。BinderProxy实现了java层的IBiner接口。

其中javaObjectForIBinder是将一个BpBinder转化为BinderProxy,也就是将native层的biner代理对象转化java层的代理对象。

最后才将biner返回到java层。

说白了BinderInternal.getContextObject()其实拿到的其是一个native层的biner对象,中间通过jni的调用转换成了java层的binder也就是BinderProxy.

拿到这个java层的binder对象干什么用能,其实就是为了调用java层的中binder的transact方法,当然说的有点绝对了,肯定还做了其他的事。然后我们又回到了之前分析的transact方法。

8,继续分析之前的tranct方法.

 根据之前的分析BinderInternal.getContextObject()反会的是一个实现了IBinder接口的BinderProxy对象,最后传给了ServiceManagerProxy,然后getService的时候调用了transact方法。所以我们接着分析BinderProxy的transact方法

    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");

        if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)) {
            // For now, avoid spamming the log by disabling after we've logged
            // about this interface at least once
            mWarnOnBlocking = false;
            Log.w(Binder.TAG, "Outgoing transactions from this process must be FLAG_ONEWAY",
                    new Throwable());
        }

        final boolean tracingEnabled = Binder.isTracingEnabled();
        if (tracingEnabled) {
            final Throwable tr = new Throwable();
            Binder.getTransactionTracker().addTrace(tr);
            StackTraceElement stackTraceElement = tr.getStackTrace()[1];
            Trace.traceBegin(Trace.TRACE_TAG_ALWAYS,
                    stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName());
        }
        try {
            return transactNative(code, data, reply, flags);
        } finally {
            if (tracingEnabled) {
                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
            }
        }
    }

可以看到最终还是调用到了native层的transactNative方法

接着看 frameworks\base\core\jni\android_util_Binder.cpp

static const JNINativeMethod gBinderProxyMethods[] = {
     /* name, signature, funcPtr */
    {"pingBinder",          "()Z", (void*)android_os_BinderProxy_pingBinder},
    {"isBinderAlive",       "()Z", (void*)android_os_BinderProxy_isBinderAlive},
    {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
    {"transactNative",      "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
    {"linkToDeath",         "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
    {"unlinkToDeath",       "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
    {"destroy",             "()V", (void*)android_os_BinderProxy_destroy},
};

通过android_util_Binder.cpp中的jni注册函数看,java层transactNative方法对应的是android_os_BinderProxy_transact这个方法

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*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    if (target == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
        return JNI_FALSE;
    }

    ALOGV("Java code calling transact on %p in Java object %p with code %" PRId32 "\n",
            target, obj, code);


    bool time_binder_calls;
    int64_t start_millis;
    if (kEnableBinderSample) {
        // Only log the binder call duration for things on the Java-level main thread.
        // But if we don't
        time_binder_calls = should_time_binder_calls();

        if (time_binder_calls) {
            start_millis = uptimeMillis();
        }
    }

    //printf("Transact from Java code to %p sending: ", target); data->print();
    status_t err = target->transact(code, *data, reply, flags);
    //if (reply) printf("Transact from Java code to %p received: ", target); reply->print();

    if (kEnableBinderSample) {
        if (time_binder_calls) {
            conditionally_log_binder_call(start_millis, target, code);
        }
    }

    if (err == NO_ERROR) {
        return JNI_TRUE;
    } else if (err == UNKNOWN_TRANSACTION) {
        return JNI_FALSE;
    }

    signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize());
    return JNI_FALSE;
}

通过这一行代码 status_t err = target->transact(code, *data, reply, flags);发现

最终调用的了到了native层BpBinder.cpp里面的transact函数。根据前面的分析,之前是将native层的Bpbiner对象转化为java层的

BinderProxy对象,在这个方法里面肯定要转换回去,不然怎么调用native层的transact函数。

其中的 gBinderProxyOffsets.mObject记录的是native层的对象对象属性id,然后就可以通过GetLongField获取这个对象的内存地址了。接着就可以通过这个指针调用c层的transact方法:

status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    // Once a binder has died, it will never come back to life.
    if (mAlive) {
        status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }

    return DEAD_OBJECT;
}

然后用到了IPCThreadState.

整个过程最重要的就是如Binder的native层的biner代理的和java层的binder代理的互相转化,比较深层次的进程通信还未说道。

重点就要关注ProcessState和IPCThreadState这两个类,以后待分析

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值