HIDL Hal 开发笔记4----Passthrough HALs 实例分析

目录

  • 一、整体框架
  • [二、HAL 层服务端实现](#二、HAL 层服务端实现)
  • [三、Framework 层客户端实现](#三、Framework 层客户端实现)

|---------------------------|
| Passthrough HALs 实例分析 |

一、整体框架

Passthrough HALs 的存在,主要是为了复用传统 HAL 的实现。HAL 层以进程的形式存在,内部有一个 HwBinder 服务端对象,对外提供 HwBinder 远程调用服务。Framework 通过 HwBinder 远程调用到 HAL 中的函数,这些函数会去加载传统 HAL 实现来操作具体硬件。整体架构如下:

在源码下 hardware/interfaces/vibrator/1.0 目录下,就是一个振动器的 Passthrough HALs 实现。接下来我们就来分析其源码。


二、HAL 层服务端实现

源码的整体结构如下:

我们从 hardware/interfaces/vibrator/1.0/default/Android.bp 下手:

c 复制代码
cc_library_shared {
    name: "android.hardware.vibrator@1.0-impl",
    defaults: ["hidl_defaults"],
    vendor: true,
    relative_install_path: "hw",
    srcs: ["Vibrator.cpp"],
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "liblog",
        "libutils",
        "libhardware",
        "android.hardware.vibrator@1.0",
    ],
}

cc_binary {
    name: "android.hardware.vibrator@1.0-service",
    defaults: ["hidl_defaults"],
    init_rc: ["android.hardware.vibrator@1.0-service.rc"],
    vendor: true,
    relative_install_path: "hw",
    srcs: ["service.cpp"],

    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "liblog",
        "libutils",
        "libhardware",
        "android.hardware.vibrator@1.0",
    ],
}

一个共享库 android.hardware.vibrator@1.0-impl,一个 native 可执行程序 android.hardware.vibrator@1.3-service.coral

android.hardware.vibrator@1.0-impl 共享库中,主要包含了 Vibrator HwBinder 服务端对象,对上提供 HwBinder 远程调用服务,对下调用传统 Hal 操作具体硬件。

android.hardware.vibrator@1.0-service 可执行程序对应的源码是 hardware/interfaces/vibrator/1.0/default/service.cpp

c 复制代码
#define LOG_TAG "android.hardware.vibrator@1.0-service"

#include <android/hardware/vibrator/1.0/IVibrator.h>
#include <hidl/LegacySupport.h>

using android::hardware::vibrator::V1_0::IVibrator;
using android::hardware::defaultPassthroughServiceImplementation;

int main() {
    return defaultPassthroughServiceImplementation<IVibrator>();
}

主函数的实现很简单,就是调用 defaultPassthroughServiceImplementation,其实现如下:

c 复制代码
// system/libhidl/transport/include/hidl/LegacySupport.h

template<class Interface>
__attribute__((warn_unused_result))
status_t defaultPassthroughServiceImplementation(size_t maxThreads = 1) {
    return defaultPassthroughServiceImplementation<Interface>("default", maxThreads);
}

template <class Interface>
__attribute__((warn_unused_result)) status_t defaultPassthroughServiceImplementation(
    const std::string& name, size_t maxThreads = 1) {
    configureRpcThreadpool(maxThreads, true);
    status_t result = registerPassthroughServiceImplementation<Interface>(name);

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

    joinRpcThreadpool();
    return UNKNOWN_ERROR;
}

这里会:

  • 配置好 HwBinder 线程
  • 调用 registerPassthroughServiceImplementation 函数
c 复制代码
// system/libhidl/transport/include/hidl/LegacySupport.h

template <class Interface>
__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(
    const std::string& name = "default") {
    return details::registerPassthroughServiceImplementation<Interface>(
        [](const sp<Interface>& service, const std::string& name) {
            return service->registerAsService(name);
        },
        name);
}

这里接着调用 registerPassthroughServiceImplementation 函数,同时传入了一个 lamda 表达式。

