Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 39502ee9 authored by Lais Andrade's avatar Lais Andrade
Browse files

Use vibrator HAL controller for composed vibrations

This server calls always uses the HAL callback, so no extra change is
required on VibratorService to use the new api.

Bug: b/153418251
Test: manually vibrate with compose api and watch callback debug logs
Change-Id: Ia344342ee11192c1a20edc632d0087011c374081
parent e1ff28ff
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -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
+9 −3
Original line number Diff line number Diff line
@@ -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. */
+20 −14
Original line number Diff line number Diff line
@@ -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"),
+1 −26
Original line number Diff line number Diff line
@@ -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,
+2 −2
Original line number Diff line number Diff line
@@ -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);