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

Commit c1f0b55b authored by jiabin's avatar jiabin
Browse files

Pass vibrator information to audio server.

When initializing HapticGenerator, the resonant frequency and Q factor
of the vibrator engine are needed for BPF and BSF. Those values can be
got from vibrator manager service. As there is not a native interface,
those values are got by audio service when the system is ready and then
pass them to audio server.

Bug: 182612056
Test: manual, atest HapticGeneratorTest
Change-Id: I9d898ab3dee9222ae3f8a82cd030e6013f545cb0
parent 4c52d6b1
Loading
Loading
Loading
Loading
+50 −2
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <nativehelper/JNIHelp.h>
#include "core_jni_helpers.h"

#include <android/media/AudioVibratorInfo.h>
#include <audiomanager/AudioManager.h>
#include <media/AudioPolicy.h>
#include <media/AudioSystem.h>
@@ -176,7 +177,12 @@ static struct {
    jmethodID postRoutingUpdatedFromNative;
} gAudioPolicyEventHandlerMethods;

static struct { jmethodID add; } gListMethods;
jclass gListClass;
static struct {
    jmethodID add;
    jmethodID get;
    jmethodID size;
} gListMethods;

static jclass gAudioDescriptorClass;
static jmethodID gAudiODescriptorCstor;
@@ -195,6 +201,13 @@ jclass gClsAudioRecordRoutingProxy;
jclass gAudioProfileClass;
jmethodID gAudioProfileCstor;

jclass gVibratorClass;
static struct {
    jmethodID getId;
    jmethodID getResonantFrequency;
    jmethodID getQFactor;
} gVibratorMethods;

static Mutex gLock;

enum AudioError {
@@ -2627,6 +2640,29 @@ android_media_AudioSystem_getDevicesForAttributes(JNIEnv *env, jobject thiz,
    return jStatus;
}

static jint android_media_AudioSystem_setVibratorInfos(JNIEnv *env, jobject thiz,
                                                       jobject jVibrators) {
    if (!env->IsInstanceOf(jVibrators, gListClass)) {
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }
    const jint size = env->CallIntMethod(jVibrators, gListMethods.size);
    std::vector<media::AudioVibratorInfo> vibratorInfos;
    for (jint i = 0; i < size; ++i) {
        ScopedLocalRef<jobject> jVibrator(env,
                                          env->CallObjectMethod(jVibrators, gListMethods.get, i));
        if (!env->IsInstanceOf(jVibrator.get(), gVibratorClass)) {
            return (jint)AUDIO_JAVA_BAD_VALUE;
        }
        media::AudioVibratorInfo vibratorInfo;
        vibratorInfo.id = env->CallIntMethod(jVibrator.get(), gVibratorMethods.getId);
        vibratorInfo.resonantFrequency =
                env->CallFloatMethod(jVibrator.get(), gVibratorMethods.getResonantFrequency);
        vibratorInfo.qFactor = env->CallFloatMethod(jVibrator.get(), gVibratorMethods.getQFactor);
        vibratorInfos.push_back(vibratorInfo);
    }
    return (jint)check_AudioSystem_Command(AudioSystem::setVibratorInfos(vibratorInfos));
}

// ----------------------------------------------------------------------------

static const JNINativeMethod gMethods[] =
@@ -2757,7 +2793,9 @@ static const JNINativeMethod gMethods[] =
          (void *)android_media_AudioSystem_setUserIdDeviceAffinities},
         {"removeUserIdDeviceAffinities", "(I)I",
          (void *)android_media_AudioSystem_removeUserIdDeviceAffinities},
         {"setCurrentImeUid", "(I)I", (void *)android_media_AudioSystem_setCurrentImeUid}};
         {"setCurrentImeUid", "(I)I", (void *)android_media_AudioSystem_setCurrentImeUid},
         {"setVibratorInfos", "(Ljava/util/List;)I",
          (void *)android_media_AudioSystem_setVibratorInfos}};