c 复制代码
// system/libhidl/transport/include/hidl/LegacySupport.h
template <class Interface, typename Func>
__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(
    Func registerServiceCb, const std::string& name = "default") {
    sp<Interface> 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 = registerServiceCb(service, 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;
}

这里的模版 Interface 就是前面传入的 IVibrator,接着调用 IVibrator::getService 函数,这个是编译系统生成的代码:

c 复制代码
// out/soong/.intermediates/hardware/interfaces/vibrator/1.0/android.hardware.vibrator@1.0_genc++/gen/android/hardware/vibrator/1.0/VibratorAll.cpp
::android::sp<IVibrator> IVibrator::getService(const std::string &serviceName, const bool getStub) {
    return ::android::hardware::details::getServiceInternal<BpHwVibrator>(serviceName, true, getStub);
}
c 复制代码
// system/libhidl/transport/include/hidl/HidlTransportSupport.h
template <typename BpType, typename IType = typename BpType::Pure,
          typename = std::enable_if_t<std::is_same<i_tag, typename IType::_hidl_tag>::value>,
          typename = std::enable_if_t<std::is_same<bphw_tag, typename BpType::_hidl_tag>::value>>
sp<IType> getServiceInternal(const std::string& instance, bool retry, bool getStub) {
    using ::android::hidl::base::V1_0::IBase;
    
    //descriptor: android.hardware.vibrator@1.0::IVibrator
    sp<IBase> base = getRawServiceInternal(IType::descriptor, instance, retry, getStub);

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

    if (base->isRemote()) {
        // getRawServiceInternal guarantees we get the proper class
        return sp<IType>(new BpType(getOrCreateCachedBinder(base.get())));
    }

    return IType::castFrom(base);
}

接着调用 getRawServiceInternal:

c 复制代码
// system/libhidl/transport/ServiceManagement.cpp
// 参数 getStub 为 true
sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor,
                                                             const std::string& instance,
                                                             bool retry, bool getStub) {
    using Transport = ::android::hidl::manager::V1_0::IServiceManager::Transport;
    using ::android::hidl::manager::V1_0::IServiceManager;
    sp<Waiter> waiter;

    sp<IServiceManager1_1> sm;
    Transport transport = Transport::EMPTY;
    if (kIsRecovery) {
        transport = Transport::PASSTHROUGH;
    } else {
        // 获取 HwServiceManager 代理端对象。
        sm = defaultServiceManager1_1();
        if (sm == nullptr) {
            ALOGE("getService: defaultServiceManager() is null");
            return nullptr;
        }
        // 获取 vintf 中的 transport 参数
        // passthrough HAL 是 hwbinder
        Return<Transport> transportRet = sm->getTransport(descriptor, instance);

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

    // true
    const bool vintfHwbinder = (transport == Transport::HWBINDER);
    // false
    const bool vintfPassthru = (transport == Transport::PASSTHROUGH);

#ifdef ENFORCE_VINTF_MANIFEST

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

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

    // getStub 为 ture,for 循环不进入
    for (int tries = 0; !getStub && (vintfHwbinder || vintfLegacy); tries++) {
        if (waiter == nullptr && tries > 0) {
            waiter = new Waiter(descriptor, instance, sm);
        }
        if (waiter != nullptr) {
            waiter->reset();  // don't reorder this -- see comments on reset()
        }
        Return<sp<IBase>> ret = sm->get(descriptor, instance);
        if (!ret.isOk()) {
            ALOGE("getService: defaultServiceManager()->get returns %s for %s/%s.",
                  ret.description().c_str(), descriptor.c_str(), instance.c_str());
            break;
        }
        sp<IBase> base = ret;
        if (base != nullptr) {
            Return<bool> canCastRet =
                details::canCastInterface(base.get(), descriptor.c_str(), true /* emitError */);

            if (canCastRet.isOk() && canCastRet) {
                if (waiter != nullptr) {
                    waiter->done();
                }
                return base; // still needs to be wrapped by Bp class.
            }

            if (!handleCastError(canCastRet, descriptor, instance)) break;
        }

        // In case of legacy or we were not asked to retry, don't.
        if (vintfLegacy || !retry) break;

        if (waiter != nullptr) {
            ALOGI("getService: Trying again for %s/%s...", descriptor.c_str(), instance.c_str());
            waiter->wait(true /* timeout */);
        }
    }

    if (waiter != nullptr) {
        waiter->done();
    }

    // getStub 为 true,进入
    if (getStub || vintfPassthru || vintfLegacy) {
        const sp<IServiceManager> pm = getPassthroughServiceManager();
        if (pm != nullptr) {
            sp<IBase> base = pm->get(descriptor, instance).withDefault(nullptr);
            if (!getStub || trebleTestingOverride) {
                base = wrapPassthrough(base);
            }
            return base;
        }
    }

    return nullptr;
}
c 复制代码
// system/libhidl/transport/ServiceManagement.cpp
sp<IServiceManager1_0> getPassthroughServiceManager() {
    return getPassthroughServiceManager1_1();
}
sp<IServiceManager1_1> getPassthroughServiceManager1_1() {
    static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
    return manager;
}

就是 new 一个 PassthroughServiceManager,PassthroughServiceManager 实现了 IServiceManager 接口。

接着调用 PassthroughServiceManager 的 get 函数:

c 复制代码
Return<sp<IBase>> get(const hidl_string& fqName,
                      const hidl_string& name) override {
    sp<IBase> 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
        }

        // Actual fqname might be a subclass.
        // This assumption is tested in vts_treble_vintf_test
        using ::android::hardware::details::getDescriptor;
        std::string actualFqName = getDescriptor(ret.get());
        CHECK(actualFqName.size() > 0);
        registerReference(actualFqName, name);
        return false;
    });

    return ret;
}

