1. 程式人生 > >Android8.0 Binder之面向HAL服務(二)

Android8.0 Binder之面向HAL服務(二)

上一篇我們從Binder在系統native層的服務管理與提供機制,它與Framework的native層的實現大不相同,但是實現思想是一致的,都是需要藉助Binder驅動來實現服務的管理與跨程序使用。只不過,由於業務層需要導致實現上的不同,比如HAL層的Binder框架並沒有將通訊和業務絞和起來,所以在業務邏輯處理上更為複雜,當然複雜是為了更好的適應業務需求。那麼我們不妨回到Java層看看Java的HwBinder是如何為使用者提供便利操作的,首先我們來看基本的HwBinder在Java層的框架。

1. Binder頂層協議

public interface IHwBinder {
    // These MUST match their corresponding libhwbinder/IBinder.h definition !!!
public static final int FIRST_CALL_TRANSACTION = 1; public static final int FLAG_ONEWAY = 1; public void transact( //通訊操作函式 int code, HwParcel request, HwParcel reply, int flags) throws RemoteException; public IHwInterface queryLocalInterface(String descriptor); //查詢服務描述符
..... }

HwRemoteBinder 實現了 IHwBinder 介面

public class HwRemoteBinder implements IHwBinder {
    private static final String TAG = "HwRemoteBinder";

    private static final NativeAllocationRegistry sNativeRegistry;

