012.HIDL Hal 开发指南5 —— 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
下手:
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
:
#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
,其实现如下:
// 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 函数
// 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 表达式。
// 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 函数,这个是编译系统生成的代码:
// 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);
}
// 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
:
// 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;
}
// 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 函数:
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:
// 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 回调:
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
:
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 对象返回。
回到开始:
// 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 注册服务。
::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
描述:
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 服务端。
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
:
#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));
}
};
所有的函数都通过 hascall 来实现,hascall 中会去从 HwServiceManager 中去获取 Vibrator Hal 的代理对象,然后通过这个代理对象发起远程调用,从而调用到 HAL 层。