调用 openlib 并传入一个 lamda:

c 复制代码
// fqName: android.hardware.vibrator@1.0::IVibrator
static void openLibs(
        const std::string& fqName,
        const std::function<bool /* continue */ (void* /* handle */, const std::string& /* lib */,
                                                 const std::string& /* sym */)>& eachLib) {
        //fqName looks like android.hardware.foo@1.0::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;
        }
        // android.hardware.vibrator@1.0
        std::string packageAndVersion = fqName.substr(0, idx);
        // IVibrator
        std::string ifaceName = fqName.substr(idx + strlen("::"));
        // android.hardware.vibrator@1.0-impl
        const std::string prefix = packageAndVersion + "-impl";
        // HIDL_FETCH_IVibrator
        const std::string sym = "HIDL_FETCH_" + ifaceName;

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

        dlerror(); // clear

        static std::string halLibPathVndkSp = android::base::StringPrintf(
            HAL_LIBRARY_PATH_VNDK_SP_FOR_VERSION, details::getVndkVersionStr().c_str());
        // 从固定的几个目录查找 so 库
        std::vector<std::string> paths = {
            HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, halLibPathVndkSp,
#ifndef __ANDROID_VNDK__
            HAL_LIBRARY_PATH_SYSTEM,
#endif
        };

#ifdef LIBHIDL_TARGET_DEBUGGABLE
        const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
        const bool trebleTestingOverride = env && !strcmp(env, "true");
        if (trebleTestingOverride) {
            // Load HAL implementations that are statically linked
            handle = dlopen(nullptr, dlMode);
            if (handle == nullptr) {
                const char* error = dlerror();
                LOG(ERROR) << "Failed to dlopen self: "
                           << (error == nullptr ? "unknown error" : error);
            } else if (!eachLib(handle, "SELF", sym)) {
                return;
            }

            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.insert(paths.begin(), halLibraryPathVtsOverride);
            }
        }
#endif

        // 从固定的几个目录查找 android.hardware.vibrator@1.0-impl.so 库
        for (const std::string& path : paths) {
            std::vector<std::string> libs = findFiles(path, prefix, ".so");

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

                if (kIsRecovery || path == HAL_LIBRARY_PATH_SYSTEM) {
                    // dlopen 打开 so 库
                    handle = dlopen(fullPath.c_str(), dlMode);
                } else {
#if !defined(__ANDROID_RECOVERY__)
                    handle = android_load_sphal_library(fullPath.c_str(), dlMode);
#endif
                }

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

再看 lamda 回调:

c 复制代码
openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) {
    IBase* (*generator)(const char* name);
    // 加载 HIDL_FETCH_IVibrator 符号
    *(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;
    }
    // 调用 HIDL_FETCH_IVibrator 函数
    ret = (*generator)(name.c_str());

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

    // Actual fqname might be a subclass.
    // This assumption is tested in vts_treble_vintf_test
    using ::android::hardware::details::getDescriptor;
    std::string actualFqName = getDescriptor(ret.get());
    CHECK(actualFqName.size() > 0);
    registerReference(actualFqName, name);
    return false;
});

HIDL_FETCH_IVibrator 函数实现在 hardware/interfaces/vibrator/1.0/default/Vibrator.cpp

