Loading services/core/java/com/android/server/vibrator/HalNativeHandler.java +11 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.vibrator; import android.annotation.NonNull; import android.annotation.Nullable; import android.hardware.vibrator.IVibrationSession; import android.hardware.vibrator.IVibrator; import android.hardware.vibrator.IVibratorManager; /** Handles interactions with vibrator HAL services through native. */ Loading Loading @@ -48,4 +49,14 @@ interface HalNativeHandler { */ @Nullable IVibrationSession startSessionWithCallback(long sessionId, int[] vibratorIds); /** * Call {@link IVibrator#on} on single vibrator using vibration id for callbacks from HAL. * * <p>This should only be called if HAL has {@link IVibrator#CAP_ON_CALLBACK}. The HAL might * fail the request otherwise. * * @return true if successful, false otherwise. */ boolean vibrateWithCallback(int vibratorId, long vibrationId, long stepId, int durationMs); } services/core/java/com/android/server/vibrator/VibratorManagerService.java +11 −0 Original line number Diff line number Diff line Loading @@ -252,6 +252,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { private static native IBinder nativeStartSessionWithCallback(long nativePtr, long sessionId, int[] vibratorIds); /** Calls {@link IVibrator#on} with callback. */ private static native boolean nativeVibratorOnWithCallback(long nativePtr, int vibratorId, long vibrationId, long stepId, int durationMs); // TODO(b/409002423): remove native methods below once remove_hidl_support flag removed static native long nativeInit(HalVibratorManager.Callbacks callback); Loading Loading @@ -2371,6 +2375,13 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } return android.hardware.vibrator.IVibrationSession.Stub.asInterface(token); } @Override public boolean vibrateWithCallback(int vibratorId, long vibrationId, long stepId, int durationMs) { return nativeVibratorOnWithCallback(mNativePtr, vibratorId, vibrationId, stepId, durationMs); } } /** Keep records of vibrations played and provide debug information for this service. */ Loading services/core/java/com/android/server/vibrator/VintfHalVibrator.java +41 −4 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.annotation.Nullable; import android.hardware.vibrator.FrequencyAccelerationMapEntry; import android.hardware.vibrator.IVibrator; import android.os.Binder; import android.os.Handler; import android.os.IVibratorStateListener; import android.os.RemoteCallbackList; import android.os.RemoteException; Loading Loading @@ -56,20 +57,27 @@ class VintfHalVibrator { private final Object mLock = new Object(); private final int mVibratorId; private final VintfSupplier<IVibrator> mHalSupplier; private final Handler mHandler; private final HalNativeHandler mNativeHandler; @GuardedBy("mLock") private final RemoteCallbackList<IVibratorStateListener> mVibratorStateListeners = new RemoteCallbackList<>(); private Callbacks mCallbacks; // Vibrator state variables that are updated from synchronized blocks but can be read // anytime for a snippet of the current known vibrator state/info. private volatile VibratorInfo mVibratorInfo; private volatile State mCurrentState; private volatile float mCurrentAmplitude; DefaultHalVibrator(int vibratorId, VintfSupplier<IVibrator> supplier) { DefaultHalVibrator(int vibratorId, VintfSupplier<IVibrator> supplier, Handler handler, HalNativeHandler nativeHandler) { mVibratorId = vibratorId; mHalSupplier = supplier; mHandler = handler; mNativeHandler = nativeHandler; mVibratorInfo = new VibratorInfo.Builder(vibratorId).build(); mCurrentState = State.IDLE; mCurrentAmplitude = 0; Loading @@ -79,6 +87,7 @@ class VintfHalVibrator { public void init(@NonNull Callbacks callbacks) { Trace.traceBegin(TRACE_TAG_VIBRATOR, "DefaultHalVibrator#init"); try { mCallbacks = callbacks; int capabilities = getValue(IVibrator::getCapabilities, "Error loading capabilities during init").orElse(0); Loading Loading @@ -170,7 +179,9 @@ class VintfHalVibrator { boolean result = VintfUtils.runNoThrow(mHalSupplier, hal -> hal.setExternalControl(enabled), e -> logError("Error setting external control to " + enabled, e)); if (result) { updateStateAndNotifyListenersLocked(newState); } return result; } } finally { Loading Loading @@ -234,8 +245,30 @@ class VintfHalVibrator { public long on(long vibrationId, long stepId, long milliseconds) { Trace.traceBegin(TRACE_TAG_VIBRATOR, "DefaultHalVibrator#on"); try { // TODO(b/422944962): implement return 0; synchronized (mLock) { boolean result; if (mVibratorInfo.hasCapability(IVibrator.CAP_ON_CALLBACK)) { // Delegate vibrate with callback to native, to avoid creating a new // callback instance for each call, overloading the GC. result = mNativeHandler.vibrateWithCallback(mVibratorId, vibrationId, stepId, (int) milliseconds); } else { // Vibrate callback not supported, avoid unnecessary JNI round trip and // simulate HAL callback here using a Handler. result = VintfUtils.runNoThrow(mHalSupplier, hal -> hal.on((int) milliseconds, null), e -> logError("Error turning on for " + milliseconds + "ms", e)); if (result) { mHandler.postDelayed(newVibrationCallback(vibrationId, stepId), milliseconds); } } if (result) { updateStateAndNotifyListenersLocked(State.VIBRATING); } // IVibrator.on API should never be unsupported. return result ? milliseconds : -1; } } finally { Trace.traceEnd(TRACE_TAG_VIBRATOR); } Loading Loading @@ -366,6 +399,10 @@ class VintfHalVibrator { } } private Runnable newVibrationCallback(long vibrationId, long stepId) { return () -> mCallbacks.onVibrationStepComplete(mVibratorId, vibrationId, stepId); } private VibratorInfo loadVibratorInfo(int vibratorId) { VibratorInfo.Builder builder = new VibratorInfo.Builder(vibratorId); int capabilities = getValue(IVibrator::getCapabilities, "Error loading capabilities") Loading services/core/jni/com_android_server_vibrator_VibratorManagerService.cpp +126 −7 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ namespace android { using BnVibratorCallback = aidl::android::hardware::vibrator::BnVibratorCallback; using IVibrator = aidl::android::hardware::vibrator::IVibrator; using IVibratorManager = aidl::android::hardware::vibrator::IVibratorManager; using IVibrationSession = aidl::android::hardware::vibrator::IVibrationSession; using VibrationSessionConfig = aidl::android::hardware::vibrator::VibrationSessionConfig; Loading @@ -41,11 +43,68 @@ using VibrationSessionConfig = aidl::android::hardware::vibrator::VibrationSessi static JavaVM* sJvm = nullptr; static jmethodID sMethodIdOnSyncedVibrationComplete; static jmethodID sMethodIdOnVibrationSessionComplete; static jmethodID sMethodIdOnVibrationComplete; // TODO(b/409002423): remove this once remove_hidl_support flag removed static std::mutex gManagerMutex; static vibrator::ManagerHalController* gManager GUARDED_BY(gManagerMutex) = nullptr; // IVibratorCallback implementation for HalVibrator.Callbacks. class VibrationCallback : public BnVibratorCallback { public: VibrationCallback(jweak callback, jint vibratorId, jlong vibrationId, jlong stepId) : mCallbackRef(callback), mVibratorId(vibratorId), mVibrationId(vibrationId), mStepId(stepId) {} virtual ~VibrationCallback() = default; ndk::ScopedAStatus onComplete() override { auto env = GetOrAttachJNIEnvironment(sJvm); if (env->IsSameObject(mCallbackRef, NULL)) { ALOGE("Null reference to vibrator service callbacks"); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } env->CallVoidMethod(mCallbackRef, sMethodIdOnVibrationComplete, mVibratorId, mVibrationId, mStepId); return ndk::ScopedAStatus::ok(); } private: const jweak mCallbackRef; const jint mVibratorId; const jlong mVibrationId; const jlong mStepId; }; // Provides IVibrator instances loaded from IVibratorManager. class ManagedVibratorProvider : public HalProvider<IVibrator> { public: ManagedVibratorProvider(std::shared_ptr<HalProvider<IVibratorManager>> managerProvider, int32_t vibratorId) : mManagerProvider(std::move(managerProvider)), mVibratorId(vibratorId) {} virtual ~ManagedVibratorProvider() = default; private: std::shared_ptr<HalProvider<IVibratorManager>> mManagerProvider; const int32_t mVibratorId; std::shared_ptr<IVibrator> loadHal() override { auto managerHal = mManagerProvider->getHal(); if (managerHal == nullptr) { ALOGE("%s: Error loading manager HAL to get vibrator id=%d", __func__, mVibratorId); return nullptr; } std::shared_ptr<IVibrator> hal; auto status = managerHal->getVibrator(mVibratorId, &hal); if (!status.isOk() || hal == nullptr) { ALOGE("%s: Error on getVibrator(%d): %s", __func__, mVibratorId, status.getMessage()); return nullptr; } return hal; } }; class NativeVibratorManagerService { public: // TODO(b/409002423): remove this once remove_hidl_support flag removed Loading @@ -53,20 +112,23 @@ public: : mHal(std::make_unique<vibrator::ManagerHalController>()), mCallbackListener(env->NewGlobalRef(callbackListener)), mManagerCallbacks(nullptr), mVibratorCallbacks(nullptr), mManagerHalProvider(nullptr) { LOG_ALWAYS_FATAL_IF(mHal == nullptr, "Unable to find reference to vibrator manager hal"); LOG_ALWAYS_FATAL_IF(mCallbackListener == nullptr, "Unable to create global reference to vibration callback handler"); } NativeVibratorManagerService(JNIEnv* env, jobject managerCallbacks, jobject /* vibratorCallbacks */) NativeVibratorManagerService(JNIEnv* env, jobject managerCallbacks, jobject vibratorCallbacks) : mHal(nullptr), mCallbackListener(nullptr), mManagerCallbacks(env->NewWeakGlobalRef(managerCallbacks)), mVibratorCallbacks(env->NewWeakGlobalRef(vibratorCallbacks)), mManagerHalProvider(defaultProviderForDeclaredService<IVibratorManager>()) { LOG_ALWAYS_FATAL_IF(mManagerCallbacks == nullptr, "Unable to create global reference to vibrator manager callbacks"); LOG_ALWAYS_FATAL_IF(mVibratorCallbacks == nullptr, "Unable to create global reference to vibrator callbacks"); } ~NativeVibratorManagerService() { Loading @@ -77,16 +139,35 @@ public: if (mManagerCallbacks) { jniEnv->DeleteWeakGlobalRef(mManagerCallbacks); } if (mVibratorCallbacks) { jniEnv->DeleteWeakGlobalRef(mVibratorCallbacks); } } jweak managerCallbacks() { return mManagerCallbacks; } jweak vibratorCallbacks() { return mVibratorCallbacks; } std::shared_ptr<IVibratorManager> managerHal() { return mManagerHalProvider ? mManagerHalProvider->getHal() : nullptr; } std::shared_ptr<IVibrator> vibratorHal(int32_t vibratorId) { if (mVibratorHalProviders.find(vibratorId) == mVibratorHalProviders.end()) { mVibratorHalProviders[vibratorId] = mManagerHalProvider ? std::make_unique<ManagedVibratorProvider>(mManagerHalProvider, vibratorId) : defaultProviderForDeclaredService<IVibrator>(); } if (mVibratorHalProviders[vibratorId] == nullptr) { return nullptr; } return mVibratorHalProviders[vibratorId]->getHal(); } // TODO(b/409002423): remove functions below once remove_hidl_support flag removed vibrator::ManagerHalController* hal() const { return mHal.get(); } Loading Loading @@ -157,7 +238,9 @@ private: const jobject mCallbackListener; const jweak mManagerCallbacks; std::unique_ptr<HalProvider<IVibratorManager>> mManagerHalProvider; const jweak mVibratorCallbacks; std::shared_ptr<HalProvider<IVibratorManager>> mManagerHalProvider; std::unordered_map<int32_t, std::unique_ptr<HalProvider<IVibrator>>> mVibratorHalProviders; }; // TODO(b/409002423): remove this once remove_hidl_support flag removed Loading Loading @@ -186,6 +269,18 @@ static std::shared_ptr<IVibratorManager> loadManagerHal(NativeVibratorManagerSer return hal; } static std::shared_ptr<IVibrator> loadVibratorHal(NativeVibratorManagerService* service, int32_t vibratorId, const char* logLabel) { if (service == nullptr) { return nullptr; } auto hal = service->vibratorHal(vibratorId); if (hal == nullptr) { ALOGE("%s: vibrator HAL not available for vibrator id %d", logLabel, vibratorId); } return hal; } static void destroyNativeService(void* ptr) { ALOGD("%s", __func__); auto service = reinterpret_cast<NativeVibratorManagerService*>(ptr); Loading Loading @@ -264,6 +359,25 @@ static jobject nativeStartSessionWithCallback(JNIEnv* env, jclass /* clazz */, j return AIBinder_toJavaBinder(env, session->asBinder().get()); } static jboolean nativeVibratorOnWithCallback(JNIEnv* env, jclass /* clazz */, jlong ptr, jint vibratorId, jlong vibrationId, jlong stepId, jint durationMs) { ALOGD("%s", __func__); auto service = toNativeService(ptr, __func__); auto hal = loadVibratorHal(service, static_cast<int32_t>(vibratorId), __func__); if (service == nullptr || hal == nullptr) { return JNI_FALSE; } auto callback = ndk::SharedRefBase::make<VibrationCallback>(service->vibratorCallbacks(), vibratorId, vibrationId, stepId); auto status = hal->on(static_cast<int32_t>(durationMs), callback); if (!status.isOk()) { ALOGE("%s: %s", __func__, status.getMessage()); return JNI_FALSE; } return JNI_TRUE; } // TODO(b/409002423): remove functions below once remove_hidl_support flag removed static jlong nativeGetCapabilities(JNIEnv* env, jclass /* clazz */, jlong servicePtr) { Loading Loading @@ -391,16 +505,21 @@ static const JNINativeMethod method_table[] = { {"nativeTriggerSyncedWithCallback", "(JJ)Z", (void*)nativeTriggerSyncedWithCallback}, {"nativeStartSessionWithCallback", "(JJ[I)Landroid/os/IBinder;", (void*)nativeStartSessionWithCallback}, {"nativeVibratorOnWithCallback", "(JIJJI)Z", (void*)nativeVibratorOnWithCallback}, }; int register_android_server_vibrator_VibratorManagerService(JavaVM* jvm, JNIEnv* env) { sJvm = jvm; auto listenerClassName = "com/android/server/vibrator/HalVibratorManager$Callbacks"; jclass listenerClass = FindClassOrDie(env, listenerClassName); jclass managerCallbacksClass = FindClassOrDie(env, "com/android/server/vibrator/HalVibratorManager$Callbacks"); jclass vibratorCallbacksClass = FindClassOrDie(env, "com/android/server/vibrator/HalVibrator$Callbacks"); sMethodIdOnSyncedVibrationComplete = GetMethodIDOrDie(env, listenerClass, "onSyncedVibrationComplete", "(J)V"); GetMethodIDOrDie(env, managerCallbacksClass, "onSyncedVibrationComplete", "(J)V"); sMethodIdOnVibrationSessionComplete = GetMethodIDOrDie(env, listenerClass, "onVibrationSessionComplete", "(J)V"); GetMethodIDOrDie(env, managerCallbacksClass, "onVibrationSessionComplete", "(J)V"); sMethodIdOnVibrationComplete = GetMethodIDOrDie(env, vibratorCallbacksClass, "onVibrationStepComplete", "(IJJ)V"); return jniRegisterNativeMethods(env, "com/android/server/vibrator/VibratorManagerService", method_table, NELEM(method_table)); } Loading services/core/jni/com_android_server_vibrator_VibratorManagerService.h +25 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ #define _ANDROID_SERVER_VIBRATOR_MANAGER_SERVICE_H #include <aidl/android/hardware/vibrator/BnVibratorCallback.h> #include <aidl/android/hardware/vibrator/IVibrator.h> #include <aidl/android/hardware/vibrator/IVibratorManager.h> #include <android-base/thread_annotations.h> #include <android/binder_manager.h> #include <utils/Log.h> Loading @@ -34,7 +36,7 @@ namespace android { // TODO(b/409002423): remove this once remove_hidl_support flag removed extern vibrator::ManagerHalController* android_server_vibrator_VibratorManagerService_getManager(); // Base IVibratorCallback implementation using JNI to send callback ID to vibrator service. // IVibratorCallback implementation using JNI to send callback ID to vibrator service. class VibratorCallback : public aidl::android::hardware::vibrator::BnVibratorCallback { public: VibratorCallback(JavaVM* jvm, jweak callback, jmethodID methodId, jlong callbackId) Loading Loading @@ -83,8 +85,7 @@ public: if (mHal) { return mHal; } auto serviceName = std::string(I::descriptor) + "/default"; mHal = I::fromBinder(ndk::SpAIBinder(AServiceManager_checkService(serviceName.c_str()))); mHal = loadHal(); if (mHal == nullptr) { ALOGE("%s: Error connecting to HAL", __func__); return mHal; Loading Loading @@ -143,13 +144,33 @@ private: } mDeathRecipientCv.notify_all(); } virtual std::shared_ptr<I> loadHal() = 0; }; // Provides default service declared on the device, using link-to-death to reload dead objects. template <typename I> class DefaultProvider : public HalProvider<I> { public: DefaultProvider() = default; virtual ~DefaultProvider() = default; private: std::shared_ptr<I> loadHal() override { auto halName = std::string(I::descriptor) + "/default"; auto hal = I::fromBinder(ndk::SpAIBinder(AServiceManager_checkService(halName.c_str()))); if (hal == nullptr) { ALOGE("%s: Error connecting to %s", halName.c_str(), __func__); } return hal; } }; // Returns a new provider for the default HAL service declared on the device, null if not declared. template <typename I> std::unique_ptr<HalProvider<I>> defaultProviderForDeclaredService() { if (AServiceManager_isDeclared((std::string(I::descriptor) + "/default").c_str())) { return std::make_unique<HalProvider<I>>(); return std::make_unique<DefaultProvider<I>>(); } return nullptr; } Loading Loading
services/core/java/com/android/server/vibrator/HalNativeHandler.java +11 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.vibrator; import android.annotation.NonNull; import android.annotation.Nullable; import android.hardware.vibrator.IVibrationSession; import android.hardware.vibrator.IVibrator; import android.hardware.vibrator.IVibratorManager; /** Handles interactions with vibrator HAL services through native. */ Loading Loading @@ -48,4 +49,14 @@ interface HalNativeHandler { */ @Nullable IVibrationSession startSessionWithCallback(long sessionId, int[] vibratorIds); /** * Call {@link IVibrator#on} on single vibrator using vibration id for callbacks from HAL. * * <p>This should only be called if HAL has {@link IVibrator#CAP_ON_CALLBACK}. The HAL might * fail the request otherwise. * * @return true if successful, false otherwise. */ boolean vibrateWithCallback(int vibratorId, long vibrationId, long stepId, int durationMs); }
services/core/java/com/android/server/vibrator/VibratorManagerService.java +11 −0 Original line number Diff line number Diff line Loading @@ -252,6 +252,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { private static native IBinder nativeStartSessionWithCallback(long nativePtr, long sessionId, int[] vibratorIds); /** Calls {@link IVibrator#on} with callback. */ private static native boolean nativeVibratorOnWithCallback(long nativePtr, int vibratorId, long vibrationId, long stepId, int durationMs); // TODO(b/409002423): remove native methods below once remove_hidl_support flag removed static native long nativeInit(HalVibratorManager.Callbacks callback); Loading Loading @@ -2371,6 +2375,13 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } return android.hardware.vibrator.IVibrationSession.Stub.asInterface(token); } @Override public boolean vibrateWithCallback(int vibratorId, long vibrationId, long stepId, int durationMs) { return nativeVibratorOnWithCallback(mNativePtr, vibratorId, vibrationId, stepId, durationMs); } } /** Keep records of vibrations played and provide debug information for this service. */ Loading
services/core/java/com/android/server/vibrator/VintfHalVibrator.java +41 −4 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.annotation.Nullable; import android.hardware.vibrator.FrequencyAccelerationMapEntry; import android.hardware.vibrator.IVibrator; import android.os.Binder; import android.os.Handler; import android.os.IVibratorStateListener; import android.os.RemoteCallbackList; import android.os.RemoteException; Loading Loading @@ -56,20 +57,27 @@ class VintfHalVibrator { private final Object mLock = new Object(); private final int mVibratorId; private final VintfSupplier<IVibrator> mHalSupplier; private final Handler mHandler; private final HalNativeHandler mNativeHandler; @GuardedBy("mLock") private final RemoteCallbackList<IVibratorStateListener> mVibratorStateListeners = new RemoteCallbackList<>(); private Callbacks mCallbacks; // Vibrator state variables that are updated from synchronized blocks but can be read // anytime for a snippet of the current known vibrator state/info. private volatile VibratorInfo mVibratorInfo; private volatile State mCurrentState; private volatile float mCurrentAmplitude; DefaultHalVibrator(int vibratorId, VintfSupplier<IVibrator> supplier) { DefaultHalVibrator(int vibratorId, VintfSupplier<IVibrator> supplier, Handler handler, HalNativeHandler nativeHandler) { mVibratorId = vibratorId; mHalSupplier = supplier; mHandler = handler; mNativeHandler = nativeHandler; mVibratorInfo = new VibratorInfo.Builder(vibratorId).build(); mCurrentState = State.IDLE; mCurrentAmplitude = 0; Loading @@ -79,6 +87,7 @@ class VintfHalVibrator { public void init(@NonNull Callbacks callbacks) { Trace.traceBegin(TRACE_TAG_VIBRATOR, "DefaultHalVibrator#init"); try { mCallbacks = callbacks; int capabilities = getValue(IVibrator::getCapabilities, "Error loading capabilities during init").orElse(0); Loading Loading @@ -170,7 +179,9 @@ class VintfHalVibrator { boolean result = VintfUtils.runNoThrow(mHalSupplier, hal -> hal.setExternalControl(enabled), e -> logError("Error setting external control to " + enabled, e)); if (result) { updateStateAndNotifyListenersLocked(newState); } return result; } } finally { Loading Loading @@ -234,8 +245,30 @@ class VintfHalVibrator { public long on(long vibrationId, long stepId, long milliseconds) { Trace.traceBegin(TRACE_TAG_VIBRATOR, "DefaultHalVibrator#on"); try { // TODO(b/422944962): implement return 0; synchronized (mLock) { boolean result; if (mVibratorInfo.hasCapability(IVibrator.CAP_ON_CALLBACK)) { // Delegate vibrate with callback to native, to avoid creating a new // callback instance for each call, overloading the GC. result = mNativeHandler.vibrateWithCallback(mVibratorId, vibrationId, stepId, (int) milliseconds); } else { // Vibrate callback not supported, avoid unnecessary JNI round trip and // simulate HAL callback here using a Handler. result = VintfUtils.runNoThrow(mHalSupplier, hal -> hal.on((int) milliseconds, null), e -> logError("Error turning on for " + milliseconds + "ms", e)); if (result) { mHandler.postDelayed(newVibrationCallback(vibrationId, stepId), milliseconds); } } if (result) { updateStateAndNotifyListenersLocked(State.VIBRATING); } // IVibrator.on API should never be unsupported. return result ? milliseconds : -1; } } finally { Trace.traceEnd(TRACE_TAG_VIBRATOR); } Loading Loading @@ -366,6 +399,10 @@ class VintfHalVibrator { } } private Runnable newVibrationCallback(long vibrationId, long stepId) { return () -> mCallbacks.onVibrationStepComplete(mVibratorId, vibrationId, stepId); } private VibratorInfo loadVibratorInfo(int vibratorId) { VibratorInfo.Builder builder = new VibratorInfo.Builder(vibratorId); int capabilities = getValue(IVibrator::getCapabilities, "Error loading capabilities") Loading
services/core/jni/com_android_server_vibrator_VibratorManagerService.cpp +126 −7 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ namespace android { using BnVibratorCallback = aidl::android::hardware::vibrator::BnVibratorCallback; using IVibrator = aidl::android::hardware::vibrator::IVibrator; using IVibratorManager = aidl::android::hardware::vibrator::IVibratorManager; using IVibrationSession = aidl::android::hardware::vibrator::IVibrationSession; using VibrationSessionConfig = aidl::android::hardware::vibrator::VibrationSessionConfig; Loading @@ -41,11 +43,68 @@ using VibrationSessionConfig = aidl::android::hardware::vibrator::VibrationSessi static JavaVM* sJvm = nullptr; static jmethodID sMethodIdOnSyncedVibrationComplete; static jmethodID sMethodIdOnVibrationSessionComplete; static jmethodID sMethodIdOnVibrationComplete; // TODO(b/409002423): remove this once remove_hidl_support flag removed static std::mutex gManagerMutex; static vibrator::ManagerHalController* gManager GUARDED_BY(gManagerMutex) = nullptr; // IVibratorCallback implementation for HalVibrator.Callbacks. class VibrationCallback : public BnVibratorCallback { public: VibrationCallback(jweak callback, jint vibratorId, jlong vibrationId, jlong stepId) : mCallbackRef(callback), mVibratorId(vibratorId), mVibrationId(vibrationId), mStepId(stepId) {} virtual ~VibrationCallback() = default; ndk::ScopedAStatus onComplete() override { auto env = GetOrAttachJNIEnvironment(sJvm); if (env->IsSameObject(mCallbackRef, NULL)) { ALOGE("Null reference to vibrator service callbacks"); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } env->CallVoidMethod(mCallbackRef, sMethodIdOnVibrationComplete, mVibratorId, mVibrationId, mStepId); return ndk::ScopedAStatus::ok(); } private: const jweak mCallbackRef; const jint mVibratorId; const jlong mVibrationId; const jlong mStepId; }; // Provides IVibrator instances loaded from IVibratorManager. class ManagedVibratorProvider : public HalProvider<IVibrator> { public: ManagedVibratorProvider(std::shared_ptr<HalProvider<IVibratorManager>> managerProvider, int32_t vibratorId) : mManagerProvider(std::move(managerProvider)), mVibratorId(vibratorId) {} virtual ~ManagedVibratorProvider() = default; private: std::shared_ptr<HalProvider<IVibratorManager>> mManagerProvider; const int32_t mVibratorId; std::shared_ptr<IVibrator> loadHal() override { auto managerHal = mManagerProvider->getHal(); if (managerHal == nullptr) { ALOGE("%s: Error loading manager HAL to get vibrator id=%d", __func__, mVibratorId); return nullptr; } std::shared_ptr<IVibrator> hal; auto status = managerHal->getVibrator(mVibratorId, &hal); if (!status.isOk() || hal == nullptr) { ALOGE("%s: Error on getVibrator(%d): %s", __func__, mVibratorId, status.getMessage()); return nullptr; } return hal; } }; class NativeVibratorManagerService { public: // TODO(b/409002423): remove this once remove_hidl_support flag removed Loading @@ -53,20 +112,23 @@ public: : mHal(std::make_unique<vibrator::ManagerHalController>()), mCallbackListener(env->NewGlobalRef(callbackListener)), mManagerCallbacks(nullptr), mVibratorCallbacks(nullptr), mManagerHalProvider(nullptr) { LOG_ALWAYS_FATAL_IF(mHal == nullptr, "Unable to find reference to vibrator manager hal"); LOG_ALWAYS_FATAL_IF(mCallbackListener == nullptr, "Unable to create global reference to vibration callback handler"); } NativeVibratorManagerService(JNIEnv* env, jobject managerCallbacks, jobject /* vibratorCallbacks */) NativeVibratorManagerService(JNIEnv* env, jobject managerCallbacks, jobject vibratorCallbacks) : mHal(nullptr), mCallbackListener(nullptr), mManagerCallbacks(env->NewWeakGlobalRef(managerCallbacks)), mVibratorCallbacks(env->NewWeakGlobalRef(vibratorCallbacks)), mManagerHalProvider(defaultProviderForDeclaredService<IVibratorManager>()) { LOG_ALWAYS_FATAL_IF(mManagerCallbacks == nullptr, "Unable to create global reference to vibrator manager callbacks"); LOG_ALWAYS_FATAL_IF(mVibratorCallbacks == nullptr, "Unable to create global reference to vibrator callbacks"); } ~NativeVibratorManagerService() { Loading @@ -77,16 +139,35 @@ public: if (mManagerCallbacks) { jniEnv->DeleteWeakGlobalRef(mManagerCallbacks); } if (mVibratorCallbacks) { jniEnv->DeleteWeakGlobalRef(mVibratorCallbacks); } } jweak managerCallbacks() { return mManagerCallbacks; } jweak vibratorCallbacks() { return mVibratorCallbacks; } std::shared_ptr<IVibratorManager> managerHal() { return mManagerHalProvider ? mManagerHalProvider->getHal() : nullptr; } std::shared_ptr<IVibrator> vibratorHal(int32_t vibratorId) { if (mVibratorHalProviders.find(vibratorId) == mVibratorHalProviders.end()) { mVibratorHalProviders[vibratorId] = mManagerHalProvider ? std::make_unique<ManagedVibratorProvider>(mManagerHalProvider, vibratorId) : defaultProviderForDeclaredService<IVibrator>(); } if (mVibratorHalProviders[vibratorId] == nullptr) { return nullptr; } return mVibratorHalProviders[vibratorId]->getHal(); } // TODO(b/409002423): remove functions below once remove_hidl_support flag removed vibrator::ManagerHalController* hal() const { return mHal.get(); } Loading Loading @@ -157,7 +238,9 @@ private: const jobject mCallbackListener; const jweak mManagerCallbacks; std::unique_ptr<HalProvider<IVibratorManager>> mManagerHalProvider; const jweak mVibratorCallbacks; std::shared_ptr<HalProvider<IVibratorManager>> mManagerHalProvider; std::unordered_map<int32_t, std::unique_ptr<HalProvider<IVibrator>>> mVibratorHalProviders; }; // TODO(b/409002423): remove this once remove_hidl_support flag removed Loading Loading @@ -186,6 +269,18 @@ static std::shared_ptr<IVibratorManager> loadManagerHal(NativeVibratorManagerSer return hal; } static std::shared_ptr<IVibrator> loadVibratorHal(NativeVibratorManagerService* service, int32_t vibratorId, const char* logLabel) { if (service == nullptr) { return nullptr; } auto hal = service->vibratorHal(vibratorId); if (hal == nullptr) { ALOGE("%s: vibrator HAL not available for vibrator id %d", logLabel, vibratorId); } return hal; } static void destroyNativeService(void* ptr) { ALOGD("%s", __func__); auto service = reinterpret_cast<NativeVibratorManagerService*>(ptr); Loading Loading @@ -264,6 +359,25 @@ static jobject nativeStartSessionWithCallback(JNIEnv* env, jclass /* clazz */, j return AIBinder_toJavaBinder(env, session->asBinder().get()); } static jboolean nativeVibratorOnWithCallback(JNIEnv* env, jclass /* clazz */, jlong ptr, jint vibratorId, jlong vibrationId, jlong stepId, jint durationMs) { ALOGD("%s", __func__); auto service = toNativeService(ptr, __func__); auto hal = loadVibratorHal(service, static_cast<int32_t>(vibratorId), __func__); if (service == nullptr || hal == nullptr) { return JNI_FALSE; } auto callback = ndk::SharedRefBase::make<VibrationCallback>(service->vibratorCallbacks(), vibratorId, vibrationId, stepId); auto status = hal->on(static_cast<int32_t>(durationMs), callback); if (!status.isOk()) { ALOGE("%s: %s", __func__, status.getMessage()); return JNI_FALSE; } return JNI_TRUE; } // TODO(b/409002423): remove functions below once remove_hidl_support flag removed static jlong nativeGetCapabilities(JNIEnv* env, jclass /* clazz */, jlong servicePtr) { Loading Loading @@ -391,16 +505,21 @@ static const JNINativeMethod method_table[] = { {"nativeTriggerSyncedWithCallback", "(JJ)Z", (void*)nativeTriggerSyncedWithCallback}, {"nativeStartSessionWithCallback", "(JJ[I)Landroid/os/IBinder;", (void*)nativeStartSessionWithCallback}, {"nativeVibratorOnWithCallback", "(JIJJI)Z", (void*)nativeVibratorOnWithCallback}, }; int register_android_server_vibrator_VibratorManagerService(JavaVM* jvm, JNIEnv* env) { sJvm = jvm; auto listenerClassName = "com/android/server/vibrator/HalVibratorManager$Callbacks"; jclass listenerClass = FindClassOrDie(env, listenerClassName); jclass managerCallbacksClass = FindClassOrDie(env, "com/android/server/vibrator/HalVibratorManager$Callbacks"); jclass vibratorCallbacksClass = FindClassOrDie(env, "com/android/server/vibrator/HalVibrator$Callbacks"); sMethodIdOnSyncedVibrationComplete = GetMethodIDOrDie(env, listenerClass, "onSyncedVibrationComplete", "(J)V"); GetMethodIDOrDie(env, managerCallbacksClass, "onSyncedVibrationComplete", "(J)V"); sMethodIdOnVibrationSessionComplete = GetMethodIDOrDie(env, listenerClass, "onVibrationSessionComplete", "(J)V"); GetMethodIDOrDie(env, managerCallbacksClass, "onVibrationSessionComplete", "(J)V"); sMethodIdOnVibrationComplete = GetMethodIDOrDie(env, vibratorCallbacksClass, "onVibrationStepComplete", "(IJJ)V"); return jniRegisterNativeMethods(env, "com/android/server/vibrator/VibratorManagerService", method_table, NELEM(method_table)); } Loading
services/core/jni/com_android_server_vibrator_VibratorManagerService.h +25 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ #define _ANDROID_SERVER_VIBRATOR_MANAGER_SERVICE_H #include <aidl/android/hardware/vibrator/BnVibratorCallback.h> #include <aidl/android/hardware/vibrator/IVibrator.h> #include <aidl/android/hardware/vibrator/IVibratorManager.h> #include <android-base/thread_annotations.h> #include <android/binder_manager.h> #include <utils/Log.h> Loading @@ -34,7 +36,7 @@ namespace android { // TODO(b/409002423): remove this once remove_hidl_support flag removed extern vibrator::ManagerHalController* android_server_vibrator_VibratorManagerService_getManager(); // Base IVibratorCallback implementation using JNI to send callback ID to vibrator service. // IVibratorCallback implementation using JNI to send callback ID to vibrator service. class VibratorCallback : public aidl::android::hardware::vibrator::BnVibratorCallback { public: VibratorCallback(JavaVM* jvm, jweak callback, jmethodID methodId, jlong callbackId) Loading Loading @@ -83,8 +85,7 @@ public: if (mHal) { return mHal; } auto serviceName = std::string(I::descriptor) + "/default"; mHal = I::fromBinder(ndk::SpAIBinder(AServiceManager_checkService(serviceName.c_str()))); mHal = loadHal(); if (mHal == nullptr) { ALOGE("%s: Error connecting to HAL", __func__); return mHal; Loading Loading @@ -143,13 +144,33 @@ private: } mDeathRecipientCv.notify_all(); } virtual std::shared_ptr<I> loadHal() = 0; }; // Provides default service declared on the device, using link-to-death to reload dead objects. template <typename I> class DefaultProvider : public HalProvider<I> { public: DefaultProvider() = default; virtual ~DefaultProvider() = default; private: std::shared_ptr<I> loadHal() override { auto halName = std::string(I::descriptor) + "/default"; auto hal = I::fromBinder(ndk::SpAIBinder(AServiceManager_checkService(halName.c_str()))); if (hal == nullptr) { ALOGE("%s: Error connecting to %s", halName.c_str(), __func__); } return hal; } }; // Returns a new provider for the default HAL service declared on the device, null if not declared. template <typename I> std::unique_ptr<HalProvider<I>> defaultProviderForDeclaredService() { if (AServiceManager_isDeclared((std::string(I::descriptor) + "/default").c_str())) { return std::make_unique<HalProvider<I>>(); return std::make_unique<DefaultProvider<I>>(); } return nullptr; } Loading