Android Binder getService(java)源码分析

Posted we1less

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Binder getService(java)源码分析相关的知识,希望对你有一定的参考价值。

本篇是继续上一篇进行分析的https://blog.csdn.net/we1less/article/details/120731185

代码回到ServiceManager.java  路径frameworks/base/core/java/android/os/ServiceManager.java

        上一篇文章说道 BinderInternal.getContextObject() 返回的是android/os/BinderProxy对象,它是java层的,这个对象的mObject成员变量带有native层ServiceManager代理类对象

        而getIServiceManager().getService(name) 其实调用的是ServiceManagerProxy的getService

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


private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }
 
        // Find the service manager
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
    }

ServiceManagerNative .asInterface

        路径  :frameworks/base/core/java/android/os/ServiceManagerNative.java

        所以asInterface就是new ServiceManagerProxy(obj);

        这个obj就是上面返回的带有native层ServiceManager代理类对象的java层的android/os/BinderProxy对象。把它赋值给ServiceManagerProxy中的mRemote成员,通信就是调用mRemote成员的transact方法。

        到此我们知道getIServiceManager().getService(name) 其实调用的是ServiceManagerProxygetService

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

ServiceManagerProxy.getService

        路径  :frameworks/base/core/java/android/os/ServiceManagerNative.java

        mRemote 就是  android/os/BinderProxy对象

        IServiceManager.descriptor :

        static final String descriptor = "android.os.IServiceManager";

        int GET_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;

        其实最后就是变成了与Binder驱动通信获取对应服务,Binder驱动填充reply的过程

public IBinder getService(String name) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IServiceManager.descriptor);
    data.writeString(name);
    //mRemote 就是  android/os/BinderProxy对象
    mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
    IBinder binder = reply.readStrongBinder();
    reply.recycle();
    data.recycle();
    return binder;
}

 BinderProxy.transact

        路径 :frameworks/base/core/java/android/os/Binder.java

        核心就是调用的 transactNative,这是一个native方法

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    ...
    try {
        //native方法
        return transactNative(code, data, reply, flags);
    } finally {
        if (tracingEnabled) {
            Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
        }
    }
}

public native boolean transactNative(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException;

 transactNative

        路径  frameworks/base/core/jni/android_util_Binder.cpp

        gBinderProxyOffsets 就是 android/os/BinderProxy

        gBinderProxyOffsets.mObject 就是native层的ServiceManager

        调用BpBinder(0)的transact方法

        最后就是填充reply  将replyObj填充为java的android/os/Parcel 可打包对象

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
    //一系列的判空 ...
    //填充reply  将replyObj填充为java的android/os/Parcel 可打包对象
    Parcel* reply = parcelForJavaObject(env, replyObj);

    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    //一系列判空 ...
    status_t err = target->transact(code, *data, reply, flags);
    ...
    signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize());
    return JNI_FALSE;
}

这里补一下JNINativeMethod  

//路径  frameworks/base/core/jni/core_jni_helpers.h
static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className,
                                       const JNINativeMethod* gMethods, int numMethods) {
    int res = AndroidRuntime::registerNativeMethods(env, className, gMethods, numMethods);
    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
    return res;
}

//路径  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},
};

BpBinder(0)的transact

        路径  frameworks/native/libs/binder/BpBinder.cpp

        调用了IPCThreadState::self()->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::self()->transact

        路径:frameworks/native/libs/binder/IPCThreadState.cpp

        调用了writeTransactionData  

        //BC_TRANSACTION 一般代表客户端调用驱动端 BR_xxx  一般指驱动返回给客户端

        (flags & TF_ONE_WAY) == 0  判断是不是oneway函数  很显然获取服务不是

        填充reply

        然后调用waitForResponse

status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
    ...
        //BC_TRANSACTION 一般代表客户端调用驱动端
        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
    }
    ...
    //oneway ? 1 : 0  
    if ((flags & TF_ONE_WAY) == 0) {
        ...
        if (reply) {
            //填充reply
            err = waitForResponse(reply);
        ...

    return err;
}

writeTransactionData

        路径 : frameworks/native/libs/binder/IPCThreadState.cpp

        主要是填充  binder_transaction_data  结构体向驱动发送

        code为java传递过来的GET_SERVICE_TRANSACTION == 0

status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
    int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
    binder_transaction_data tr;
    ...
    mOut.writeInt32(cmd);
    mOut.write(&tr, sizeof(tr));

    return NO_ERROR;
}

waitForResponse

        路径 : frameworks/native/libs/binder/IPCThreadState.cpp

        最终到这里就是跟驱动获取返回数据了

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    uint32_t cmd;
    int32_t err;

    while (1) {
        if ((err=talkWithDriver()) < NO_ERROR) break;
        err = mIn.errorCheck();
        if (err < NO_ERROR) break;
        if (mIn.dataAvail() == 0) continue;

        cmd = (uint32_t)mIn.readInt32();

        IF_LOG_COMMANDS() {
            alog << "Processing waitForResponse Command: "
                << getReturnString(cmd) << endl;
        }

        switch (cmd) {
        case BR_TRANSACTION_COMPLETE:
            if (!reply && !acquireResult) goto finish;
            break;

        case BR_DEAD_REPLY:
            err = DEAD_OBJECT;
            goto finish;

        case BR_FAILED_REPLY:
            err = FAILED_TRANSACTION;
            goto finish;

        case BR_ACQUIRE_RESULT:
            {
                ALOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");
                const int32_t result = mIn.readInt32();
                if (!acquireResult) continue;
                *acquireResult = result ? NO_ERROR : INVALID_OPERATION;
            }
            goto finish;

        case BR_REPLY:
            {
                binder_transaction_data tr;
                err = mIn.read(&tr, sizeof(tr));
                ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");
                if (err != NO_ERROR) goto finish;

                if (reply) {
                    if ((tr.flags & TF_STATUS_CODE) == 0) {
                        reply->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);
                    } else {
                        err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
                        freeBuffer(NULL,
                            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), this);
                    }
                } else {
                    freeBuffer(NULL,
                        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), this);
                    continue;
                }
            }
            goto finish;

        default:
            err = executeCommand(cmd);
            if (err != NO_ERROR) goto finish;
            break;
        }
    }

finish:
    if (err != NO_ERROR) {
        if (acquireResult) *acquireResult = err;
        if (reply) reply->setError(err);
        mLastError = err;
    }

    return err;
}

其实后面与binder驱动相关的可以参考这篇原理Android Binder(C语言版本例子)_we1less的博客-CSDN博客 

这里返回结果为对应的Serivce的handle,然后利用这个handle构造出对应的BpBinder,这一部分就完全和IServiceManager的获取是一样的,只不过ServiceManager是直接new BpBinder(0)
而远程服务则是需要先从ServiceManager中获取handle,然后再new BpBinder(handle)

以上是关于Android Binder getService(java)源码分析的主要内容,如果未能解决你的问题,请参考以下文章

Android service Binder用法

Android驱动学习-内部机制_回顾binder框架关键点

android的Binder通信机制java层浅谈

Android 进阶——Binder IPC之Native 服务的启动及代理对象的获取详解

Android 进阶——Binder IPC之Native 服务的启动及代理对象的获取详解

获取服务(getService)