diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 6f9a3815a302f..f0a7a3620c5bc 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -26,6 +26,7 @@ #include #include "core_jni_helpers.h" +#include #include #include #include @@ -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 vibratorInfos; + for (jint i = 0; i < size; ++i) { + ScopedLocalRef 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, "", "(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)); diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 8134d6f8352db..7220379e836bb 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -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 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 vibrators); + // Items shared with audio service /** diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index cdeaca26375bb..2de2fdf1f188a 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -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 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) {