c 复制代码
IVibrator* HIDL_FETCH_IVibrator(const char * /*hal*/) {
    vibrator_device_t *vib_device;
    const hw_module_t *hw_module = nullptr;

    int ret = hw_get_module(VIBRATOR_HARDWARE_MODULE_ID, &hw_module);
    if (ret == 0) {
        ret = vibrator_open(hw_module, &vib_device);
        if (ret != 0) {
            ALOGE("vibrator_open failed: %d", ret);
        }
    } else {
        ALOGE("hw_get_module %s failed: %d", VIBRATOR_HARDWARE_MODULE_ID, ret);
    }

    if (ret == 0) {
        return new Vibrator(vib_device);
    } else {
        ALOGE("Passthrough failed to open legacy HAL.");
        return nullptr;
    }
}

这里就是加载传统 HAL 实现,并将传统 HAL 包装成一个 Vibrator 对象返回。

回到开始:

c 复制代码
// system/libhidl/transport/include/hidl/LegacySupport.h

template <class Interface>
__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(
    const std::string& name = "default") {
    return details::registerPassthroughServiceImplementation<Interface>(
        [](const sp<Interface>& service, const std::string& name) {
            return service->registerAsService(name);
        },
        name);
}

template <class Interface, typename Func>
__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(
    Func registerServiceCb, const std::string& name = "default") {
    // 获取到 Vibrator
    sp<Interface> 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());
    // 调用 lamda 注册
    status_t status = registerServiceCb(service, 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;
}

获取到 Vibrator 后,接着调用 lamda 注册服务。

c 复制代码
::android::status_t IVibrator::registerAsService(const std::string &serviceName) {
    return ::android::hardware::details::registerAsServiceInternal(this, serviceName);
}

这里将 Vibrator 服务注册到 HwServiceManager,具体细节我们就不去深入,不是我们的重点。


三、Framework 层客户端实现

对于客户端,我们只要知道 Hal 对外提供的接口即可,这个接口由 hardware/interfaces/vibrator/1.0/IVibrator.hal 描述:

c 复制代码
package android.hardware.vibrator@1.0;

interface IVibrator {
  /**
   * Turn on vibrator
   *
   * This function must only be called after the previous timeout has expired or
   * was canceled (through off()).
   * @param timeout_ms number of milliseconds to vibrate.
   * @return vibratorOnRet whether vibrator command was successful or not.
   */
  on(uint32_t timeoutMs) generates (Status vibratorOnRet);

  /**
   * Turn off vibrator
   *
   * Cancel a previously-started vibration, if any.
   * @return vibratorOffRet whether vibrator command was successful or not.
   */
  off() generates (Status vibratorOffRet);

  /**
   * Returns whether the vibrator supports changes to its vibrational amplitude.
   */
  supportsAmplitudeControl() generates (bool supports);

  /**
   * Sets the motor's vibrational amplitude.
   *
   * Changes the force being produced by the underlying motor.
   *
   * @param amplitude The unitless force setting. Note that this number must
   *                  be between 1 and 255, inclusive. If the motor does not
   *                  have exactly 255 steps, it must do it's best to map it
   *                  onto the number of steps it does have.
   * @return status Whether the command was successful or not. Must return
   *                Status::UNSUPPORTED_OPERATION if setting the amplitude is
   *                not supported by the device.
   */
  setAmplitude(uint8_t amplitude) generates (Status status);

  /**
   * Fire off a predefined haptic event.
   *
   * @param event The type of haptic event to trigger.
   * @return status Whether the effect was successfully performed or not. Must
   *                return Status::UNSUPPORTED_OPERATION is the effect is not
   *                supported.
   * @return lengthMs The length of time the event is expected to take in
   *                  milliseconds. This doesn't need to be perfectly accurate,
   *                  but should be a reasonable approximation. Should be a
   *                  positive, non-zero value if the returned status is
   *                  Status::OK, and set to 0 otherwise.
   */
  perform(Effect effect, EffectStrength strength) generates (Status status, uint32_t lengthMs);
};

frameworks/base/services/core/java/com/android/server/VibratorService.java 本身是一个 Binder 服务端向 App 提供服务,同时也是一个 HwBinder 客户端通过 JNI 访问到 HAL 服务端。

c 复制代码
public class VibratorService extends IVibratorService.Stub
        implements InputManager.InputDeviceListener {
    // ......
    static native boolean vibratorExists();
    static native void vibratorInit();
    static native void vibratorOn(long milliseconds);
    static native void vibratorOff();
    static native boolean vibratorSupportsAmplitudeControl();
    static native void vibratorSetAmplitude(int amplitude);
    static native long vibratorPerformEffect(long effect, long strength);
    static native boolean vibratorSupportsExternalControl();
    static native void vibratorSetExternalControl(boolean enabled);
    // ......     
}