    public HwRemoteBinder() {
        native_setup_empty();

        sNativeRegistry.registerNativeAllocation(
                this
, mNativeContext); } @Override public IHwInterface queryLocalInterface(String descriptor) { return null; //返回為空 } @Override public native final void transact( //未實現 int code, HwParcel request, HwParcel reply, int flags) throws RemoteException; } ...... private static native final long native_init(); private native final void native_setup_empty(); ...... private long mNativeContext; }

HwBinder 實現了 IHwBinder 介面

public abstract class HwBinder implements IHwBinder {
    private static final String TAG = "HwBinder";

    private static final NativeAllocationRegistry sNativeRegistry;

    public HwBinder() {
        native_setup();

        sNativeRegistry.registerNativeAllocation(
                this,
                mNativeContext);
    }

    @Override
    public final native void transact( //未實現
            int code, HwParcel request, HwParcel reply, int flags)
        throws RemoteException;

    public abstract void onTransact(// 新增
            int code, HwParcel request, HwParcel reply, int flags)
        throws RemoteException;

    public native final void registerService(String serviceName)
        throws RemoteException;

    public static native final IHwBinder getService(
            String iface,
            String serviceName)
        throws RemoteException, NoSuchElementException;

    // Returns address of the "freeFunction".
    private static native final long native_init();

    private native final void native_setup();
    ......
    private long mNativeContext;
}

IHwInterface 介面

public interface IHwInterface {
    public IHwBinder asBinder();
}

在 frameworks\base\core\jni\android_os_HwBinder.cpp 檔案中可以看到登錄檔

static JNINativeMethod gMethods[] = {
    { "native_init", "()J", (void *)JHwBinder_native_init },
    { "native_setup", "()V", (void *)JHwBinder_native_setup },

    { "transact",
        "(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V",
        (void *)JHwBinder_native_transact },

    { "registerService", "(Ljava/lang/String;)V",
        (void *)JHwBinder_native_registerService },

    { "getService", "(Ljava/lang/String;Ljava/lang/String;)L" PACKAGE_PATH "/IHwBinder;",
        (void *)JHwBinder_native_getService },
};
static jlong JHwBinder_native_init(JNIEnv *env) {
    JHwBinder::InitClass(env);

    return reinterpret_cast<jlong>(&releaseNativeContext);
}

初始化類

void JHwBinder::InitClass(JNIEnv *env) {
    ScopedLocalRef<jclass> clazz(
            env, FindClassOrDie(env, CLASS_PATH));

    gFields.contextID =
        GetFieldIDOrDie(env, clazz.get(), "mNativeContext", "J");

    gFields.onTransactID =
        GetMethodIDOrDie(
                env,
                clazz.get(),
                "onTransact",
                "(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V");
}
static void JHwBinder_native_setup(JNIEnv *env, jobject thiz) {
    sp<JHwBinder> context = new JHwBinder(env, thiz);

    JHwBinder::SetNativeContext(env, thiz, context);
}

設定上下文

sp<JHwBinder> JHwBinder::SetNativeContext(
        JNIEnv *env, jobject thiz, const sp<JHwBinder> &context) {
    sp<JHwBinder> old =
        (JHwBinder *)env->GetLongField(thiz, gFields.contextID);

    if (context != NULL) {
        context->incStrong(NULL /* id */);
    }

    if (old != NULL) {
        old->decStrong(NULL /* id */);
    }

    env->SetLongField(thiz, gFields.contextID, (long)context.get());

    return old;
}

獲取服務流程

static jobject JHwBinder_native_getService(
        JNIEnv *env,
        jclass /* clazzObj */,
        jstring ifaceNameObj,
        jstring serviceNameObj) {

    using ::android::hidl::base::V1_0::IBase;
    using ::android::hidl::manager::V1_0::IServiceManager;

    .......

    auto manager = hardware::defaultServiceManager(); //獲取服務管家

    if (manager == nullptr) {
        LOG(ERROR) << "Could not get hwservicemanager.";
        signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
        return NULL;
    }

    const char *ifaceNameCStr = env->GetStringUTFChars(ifaceNameObj, NULL);
    if (ifaceNameCStr == NULL) {
        return NULL; // XXX exception already pending?
    }
    std::string ifaceName(ifaceNameCStr);
    env->ReleaseStringUTFChars(ifaceNameObj, ifaceNameCStr);
    ::android::hardware::hidl_string ifaceNameHStr;
    ifaceNameHStr.setToExternal(ifaceName.c_str(), ifaceName.size());

    const char *serviceNameCStr = env->GetStringUTFChars(serviceNameObj, NULL);
    if (serviceNameCStr == NULL) {
        return NULL; // XXX exception already pending?
    }
    std::string serviceName(serviceNameCStr);
    env->ReleaseStringUTFChars(serviceNameObj, serviceNameCStr);
    ::android::hardware::hidl_string serviceNameHStr;
    serviceNameHStr.setToExternal(serviceName.c_str(), serviceName.size());
    //查詢Binder型別
    Return<IServiceManager::Transport> transportRet =
            manager->getTransport(ifaceNameHStr, serviceNameHStr);

    if (!transportRet.isOk()) {
        signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
        return NULL;
    }

    IServiceManager::Transport transport = transportRet;

#ifdef __ANDROID_TREBLE__
#ifdef __ANDROID_DEBUGGABLE__
    const char* testingOverride = std::getenv("TREBLE_TESTING_OVERRIDE");
    const bool vintfLegacy = (transport == IServiceManager::Transport::EMPTY)
            && testingOverride && !strcmp(testingOverride, "true");
#else // __ANDROID_TREBLE__ but not __ANDROID_DEBUGGABLE__
    const bool vintfLegacy = false;
#endif // __ANDROID_DEBUGGABLE__
#else // not __ANDROID_TREBLE__
    const bool vintfLegacy = (transport == IServiceManager::Transport::EMPTY);
#endif // __ANDROID_TREBLE__";

    if (transport != IServiceManager::Transport::HWBINDER && !vintfLegacy) {
        LOG(ERROR) << "service " << ifaceName << " declares transport method "
                   << toString(transport) << " but framework expects hwbinder.";
        signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
        return NULL;
    }

    Return<sp<hidl::base::V1_0::IBase>> ret = manager->get(ifaceNameHStr, serviceNameHStr); //返回服務

    if (!ret.isOk()) {
        signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
        return NULL;
    }

    sp<hardware::IBinder> service = hardware::toBinder< //轉換為Binder
            hidl::base::V1_0::IBase, hidl::base::V1_0::BpHwBase>(ret);

    if (service == NULL) {
        signalExceptionForError(env, NAME_NOT_FOUND);
        return NULL;
    }

    LOG(INFO) << "Starting thread pool.";
    ::android::hardware::ProcessState::self()->startThreadPool();

    return JHwRemoteBinder::NewObject(env, service); //建立BpBinder物件並返回
}

可以看到獲取服務最終還是需要呼叫native層的Binder框架來處理,這一點可Framework層中的Binder(Java)設計思想是一致的

2. Power.hal生成的服務介面

由於定義了.hal檔案,通過編譯會生成對響應的服務程式碼,out/target/gen/JAVA_LIBRARIES/android.hardware.power-V1.0-java_intermediates目錄下IPower.java檔案

public static IPower getService(String serviceName) throws android.os.RemoteException {
        return IPower.asInterface(android.os.HwBinder.getService("[email protected]::IPower",serviceName));
    }

static IPower asInterface(android.os.IHwBinder binder) { //查詢
        if (binder == null) {
            return null;
        }

        android.os.IHwInterface iface =
                binder.queryLocalInterface(kInterfaceName);

        if ((iface != null) && (iface instanceof IPower)) {
            return (IPower)iface;
        }

        IPower proxy = new IPower.Proxy(binder); //Proxy內部類

        try {
            for (String descriptor : proxy.interfaceChain()) {
                if (descriptor.equals(kInterfaceName)) {
                    return proxy;
                }
            }
        } catch (android.os.RemoteException e) {
        }

        return null;
    }

內部類,返回遠端Binder代理物件

public static final class Proxy implements IPower {
        private android.os.IHwBinder mRemote;

        public Proxy(android.os.IHwBinder remote) {
            mRemote = java.util.Objects.requireNonNull(remote);
        }

        @Override
        public android.os.IHwBinder asBinder() {
            return mRemote;
        }
        ......
}

內部類,通過Stub呼叫

public static abstract class Stub extends android.os.HwBinder implements IBase {
        @Override
        public android.os.IHwBinder asBinder() {
            return this;
        }

        @Override
        public final java.util.ArrayList<String> interfaceChain() {
            return new java.util.ArrayList<String>(java.util.Arrays.asList(
                    IBase.kInterfaceName));
        }

        @Override
        public final String interfaceDescriptor() {
            return IBase.kInterfaceName;

        }
        ......
         @Override
        public void onTransact(int _hidl_code, android.os.HwParcel _hidl_request, final android.os.HwParcel _hidl_reply, int _hidl_flags)
                throws android.os.RemoteException {
        }
 }

由此可以看出HIDL生成的服務程式碼與AIDL是相似的,繼續看會發現IPower繼承了android.hidl.base.V1_0.IBase.java, IBase繼承自android.os.IHwInterface.java

本篇跟蹤了Java層仍然需要通過native層的Binder框架來使用Hw層服務的,流程和Framework層的Binder呼叫大致一樣,較為簡單,今天就到此為止。