Loading services/vibratorservice/VibratorHalWrapper.cpp +35 −102 Original line number Diff line number Diff line Loading @@ -56,75 +56,6 @@ bool isStaticCastValid(Effect effect) { // ------------------------------------------------------------------------------------------------- const constexpr char* STATUS_T_ERROR_MESSAGE_PREFIX = "status_t = "; const constexpr char* STATUS_V_1_0_ERROR_MESSAGE_PREFIX = "android::hardware::vibrator::V1_0::Status = "; template <typename T> HalResult<T> HalResult<T>::fromStatus(V1_0::Status status, T data) { switch (status) { case V1_0::Status::OK: return HalResult<T>::ok(data); case V1_0::Status::UNSUPPORTED_OPERATION: return HalResult<T>::unsupported(); default: return HalResult<T>::failed(STATUS_V_1_0_ERROR_MESSAGE_PREFIX + toString(status)); } } template <typename T> template <typename R> HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, T data) { return ret.isOk() ? HalResult<T>::ok(data) : HalResult<T>::failed(ret.description()); } template <typename T> template <typename R> HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, V1_0::Status status, T data) { return ret.isOk() ? HalResult<T>::fromStatus(status, data) : HalResult<T>::failed(ret.description()); } // ------------------------------------------------------------------------------------------------- HalResult<void> HalResult<void>::fromStatus(status_t status) { if (status == android::OK) { return HalResult<void>::ok(); } return HalResult<void>::failed(STATUS_T_ERROR_MESSAGE_PREFIX + statusToString(status)); } HalResult<void> HalResult<void>::fromStatus(binder::Status status) { if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION || status.transactionError() == android::UNKNOWN_TRANSACTION) { // UNKNOWN_TRANSACTION means the HAL implementation is an older version, so this is // the same as the operation being unsupported by this HAL. Should not retry. return HalResult<void>::unsupported(); } if (status.isOk()) { return HalResult<void>::ok(); } return HalResult<void>::failed(std::string(status.toString8().c_str())); } HalResult<void> HalResult<void>::fromStatus(V1_0::Status status) { switch (status) { case V1_0::Status::OK: return HalResult<void>::ok(); case V1_0::Status::UNSUPPORTED_OPERATION: return HalResult<void>::unsupported(); default: return HalResult<void>::failed(STATUS_V_1_0_ERROR_MESSAGE_PREFIX + toString(status)); } } template <typename R> HalResult<void> HalResult<void>::fromReturn(hardware::Return<R>& ret) { return ret.isOk() ? HalResult<void>::ok() : HalResult<void>::failed(ret.description()); } // ------------------------------------------------------------------------------------------------- Info HalWrapper::getInfo() { getCapabilities(); getPrimitiveDurations(); Loading Loading @@ -269,7 +200,7 @@ HalResult<std::vector<float>> HalWrapper::getMaxAmplitudesInternal() { // ------------------------------------------------------------------------------------------------- HalResult<void> AidlHalWrapper::ping() { return HalResult<void>::fromStatus(IInterface::asBinder(getHal())->pingBinder()); return HalResultFactory::fromStatus(IInterface::asBinder(getHal())->pingBinder()); } void AidlHalWrapper::tryReconnect() { Loading @@ -291,7 +222,7 @@ HalResult<void> AidlHalWrapper::on(milliseconds timeout, static_cast<int32_t>(capabilities.value() & Capabilities::ON_CALLBACK); auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr; auto ret = HalResult<void>::fromStatus(getHal()->on(timeout.count(), cb)); auto ret = HalResultFactory::fromStatus(getHal()->on(timeout.count(), cb)); if (!supportsCallback && ret.isOk()) { mCallbackScheduler->schedule(completionCallback, timeout); } Loading @@ -300,23 +231,23 @@ HalResult<void> AidlHalWrapper::on(milliseconds timeout, } HalResult<void> AidlHalWrapper::off() { return HalResult<void>::fromStatus(getHal()->off()); return HalResultFactory::fromStatus(getHal()->off()); } HalResult<void> AidlHalWrapper::setAmplitude(float amplitude) { return HalResult<void>::fromStatus(getHal()->setAmplitude(amplitude)); return HalResultFactory::fromStatus(getHal()->setAmplitude(amplitude)); } HalResult<void> AidlHalWrapper::setExternalControl(bool enabled) { return HalResult<void>::fromStatus(getHal()->setExternalControl(enabled)); return HalResultFactory::fromStatus(getHal()->setExternalControl(enabled)); } HalResult<void> AidlHalWrapper::alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) { return HalResult<void>::fromStatus(getHal()->alwaysOnEnable(id, effect, strength)); return HalResultFactory::fromStatus(getHal()->alwaysOnEnable(id, effect, strength)); } HalResult<void> AidlHalWrapper::alwaysOnDisable(int32_t id) { return HalResult<void>::fromStatus(getHal()->alwaysOnDisable(id)); return HalResultFactory::fromStatus(getHal()->alwaysOnDisable(id)); } HalResult<milliseconds> AidlHalWrapper::performEffect( Loading @@ -330,7 +261,7 @@ HalResult<milliseconds> AidlHalWrapper::performEffect( auto result = getHal()->perform(effect, strength, cb, &lengthMs); milliseconds length = milliseconds(lengthMs); auto ret = HalResult<milliseconds>::fromStatus(result, length); auto ret = HalResultFactory::fromStatus<milliseconds>(result, length); if (!supportsCallback && ret.isOk()) { mCallbackScheduler->schedule(completionCallback, length); } Loading @@ -357,38 +288,40 @@ HalResult<milliseconds> AidlHalWrapper::performComposedEffect( duration += milliseconds(effect.delayMs); } return HalResult<milliseconds>::fromStatus(getHal()->compose(primitives, cb), duration); return HalResultFactory::fromStatus<milliseconds>(getHal()->compose(primitives, cb), duration); } HalResult<void> AidlHalWrapper::performPwleEffect(const std::vector<PrimitivePwle>& primitives, const std::function<void()>& completionCallback) { // This method should always support callbacks, so no need to double check. auto cb = new HalCallbackWrapper(completionCallback); return HalResult<void>::fromStatus(getHal()->composePwle(primitives, cb)); return HalResultFactory::fromStatus(getHal()->composePwle(primitives, cb)); } HalResult<Capabilities> AidlHalWrapper::getCapabilitiesInternal() { int32_t capabilities = 0; auto result = getHal()->getCapabilities(&capabilities); return HalResult<Capabilities>::fromStatus(result, static_cast<Capabilities>(capabilities)); return HalResultFactory::fromStatus<Capabilities>(result, static_cast<Capabilities>(capabilities)); } HalResult<std::vector<Effect>> AidlHalWrapper::getSupportedEffectsInternal() { std::vector<Effect> supportedEffects; auto result = getHal()->getSupportedEffects(&supportedEffects); return HalResult<std::vector<Effect>>::fromStatus(result, supportedEffects); return HalResultFactory::fromStatus<std::vector<Effect>>(result, supportedEffects); } HalResult<std::vector<Braking>> AidlHalWrapper::getSupportedBrakingInternal() { std::vector<Braking> supportedBraking; auto result = getHal()->getSupportedBraking(&supportedBraking); return HalResult<std::vector<Braking>>::fromStatus(result, supportedBraking); return HalResultFactory::fromStatus<std::vector<Braking>>(result, supportedBraking); } HalResult<std::vector<CompositePrimitive>> AidlHalWrapper::getSupportedPrimitivesInternal() { std::vector<CompositePrimitive> supportedPrimitives; auto result = getHal()->getSupportedPrimitives(&supportedPrimitives); return HalResult<std::vector<CompositePrimitive>>::fromStatus(result, supportedPrimitives); return HalResultFactory::fromStatus<std::vector<CompositePrimitive>>(result, supportedPrimitives); } HalResult<std::vector<milliseconds>> AidlHalWrapper::getPrimitiveDurationsInternal( Loading @@ -408,7 +341,7 @@ HalResult<std::vector<milliseconds>> AidlHalWrapper::getPrimitiveDurationsIntern } int32_t duration = 0; auto result = getHal()->getPrimitiveDuration(primitive, &duration); auto halResult = HalResult<int32_t>::fromStatus(result, duration); auto halResult = HalResultFactory::fromStatus<int32_t>(result, duration); if (halResult.isUnsupported()) { // Should not happen, supported primitives should always support requesting duration. ALOGE("Supported primitive %zu returned unsupported for getPrimitiveDuration", Loading @@ -427,55 +360,55 @@ HalResult<std::vector<milliseconds>> AidlHalWrapper::getPrimitiveDurationsIntern HalResult<milliseconds> AidlHalWrapper::getPrimitiveDelayMaxInternal() { int32_t delay = 0; auto result = getHal()->getCompositionDelayMax(&delay); return HalResult<milliseconds>::fromStatus(result, milliseconds(delay)); return HalResultFactory::fromStatus<milliseconds>(result, milliseconds(delay)); } HalResult<milliseconds> AidlHalWrapper::getPrimitiveDurationMaxInternal() { int32_t delay = 0; auto result = getHal()->getPwlePrimitiveDurationMax(&delay); return HalResult<milliseconds>::fromStatus(result, milliseconds(delay)); return HalResultFactory::fromStatus<milliseconds>(result, milliseconds(delay)); } HalResult<int32_t> AidlHalWrapper::getCompositionSizeMaxInternal() { int32_t size = 0; auto result = getHal()->getCompositionSizeMax(&size); return HalResult<int32_t>::fromStatus(result, size); return HalResultFactory::fromStatus<int32_t>(result, size); } HalResult<int32_t> AidlHalWrapper::getPwleSizeMaxInternal() { int32_t size = 0; auto result = getHal()->getPwleCompositionSizeMax(&size); return HalResult<int32_t>::fromStatus(result, size); return HalResultFactory::fromStatus<int32_t>(result, size); } HalResult<float> AidlHalWrapper::getMinFrequencyInternal() { float minFrequency = 0; auto result = getHal()->getFrequencyMinimum(&minFrequency); return HalResult<float>::fromStatus(result, minFrequency); return HalResultFactory::fromStatus<float>(result, minFrequency); } HalResult<float> AidlHalWrapper::getResonantFrequencyInternal() { float f0 = 0; auto result = getHal()->getResonantFrequency(&f0); return HalResult<float>::fromStatus(result, f0); return HalResultFactory::fromStatus<float>(result, f0); } HalResult<float> AidlHalWrapper::getFrequencyResolutionInternal() { float frequencyResolution = 0; auto result = getHal()->getFrequencyResolution(&frequencyResolution); return HalResult<float>::fromStatus(result, frequencyResolution); return HalResultFactory::fromStatus<float>(result, frequencyResolution); } HalResult<float> AidlHalWrapper::getQFactorInternal() { float qFactor = 0; auto result = getHal()->getQFactor(&qFactor); return HalResult<float>::fromStatus(result, qFactor); return HalResultFactory::fromStatus<float>(result, qFactor); } HalResult<std::vector<float>> AidlHalWrapper::getMaxAmplitudesInternal() { std::vector<float> amplitudes; auto result = getHal()->getBandwidthAmplitudeMap(&litudes); return HalResult<std::vector<float>>::fromStatus(result, amplitudes); return HalResultFactory::fromStatus<std::vector<float>>(result, amplitudes); } sp<Aidl::IVibrator> AidlHalWrapper::getHal() { Loading @@ -488,7 +421,7 @@ sp<Aidl::IVibrator> AidlHalWrapper::getHal() { template <typename I> HalResult<void> HidlHalWrapper<I>::ping() { auto result = getHal()->ping(); return HalResult<void>::fromReturn(result); return HalResultFactory::fromReturn(result); } template <typename I> Loading @@ -504,7 +437,7 @@ template <typename I> HalResult<void> HidlHalWrapper<I>::on(milliseconds timeout, const std::function<void()>& completionCallback) { auto result = getHal()->on(timeout.count()); auto ret = HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); auto ret = HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); if (ret.isOk()) { mCallbackScheduler->schedule(completionCallback, timeout); } Loading @@ -514,14 +447,14 @@ HalResult<void> HidlHalWrapper<I>::on(milliseconds timeout, template <typename I> HalResult<void> HidlHalWrapper<I>::off() { auto result = getHal()->off(); return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); return HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); } template <typename I> HalResult<void> HidlHalWrapper<I>::setAmplitude(float amplitude) { uint8_t amp = static_cast<uint8_t>(amplitude * std::numeric_limits<uint8_t>::max()); auto result = getHal()->setAmplitude(amp); return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); return HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); } template <typename I> Loading @@ -547,7 +480,7 @@ HalResult<Capabilities> HidlHalWrapper<I>::getCapabilitiesInternal() { hardware::Return<bool> result = getHal()->supportsAmplitudeControl(); Capabilities capabilities = result.withDefault(false) ? Capabilities::AMPLITUDE_CONTROL : Capabilities::NONE; return HalResult<Capabilities>::fromReturn(result, capabilities); return HalResultFactory::fromReturn<Capabilities>(result, capabilities); } template <typename I> Loading @@ -566,7 +499,7 @@ HalResult<milliseconds> HidlHalWrapper<I>::performInternal( auto result = std::invoke(performFn, handle, effect, effectStrength, effectCallback); milliseconds length = milliseconds(lengthMs); auto ret = HalResult<milliseconds>::fromReturn(result, status, length); auto ret = HalResultFactory::fromReturn<milliseconds>(result, status, length); if (ret.isOk()) { mCallbackScheduler->schedule(completionCallback, length); } Loading Loading @@ -638,7 +571,7 @@ HalResult<milliseconds> HidlHalWrapperV1_2::performEffect( HalResult<void> HidlHalWrapperV1_3::setExternalControl(bool enabled) { auto result = getHal()->setExternalControl(static_cast<uint32_t>(enabled)); return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); return HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); } HalResult<milliseconds> HidlHalWrapperV1_3::performEffect( Loading Loading @@ -671,7 +604,7 @@ HalResult<Capabilities> HidlHalWrapperV1_3::getCapabilitiesInternal() { sp<V1_3::IVibrator> hal = getHal(); auto amplitudeResult = hal->supportsAmplitudeControl(); if (!amplitudeResult.isOk()) { return HalResult<Capabilities>::fromReturn(amplitudeResult, capabilities); return HalResultFactory::fromReturn<Capabilities>(amplitudeResult, capabilities); } auto externalControlResult = hal->supportsExternalControl(); Loading @@ -686,7 +619,7 @@ HalResult<Capabilities> HidlHalWrapperV1_3::getCapabilitiesInternal() { } } return HalResult<Capabilities>::fromReturn(externalControlResult, capabilities); return HalResultFactory::fromReturn<Capabilities>(externalControlResult, capabilities); } // ------------------------------------------------------------------------------------------------- Loading services/vibratorservice/VibratorManagerHalController.cpp +8 −6 Original line number Diff line number Diff line Loading @@ -46,8 +46,6 @@ template <typename T> HalResult<T> ManagerHalController::processHalResult(HalResult<T> result, const char* functionName) { if (result.isFailed()) { ALOGE("VibratorManager HAL %s failed: %s", functionName, result.errorMessage()); std::lock_guard<std::mutex> lock(mConnectedHalMutex); mConnectedHal->tryReconnect(); } return result; } Loading @@ -70,12 +68,16 @@ HalResult<T> ManagerHalController::apply(ManagerHalController::hal_fn<T>& halFn, hal = mConnectedHal; } HalResult<T> ret = processHalResult(halFn(hal), functionName); for (int i = 0; i < MAX_RETRIES && ret.isFailed(); i++) { ret = processHalResult(halFn(hal), functionName); HalResult<T> result = processHalResult(halFn(hal), functionName); for (int i = 0; i < MAX_RETRIES && result.shouldRetry(); i++) { { std::lock_guard<std::mutex> lock(mConnectedHalMutex); mConnectedHal->tryReconnect(); } result = processHalResult(halFn(hal), functionName); } return ret; return result; } // ------------------------------------------------------------------------------------------------- Loading services/vibratorservice/VibratorManagerHalWrapper.cpp +15 −15 Original line number Diff line number Diff line Loading @@ -55,8 +55,8 @@ HalResult<std::shared_ptr<HalController>> LegacyManagerHalWrapper::getVibrator(i return HalResult<std::shared_ptr<HalController>>::ok(mController); } // Controller.init did not connect to any vibrator HAL service, so the device has no vibrator. return HalResult<std::shared_ptr<HalController>>::failed(MISSING_VIBRATOR_MESSAGE_PREFIX + std::to_string(id)); return HalResult<std::shared_ptr<HalController>>::failed( (MISSING_VIBRATOR_MESSAGE_PREFIX + std::to_string(id)).c_str()); } HalResult<void> LegacyManagerHalWrapper::prepareSynced(const std::vector<int32_t>&) { Loading @@ -75,10 +75,10 @@ HalResult<void> LegacyManagerHalWrapper::cancelSynced() { std::shared_ptr<HalWrapper> AidlManagerHalWrapper::connectToVibrator( int32_t vibratorId, std::shared_ptr<CallbackScheduler> callbackScheduler) { std::function<HalResult<sp<Aidl::IVibrator>>()> reconnectFn = [=]() { std::function<HalResult<sp<Aidl::IVibrator>>()> reconnectFn = [=, this]() { sp<Aidl::IVibrator> vibrator; auto result = this->getHal()->getVibrator(vibratorId, &vibrator); return HalResult<sp<Aidl::IVibrator>>::fromStatus(result, vibrator); return HalResultFactory::fromStatus<sp<Aidl::IVibrator>>(result, vibrator); }; auto result = reconnectFn(); if (!result.isOk()) { Loading @@ -88,12 +88,12 @@ std::shared_ptr<HalWrapper> AidlManagerHalWrapper::connectToVibrator( if (!vibrator) { return nullptr; } return std::move(std::make_unique<AidlHalWrapper>(std::move(callbackScheduler), std::move(vibrator), reconnectFn)); return std::make_unique<AidlHalWrapper>(std::move(callbackScheduler), std::move(vibrator), reconnectFn); } HalResult<void> AidlManagerHalWrapper::ping() { return HalResult<void>::fromStatus(IInterface::asBinder(getHal())->pingBinder()); return HalResultFactory::fromStatus(IInterface::asBinder(getHal())->pingBinder()); } void AidlManagerHalWrapper::tryReconnect() { Loading @@ -112,8 +112,8 @@ HalResult<ManagerCapabilities> AidlManagerHalWrapper::getCapabilities() { } int32_t cap = 0; auto result = getHal()->getCapabilities(&cap); auto ret = HalResult<ManagerCapabilities>::fromStatus(result, static_cast<ManagerCapabilities>(cap)); auto capabilities = static_cast<ManagerCapabilities>(cap); auto ret = HalResultFactory::fromStatus<ManagerCapabilities>(result, capabilities); if (ret.isOk()) { // Cache copy of returned value. mCapabilities.emplace(ret.value()); Loading @@ -129,7 +129,7 @@ HalResult<std::vector<int32_t>> AidlManagerHalWrapper::getVibratorIds() { } std::vector<int32_t> ids; auto result = getHal()->getVibratorIds(&ids); auto ret = HalResult<std::vector<int32_t>>::fromStatus(result, ids); auto ret = HalResultFactory::fromStatus<std::vector<int32_t>>(result, ids); if (ret.isOk()) { // Cache copy of returned value and the individual controllers. mVibratorIds.emplace(ret.value()); Loading @@ -152,12 +152,12 @@ HalResult<std::shared_ptr<HalController>> AidlManagerHalWrapper::getVibrator(int if (it != mVibrators.end()) { return HalResult<std::shared_ptr<HalController>>::ok(it->second); } return HalResult<std::shared_ptr<HalController>>::failed(MISSING_VIBRATOR_MESSAGE_PREFIX + std::to_string(id)); return HalResult<std::shared_ptr<HalController>>::failed( (MISSING_VIBRATOR_MESSAGE_PREFIX + std::to_string(id)).c_str()); } HalResult<void> AidlManagerHalWrapper::prepareSynced(const std::vector<int32_t>& ids) { auto ret = HalResult<void>::fromStatus(getHal()->prepareSynced(ids)); auto ret = HalResultFactory::fromStatus(getHal()->prepareSynced(ids)); if (ret.isOk()) { // Force reload of all vibrator controllers that were prepared for a sync operation here. // This will trigger calls to getVibrator(id) on each controller, so they can use the Loading @@ -179,11 +179,11 @@ HalResult<void> AidlManagerHalWrapper::triggerSynced( bool supportsCallback = capabilities.isOk() && static_cast<int32_t>(capabilities.value() & ManagerCapabilities::TRIGGER_CALLBACK); auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr; return HalResult<void>::fromStatus(getHal()->triggerSynced(cb)); return HalResultFactory::fromStatus(getHal()->triggerSynced(cb)); } HalResult<void> AidlManagerHalWrapper::cancelSynced() { auto ret = HalResult<void>::fromStatus(getHal()->cancelSynced()); auto ret = HalResultFactory::fromStatus(getHal()->cancelSynced()); if (ret.isOk()) { // Force reload of all vibrator controllers that were prepared for a sync operation before. // This will trigger calls to getVibrator(id) on each controller, so they can use the Loading services/vibratorservice/include/vibratorservice/VibratorHalController.h +40 −11 Original line number Diff line number Diff line Loading @@ -64,7 +64,29 @@ public: */ Info getInfo() { static Info sDefaultInfo = InfoCache().get(); return apply<Info>([](HalWrapper* hal) { return hal->getInfo(); }, sDefaultInfo, "getInfo"); if (!init()) { ALOGV("Skipped getInfo because Vibrator HAL is not available"); return sDefaultInfo; } std::shared_ptr<HalWrapper> hal; { std::lock_guard<std::mutex> lock(mConnectedHalMutex); hal = mConnectedHal; } for (int i = 0; i < MAX_RETRIES; i++) { Info result = hal.get()->getInfo(); result.logFailures(); if (result.shouldRetry()) { tryReconnect(); } else { return result; } } Info result = hal.get()->getInfo(); result.logFailures(); return result; } /* Calls given HAL function, applying automatic retries to reconnect with the HAL when the Loading @@ -72,7 +94,7 @@ public: */ template <typename T> HalResult<T> doWithRetry(const HalFunction<HalResult<T>>& halFn, const char* functionName) { return apply(halFn, HalResult<T>::unsupported(), functionName); return doWithRetry<T>(halFn, HalResult<T>::unsupported(), functionName); } private: Loading @@ -90,7 +112,8 @@ private: * function name is for logging purposes. */ template <typename T> T apply(const HalFunction<T>& halFn, T defaultValue, const char* functionName) { HalResult<T> doWithRetry(const HalFunction<HalResult<T>>& halFn, HalResult<T> defaultValue, const char* functionName) { if (!init()) { ALOGV("Skipped %s because Vibrator HAL is not available", functionName); return defaultValue; Loading @@ -101,16 +124,22 @@ private: hal = mConnectedHal; } for (int i = 0; i < MAX_RETRIES; i++) { T result = halFn(hal.get()); if (result.isFailedLogged(functionName)) { HalResult<T> result = doOnce(hal.get(), halFn, functionName); for (int i = 0; i < MAX_RETRIES && result.shouldRetry(); i++) { tryReconnect(); } else { return result; result = doOnce(hal.get(), halFn, functionName); } return result; } return halFn(hal.get()); template <typename T> HalResult<T> doOnce(HalWrapper* hal, const HalFunction<HalResult<T>>& halFn, const char* functionName) { HalResult<T> result = halFn(hal); if (result.isFailed()) { ALOGE("Vibrator HAL %s failed: %s", functionName, result.errorMessage()); } return result; } }; Loading services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h +173 −95 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/vibratorservice/VibratorHalWrapper.cpp +35 −102 Original line number Diff line number Diff line Loading @@ -56,75 +56,6 @@ bool isStaticCastValid(Effect effect) { // ------------------------------------------------------------------------------------------------- const constexpr char* STATUS_T_ERROR_MESSAGE_PREFIX = "status_t = "; const constexpr char* STATUS_V_1_0_ERROR_MESSAGE_PREFIX = "android::hardware::vibrator::V1_0::Status = "; template <typename T> HalResult<T> HalResult<T>::fromStatus(V1_0::Status status, T data) { switch (status) { case V1_0::Status::OK: return HalResult<T>::ok(data); case V1_0::Status::UNSUPPORTED_OPERATION: return HalResult<T>::unsupported(); default: return HalResult<T>::failed(STATUS_V_1_0_ERROR_MESSAGE_PREFIX + toString(status)); } } template <typename T> template <typename R> HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, T data) { return ret.isOk() ? HalResult<T>::ok(data) : HalResult<T>::failed(ret.description()); } template <typename T> template <typename R> HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, V1_0::Status status, T data) { return ret.isOk() ? HalResult<T>::fromStatus(status, data) : HalResult<T>::failed(ret.description()); } // ------------------------------------------------------------------------------------------------- HalResult<void> HalResult<void>::fromStatus(status_t status) { if (status == android::OK) { return HalResult<void>::ok(); } return HalResult<void>::failed(STATUS_T_ERROR_MESSAGE_PREFIX + statusToString(status)); } HalResult<void> HalResult<void>::fromStatus(binder::Status status) { if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION || status.transactionError() == android::UNKNOWN_TRANSACTION) { // UNKNOWN_TRANSACTION means the HAL implementation is an older version, so this is // the same as the operation being unsupported by this HAL. Should not retry. return HalResult<void>::unsupported(); } if (status.isOk()) { return HalResult<void>::ok(); } return HalResult<void>::failed(std::string(status.toString8().c_str())); } HalResult<void> HalResult<void>::fromStatus(V1_0::Status status) { switch (status) { case V1_0::Status::OK: return HalResult<void>::ok(); case V1_0::Status::UNSUPPORTED_OPERATION: return HalResult<void>::unsupported(); default: return HalResult<void>::failed(STATUS_V_1_0_ERROR_MESSAGE_PREFIX + toString(status)); } } template <typename R> HalResult<void> HalResult<void>::fromReturn(hardware::Return<R>& ret) { return ret.isOk() ? HalResult<void>::ok() : HalResult<void>::failed(ret.description()); } // ------------------------------------------------------------------------------------------------- Info HalWrapper::getInfo() { getCapabilities(); getPrimitiveDurations(); Loading Loading @@ -269,7 +200,7 @@ HalResult<std::vector<float>> HalWrapper::getMaxAmplitudesInternal() { // ------------------------------------------------------------------------------------------------- HalResult<void> AidlHalWrapper::ping() { return HalResult<void>::fromStatus(IInterface::asBinder(getHal())->pingBinder()); return HalResultFactory::fromStatus(IInterface::asBinder(getHal())->pingBinder()); } void AidlHalWrapper::tryReconnect() { Loading @@ -291,7 +222,7 @@ HalResult<void> AidlHalWrapper::on(milliseconds timeout, static_cast<int32_t>(capabilities.value() & Capabilities::ON_CALLBACK); auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr; auto ret = HalResult<void>::fromStatus(getHal()->on(timeout.count(), cb)); auto ret = HalResultFactory::fromStatus(getHal()->on(timeout.count(), cb)); if (!supportsCallback && ret.isOk()) { mCallbackScheduler->schedule(completionCallback, timeout); } Loading @@ -300,23 +231,23 @@ HalResult<void> AidlHalWrapper::on(milliseconds timeout, } HalResult<void> AidlHalWrapper::off() { return HalResult<void>::fromStatus(getHal()->off()); return HalResultFactory::fromStatus(getHal()->off()); } HalResult<void> AidlHalWrapper::setAmplitude(float amplitude) { return HalResult<void>::fromStatus(getHal()->setAmplitude(amplitude)); return HalResultFactory::fromStatus(getHal()->setAmplitude(amplitude)); } HalResult<void> AidlHalWrapper::setExternalControl(bool enabled) { return HalResult<void>::fromStatus(getHal()->setExternalControl(enabled)); return HalResultFactory::fromStatus(getHal()->setExternalControl(enabled)); } HalResult<void> AidlHalWrapper::alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) { return HalResult<void>::fromStatus(getHal()->alwaysOnEnable(id, effect, strength)); return HalResultFactory::fromStatus(getHal()->alwaysOnEnable(id, effect, strength)); } HalResult<void> AidlHalWrapper::alwaysOnDisable(int32_t id) { return HalResult<void>::fromStatus(getHal()->alwaysOnDisable(id)); return HalResultFactory::fromStatus(getHal()->alwaysOnDisable(id)); } HalResult<milliseconds> AidlHalWrapper::performEffect( Loading @@ -330,7 +261,7 @@ HalResult<milliseconds> AidlHalWrapper::performEffect( auto result = getHal()->perform(effect, strength, cb, &lengthMs); milliseconds length = milliseconds(lengthMs); auto ret = HalResult<milliseconds>::fromStatus(result, length); auto ret = HalResultFactory::fromStatus<milliseconds>(result, length); if (!supportsCallback && ret.isOk()) { mCallbackScheduler->schedule(completionCallback, length); } Loading @@ -357,38 +288,40 @@ HalResult<milliseconds> AidlHalWrapper::performComposedEffect( duration += milliseconds(effect.delayMs); } return HalResult<milliseconds>::fromStatus(getHal()->compose(primitives, cb), duration); return HalResultFactory::fromStatus<milliseconds>(getHal()->compose(primitives, cb), duration); } HalResult<void> AidlHalWrapper::performPwleEffect(const std::vector<PrimitivePwle>& primitives, const std::function<void()>& completionCallback) { // This method should always support callbacks, so no need to double check. auto cb = new HalCallbackWrapper(completionCallback); return HalResult<void>::fromStatus(getHal()->composePwle(primitives, cb)); return HalResultFactory::fromStatus(getHal()->composePwle(primitives, cb)); } HalResult<Capabilities> AidlHalWrapper::getCapabilitiesInternal() { int32_t capabilities = 0; auto result = getHal()->getCapabilities(&capabilities); return HalResult<Capabilities>::fromStatus(result, static_cast<Capabilities>(capabilities)); return HalResultFactory::fromStatus<Capabilities>(result, static_cast<Capabilities>(capabilities)); } HalResult<std::vector<Effect>> AidlHalWrapper::getSupportedEffectsInternal() { std::vector<Effect> supportedEffects; auto result = getHal()->getSupportedEffects(&supportedEffects); return HalResult<std::vector<Effect>>::fromStatus(result, supportedEffects); return HalResultFactory::fromStatus<std::vector<Effect>>(result, supportedEffects); } HalResult<std::vector<Braking>> AidlHalWrapper::getSupportedBrakingInternal() { std::vector<Braking> supportedBraking; auto result = getHal()->getSupportedBraking(&supportedBraking); return HalResult<std::vector<Braking>>::fromStatus(result, supportedBraking); return HalResultFactory::fromStatus<std::vector<Braking>>(result, supportedBraking); } HalResult<std::vector<CompositePrimitive>> AidlHalWrapper::getSupportedPrimitivesInternal() { std::vector<CompositePrimitive> supportedPrimitives; auto result = getHal()->getSupportedPrimitives(&supportedPrimitives); return HalResult<std::vector<CompositePrimitive>>::fromStatus(result, supportedPrimitives); return HalResultFactory::fromStatus<std::vector<CompositePrimitive>>(result, supportedPrimitives); } HalResult<std::vector<milliseconds>> AidlHalWrapper::getPrimitiveDurationsInternal( Loading @@ -408,7 +341,7 @@ HalResult<std::vector<milliseconds>> AidlHalWrapper::getPrimitiveDurationsIntern } int32_t duration = 0; auto result = getHal()->getPrimitiveDuration(primitive, &duration); auto halResult = HalResult<int32_t>::fromStatus(result, duration); auto halResult = HalResultFactory::fromStatus<int32_t>(result, duration); if (halResult.isUnsupported()) { // Should not happen, supported primitives should always support requesting duration. ALOGE("Supported primitive %zu returned unsupported for getPrimitiveDuration", Loading @@ -427,55 +360,55 @@ HalResult<std::vector<milliseconds>> AidlHalWrapper::getPrimitiveDurationsIntern HalResult<milliseconds> AidlHalWrapper::getPrimitiveDelayMaxInternal() { int32_t delay = 0; auto result = getHal()->getCompositionDelayMax(&delay); return HalResult<milliseconds>::fromStatus(result, milliseconds(delay)); return HalResultFactory::fromStatus<milliseconds>(result, milliseconds(delay)); } HalResult<milliseconds> AidlHalWrapper::getPrimitiveDurationMaxInternal() { int32_t delay = 0; auto result = getHal()->getPwlePrimitiveDurationMax(&delay); return HalResult<milliseconds>::fromStatus(result, milliseconds(delay)); return HalResultFactory::fromStatus<milliseconds>(result, milliseconds(delay)); } HalResult<int32_t> AidlHalWrapper::getCompositionSizeMaxInternal() { int32_t size = 0; auto result = getHal()->getCompositionSizeMax(&size); return HalResult<int32_t>::fromStatus(result, size); return HalResultFactory::fromStatus<int32_t>(result, size); } HalResult<int32_t> AidlHalWrapper::getPwleSizeMaxInternal() { int32_t size = 0; auto result = getHal()->getPwleCompositionSizeMax(&size); return HalResult<int32_t>::fromStatus(result, size); return HalResultFactory::fromStatus<int32_t>(result, size); } HalResult<float> AidlHalWrapper::getMinFrequencyInternal() { float minFrequency = 0; auto result = getHal()->getFrequencyMinimum(&minFrequency); return HalResult<float>::fromStatus(result, minFrequency); return HalResultFactory::fromStatus<float>(result, minFrequency); } HalResult<float> AidlHalWrapper::getResonantFrequencyInternal() { float f0 = 0; auto result = getHal()->getResonantFrequency(&f0); return HalResult<float>::fromStatus(result, f0); return HalResultFactory::fromStatus<float>(result, f0); } HalResult<float> AidlHalWrapper::getFrequencyResolutionInternal() { float frequencyResolution = 0; auto result = getHal()->getFrequencyResolution(&frequencyResolution); return HalResult<float>::fromStatus(result, frequencyResolution); return HalResultFactory::fromStatus<float>(result, frequencyResolution); } HalResult<float> AidlHalWrapper::getQFactorInternal() { float qFactor = 0; auto result = getHal()->getQFactor(&qFactor); return HalResult<float>::fromStatus(result, qFactor); return HalResultFactory::fromStatus<float>(result, qFactor); } HalResult<std::vector<float>> AidlHalWrapper::getMaxAmplitudesInternal() { std::vector<float> amplitudes; auto result = getHal()->getBandwidthAmplitudeMap(&litudes); return HalResult<std::vector<float>>::fromStatus(result, amplitudes); return HalResultFactory::fromStatus<std::vector<float>>(result, amplitudes); } sp<Aidl::IVibrator> AidlHalWrapper::getHal() { Loading @@ -488,7 +421,7 @@ sp<Aidl::IVibrator> AidlHalWrapper::getHal() { template <typename I> HalResult<void> HidlHalWrapper<I>::ping() { auto result = getHal()->ping(); return HalResult<void>::fromReturn(result); return HalResultFactory::fromReturn(result); } template <typename I> Loading @@ -504,7 +437,7 @@ template <typename I> HalResult<void> HidlHalWrapper<I>::on(milliseconds timeout, const std::function<void()>& completionCallback) { auto result = getHal()->on(timeout.count()); auto ret = HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); auto ret = HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); if (ret.isOk()) { mCallbackScheduler->schedule(completionCallback, timeout); } Loading @@ -514,14 +447,14 @@ HalResult<void> HidlHalWrapper<I>::on(milliseconds timeout, template <typename I> HalResult<void> HidlHalWrapper<I>::off() { auto result = getHal()->off(); return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); return HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); } template <typename I> HalResult<void> HidlHalWrapper<I>::setAmplitude(float amplitude) { uint8_t amp = static_cast<uint8_t>(amplitude * std::numeric_limits<uint8_t>::max()); auto result = getHal()->setAmplitude(amp); return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); return HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); } template <typename I> Loading @@ -547,7 +480,7 @@ HalResult<Capabilities> HidlHalWrapper<I>::getCapabilitiesInternal() { hardware::Return<bool> result = getHal()->supportsAmplitudeControl(); Capabilities capabilities = result.withDefault(false) ? Capabilities::AMPLITUDE_CONTROL : Capabilities::NONE; return HalResult<Capabilities>::fromReturn(result, capabilities); return HalResultFactory::fromReturn<Capabilities>(result, capabilities); } template <typename I> Loading @@ -566,7 +499,7 @@ HalResult<milliseconds> HidlHalWrapper<I>::performInternal( auto result = std::invoke(performFn, handle, effect, effectStrength, effectCallback); milliseconds length = milliseconds(lengthMs); auto ret = HalResult<milliseconds>::fromReturn(result, status, length); auto ret = HalResultFactory::fromReturn<milliseconds>(result, status, length); if (ret.isOk()) { mCallbackScheduler->schedule(completionCallback, length); } Loading Loading @@ -638,7 +571,7 @@ HalResult<milliseconds> HidlHalWrapperV1_2::performEffect( HalResult<void> HidlHalWrapperV1_3::setExternalControl(bool enabled) { auto result = getHal()->setExternalControl(static_cast<uint32_t>(enabled)); return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); return HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); } HalResult<milliseconds> HidlHalWrapperV1_3::performEffect( Loading Loading @@ -671,7 +604,7 @@ HalResult<Capabilities> HidlHalWrapperV1_3::getCapabilitiesInternal() { sp<V1_3::IVibrator> hal = getHal(); auto amplitudeResult = hal->supportsAmplitudeControl(); if (!amplitudeResult.isOk()) { return HalResult<Capabilities>::fromReturn(amplitudeResult, capabilities); return HalResultFactory::fromReturn<Capabilities>(amplitudeResult, capabilities); } auto externalControlResult = hal->supportsExternalControl(); Loading @@ -686,7 +619,7 @@ HalResult<Capabilities> HidlHalWrapperV1_3::getCapabilitiesInternal() { } } return HalResult<Capabilities>::fromReturn(externalControlResult, capabilities); return HalResultFactory::fromReturn<Capabilities>(externalControlResult, capabilities); } // ------------------------------------------------------------------------------------------------- Loading
services/vibratorservice/VibratorManagerHalController.cpp +8 −6 Original line number Diff line number Diff line Loading @@ -46,8 +46,6 @@ template <typename T> HalResult<T> ManagerHalController::processHalResult(HalResult<T> result, const char* functionName) { if (result.isFailed()) { ALOGE("VibratorManager HAL %s failed: %s", functionName, result.errorMessage()); std::lock_guard<std::mutex> lock(mConnectedHalMutex); mConnectedHal->tryReconnect(); } return result; } Loading @@ -70,12 +68,16 @@ HalResult<T> ManagerHalController::apply(ManagerHalController::hal_fn<T>& halFn, hal = mConnectedHal; } HalResult<T> ret = processHalResult(halFn(hal), functionName); for (int i = 0; i < MAX_RETRIES && ret.isFailed(); i++) { ret = processHalResult(halFn(hal), functionName); HalResult<T> result = processHalResult(halFn(hal), functionName); for (int i = 0; i < MAX_RETRIES && result.shouldRetry(); i++) { { std::lock_guard<std::mutex> lock(mConnectedHalMutex); mConnectedHal->tryReconnect(); } result = processHalResult(halFn(hal), functionName); } return ret; return result; } // ------------------------------------------------------------------------------------------------- Loading
services/vibratorservice/VibratorManagerHalWrapper.cpp +15 −15 Original line number Diff line number Diff line Loading @@ -55,8 +55,8 @@ HalResult<std::shared_ptr<HalController>> LegacyManagerHalWrapper::getVibrator(i return HalResult<std::shared_ptr<HalController>>::ok(mController); } // Controller.init did not connect to any vibrator HAL service, so the device has no vibrator. return HalResult<std::shared_ptr<HalController>>::failed(MISSING_VIBRATOR_MESSAGE_PREFIX + std::to_string(id)); return HalResult<std::shared_ptr<HalController>>::failed( (MISSING_VIBRATOR_MESSAGE_PREFIX + std::to_string(id)).c_str()); } HalResult<void> LegacyManagerHalWrapper::prepareSynced(const std::vector<int32_t>&) { Loading @@ -75,10 +75,10 @@ HalResult<void> LegacyManagerHalWrapper::cancelSynced() { std::shared_ptr<HalWrapper> AidlManagerHalWrapper::connectToVibrator( int32_t vibratorId, std::shared_ptr<CallbackScheduler> callbackScheduler) { std::function<HalResult<sp<Aidl::IVibrator>>()> reconnectFn = [=]() { std::function<HalResult<sp<Aidl::IVibrator>>()> reconnectFn = [=, this]() { sp<Aidl::IVibrator> vibrator; auto result = this->getHal()->getVibrator(vibratorId, &vibrator); return HalResult<sp<Aidl::IVibrator>>::fromStatus(result, vibrator); return HalResultFactory::fromStatus<sp<Aidl::IVibrator>>(result, vibrator); }; auto result = reconnectFn(); if (!result.isOk()) { Loading @@ -88,12 +88,12 @@ std::shared_ptr<HalWrapper> AidlManagerHalWrapper::connectToVibrator( if (!vibrator) { return nullptr; } return std::move(std::make_unique<AidlHalWrapper>(std::move(callbackScheduler), std::move(vibrator), reconnectFn)); return std::make_unique<AidlHalWrapper>(std::move(callbackScheduler), std::move(vibrator), reconnectFn); } HalResult<void> AidlManagerHalWrapper::ping() { return HalResult<void>::fromStatus(IInterface::asBinder(getHal())->pingBinder()); return HalResultFactory::fromStatus(IInterface::asBinder(getHal())->pingBinder()); } void AidlManagerHalWrapper::tryReconnect() { Loading @@ -112,8 +112,8 @@ HalResult<ManagerCapabilities> AidlManagerHalWrapper::getCapabilities() { } int32_t cap = 0; auto result = getHal()->getCapabilities(&cap); auto ret = HalResult<ManagerCapabilities>::fromStatus(result, static_cast<ManagerCapabilities>(cap)); auto capabilities = static_cast<ManagerCapabilities>(cap); auto ret = HalResultFactory::fromStatus<ManagerCapabilities>(result, capabilities); if (ret.isOk()) { // Cache copy of returned value. mCapabilities.emplace(ret.value()); Loading @@ -129,7 +129,7 @@ HalResult<std::vector<int32_t>> AidlManagerHalWrapper::getVibratorIds() { } std::vector<int32_t> ids; auto result = getHal()->getVibratorIds(&ids); auto ret = HalResult<std::vector<int32_t>>::fromStatus(result, ids); auto ret = HalResultFactory::fromStatus<std::vector<int32_t>>(result, ids); if (ret.isOk()) { // Cache copy of returned value and the individual controllers. mVibratorIds.emplace(ret.value()); Loading @@ -152,12 +152,12 @@ HalResult<std::shared_ptr<HalController>> AidlManagerHalWrapper::getVibrator(int if (it != mVibrators.end()) { return HalResult<std::shared_ptr<HalController>>::ok(it->second); } return HalResult<std::shared_ptr<HalController>>::failed(MISSING_VIBRATOR_MESSAGE_PREFIX + std::to_string(id)); return HalResult<std::shared_ptr<HalController>>::failed( (MISSING_VIBRATOR_MESSAGE_PREFIX + std::to_string(id)).c_str()); } HalResult<void> AidlManagerHalWrapper::prepareSynced(const std::vector<int32_t>& ids) { auto ret = HalResult<void>::fromStatus(getHal()->prepareSynced(ids)); auto ret = HalResultFactory::fromStatus(getHal()->prepareSynced(ids)); if (ret.isOk()) { // Force reload of all vibrator controllers that were prepared for a sync operation here. // This will trigger calls to getVibrator(id) on each controller, so they can use the Loading @@ -179,11 +179,11 @@ HalResult<void> AidlManagerHalWrapper::triggerSynced( bool supportsCallback = capabilities.isOk() && static_cast<int32_t>(capabilities.value() & ManagerCapabilities::TRIGGER_CALLBACK); auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr; return HalResult<void>::fromStatus(getHal()->triggerSynced(cb)); return HalResultFactory::fromStatus(getHal()->triggerSynced(cb)); } HalResult<void> AidlManagerHalWrapper::cancelSynced() { auto ret = HalResult<void>::fromStatus(getHal()->cancelSynced()); auto ret = HalResultFactory::fromStatus(getHal()->cancelSynced()); if (ret.isOk()) { // Force reload of all vibrator controllers that were prepared for a sync operation before. // This will trigger calls to getVibrator(id) on each controller, so they can use the Loading
services/vibratorservice/include/vibratorservice/VibratorHalController.h +40 −11 Original line number Diff line number Diff line Loading @@ -64,7 +64,29 @@ public: */ Info getInfo() { static Info sDefaultInfo = InfoCache().get(); return apply<Info>([](HalWrapper* hal) { return hal->getInfo(); }, sDefaultInfo, "getInfo"); if (!init()) { ALOGV("Skipped getInfo because Vibrator HAL is not available"); return sDefaultInfo; } std::shared_ptr<HalWrapper> hal; { std::lock_guard<std::mutex> lock(mConnectedHalMutex); hal = mConnectedHal; } for (int i = 0; i < MAX_RETRIES; i++) { Info result = hal.get()->getInfo(); result.logFailures(); if (result.shouldRetry()) { tryReconnect(); } else { return result; } } Info result = hal.get()->getInfo(); result.logFailures(); return result; } /* Calls given HAL function, applying automatic retries to reconnect with the HAL when the Loading @@ -72,7 +94,7 @@ public: */ template <typename T> HalResult<T> doWithRetry(const HalFunction<HalResult<T>>& halFn, const char* functionName) { return apply(halFn, HalResult<T>::unsupported(), functionName); return doWithRetry<T>(halFn, HalResult<T>::unsupported(), functionName); } private: Loading @@ -90,7 +112,8 @@ private: * function name is for logging purposes. */ template <typename T> T apply(const HalFunction<T>& halFn, T defaultValue, const char* functionName) { HalResult<T> doWithRetry(const HalFunction<HalResult<T>>& halFn, HalResult<T> defaultValue, const char* functionName) { if (!init()) { ALOGV("Skipped %s because Vibrator HAL is not available", functionName); return defaultValue; Loading @@ -101,16 +124,22 @@ private: hal = mConnectedHal; } for (int i = 0; i < MAX_RETRIES; i++) { T result = halFn(hal.get()); if (result.isFailedLogged(functionName)) { HalResult<T> result = doOnce(hal.get(), halFn, functionName); for (int i = 0; i < MAX_RETRIES && result.shouldRetry(); i++) { tryReconnect(); } else { return result; result = doOnce(hal.get(), halFn, functionName); } return result; } return halFn(hal.get()); template <typename T> HalResult<T> doOnce(HalWrapper* hal, const HalFunction<HalResult<T>>& halFn, const char* functionName) { HalResult<T> result = halFn(hal); if (result.isFailed()) { ALOGE("Vibrator HAL %s failed: %s", functionName, result.errorMessage()); } return result; } }; Loading
services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h +173 −95 File changed.Preview size limit exceeded, changes collapsed. Show changes