diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index a0e1bcafedb7b..28ac464bdf72e 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -2962,13 +2962,18 @@ static jboolean android_media_AudioSystem_canBeSpatialized(JNIEnv *env, jobject return canBeSpatialized; } -static jint android_media_AudioSystem_registerSoundDoseCallback(JNIEnv *env, jobject thiz, - jobject jISoundDoseCallback) { +static jobject android_media_AudioSystem_nativeGetSoundDose(JNIEnv *env, jobject thiz, + jobject jISoundDoseCallback) { sp nISoundDoseCallback = interface_cast( ibinderForJavaObject(env, jISoundDoseCallback)); - return static_cast( - check_AudioSystem_Command(AudioSystem::registerSoundDoseCallback(nISoundDoseCallback))); + sp nSoundDose; + status_t status = AudioSystem::getSoundDoseInterface(nISoundDoseCallback, &nSoundDose); + + if (status != NO_ERROR) { + return nullptr; + } + return javaObjectForIBinder(env, IInterface::asBinder(nSoundDose)); } // keep these values in sync with AudioSystem.java @@ -3343,8 +3348,8 @@ static const JNINativeMethod gMethods[] = "(Landroid/media/AudioAttributes;Landroid/media/AudioFormat;" "[Landroid/media/AudioDeviceAttributes;)Z", (void *)android_media_AudioSystem_canBeSpatialized}, - {"registerSoundDoseCallback", "(Landroid/media/ISoundDoseCallback;)I", - (void *)android_media_AudioSystem_registerSoundDoseCallback}, + {"nativeGetSoundDose", "(Landroid/media/ISoundDoseCallback;)Landroid/os/IBinder;", + (void *)android_media_AudioSystem_nativeGetSoundDose}, {"getDirectPlaybackSupport", "(Landroid/media/AudioFormat;Landroid/media/AudioAttributes;)I", (void *)android_media_AudioSystem_getDirectPlaybackSupport}, diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 607225ea18224..3e0d657588e5c 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -2260,11 +2260,17 @@ public class AudioSystem /** * @hide - * Register the sound dose callback with the audio server. + * Register the sound dose callback with the audio server and returns the binder to the + * ISoundDose interface. * - * @return {@link #SUCCESS} if the callback was registered successfully. + * @return ISoundDose interface with registered callback. */ - public static native int registerSoundDoseCallback(ISoundDoseCallback callback); + @Nullable + public static ISoundDose getSoundDoseInterface(ISoundDoseCallback callback) { + return ISoundDose.Stub.asInterface(nativeGetSoundDose(callback)); + } + + private static native IBinder nativeGetSoundDose(ISoundDoseCallback callback); /** * @hide diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 66770cb66b23d..6fbd7b6a5f9d8 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -1702,6 +1702,7 @@ public class AudioService extends IAudioService.Stub } mSpatializerHelper.reset(/* featureEnabled */ mHasSpatializerEffect); + mSoundDoseHelper.reset(); onIndicateSystemReady(); // indicate the end of reconfiguration phase to audio HAL diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java index db406a642c0c2..1d25e31ab8e2c 100644 --- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java +++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java @@ -22,6 +22,7 @@ import android.media.AudioAttributes; import android.media.AudioDeviceAttributes; import android.media.AudioMixerAttributes; import android.media.AudioSystem; +import android.media.ISoundDose; import android.media.ISoundDoseCallback; import android.media.audiopolicy.AudioMix; import android.os.SystemClock; @@ -497,12 +498,12 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback, } /** - * Same as {@link AudioSystem#registerSoundDoseCallback(ISoundDoseCallback)} + * Same as {@link AudioSystem#getSoundDoseInterface(ISoundDoseCallback)} * @param callback * @return */ - public int registerSoundDoseCallback(ISoundDoseCallback callback) { - return AudioSystem.registerSoundDoseCallback(callback); + public ISoundDose getSoundDoseInterface(ISoundDoseCallback callback) { + return AudioSystem.getSoundDoseInterface(callback); } /** diff --git a/services/core/java/com/android/server/audio/SoundDoseHelper.java b/services/core/java/com/android/server/audio/SoundDoseHelper.java index ff6a7f103ce92..0d0de8ad28862 100644 --- a/services/core/java/com/android/server/audio/SoundDoseHelper.java +++ b/services/core/java/com/android/server/audio/SoundDoseHelper.java @@ -27,10 +27,12 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.media.AudioSystem; +import android.media.ISoundDose; import android.media.ISoundDoseCallback; import android.media.SoundDoseRecord; import android.os.Binder; import android.os.Message; +import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; @@ -43,8 +45,10 @@ import com.android.server.audio.AudioService.AudioHandler; import com.android.server.audio.AudioService.ISafeHearingVolumeController; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; /** @@ -88,6 +92,8 @@ public class SoundDoseHelper { private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval private static final int REQUEST_CODE_CHECK_MUSIC_ACTIVE = 1; + private static final float CUSTOM_RS2_VALUE = 90; + private int mMcc = 0; final Object mSafeMediaVolumeStateLock = new Object(); @@ -131,6 +137,10 @@ public class SoundDoseHelper { @NonNull private final AudioHandler mAudioHandler; @NonNull private final ISafeHearingVolumeController mVolumeController; + private ISoundDose mSoundDose; + private float mCurrentCsd = 0.f; + private final List mDoseRecords = new ArrayList<>(); + private final Context mContext; private final ISoundDoseCallback.Stub mSoundDoseCallback = new ISoundDoseCallback.Stub() { @@ -141,6 +151,8 @@ public class SoundDoseHelper { public void onNewCsdValue(float currentCsd, SoundDoseRecord[] records) { Log.i(TAG, "onNewCsdValue: " + currentCsd); + mCurrentCsd = currentCsd; + mDoseRecords.addAll(Arrays.asList(records)); for (SoundDoseRecord record : records) { Log.i(TAG, " new record: csd=" + record.value + " averageMel=" + record.averageMel + " timestamp=" + record.timestamp @@ -162,10 +174,6 @@ public class SoundDoseHelper { mSafeMediaVolumeState = mSettings.getGlobalInt(audioService.getContentResolver(), Settings.Global.AUDIO_SAFE_VOLUME_STATE, 0); - if (USE_CSD_FOR_SAFE_HEARING) { - AudioSystem.registerSoundDoseCallback(mSoundDoseCallback); - mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED; - } // The default safe volume index read here will be replaced by the actual value when // the mcc is read by onConfigureSafeVolume() @@ -174,6 +182,8 @@ public class SoundDoseHelper { mAlarmManager = (AlarmManager) mContext.getSystemService( Context.ALARM_SERVICE); + + initCsd(); } /*package*/ int safeMediaVolumeIndex(int device) { @@ -392,6 +402,35 @@ public class SoundDoseHelper { pw.print(" mPendingVolumeCommand="); pw.println(mPendingVolumeCommand); } + /*package*/void reset() { + Log.d(TAG, "Reset the sound dose helper"); + initCsd(); + } + + private void initCsd() { + synchronized (mSafeMediaVolumeStateLock) { + if (USE_CSD_FOR_SAFE_HEARING) { + Log.v(TAG, "Initializing sound dose"); + + mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED; + mSoundDose = AudioSystem.getSoundDoseInterface(mSoundDoseCallback); + try { + if (mSoundDose != null && mSoundDose.asBinder().isBinderAlive()) { + mSoundDose.setOutputRs2(CUSTOM_RS2_VALUE); + if (mCurrentCsd != 0.f) { + Log.d(TAG, "Resetting the saved sound dose value " + mCurrentCsd); + SoundDoseRecord[] records = mDoseRecords.toArray( + new SoundDoseRecord[0]); + mSoundDose.resetCsd(mCurrentCsd, records); + } + } + } catch (RemoteException e) { + // noop + } + } + } + } + private void onConfigureSafeVolume(boolean force, String caller) { synchronized (mSafeMediaVolumeStateLock) { int mcc = mContext.getResources().getConfiguration().mcc;