Android O HIDL框架

HIDL简介

  Android O开始,Google为了将framework和HAL层分割开来,使得framework可以独立于HAL层更新,设计了HIDL。有了HIDL,HAL模块可以以一个独立的Service启动,framework可以通过Binder来和HAL模块进行通信,厂家实现的HAL模块将会被放到设备的/vendor目录下。
  HIDL分为两种模式:Passthrough模式和Binderized模式。Passthrough模式是为了兼容Android O以前打开HAL的模式:首次调用该HAL接口时会调用hw_get_module打开HAL模块。但是Passthrough模式仅能用于C++层,Java层值能使用Binderized模式。而Binderized模式会启动一个Service进程,里面已经加载好HAL的so库,framework直接通过Binder和该HAL service通信。

HIDL用法

  系统定义的所有的.hal接口,都是通过hidl-gen工具转换成对应的代码。hidl-gen源码路径:system/tools/hidl,是在ubuntu上可执行的二进制文件。
  使用方法(可执行文件位于源码的out/host/linux-x86/bin/hidl-gen):`

usage: ./host/linux-x86/bin/hidl-gen [-p ] -o  -L  (-r )+ [-t] fqname+
         -h: Prints this menu.
         -L : The following options are available:
            check           : Parses the interface to see if valid but doesn't write any files.
            c++             : (internal) (deprecated) Generates C++ interface files for talking to HIDL interfaces.
            c++-headers     : (internal) Generates C++ headers for interface files for talking to HIDL interfaces.
            c++-sources     : (internal) Generates C++ sources for interface files for talking to HIDL interfaces.
            export-header   : Generates a header file from @export enumerations to help maintain legacy code.
            c++-impl        : Generates boilerplate implementation of a hidl interface in C++ (for convenience).
            c++-impl-headers: c++-impl but headers only
            c++-impl-sources: c++-impl but sources only
            java            : (internal) Generates Java library for talking to HIDL interfaces in Java.
            java-constants  : (internal) Like export-header but for Java (always created by -Lmakefile if @export exists).
            vts             : (internal) Generates vts proto files for use in vtsd.
            makefile        : (internal) Generates makefiles for -Ljava and -Ljava-constants.
            androidbp       : (internal) Generates Soong bp files for -Lc++-headers and -Lc++-sources.
            androidbp-impl  : Generates boilerplate bp files for implementation created with -Lc++-impl.
            hash            : Prints hashes of interface in `current.txt` format to standard out.
         -o : Location to output files.
         -p : Android build root, defaults to $ANDROID_BUILD_TOP or pwd.
         -r : E.g., android.hardware:hardware/interfaces.
         -t: generate build scripts (Android.bp) for tests.

BootControl模块编译过程

  在Android的frameworks/hardware(对应包前缀android.frameworks.),hardware/interfaces(对应包前缀android.hardware.),system/libhidl(对应包前缀android.hidl.),system/hardware/interfaces(对应包前缀android.system.)目录下均放置有update-makefiles.sh脚本,执行这个脚本就会在上述目录下找到*.hal文件的位置,自动生成对应的mk(只在hardware/interfaces才生成)和bp文件。Google设计使用hidl-gen工具编译*.hal文件来自动生成对应的java,cpp,.h等文件,通过*.hal来描述所有的HIDL接口和类型。在对应的mk和bp文件可以看到具体的hidl-gen生成规则和输出路径。本文将以IBootControl.hal为例讲HIDL的框架,不再讨论这个HAL的具体功能。使用hidl-gen工具后,在out目录生成的文件主要有IBootControl.java(Java层对HIDL的封装),BpHwBootControl.h(Binder Bp端头文件),BnHwBootControl.h(Binder Bn端头文件),BsBootControl.h(Passthrough模式的封装),BootControlAll.cpp(包含Binder Bp端函数实现,Binder Bn端函数实现,BsBootControl部分函数实现还有IBootControl的getService实现等)。
  可以看到*.hal文件的内容很简单,package指明了这个IBootControl.hal文件所属的包,interface声明了IBootControl.hal的接口。所有的IXXX.hal的接口均隐式继承自IBase.hal的接口,类比Java所有类都继承自java.lang.Object。IBase.hal包含了一些体现HAL接口共性的接口,类比Java所有的实例对象都能使用Obejct类的notify()方法。
  IBootControl.hal和types.hal编译自动生成出来的cpp,.h等文件会被放到[email protected]里面,java文件会被放到android.hidl.base-V1.0-java.jar动态库和android.hardware.boot-V1.0-java-static静态库里面。这些so和jar会被放在设备的/system下面,然而default目录下service.cpp则被编译成[email protected],跟HAL具体实现的so一起被放在/vendor下。Bootcontol模块的目录结构如下:

├── 1.0
│   ├── Android.bp
│   ├── Android.mk
│   ├── default
│   │   ├── [email protected]
│   │   ├── Android.mk
│   │   ├── BootControl.cpp
│   │   ├── BootControl.h
│   │   └── service.cpp
│   ├── IBootControl.hal
│   ├── types.hal
│   └── vts
│       ├── Android.bp
│       ├── Android.mk
│       └── functional
│           ├── Android.bp
│           └── VtsHalBootV1_0TargetTest.cpp
└── Android.bp

hardware/interfaces/boot/1.0/IBootControl.hal

package [email protected];

/**
 * The Boot Control HAL is designed to allow for managing sets of redundant
 * partitions, called slots, that can be booted from independently. Slots
 * are sets of partitions whose names differ only by a given suffix.
 * They are identified here by a 0 indexed number and associated with their
 * suffix, which is appended to the base name for any particular partition
 * to find the one associated with that slot.
 * The primary use of this set up is to allow for background updates while
 * the device is running, and to provide a fallback in the event that the
 * update fails.
 */
interface IBootControl {
  /**
   * getNumberSlots() returns the number of available slots.
   * For instance, a system with a single set of partitions must return
   * 1, a system with A/B must return 2, A/B/C -> 3 and so on. A system with
   * less than two slots doesn't support background updates, for example if
   * running from a virtual machine with only one copy of each partition for the
   * purpose of testing.
   */
  getNumberSlots() generates (uint32_t numSlots);
  ...
  getSuffix(Slot slot) generates (string slotSuffix);
};

hardware/interfaces/boot/1.0/types.hal

package [email protected];

/**
 * A command result encapsulating whether the command succeeded and
 * an error string.
 */
struct CommandResult {
    bool success;
    string errMsg;
};

/**
 * An identifier for a slot number.
 */
typedef uint32_t Slot;

/**
 * A result encapsulating whether a function returned true, false or
 * failed due to an invalid slot number
 */
enum BoolResult : int32_t {
    FALSE = 0,
    TRUE = 1,
    INVALID_SLOT = -1
};

  再看看同级目录下的Android.bp和Android.m k。
  以types.hal和IBootControl.hal作为一个名为"[email protected]_hal"的filegroup,通过genrule定义的hidl-gen规则生成相应的文件。hidl-gen的-L参数为“c++source”时,生成的是cpp文件;-L参数为“c+±headers”时,生成的是头文件;-o参数为genDir的变量,一般位于./soong/.intermediates下面,根据编译出来的文件类型个模块所处的源码位置有所不同,例如IBootControl.h位于./soong/.intermediates/hardware/interfaces/boot/1.0/[email protected]_genc++_headers/gen/android/hardware/boot/1.0/IBootControl.h,BootControlAll.cpp位于./soong/.intermediates/hardware/interfaces/boot/1.0/[email protected]_genc++/gen/android/hardware/boot/1.0/BootControlAll.cpp,“hardware/interfaces/boot/1.0”这部分为源码的位置,“[email protected]_gencxxx”由模块的全限定名加生成文件类型确定,剩下的部分则可以参考genrule规则的out选项。
  最后的cc_library选项将之前genrule产生的头文件和源文件编译成一个so。
  Android.m k则用于编译出对应的Java动态库,静态库和Java文件,不再详细叙述。

hardware/interfaces/boot/1.0/Android.bp

// This file is autogenerated by hidl-gen. Do not edit manually.

filegroup {
    name: "[email protected]_hal",
    srcs: [
        "types.hal",
        "IBootControl.hal",
    ],
}

genrule {
    name: "[email protected]_genc++",
    tools: ["hidl-gen"],
    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport [email protected]",
    srcs: [
        ":[email protected]_hal",
    ],
    out: [
        "android/hardware/boot/1.0/types.cpp",
        "android/hardware/boot/1.0/BootControlAll.cpp",
    ],
}

genrule {
    name: "[email protected]_genc++_headers",
    tools: ["hidl-gen"],
    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport [email protected]",
    srcs: [
        ":[email protected]_hal",
    ],
    out: [
        "android/hardware/boot/1.0/types.h",
        "android/hardware/boot/1.0/hwtypes.h",
        "android/hardware/boot/1.0/IBootControl.h",
        "android/hardware/boot/1.0/IHwBootControl.h",
        "android/hardware/boot/1.0/BnHwBootControl.h",
        "android/hardware/boot/1.0/BpHwBootControl.h",
        "android/hardware/boot/1.0/BsBootControl.h",
    ],
}

cc_library {
    name: "[email protected]",
    defaults: ["hidl-module-defaults"],
    generated_sources: ["[email protected]_genc++"],
    generated_headers: ["[email protected]_genc++_headers"],
    export_generated_headers: ["[email protected]_genc++_headers"],
    vendor_available: true,
    vndk: {
        enabled: true,
    },
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libhwbinder",
        "liblog",
        "libutils",
        "libcutils",
    ],
    export_shared_lib_headers: [
        "libhidlbase",
        "libhidltransport",
        "libhwbinder",
        "libutils",
    ],
}

  在default文件夹下,有一个rc文件,用来启动HAL服务进程的:

hardware/interfaces/boot/1.0/default/[email protected]

service boot-hal-1-0 /vendor/bin/hw/[email protected]
    class early_hal
    user root
    group root

  再看看这个服务的来历。可以看到service.cpp被编译成[email protected],其main函数也是该服务的入口。

hardware/interfaces/boot/1.0/default

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := [email protected]
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_PROPRIETARY_MODULE := true
LOCAL_SRC_FILES := \
    BootControl.cpp \

LOCAL_SHARED_LIBRARIES := \
    liblog \
    libhidlbase \
    libhidltransport \
    libhardware \
    libutils \
    [email protected] \

include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_PROPRIETARY_MODULE := true
LOCAL_MODULE := [email protected]
LOCAL_INIT_RC := [email protected]
LOCAL_SRC_FILES := \
    service.cpp

LOCAL_SHARED_LIBRARIES := \
    liblog \
    libhardware \
    libhidlbase \
    libhidltransport \
    libutils \
    [email protected] \

include $(BUILD_EXECUTABLE)

  启动服务:

hardware/interfaces/boot/1.0/default/service.cpp

int main (int /* argc */, char * /* argv */ []) {
    return defaultPassthroughServiceImplementation();
}

  首先是调用IBootControl::getService获取服务,这时候会首次加载底层HAL的so,然后调用IBootControl::registerAsService向HwServiceManager注册服务,这样,framework就可以通过Binder跟[email protected]这个厂商Service进程进行通信了。

system/libhidl/transport/include/hidl/LegacySupport.h

template
__attribute__((warn_unused_result))
status_t defaultPassthroughServiceImplementation(std::string name,
                                            size_t maxThreads = 1) {
    configureRpcThreadpool(maxThreads, true);
    status_t result = registerPassthroughServiceImplementation(name);

    if (result != OK) {
        return result;
    }

    joinRpcThreadpool();
    return 0;
}

system/libhidl/transport/include/hidl/LegacySupport.h

template
__attribute__((warn_unused_result))
status_t registerPassthroughServiceImplementation(
        std::string name = "default") {
    sp service = Interface::getService(name, true /* getStub */);

    if (service == nullptr) {
        ALOGE("Could not get passthrough implementation for %s/%s.",
            Interface::descriptor, name.c_str());
        return EXIT_FAILURE;
    }

    LOG_FATAL_IF(service->isRemote(), "Implementation of %s/%s is remote!",
            Interface::descriptor, name.c_str());

    status_t status = service->registerAsService(name);

    if (status == OK) {
        ALOGI("Registration complete for %s/%s.",
            Interface::descriptor, name.c_str());
    } else {
        ALOGE("Could not register service %s/%s (%d).",
            Interface::descriptor, name.c_str(), status);
    }

    return status;
}

out/soong/.intermediates/hardware/interfaces/boot/1.0/[email protected]_genc++/gen/android/hardware/boot/1.0/BootControlAll.cpp

::android::status_t IBootControl::registerAsService(const std::string &serviceName) {
    ::android::hardware::details::onRegistration("[email protected]", "IBootControl", serviceName);

    const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm
            = ::android::hardware::defaultServiceManager();
    if (sm == nullptr) {
        return ::android::INVALID_OPERATION;
    }
    ::android::hardware::Return ret = sm->add(serviceName.c_str(), this);
    return ret.isOk() && ret ? ::android::OK : ::android::UNKNOWN_ERROR;
}

   ProcessState::self()->getContextObject(NULL))会返回一个跟HwServiceManager的BpBinder,然后使用fromBinder将其转换为一个BpHwServiceManager对象。接着和以前AIDL的方式一样,调用IServiceManager::add添加服务。
  HIDL框架有几个函数要注意一下:fromBinder接受一个Binder对象参数,如果该参数是Bp端的Binder对象,就会返回对应的BpHwXXXX对象;如果是Bn端的Binder对象,就会返回对应的BnHwXXXX对象的_hidl_mImpl成员。toBinder接受一个IXXXX接口对象参数,如果该参数是Bp端的Binder对象,就会返回内置的IBinder对象;如果是Bn端的Binder对象,’就返回对应的BnHwXXXX对象。可以看到,BpHwXXXX并不直接继承自IBinder,但是其拥有的mImpl成员就是一个IBinder对象。BnHwXXXX直接继承自IBinder,但是不继承自所有HAL节后的父类IBase,所以只能用IBase类型的_hidl_mImpl成员实现IXXXX接口。
Android O HIDL框架_第1张图片

system/libhidl/transport/ServiceManagement.cpp

sp defaultServiceManager() {
    return defaultServiceManager1_1();
}
sp defaultServiceManager1_1() {
    {
        AutoMutex _l(details::gDefaultServiceManagerLock);
        if (details::gDefaultServiceManager != NULL) {
            return details::gDefaultServiceManager;
        }

        if (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) {
            // HwBinder not available on this device or not accessible to
            // this process.
            return nullptr;
        }

        waitForHwServiceManager();

        while (details::gDefaultServiceManager == NULL) {
            details::gDefaultServiceManager =
                    fromBinder(
                        ProcessState::self()->getContextObject(NULL));
            if (details::gDefaultServiceManager == NULL) {
                LOG(ERROR) << "Waited for hwservicemanager, but got nullptr.";
                sleep(1);
            }
        }
    }

    return details::gDefaultServiceManager;
}

获取服务IBootControl::getService

  在C++层,我们只需调用IXXX::getService便能获取到对应HAL的功能。
  值得注意的是,我们在启动BootControl服务时调用IBootControl::getService的第二个参数getStub参数为true,这意味着启动BootControl的时候使用的是Passthrough模式,这既是启动HAL服务的函数被命名为defaultPassthroughServiceImplementation的原因。目测除了首次启动HAL服务,其他情况下
getStub参数都是false,例如应用程序获取HAL服务时。

out/soong/.intermediates/hardware/interfaces/boot/1.0/[email protected]_genc++/gen/android/hardware/boot/1.0/BootControlAll.cpp

// static
::android::sp IBootControl::getService(const std::string &serviceName, const bool getStub) {
    using ::android::hardware::defaultServiceManager;
    using ::android::hardware::details::waitForHwService;
    using ::android::hardware::getPassthroughServiceManager;
    using ::android::hardware::Return;
    using ::android::sp;
    using Transport = ::android::hidl::manager::V1_0::IServiceManager::Transport;

    sp iface = nullptr;

    const sp<::android::hidl::manager::V1_0::IServiceManager> sm = defaultServiceManager();
    if (sm == nullptr) {
        ALOGE("getService: defaultServiceManager() is null");
        return nullptr;
    }

    Return transportRet = sm->getTransport(IBootControl::descriptor, serviceName);

    if (!transportRet.isOk()) {
        ALOGE("getService: defaultServiceManager()->getTransport returns %s", transportRet.description().c_str());
        return nullptr;
    }
    Transport transport = transportRet;
    const bool vintfHwbinder = (transport == Transport::HWBINDER);
    const bool vintfPassthru = (transport == Transport::PASSTHROUGH);

    #ifdef __ANDROID_TREBLE__

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

    #else // not __ANDROID_TREBLE__
    const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
    const bool trebleTestingOverride =  env && !strcmp(env, "true");
    const bool vintfLegacy = (transport == Transport::EMPTY);

    #endif // __ANDROID_TREBLE__

    for (int tries = 0; !getStub && (vintfHwbinder || (vintfLegacy && tries == 0)); tries++) {
        if (tries > 1) {
            ALOGI("getService: Will do try %d for %s/%s in 1s...", tries, IBootControl::descriptor, serviceName.c_str());
            sleep(1);
        }
        if (vintfHwbinder && tries > 0) {
            waitForHwService(IBootControl::descriptor, serviceName);
        }
        Return> ret = 
                sm->get(IBootControl::descriptor, serviceName);
        if (!ret.isOk()) {
            ALOGE("IBootControl: defaultServiceManager()->get returns %s", ret.description().c_str());
            break;
        }
        sp<::android::hidl::base::V1_0::IBase> base = ret;
        if (base == nullptr) {
            if (tries > 0) {
                ALOGW("IBootControl: found null hwbinder interface");
            }continue;
        }
        Return> castRet = IBootControl::castFrom(base, true /* emitError */);
        if (!castRet.isOk()) {
            if (castRet.isDeadObject()) {
                ALOGW("IBootControl: found dead hwbinder service");
                continue;
            } else {
                ALOGW("IBootControl: cannot call into hwbinder service: %s; No permission? Check for selinux denials.", castRet.description().c_str());
                break;
            }
        }
        iface = castRet;
        if (iface == nullptr) {
            ALOGW("IBootControl: received incompatible service; bug in hwservicemanager?");
            break;
        }
        return iface;
    }
    if (getStub || vintfPassthru || vintfLegacy) {
        const sp<::android::hidl::manager::V1_0::IServiceManager> pm = getPassthroughServiceManager();
        if (pm != nullptr) {
            Return> ret = 
                    pm->get(IBootControl::descriptor, serviceName);
            if (ret.isOk()) {
                sp<::android::hidl::base::V1_0::IBase> baseInterface = ret;
                if (baseInterface != nullptr) {
                    iface = IBootControl::castFrom(baseInterface);
                    if (!getStub || trebleTestingOverride) {
                        iface = new BsBootControl(iface);
                    }
                }
            }
        }
    }
    return iface;
}

  defaultServiceManager返回一个BpHwServiceManager对象,getTransport会决定获取服务是通过Passthrough模式还是Binderized模式。getTransport接受两个参数,第一个是HAL服务的全限定名,本文中是[email protected]::IBootControl;第二个是instance名,通过先后匹配/system/manifest.xml和/vendor/manifest.xml来决定使用哪种方式。
  manifest.xml的每一项如下所示。android.hardware.boot对应< name>项,1.0对应< version>项,IBootControl对应< interface>项里面的< name>项,启动服务的函数defaultPassthroughServiceImplementation的第一个参数,如果没有,默认参数为"default"。getTransport会按上述的项去寻找符合要求的项,根据< transport>的值决定返回值,其中hwbinder是Binderized模式,passthrough是PassThrough模式。

/system/manifest.xml

    
        android.hardware.graphics.composer
        hwbinder
        2.1
        
            IComposer
            vr
        
    

  回到IBootControl::getService函数。下面几个参数将决定走的是Binderized模式还是Passthrough模式:1.getStub参数,目前我看到只在首次启动服务时是true,在其他情况为false;2.vintfHwbinder在getTransport函数返回的是Binderized模式时为true;3.vintfPassthru在getTransport函数返回的是PassThrough模式为true;4.vintfLegacy在Android Treble架构下且未开启__ANDROID_DEBUGGABLE__宏时为false,即默认为false。下面情况均按vintfLegacy为false来说明。
  当getStub参数为false且vintfHwbinder为true时,使用Binderized模式;当getStub参数为true或者vintfPassthru为true时,使用PassThrough模式。也就是说这个[email protected]服务时以PassThrough模式启动的,但是跟[email protected]服务通信时用的是Binderized模式。

PassThrough模式

  可见PassThrough模式时通过PassthroughServiceManager进行的。

system/libhidl/transport/ServiceManagement.cpp

sp getPassthroughServiceManager() {
    return getPassthroughServiceManager1_1();
}
sp getPassthroughServiceManager1_1() {
    static sp manager(new PassthroughServiceManager());
    return manager;
}

  PassthroughServiceManager::get函数的任务是使用dlopen打开对应的*-impl的so库,本文中是[email protected],找到其中HIDL_FETCH_XXX函数执行并返回执行后的返回值,本文中是BootControl.cpp中的HIDL_FETCH_IBootControl函数。

system/libhidl/transport/ServiceManagement.cpp

struct PassthroughServiceManager : IServiceManager1_1 {
    static void openLibs(const std::string& fqName,
            std::function eachLib) {
        //fqName looks like [email protected]::IFoo
        size_t idx = fqName.find("::");

        if (idx == std::string::npos ||
                idx + strlen("::") + 1 >= fqName.size()) {
            LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
            return;
        }

        std::string packageAndVersion = fqName.substr(0, idx);
        std::string ifaceName = fqName.substr(idx + strlen("::"));

        const std::string prefix = packageAndVersion + "-impl";
        const std::string sym = "HIDL_FETCH_" + ifaceName;

        const int dlMode = RTLD_LAZY;
        void *handle = nullptr;

        dlerror(); // clear

        std::vector paths = {HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR,
                                          HAL_LIBRARY_PATH_VNDK_SP, HAL_LIBRARY_PATH_SYSTEM};
#ifdef LIBHIDL_TARGET_DEBUGGABLE
        const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
        const bool trebleTestingOverride = env && !strcmp(env, "true");
        if (trebleTestingOverride) {
            const char* vtsRootPath = std::getenv("VTS_ROOT_PATH");
            if (vtsRootPath && strlen(vtsRootPath) > 0) {
                const std::string halLibraryPathVtsOverride =
                    std::string(vtsRootPath) + HAL_LIBRARY_PATH_SYSTEM;
                paths.push_back(halLibraryPathVtsOverride);
            }
        }
#endif
        for (const std::string& path : paths) {
            std::vector libs = search(path, prefix, ".so");

            for (const std::string &lib : libs) {
                const std::string fullPath = path + lib;

                if (path != HAL_LIBRARY_PATH_SYSTEM) {
                    handle = android_load_sphal_library(fullPath.c_str(), dlMode);
                } else {
                    handle = dlopen(fullPath.c_str(), dlMode);
                }

                if (handle == nullptr) {
                    const char* error = dlerror();
                    LOG(ERROR) << "Failed to dlopen " << lib << ": "
                               << (error == nullptr ? "unknown error" : error);
                    continue;
                }

                if (!eachLib(handle, lib, sym)) {
                    return;
                }
            }
        }
    }

    Return> get(const hidl_string& fqName,
                          const hidl_string& name) override {
        sp ret = nullptr;

        openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) {
            IBase* (*generator)(const char* name);
            *(void **)(&generator) = dlsym(handle, sym.c_str());
            if(!generator) {
                const char* error = dlerror();
                LOG(ERROR) << "Passthrough lookup opened " << lib
                           << " but could not find symbol " << sym << ": "
                           << (error == nullptr ? "unknown error" : error);
                dlclose(handle);
                return true;
            }

            ret = (*generator)(name.c_str());

            if (ret == nullptr) {
                dlclose(handle);
                return true; // this module doesn't provide this instance name
            }

            registerReference(fqName, name);
            return false;
        });

        return ret;
    }

  HIDL_FETCH_IBootControl的作用就是hw_get_module加载对应HAL的实现了,最后用一个BootControl对象封装好HAL的实现并将其返回。BootControl继承自IBootControl。IBootControl::getService在最后用该BootControl对象为参数构建一个BsBootControl返回。

hardware/interfaces/boot/1.0/default/BootControl.cpp

IBootControl* HIDL_FETCH_IBootControl(const char* /* hal */) {
    int ret = 0;
    boot_control_module_t* module = NULL;
    hw_module_t **hwm = reinterpret_cast(&module);
    ret = hw_get_module(BOOT_CONTROL_HARDWARE_MODULE_ID, const_cast(hwm));
    if (ret)
    {
        ALOGE("hw_get_module %s failed: %d", BOOT_CONTROL_HARDWARE_MODULE_ID, ret);
        return nullptr;
    }
    module->init(module);
    return new BootControl(module);
}

Binderized模式

  Binderized模式就是通过BpHwServiceManager::get来获取HAL服务。

out/soong/.intermediates/system/libhidl/transport/manager/1.1/[email protected]_genc++/gen/android/hidl/manager/1.1/ServiceManagerAll.cpp

::android::hardware::Return<::android::sp<::android::hidl::base::V1_0::IBase>> BpHwServiceManager::get(const ::android::hardware::hidl_string& fqName, const ::android::hardware::hidl_string& name){
    ::android::hardware::Return<::android::sp<::android::hidl::base::V1_0::IBase>>  _hidl_out = ::android::hidl::manager::V1_0::BpHwServiceManager::_hidl_get(this, this, fqName, name);

    return _hidl_out;
}

  在这里便可以看到明显的Binder框架了:Bp端的transact对应Bn端的onTransact,进而调用到BnHwServiceManager::_hidl_get。

out/soong/.intermediates/system/libhidl/transport/manager/1.1/[email protected]_genc++/gen/android/hidl/manager/1.1/ServiceManagerAll.cpp

// Methods from IServiceManager follow.
::android::hardware::Return<::android::sp<::android::hidl::base::V1_0::IBase>> BpHwServiceManager::_hidl_get(::android::hardware::IInterface *_hidl_this, ::android::hardware::details::HidlInstrumentor *_hidl_this_instrumentor, const ::android::hardware::hidl_string& fqName, const ::android::hardware::hidl_string& name) {
    #ifdef __ANDROID_DEBUGGABLE__
    bool mEnableInstrumentation = _hidl_this_instrumentor->isInstrumentationEnabled();
    const auto &mInstrumentationCallbacks = _hidl_this_instrumentor->getInstrumentationCallbacks();
    #else
    (void) _hidl_this_instrumentor;
    #endif // __ANDROID_DEBUGGABLE__
    atrace_begin(ATRACE_TAG_HAL, "HIDL::IServiceManager::get::client");
    #ifdef __ANDROID_DEBUGGABLE__
    if (UNLIKELY(mEnableInstrumentation)) {
        std::vector _hidl_args;
        _hidl_args.push_back((void *)&fqName);
        _hidl_args.push_back((void *)&name);
        for (const auto &callback: mInstrumentationCallbacks) {
            callback(InstrumentationEvent::CLIENT_API_ENTRY, "android.hidl.manager", "1.0", "IServiceManager", "get", &_hidl_args);
        }
    }
    #endif // __ANDROID_DEBUGGABLE__

    ::android::hardware::Parcel _hidl_data;
    ::android::hardware::Parcel _hidl_reply;
    ::android::status_t _hidl_err;
    ::android::hardware::Status _hidl_status;

    ::android::sp<::android::hidl::base::V1_0::IBase> _hidl_out_service;

    _hidl_err = _hidl_data.writeInterfaceToken(BpHwServiceManager::descriptor);
    if (_hidl_err != ::android::OK) { goto _hidl_error; }

    size_t _hidl_fqName_parent;

    _hidl_err = _hidl_data.writeBuffer(&fqName, sizeof(fqName), &_hidl_fqName_parent);
    if (_hidl_err != ::android::OK) { goto _hidl_error; }

    _hidl_err = ::android::hardware::writeEmbeddedToParcel(
            fqName,
            &_hidl_data,
            _hidl_fqName_parent,
            0 /* parentOffset */);

    if (_hidl_err != ::android::OK) { goto _hidl_error; }

    size_t _hidl_name_parent;

    _hidl_err = _hidl_data.writeBuffer(&name, sizeof(name), &_hidl_name_parent);
    if (_hidl_err != ::android::OK) { goto _hidl_error; }

    _hidl_err = ::android::hardware::writeEmbeddedToParcel(
            name,
            &_hidl_data,
            _hidl_name_parent,
            0 /* parentOffset */);

    if (_hidl_err != ::android::OK) { goto _hidl_error; }

    _hidl_err = ::android::hardware::IInterface::asBinder(_hidl_this)->transact(1 /* get */, _hidl_data, &_hidl_reply);
    if (_hidl_err != ::android::OK) { goto _hidl_error; }

    _hidl_err = ::android::hardware::readFromParcel(&_hidl_status, _hidl_reply);
    if (_hidl_err != ::android::OK) { goto _hidl_error; }

    if (!_hidl_status.isOk()) { return _hidl_status; }

    {
        ::android::sp<::android::hardware::IBinder> _hidl__hidl_out_service_binder;
        _hidl_err = _hidl_reply.readNullableStrongBinder(&_hidl__hidl_out_service_binder);
        if (_hidl_err != ::android::OK) { goto _hidl_error; }

        _hidl_out_service = ::android::hardware::fromBinder<::android::hidl::base::V1_0::IBase,::android::hidl::base::V1_0::BpHwBase,::android::hidl::base::V1_0::BnHwBase>(_hidl__hidl_out_service_binder);
    }

    atrace_end(ATRACE_TAG_HAL);
    #ifdef __ANDROID_DEBUGGABLE__
    if (UNLIKELY(mEnableInstrumentation)) {
        std::vector _hidl_args;
        _hidl_args.push_back((void *)&_hidl_out_service);
        for (const auto &callback: mInstrumentationCallbacks) {
            callback(InstrumentationEvent::CLIENT_API_EXIT, "android.hidl.manager", "1.0", "IServiceManager", "get", &_hidl_args);
        }
    }
    #endif // __ANDROID_DEBUGGABLE__

    _hidl_status.setFromStatusT(_hidl_err);
    return ::android::hardware::Return<::android::sp<::android::hidl::base::V1_0::IBase>>(_hidl_out_service);

_hidl_error:
    _hidl_status.setFromStatusT(_hidl_err);
    return ::android::hardware::Return<::android::sp<::android::hidl::base::V1_0::IBase>>(_hidl_status);
}

  之前提到,BnHwXXXX的_hidl_mImpl为对应的IXXXX接口实现。BnHwServiceManager::_hidl_get调用了其_hidl_mImpl的get函数。

out/soong/.intermediates/system/libhidl/transport/manager/1.1/[email protected]_genc++/gen/android/hidl/manager/1.1/ServiceManagerAll.cpp

// Methods from IServiceManager follow.
::android::status_t BnHwServiceManager::_hidl_get(
        ::android::hidl::base::V1_0::BnHwBase* _hidl_this,
        const ::android::hardware::Parcel &_hidl_data,
        ::android::hardware::Parcel *_hidl_reply,
        TransactCallback _hidl_cb) {
    #ifdef __ANDROID_DEBUGGABLE__
    bool mEnableInstrumentation = _hidl_this->isInstrumentationEnabled();
    const auto &mInstrumentationCallbacks = _hidl_this->getInstrumentationCallbacks();
    #endif // __ANDROID_DEBUGGABLE__

    ::android::status_t _hidl_err = ::android::OK;
    if (!_hidl_data.enforceInterface(BnHwServiceManager::Pure::descriptor)) {
        _hidl_err = ::android::BAD_TYPE;
        return _hidl_err;
    }

    const ::android::hardware::hidl_string* fqName;
    const ::android::hardware::hidl_string* name;

    size_t _hidl_fqName_parent;

    _hidl_err = _hidl_data.readBuffer(sizeof(*fqName), &_hidl_fqName_parent,  reinterpret_cast(&fqName));

    if (_hidl_err != ::android::OK) { return _hidl_err; }

    _hidl_err = ::android::hardware::readEmbeddedFromParcel(
            const_cast<::android::hardware::hidl_string &>(*fqName),
            _hidl_data,
            _hidl_fqName_parent,
            0 /* parentOffset */);

    if (_hidl_err != ::android::OK) { return _hidl_err; }

    size_t _hidl_name_parent;

    _hidl_err = _hidl_data.readBuffer(sizeof(*name), &_hidl_name_parent,  reinterpret_cast(&name));

    if (_hidl_err != ::android::OK) { return _hidl_err; }

    _hidl_err = ::android::hardware::readEmbeddedFromParcel(
            const_cast<::android::hardware::hidl_string &>(*name),
            _hidl_data,
            _hidl_name_parent,
            0 /* parentOffset */);

    if (_hidl_err != ::android::OK) { return _hidl_err; }

    atrace_begin(ATRACE_TAG_HAL, "HIDL::IServiceManager::get::server");
    #ifdef __ANDROID_DEBUGGABLE__
    if (UNLIKELY(mEnableInstrumentation)) {
        std::vector _hidl_args;
        _hidl_args.push_back((void *)fqName);
        _hidl_args.push_back((void *)name);
        for (const auto &callback: mInstrumentationCallbacks) {
            callback(InstrumentationEvent::SERVER_API_ENTRY, "android.hidl.manager", "1.0", "IServiceManager", "get", &_hidl_args);
        }
    }
    #endif // __ANDROID_DEBUGGABLE__

    ::android::sp<::android::hidl::base::V1_0::IBase> _hidl_out_service = static_cast(_hidl_this)->_hidl_mImpl->get(*fqName, *name);

    ::android::hardware::writeToParcel(::android::hardware::Status::ok(), _hidl_reply);

    if (_hidl_out_service == nullptr) {
        _hidl_err = _hidl_reply->writeStrongBinder(nullptr);
    } else {
        ::android::sp<::android::hardware::IBinder> _hidl_binder = ::android::hardware::toBinder<
                ::android::hidl::base::V1_0::IBase>(_hidl_out_service);
        if (_hidl_binder.get() != nullptr) {
            _hidl_err = _hidl_reply->writeStrongBinder(_hidl_binder);
        } else {
            _hidl_err = ::android::UNKNOWN_ERROR;
        }
    }
    /* _hidl_err ignored! */

    atrace_end(ATRACE_TAG_HAL);
    #ifdef __ANDROID_DEBUGGABLE__
    if (UNLIKELY(mEnableInstrumentation)) {
        std::vector _hidl_args;
        _hidl_args.push_back((void *)&_hidl_out_service);
        for (const auto &callback: mInstrumentationCallbacks) {
            callback(InstrumentationEvent::SERVER_API_EXIT, "android.hidl.manager", "1.0", "IServiceManager", "get", &_hidl_args);
        }
    }
    #endif // __ANDROID_DEBUGGABLE__

    _hidl_cb(*_hidl_reply);
    return _hidl_err;
}

  BnHwServiceManager的_hidl_mImpl来自ServiceManager,这个ServiceManager区别于Android O以前的ServiceManager,这是一个HAL服务。所有通过Binderized模式添加或者获取服务都是通过ServiceManager进行的。

system/hwservicemanager/service.cpp

int main() {
    configureRpcThreadpool(1, true /* callerWillJoin */);

    ServiceManager *manager = new ServiceManager();

    if (!manager->add(serviceName, manager)) {
        ALOGE("Failed to register hwservicemanager with itself.");
    }

    TokenManager *tokenManager = new TokenManager();

    if (!manager->add(serviceName, tokenManager)) {
        ALOGE("Failed to register ITokenManager with hwservicemanager.");
    }

    sp looper(Looper::prepare(0 /* opts */));

    int binder_fd = -1;

    IPCThreadState::self()->setupPolling(&binder_fd);
    if (binder_fd < 0) {
        ALOGE("Failed to aquire binder FD. Aborting...");
        return -1;
    }
    // Flush after setupPolling(), to make sure the binder driver
    // knows about this thread handling commands.
    IPCThreadState::self()->flushCommands();

    sp cb(new BinderCallback);
    if (looper->addFd(binder_fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb,
            nullptr) != 1) {
        ALOGE("Failed to add hwbinder FD to Looper. Aborting...");
        return -1;
    }

    // Tell IPCThreadState we're the service manager
    sp service = new BnHwServiceManager(manager);
    IPCThreadState::self()->setTheContextObject(service);
    // Then tell binder kernel
    ioctl(binder_fd, BINDER_SET_CONTEXT_MGR, 0);
    // Only enable FIFO inheritance for hwbinder
    // FIXME: remove define when in the kernel
#define BINDER_SET_INHERIT_FIFO_PRIO    _IO('b', 10)

    int rc = ioctl(binder_fd, BINDER_SET_INHERIT_FIFO_PRIO);
    if (rc) {
        ALOGE("BINDER_SET_INHERIT_FIFO_PRIO failed with error %d\n", rc);
    }

    rc = property_set("hwservicemanager.ready", "true");
    if (rc) {
        ALOGE("Failed to set \"hwservicemanager.ready\" (error %d). "\
              "HAL services will not start!\n", rc);
    }

    while (true) {
        looper->pollAll(-1 /* timeoutMillis */);
    }

    return 0;
}

  ServiceManager服务的添加和获取是通过内部的mServiceMap的map数据结构进行的,这个map键值为服务的全限定名,对应的是PackageInterfaceMap对象。其中PackageInterfaceMap又包含一个InstanceMap的map数据结构,其以服务的instance名为键值,对应的是HidlService对象。HidlService对象包含了IXXXX的实现,可以通过HidlService::getService函数获取。
  所以,跟Android O以前的ServiceManager不同的是,以往的ServiceManager会将服务信息保存到内核中,而HAL的ServiceManager把HAL服务的信息保存在map数据结构中。
  可以看到如果IBootControl::getService使用的是PassThrough模式,返回的是一个BsBootControl,也就是跟HAL服务位于同一进程,跟Android O之前的调用方式兼容;如果使用的是Binderized,返回的是一个BpHwBootControl,具备跨进程通信的能力。

system/hwservicemanager/ServiceManager.cpp

// Methods from ::android::hidl::manager::V1_0::IServiceManager follow.
Return> ServiceManager::get(const hidl_string& fqName,
                                      const hidl_string& name) {
    pid_t pid = IPCThreadState::self()->getCallingPid();
    if (!mAcl.canGet(fqName, pid)) {
        return nullptr;
    }

    auto ifaceIt = mServiceMap.find(fqName);
    if (ifaceIt == mServiceMap.end()) {
        return nullptr;
    }

    const PackageInterfaceMap &ifaceMap = ifaceIt->second;
    const HidlService *hidlService = ifaceMap.lookup(name);

    if (hidlService == nullptr) {
        return nullptr;
    }

    return hidlService->getService();
}

Java层的Binderized模式

  Java层获取HAL服务是通过HwBinder#getService获取的。这是个native方法。
  可以看到getTransport返回的不是Binderized模式时,便会抛出异常。而当getTransport返回的是Binderized模式时,在后续的流程就会走BpHwServiceManager::get函数。所以说,Java要使用HIDL的前提是这个HAL服务是使用Binderized模式的(PassThrough模式不支持Java)。

frameworks/base/core/jni/android_os_HwBinder.cpp

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;

    if (ifaceNameObj == NULL) {
        jniThrowException(env, "java/lang/NullPointerException", NULL);
        return NULL;
    }
    if (serviceNameObj == NULL) {
        jniThrowException(env, "java/lang/NullPointerException", NULL);
        return NULL;
    }

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

    LOG(INFO) << "Looking for service "
              << ifaceName
              << "/"
              << serviceName;

    Return 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, NAME_NOT_FOUND, true /* canThrowRemoteException */);
        return NULL;
    }

    Return> ret = manager->get(ifaceNameHStr, serviceNameHStr);

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

    sp service = hardware::toBinder(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);
}

你可能感兴趣的:(Framework)