VibratorService 中有多个 native 方法,这些方法用于远程调用 Hal 层。

对应的 JNI 函数实现在 frameworks/base/services/core/jni/com_android_server_VibratorService.cpp

c 复制代码
#define LOG_TAG "VibratorService"

#include <android/hardware/vibrator/1.0/IVibrator.h>
#include <android/hardware/vibrator/1.0/types.h>
#include <android/hardware/vibrator/1.0/IVibrator.h>
#include <android/hardware/vibrator/1.1/types.h>
#include <android/hardware/vibrator/1.2/IVibrator.h>
#include <android/hardware/vibrator/1.2/types.h>
#include <android/hardware/vibrator/1.3/IVibrator.h>

#include "jni.h"
#include <nativehelper/JNIHelp.h>
#include "android_runtime/AndroidRuntime.h"

#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/vibrator.h>

#include <inttypes.h>
#include <stdio.h>

using android::hardware::Return;
using android::hardware::vibrator::V1_0::EffectStrength;
using android::hardware::vibrator::V1_0::Status;
using android::hardware::vibrator::V1_1::Effect_1_1;

namespace V1_0 = android::hardware::vibrator::V1_0;
namespace V1_1 = android::hardware::vibrator::V1_1;
namespace V1_2 = android::hardware::vibrator::V1_2;
namespace V1_3 = android::hardware::vibrator::V1_3;

namespace android {

static constexpr int NUM_TRIES = 2;

// Creates a Return<R> with STATUS::EX_NULL_POINTER.
template<class R>
inline Return<R> NullptrStatus() {
    using ::android::hardware::Status;
    return Return<R>{Status::fromExceptionCode(Status::EX_NULL_POINTER)};
}

// Helper used to transparently deal with the vibrator HAL becoming unavailable.
template<class R, class I, class... Args0, class... Args1>
Return<R> halCall(Return<R> (I::* fn)(Args0...), Args1&&... args1) {
    // Assume that if getService returns a nullptr, HAL is not available on the
    // device.
    static sp<I> sHal = I::getService();
    static bool sAvailable = sHal != nullptr;

    if (!sAvailable) {
        return NullptrStatus<R>();
    }

    // Return<R> doesn't have a default constructor, so make a Return<R> with
    // STATUS::EX_NONE.
    using ::android::hardware::Status;
    Return<R> ret{Status::fromExceptionCode(Status::EX_NONE)};

    // Note that ret is guaranteed to be changed after this loop.
    for (int i = 0; i < NUM_TRIES; ++i) {
        ret = (sHal == nullptr) ? NullptrStatus<R>()
                : (*sHal.*fn)(std::forward<Args1>(args1)...);

        if (ret.isOk()) {
            break;
        }

        ALOGE("Failed to issue command to vibrator HAL. Retrying.");
        // Restoring connection to the HAL.
        sHal = I::tryGetService();
    }
    return ret;
}

template<class R>
bool isValidEffect(jlong effect) {
    if (effect < 0) {
        return false;
    }
    R val = static_cast<R>(effect);
    auto iter = hardware::hidl_enum_range<R>();
    return val >= *iter.begin() && val <= *std::prev(iter.end());
}

static void vibratorInit(JNIEnv /* env */, jobject /* clazz */)
{
    halCall(&V1_0::IVibrator::ping).isOk();
}

static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */)
{
    return halCall(&V1_0::IVibrator::ping).isOk() ? JNI_TRUE : JNI_FALSE;
}

static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms)
{
    Status retStatus = halCall(&V1_0::IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR);
    if (retStatus != Status::OK) {
        ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
    }
}

static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */)
{
    Status retStatus = halCall(&V1_0::IVibrator::off).withDefault(Status::UNKNOWN_ERROR);
    if (retStatus != Status::OK) {
        ALOGE("vibratorOff command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
    }
}

static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jobject) {
    return halCall(&V1_0::IVibrator::supportsAmplitudeControl).withDefault(false);
}

static void vibratorSetAmplitude(JNIEnv*, jobject, jint amplitude) {
    Status status = halCall(&V1_0::IVibrator::setAmplitude, static_cast<uint32_t>(amplitude))
        .withDefault(Status::UNKNOWN_ERROR);
    if (status != Status::OK) {
      ALOGE("Failed to set vibrator amplitude (%" PRIu32 ").",
            static_cast<uint32_t>(status));
    }
}