static const JNINativeMethod gEventHandlerMethods[] = {
    {"native_setup",
@@ -2959,7 +2997,10 @@ int register_android_media_AudioSystem(JNIEnv *env)
            android::GetMethodIDOrDie(env, gClsAudioRecordRoutingProxy, "native_release", "()V");

    jclass listClass = FindClassOrDie(env, "java/util/List");
    gListClass = MakeGlobalRefOrDie(env, listClass);
    gListMethods.add = GetMethodIDOrDie(env, listClass, "add", "(Ljava/lang/Object;)Z");
    gListMethods.get = GetMethodIDOrDie(env, listClass, "get", "(I)Ljava/lang/Object;");
    gListMethods.size = GetMethodIDOrDie(env, listClass, "size", "()I");

    jclass audioProfileClass = FindClassOrDie(env, "android/media/AudioProfile");
    gAudioProfileClass = MakeGlobalRefOrDie(env, audioProfileClass);
@@ -2969,6 +3010,13 @@ int register_android_media_AudioSystem(JNIEnv *env)
    gAudioDescriptorClass = MakeGlobalRefOrDie(env, audioDescriptorClass);
    gAudiODescriptorCstor = GetMethodIDOrDie(env, audioDescriptorClass, "<init>", "(II[B)V");

    jclass vibratorClass = FindClassOrDie(env, "android/os/Vibrator");
    gVibratorClass = MakeGlobalRefOrDie(env, vibratorClass);
    gVibratorMethods.getId = GetMethodIDOrDie(env, vibratorClass, "getId", "()I");
    gVibratorMethods.getResonantFrequency =
            GetMethodIDOrDie(env, vibratorClass, "getResonantFrequency", "()F");
    gVibratorMethods.getQFactor = GetMethodIDOrDie(env, vibratorClass, "getQFactor", "()F");

    AudioSystem::addErrorCallback(android_media_AudioSystem_error_callback);

    RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
+9 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.content.pm.PackageManager;
import android.media.audiofx.AudioEffect;
import android.media.audiopolicy.AudioMix;
import android.os.Build;
import android.os.Vibrator;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.Pair;
@@ -1937,6 +1938,14 @@ public class AudioSystem
    public static native int getDevicesForRoleAndCapturePreset(
            int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devices);

    /**
     * @hide
     * Set the vibrators' information. The value will be used to initialize HapticGenerator.
     * @param vibrators a list of all available vibrators
     * @return command completion status
     */
    public static native int setVibratorInfos(@NonNull List<Vibrator> vibrators);

    // Items shared with audio service

    /**
+33 −0
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.os.VibratorManager;
import android.provider.Settings;
import android.provider.Settings.System;
import android.service.notification.ZenModeConfig;
@@ -1092,6 +1093,33 @@ public class AudioService extends IAudioService.Stub
        }
    }

    private void updateVibratorInfos() {
        VibratorManager vibratorManager = mContext.getSystemService(VibratorManager.class);
        if (vibratorManager == null) {
            Slog.e(TAG, "Vibrator manager is not found");
            return;
        }
        int[] vibratorIds = vibratorManager.getVibratorIds();
        if (vibratorIds.length == 0) {
            Slog.d(TAG, "No vibrator found");
            return;
        }
        List<Vibrator> vibrators = new ArrayList<>(vibratorIds.length);
        for (int id : vibratorIds) {
            Vibrator vibrator = vibratorManager.getVibrator(id);
            if (vibrator != null) {
                vibrators.add(vibrator);
            } else {
                Slog.w(TAG, "Vibrator(" + id + ") is not found");
            }
        }
        if (vibrators.isEmpty()) {
            Slog.w(TAG, "Cannot find any available vibrator");
            return;
        }
        AudioSystem.setVibratorInfos(vibrators);
    }

    public void onSystemReady() {
        mSystemReady = true;
        scheduleLoadSoundEffects();
@@ -1149,6 +1177,8 @@ public class AudioService extends IAudioService.Stub
        setMicMuteFromSwitchInput();

        initMinStreamVolumeWithoutModifyAudioSettings();

        updateVibratorInfos();
    }

    RoleObserver mRoleObserver;
@@ -1341,6 +1371,9 @@ public class AudioService extends IAudioService.Stub

        setMicrophoneMuteNoCallerCheck(getCurrentUserId()); // will also update the mic mute cache
        setMicMuteFromSwitchInput();

        // Restore vibrator info
        updateVibratorInfos();
    }

    private void onReinitVolumes(@NonNull String caller) {