Merge "Use vibrator HAL controller for composed vibrations"

This commit is contained in:
TreeHugger Robot
2020-08-07 16:55:21 +00:00
committed by Android (Google) Code Review
5 changed files with 57 additions and 45 deletions

View File

@@ -104,6 +104,31 @@ static inline std::string getStringField(JNIEnv* env, jobject obj, jfieldID fiel
return std::string(defaultValue);
}
static inline JNIEnv* GetJNIEnvironment(JavaVM* vm, jint version = JNI_VERSION_1_4) {
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), version) != JNI_OK) {
return nullptr;
}
return env;
}
static inline JNIEnv* GetOrAttachJNIEnvironment(JavaVM* jvm, jint version = JNI_VERSION_1_4) {
JNIEnv* env = GetJNIEnvironment(jvm, version);
if (!env) {
int result = jvm->AttachCurrentThread(&env, nullptr);
LOG_ALWAYS_FATAL_IF(result != JNI_OK, "JVM thread attach failed.");
struct VmDetacher {
VmDetacher(JavaVM* vm) : mVm(vm) {}
~VmDetacher() { mVm->DetachCurrentThread(); }
private:
JavaVM* const mVm;
};
static thread_local VmDetacher detacher(jvm);
}
return env;
}
} // namespace android
#endif // CORE_JNI_HELPERS

View File

