Merge "Fix to allow setting URI without recreating ringtone" into tm-qpr-dev

This commit is contained in:
TreeHugger Robot
2022-09-12 21:45:47 +00:00
committed by Android (Google) Code Review
3 changed files with 123 additions and 48 deletions

View File

@@ -29,11 +29,12 @@ import android.net.Uri;
import android.os.Binder; import android.os.Binder;
import android.os.Build; import android.os.Build;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.Trace;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns; import android.provider.MediaStore.MediaColumns;
import android.provider.Settings; import android.provider.Settings;
import android.util.Log; import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@@ -136,13 +137,73 @@ public class Ringtone {
*/ */
public void setAudioAttributes(AudioAttributes attributes) public void setAudioAttributes(AudioAttributes attributes)
throws IllegalArgumentException { throws IllegalArgumentException {
setAudioAttributesField(attributes);
// The audio attributes have to be set before the media player is prepared.
// Re-initialize it.
setUri(mUri, mVolumeShaperConfig);
createLocalMediaPlayer();
}
/**
* Same as {@link #setAudioAttributes(AudioAttributes)} except this one does not create
* the media player.
* @hide
*/
public void setAudioAttributesField(@Nullable AudioAttributes attributes) {
if (attributes == null) { if (attributes == null) {
throw new IllegalArgumentException("Invalid null AudioAttributes for Ringtone"); throw new IllegalArgumentException("Invalid null AudioAttributes for Ringtone");
} }
mAudioAttributes = attributes; mAudioAttributes = attributes;
// The audio attributes have to be set before the media player is prepared. }
// Re-initialize it.
setUri(mUri, mVolumeShaperConfig); /**
* Creates a local media player for the ringtone using currently set attributes.
* @hide
*/
public void createLocalMediaPlayer() {
Trace.beginSection("createLocalMediaPlayer");
if (mUri == null) {
Log.e(TAG, "Could not create media player as no URI was provided.");
return;
}
destroyLocalPlayer();
// try opening uri locally before delegating to remote player
mLocalPlayer = new MediaPlayer();
try {
mLocalPlayer.setDataSource(mContext, mUri);
mLocalPlayer.setAudioAttributes(mAudioAttributes);
synchronized (mPlaybackSettingsLock) {
applyPlaybackProperties_sync();
}
if (mVolumeShaperConfig != null) {
mVolumeShaper = mLocalPlayer.createVolumeShaper(mVolumeShaperConfig);
}
mLocalPlayer.prepare();
} catch (SecurityException | IOException e) {
destroyLocalPlayer();
if (!mAllowRemote) {
Log.w(TAG, "Remote playback not allowed: " + e);
}
}
if (LOGD) {
if (mLocalPlayer != null) {
Log.d(TAG, "Successfully created local player");
} else {
Log.d(TAG, "Problem opening; delegating to remote player");
}
}
Trace.endSection();
}
/**
* Returns whether a local player has been created for this ringtone.
* @hide
*/
@VisibleForTesting
public boolean hasLocalPlayer() {
return mLocalPlayer != null;
} }
/** /**
@@ -336,8 +397,7 @@ public class Ringtone {
} }
/** /**
* Set {@link Uri} to be used for ringtone playback. Attempts to open * Set {@link Uri} to be used for ringtone playback.
* locally, otherwise will delegate playback to remote
* {@link IRingtonePlayer}. * {@link IRingtonePlayer}.
* *
* @hide * @hide
@@ -347,6 +407,13 @@ public class Ringtone {
setUri(uri, null); setUri(uri, null);
} }
/**
* @hide
*/
public void setVolumeShaperConfig(@Nullable VolumeShaper.Configuration volumeShaperConfig) {
mVolumeShaperConfig = volumeShaperConfig;
}
/** /**
* Set {@link Uri} to be used for ringtone playback. Attempts to open * Set {@link Uri} to be used for ringtone playback. Attempts to open
* locally, otherwise will delegate playback to remote * locally, otherwise will delegate playback to remote
@@ -356,41 +423,10 @@ public class Ringtone {
*/ */
public void setUri(Uri uri, @Nullable VolumeShaper.Configuration volumeShaperConfig) { public void setUri(Uri uri, @Nullable VolumeShaper.Configuration volumeShaperConfig) {
mVolumeShaperConfig = volumeShaperConfig; mVolumeShaperConfig = volumeShaperConfig;
destroyLocalPlayer();
mUri = uri; mUri = uri;
if (mUri == null) { if (mUri == null) {
return;
}
// TODO: detect READ_EXTERNAL and specific content provider case, instead of relying on throwing
// try opening uri locally before delegating to remote player
mLocalPlayer = new MediaPlayer();
try {
mLocalPlayer.setDataSource(mContext, mUri);
mLocalPlayer.setAudioAttributes(mAudioAttributes);
synchronized (mPlaybackSettingsLock) {
applyPlaybackProperties_sync();
}
if (mVolumeShaperConfig != null) {
mVolumeShaper = mLocalPlayer.createVolumeShaper(mVolumeShaperConfig);
}
mLocalPlayer.prepare();
} catch (SecurityException | IOException e) {
destroyLocalPlayer(); destroyLocalPlayer();
if (!mAllowRemote) {
Log.w(TAG, "Remote playback not allowed: " + e);
}
}
if (LOGD) {
if (mLocalPlayer != null) {
Log.d(TAG, "Successfully created local player");
} else {
Log.d(TAG, "Problem opening; delegating to remote player");
}
} }
} }

View File

@@ -481,7 +481,8 @@ public class RingtoneManager {
mPreviousRingtone.stop(); mPreviousRingtone.stop();
} }
mPreviousRingtone = getRingtone(mContext, getRingtoneUri(position), inferStreamType()); mPreviousRingtone =
getRingtone(mContext, getRingtoneUri(position), inferStreamType(), true);
return mPreviousRingtone; return mPreviousRingtone;
} }
@@ -677,7 +678,7 @@ public class RingtoneManager {
*/ */
public static Ringtone getRingtone(final Context context, Uri ringtoneUri) { public static Ringtone getRingtone(final Context context, Uri ringtoneUri) {
// Don't set the stream type // Don't set the stream type
return getRingtone(context, ringtoneUri, -1); return getRingtone(context, ringtoneUri, -1, true);
} }
/** /**
@@ -698,7 +699,34 @@ public class RingtoneManager {
final Context context, Uri ringtoneUri, final Context context, Uri ringtoneUri,
@Nullable VolumeShaper.Configuration volumeShaperConfig) { @Nullable VolumeShaper.Configuration volumeShaperConfig) {
// Don't set the stream type // Don't set the stream type
return getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig); return getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig, true);
}
/**
* @hide
*/
public static Ringtone getRingtone(final Context context, Uri ringtoneUri,
@Nullable VolumeShaper.Configuration volumeShaperConfig,
boolean createLocalMediaPlayer) {
// Don't set the stream type
return getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig,
createLocalMediaPlayer);
}
/**
* @hide
*/
public static Ringtone getRingtone(final Context context, Uri ringtoneUri,
@Nullable VolumeShaper.Configuration volumeShaperConfig,
AudioAttributes audioAttributes) {
// Don't set the stream type
Ringtone ringtone =
getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig, false);
if (ringtone != null) {
ringtone.setAudioAttributesField(audioAttributes);
ringtone.createLocalMediaPlayer();
}
return ringtone;
} }
//FIXME bypass the notion of stream types within the class //FIXME bypass the notion of stream types within the class
@@ -710,11 +738,16 @@ public class RingtoneManager {
* *
* @param streamType The stream type for the ringtone, or -1 if it should * @param streamType The stream type for the ringtone, or -1 if it should
* not be set (and the default used instead). * not be set (and the default used instead).
* @param createLocalMediaPlayer when true, the ringtone returned will be fully
* created otherwise, it will require the caller to create the media player manually
* {@link Ringtone#createLocalMediaPlayer()} in order to play the Ringtone.
* @see #getRingtone(Context, Uri) * @see #getRingtone(Context, Uri)
*/ */
@UnsupportedAppUsage @UnsupportedAppUsage
private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType) { private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType,
return getRingtone(context, ringtoneUri, streamType, null /* volumeShaperConfig */); boolean createLocalMediaPlayer) {
return getRingtone(context, ringtoneUri, streamType, null /* volumeShaperConfig */,
createLocalMediaPlayer);
} }
//FIXME bypass the notion of stream types within the class //FIXME bypass the notion of stream types within the class
@@ -730,16 +763,21 @@ public class RingtoneManager {
* @see #getRingtone(Context, Uri) * @see #getRingtone(Context, Uri)
*/ */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private static Ringtone getRingtone( private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType,
final Context context, Uri ringtoneUri, int streamType, @Nullable VolumeShaper.Configuration volumeShaperConfig,
@Nullable VolumeShaper.Configuration volumeShaperConfig) { boolean createLocalMediaPlayer) {
try { try {
final Ringtone r = new Ringtone(context, true); final Ringtone r = new Ringtone(context, true);
if (streamType >= 0) { if (streamType >= 0) {
//FIXME deprecated call //FIXME deprecated call
r.setStreamType(streamType); r.setStreamType(streamType);
} }
r.setVolumeShaperConfig(volumeShaperConfig);
r.setUri(ringtoneUri, volumeShaperConfig); r.setUri(ringtoneUri, volumeShaperConfig);
if (createLocalMediaPlayer) {
r.createLocalMediaPlayer();
}
return r; return r;
} catch (Exception ex) { } catch (Exception ex) {
Log.e(TAG, "Failed to open ringtone " + ringtoneUri + ": " + ex); Log.e(TAG, "Failed to open ringtone " + ringtoneUri + ": " + ex);

View File

@@ -96,8 +96,9 @@ public class RingtonePlayer extends CoreStartable {
mToken = token; mToken = token;
mRingtone = new Ringtone(getContextForUser(user), false); mRingtone = new Ringtone(getContextForUser(user), false);
mRingtone.setAudioAttributes(aa); mRingtone.setAudioAttributesField(aa);
mRingtone.setUri(uri, volumeShaperConfig); mRingtone.setUri(uri, volumeShaperConfig);
mRingtone.createLocalMediaPlayer();
} }
@Override @Override