static jboolean vibratorSupportsExternalControl(JNIEnv*, jobject) {
    return halCall(&V1_3::IVibrator::supportsExternalControl).withDefault(false);
}

static void vibratorSetExternalControl(JNIEnv*, jobject, jboolean enabled) {
    Status status = halCall(&V1_3::IVibrator::setExternalControl, static_cast<uint32_t>(enabled))
        .withDefault(Status::UNKNOWN_ERROR);
    if (status != Status::OK) {
      ALOGE("Failed to set vibrator external control (%" PRIu32 ").",
            static_cast<uint32_t>(status));
    }
}

static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jint strength) {
    Status status;
    uint32_t lengthMs;
    auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) {
        status = retStatus;
        lengthMs = retLengthMs;
    };
    EffectStrength effectStrength(static_cast<EffectStrength>(strength));

    Return<void> ret;
    if (isValidEffect<V1_0::Effect>(effect)) {
        ret = halCall(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(effect),
                effectStrength, callback);
    } else if (isValidEffect<Effect_1_1>(effect)) {
        ret = halCall(&V1_1::IVibrator::perform_1_1, static_cast<Effect_1_1>(effect),
                           effectStrength, callback);
    } else if (isValidEffect<V1_2::Effect>(effect)) {
        ret = halCall(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(effect),
                           effectStrength, callback);
    } else if (isValidEffect<V1_3::Effect>(effect)) {
        ret = halCall(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(effect),
                           effectStrength, callback);
    } else {
        ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")",
                static_cast<int32_t>(effect));
        return -1;
    }

    if (!ret.isOk()) {
        ALOGW("Failed to perform effect (%" PRId32 ")", static_cast<int32_t>(effect));
        return -1;
    }

    if (status == Status::OK) {
        return lengthMs;
    } else if (status != Status::UNSUPPORTED_OPERATION) {
        // Don't warn on UNSUPPORTED_OPERATION, that's a normal event and just means the motor
        // doesn't have a pre-defined waveform to perform for it, so we should just give the
        // opportunity to fall back to the framework waveforms.
        ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32
                ", error=%" PRIu32 ").", static_cast<int64_t>(effect),
                static_cast<int32_t>(strength), static_cast<uint32_t>(status));
    }

    return -1;
}

static const JNINativeMethod method_table[] = {
    { "vibratorExists", "()Z", (void*)vibratorExists },
    { "vibratorInit", "()V", (void*)vibratorInit },
    { "vibratorOn", "(J)V", (void*)vibratorOn },
    { "vibratorOff", "()V", (void*)vibratorOff },
    { "vibratorSupportsAmplitudeControl", "()Z", (void*)vibratorSupportsAmplitudeControl},
    { "vibratorSetAmplitude", "(I)V", (void*)vibratorSetAmplitude},
    { "vibratorPerformEffect", "(JJ)J", (void*)vibratorPerformEffect},
    { "vibratorSupportsExternalControl", "()Z", (void*)vibratorSupportsExternalControl},
    { "vibratorSetExternalControl", "(Z)V", (void*)vibratorSetExternalControl},
};

int register_android_server_VibratorService(JNIEnv *env)
{
    return jniRegisterNativeMethods(env, "com/android/server/VibratorService",
            method_table, NELEM(method_table));
}

};

所有的函数都通过 halcall 来实现,halcall 中会去从 HwServiceManager 中去获取 Vibrator Hal 的代理对象,然后通过这个代理对象发起远程调用,从而调用到 HAL 层。


相关推荐
louisgeek1 天前
Git 查询 Tag 列表
android
诸神黄昏EX1 天前
Android Safety 系列专题【篇二:keystore安全架构】
android
撩得Android一次心动1 天前
Android 架构模式的演变(MVC、MVP、MVVM、MVI)
android·架构·mvc·mvvm·mvp
与水同流1 天前
GNSS数据格式
android
Mars-xq1 天前
Android godot 交互数据监听
android·godot·交互
_李小白1 天前
【Android FrameWork】延伸阅读: PowerManagerService
android
_李小白1 天前
【Android 性能分析】第四天:CPU Profiler
android
lxysbly1 天前
nes模拟器安卓版下载汉化版2026
android