@@ -183,7 +183,7 @@ public class VibratorService extends IVibratorService.Stub
static native int[] vibratorGetSupportedEffects(long controllerPtr);
static native long vibratorPerformEffect(long effect, long strength, Vibration vibration,
boolean withCallback);
static native void vibratorPerformComposedEffect(
static native void vibratorPerformComposedEffect(long controllerPtr,
VibrationEffect.Composition.PrimitiveEffect[] effect, Vibration vibration);
static native void vibratorSetExternalControl(long controllerPtr, boolean enabled);
static native long vibratorGetCapabilities(long controllerPtr);
@@ -251,6 +251,9 @@ public class VibratorService extends IVibratorService.Stub
public void binderDied() {
synchronized (mLock) {
if (this == mCurrentVibration) {
if (DEBUG) {
Slog.d(TAG, "Vibration finished because binder died, cleaning up");
}
doCancelVibrateLocked();
}
}
@@ -261,6 +264,9 @@ public class VibratorService extends IVibratorService.Stub
public void onComplete() {
synchronized (mLock) {
if (this == mCurrentVibration) {
if (DEBUG) {
Slog.d(TAG, "Vibration finished by callback, cleaning up");
}
doCancelVibrateLocked();
}
}
@@ -915,7 +921,7 @@ public class VibratorService extends IVibratorService.Stub
// Callback for whenever the current vibration has finished played out
public void onVibrationFinished() {
if (DEBUG) {
Slog.e(TAG, "Vibration finished, cleaning up");
Slog.d(TAG, "Vibration finished, cleaning up");
}
synchronized (mLock) {
// Make sure the vibration is really done. This also reports that the vibration is
@@ -1766,7 +1772,7 @@ public class VibratorService extends IVibratorService.Stub
/** Turns vibrator on to perform one of the supported composed effects. */
public void vibratorPerformComposedEffect(
VibrationEffect.Composition.PrimitiveEffect[] effect, Vibration vibration) {
VibratorService.vibratorPerformComposedEffect(effect, vibration);
VibratorService.vibratorPerformComposedEffect(mNativeControllerPtr, effect, vibration);
}
/** Enabled the device vibrator to be controlled by another service. */

View File

@@ -49,6 +49,8 @@ namespace aidl = android::hardware::vibrator;
namespace android {
static JavaVM* sJvm = nullptr;
static jmethodID sMethodIdOnComplete;
static struct {
@@ -228,6 +230,12 @@ bool isValidEffect(jlong effect) {
return val >= *iter.begin() && val <= *std::prev(iter.end());
}
static void callVibrationOnComplete(jobject vibration) {
auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
jniEnv->CallVoidMethod(vibration, sMethodIdOnComplete);
jniEnv->DeleteGlobalRef(vibration);
}
static aidl::CompositeEffect effectFromJavaPrimitive(JNIEnv* env, jobject primitive) {
aidl::CompositeEffect effect;
effect.primitive = static_cast<aidl::CompositePrimitive>(
@@ -399,10 +407,11 @@ static jlong vibratorPerformEffect(JNIEnv* env, jclass /* clazz */, jlong effect
return -1;
}
static void vibratorPerformComposedEffect(JNIEnv* env, jclass /* clazz */, jobjectArray composition,
jobject vibration) {
auto hal = getHal<aidl::IVibrator>();
if (!hal) {
static void vibratorPerformComposedEffect(JNIEnv* env, jclass /* clazz */, jlong controllerPtr,
jobjectArray composition, jobject vibration) {
vibrator::HalController* controller = reinterpret_cast<vibrator::HalController*>(controllerPtr);
if (controller == nullptr) {
ALOGE("vibratorPerformComposedEffect failed because controller was not initialized");
return;
}
size_t size = env->GetArrayLength(composition);
@@ -411,14 +420,10 @@ static void vibratorPerformComposedEffect(JNIEnv* env, jclass /* clazz */, jobje
jobject element = env->GetObjectArrayElement(composition, i);
effects.push_back(effectFromJavaPrimitive(env, element));
}
sp<AidlVibratorCallback> effectCallback = new AidlVibratorCallback(env, vibration);
auto status = hal->call(&aidl::IVibrator::compose, effects, effectCallback);
if (!status.isOk()) {
if (status.exceptionCode() != binder::Status::EX_UNSUPPORTED_OPERATION) {
ALOGE("Failed to play haptic effect composition");
}
}
auto callback = [vibrationRef(MakeGlobalRefOrDie(env, vibration))]() {
callVibrationOnComplete(vibrationRef);
};
controller->performComposedEffect(effects, callback);
}
static jlong vibratorGetCapabilities(JNIEnv* env, jclass /* clazz */, jlong controllerPtr) {
@@ -462,7 +467,7 @@ static const JNINativeMethod method_table[] = {
{"vibratorPerformEffect", "(JJLcom/android/server/VibratorService$Vibration;Z)J",
(void*)vibratorPerformEffect},
{"vibratorPerformComposedEffect",
"([Landroid/os/VibrationEffect$Composition$PrimitiveEffect;Lcom/android/server/"
"(J[Landroid/os/VibrationEffect$Composition$PrimitiveEffect;Lcom/android/server/"
"VibratorService$Vibration;)V",
(void*)vibratorPerformComposedEffect},
{"vibratorGetSupportedEffects", "(J)[I", (void*)vibratorGetSupportedEffects},
@@ -472,7 +477,8 @@ static const JNINativeMethod method_table[] = {
{"vibratorAlwaysOnDisable", "(JJ)V", (void*)vibratorAlwaysOnDisable},
};
int register_android_server_VibratorService(JNIEnv *env) {
int register_android_server_VibratorService(JavaVM* vm, JNIEnv* env) {
sJvm = vm;
sMethodIdOnComplete =
GetMethodIDOrDie(env,
FindClassOrDie(env, "com/android/server/VibratorService$Vibration"),

View File

@@ -314,31 +314,6 @@ static inline InputDescs openInputs(JNIEnv* env, const JniIds& jni, jobject shel
return result;
}
static inline JNIEnv* GetJNIEnvironment(JavaVM* vm) {
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return 0;
}
return env;
}
static inline JNIEnv* GetOrAttachJNIEnvironment(JavaVM* jvm) {
JNIEnv* env = GetJNIEnvironment(jvm);
if (!env) {
int result = jvm->AttachCurrentThread(&env, nullptr);
CHECK_EQ(result, JNI_OK) << "thread attach failed";
struct VmDetacher {
VmDetacher(JavaVM* vm) : mVm(vm) {}
~VmDetacher() { mVm->DetachCurrentThread(); }
private:
JavaVM* const mVm;
};
static thread_local VmDetacher detacher(jvm);
}
return env;
}
class PMSCDataLoader;
struct OnTraceChanged {
@@ -415,7 +390,7 @@ private:
bool onPrepareImage(dataloader::DataLoaderInstallationFiles addedFiles) final {
ALOGE("onPrepareImage: start.");
JNIEnv* env = GetOrAttachJNIEnvironment(mJvm);
JNIEnv* env = GetOrAttachJNIEnvironment(mJvm, JNI_VERSION_1_6);
const auto& jni = jniIds(env);
jobject shellCommand = env->CallStaticObjectMethod(jni.packageManagerShellCommandDataLoader,

View File

@@ -37,7 +37,7 @@ int register_android_server_UsbDeviceManager(JNIEnv* env);
int register_android_server_UsbMidiDevice(JNIEnv* env);
int register_android_server_UsbHostManager(JNIEnv* env);
int register_android_server_vr_VrManagerService(JNIEnv* env);
int register_android_server_VibratorService(JNIEnv* env);
int register_android_server_VibratorService(JavaVM* vm, JNIEnv* env);
int register_android_server_location_GnssLocationProvider(JNIEnv* env);
int register_android_server_connectivity_Vpn(JNIEnv* env);
int register_android_server_TestNetworkService(JNIEnv* env);
@@ -90,7 +90,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_server_UsbAlsaJackDetector(env);
register_android_server_UsbHostManager(env);
register_android_server_vr_VrManagerService(env);
register_android_server_VibratorService(env);
register_android_server_VibratorService(vm, env);
register_android_server_SystemServer(env);
register_android_server_location_GnssLocationProvider(env);
register_android_server_connectivity_Vpn(env);