From 301b5bf50c19f6a4f327c31711a9bce960bb64b5 Mon Sep 17 00:00:00 2001 From: Yiwen Chen Date: Wed, 12 Dec 2018 12:35:43 -0800 Subject: [PATCH] Make RingtoneManager and Ringtone class support VolumeShaper Bug: 120789399 Test: When finish the whole change, flash into a dev phone to test first. Change-Id: I4620fac5f1c34d37b3b33565cebbea2c091a5d08 --- media/java/android/media/Ringtone.java | 24 +++++++++++ media/java/android/media/RingtoneManager.java | 42 ++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java index 84dfcb13083fe..42597aa0141c8 100644 --- a/media/java/android/media/Ringtone.java +++ b/media/java/android/media/Ringtone.java @@ -16,6 +16,7 @@ package android.media; +import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; import android.content.ContentProvider; import android.content.ContentResolver; @@ -60,6 +61,8 @@ public class Ringtone { private final Context mContext; private final AudioManager mAudioManager; + private VolumeShaper.Configuration mVolumeShaperConfig; + private VolumeShaper mVolumeShaper; /** * Flag indicating if we're allowed to fall back to remote playback using @@ -302,6 +305,18 @@ public class Ringtone { */ @UnsupportedAppUsage public void setUri(Uri uri) { + setUri(uri, null); + } + + /** + * Set {@link Uri} to be used for ringtone playback. Attempts to open + * locally, otherwise will delegate playback to remote + * {@link IRingtonePlayer}. Add {@link VolumeShaper} if required. + * + * @hide + */ + public void setUri(Uri uri, @Nullable VolumeShaper.Configuration volumeShaperConfig) { + mVolumeShaperConfig = volumeShaperConfig; destroyLocalPlayer(); mUri = uri; @@ -319,6 +334,9 @@ public class Ringtone { synchronized (mPlaybackSettingsLock) { applyPlaybackProperties_sync(); } + if (mVolumeShaperConfig != null) { + mVolumeShaper = mLocalPlayer.createVolumeShaper(mVolumeShaperConfig); + } mLocalPlayer.prepare(); } catch (SecurityException | IOException e) { @@ -412,6 +430,9 @@ public class Ringtone { } mLocalPlayer.setOnCompletionListener(mCompletionListener); mLocalPlayer.start(); + if (mVolumeShaper != null) { + mVolumeShaper.apply(VolumeShaper.Operation.PLAY); + } } /** @@ -458,6 +479,9 @@ public class Ringtone { synchronized (mPlaybackSettingsLock) { applyPlaybackProperties_sync(); } + if (mVolumeShaperConfig != null) { + mVolumeShaper = mLocalPlayer.createVolumeShaper(mVolumeShaperConfig); + } mLocalPlayer.prepare(); startLocalPlayer(); afd.close(); diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java index 874f21ea8c28a..0679e8e90e85e 100644 --- a/media/java/android/media/RingtoneManager.java +++ b/media/java/android/media/RingtoneManager.java @@ -694,6 +694,27 @@ public class RingtoneManager { return getRingtone(context, ringtoneUri, -1); } + /** + * Returns a {@link Ringtone} with {@link VolumeShaper} if required for a given sound URI. + *

+ * If the given URI cannot be opened for any reason, this method will + * attempt to fallback on another sound. If it cannot find any, it will + * return null. + * + * @param context A context used to query. + * @param ringtoneUri The {@link Uri} of a sound or ringtone. + * @param volumeShaperConfig config for volume shaper of the ringtone if applied. + * @return A {@link Ringtone} for the given URI, or null. + * + * @hide + */ + public static Ringtone getRingtone( + final Context context, Uri ringtoneUri, + @Nullable VolumeShaper.Configuration volumeShaperConfig) { + // Don't set the stream type + return getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig); + } + //FIXME bypass the notion of stream types within the class /** * Returns a {@link Ringtone} for a given sound URI on the given stream @@ -707,13 +728,32 @@ public class RingtoneManager { */ @UnsupportedAppUsage private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType) { + return getRingtone(context, ringtoneUri, streamType, null /* volumeShaperConfig */); + } + + //FIXME bypass the notion of stream types within the class + /** + * Returns a {@link Ringtone} with {@link VolumeShaper} if required for a given sound URI on + * the given stream type. Normally, if you change the stream type on the returned + * {@link Ringtone}, it will re-create the {@link MediaPlayer}. This is just + * an optimized route to avoid that. + * + * @param streamType The stream type for the ringtone, or -1 if it should + * not be set (and the default used instead). + * @param volumeShaperConfig config for volume shaper of the ringtone if applied. + * @see #getRingtone(Context, Uri) + */ + @UnsupportedAppUsage + private static Ringtone getRingtone( + final Context context, Uri ringtoneUri, int streamType, + @Nullable VolumeShaper.Configuration volumeShaperConfig) { try { final Ringtone r = new Ringtone(context, true); if (streamType >= 0) { //FIXME deprecated call r.setStreamType(streamType); } - r.setUri(ringtoneUri); + r.setUri(ringtoneUri, volumeShaperConfig); return r; } catch (Exception ex) { Log.e(TAG, "Failed to open ringtone " + ringtoneUri + ": " + ex);