VolumeShaper: Remove PlayerProxy constructor
Use of the VolumeShaper through PlayerProxy requires system ids,
which is different enough from PlayerBase that we don't allow
direct construction.
Test: Ducking
Bug: 31015569
Change-Id: Ia98ec5396047ae39e78237bb7e485d07f2eb1efd
diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java
index 4a2c4d8..5b43136 100644
--- a/media/java/android/media/VolumeShaper.java
+++ b/media/java/android/media/VolumeShaper.java
@@ -38,8 +38,6 @@
/* member variables */
private int mId;
private final WeakReference<PlayerBase> mWeakPlayerBase;
- private final WeakReference<PlayerProxy> mWeakPlayerProxy;
- private PlayerProxy mPlayerProxy;
/**
* Constructs a {@code VolumeShaper} from a {@link VolumeShaper.Configuration} and an
@@ -66,35 +64,6 @@
/* package */ VolumeShaper(
@NonNull Configuration configuration, @NonNull PlayerBase playerBase) {
mWeakPlayerBase = new WeakReference<PlayerBase>(playerBase);
- mPlayerProxy = null;
- mWeakPlayerProxy = null;
- mId = applyPlayer(configuration, new Operation.Builder().defer().build());
- }
-
- /**
- * @hide
- * Constructs a {@code VolumeShaper} from a {@link VolumeShaper.Configuration} and a
- * {@code PlayerProxy} object. The PlayerProxy object requires that the configuration
- * be set with a system VolumeShaper id (this is a reserved value).
- *
- * @param configuration
- * @param playerProxy
- */
- public VolumeShaper(
- @NonNull Configuration configuration,
- @NonNull PlayerProxy playerProxy,
- boolean keepReference) {
- if (configuration.getId() < 0) {
- throw new IllegalArgumentException("playerProxy configuration id must be specified");
- }
- if (keepReference) {
- mPlayerProxy = playerProxy;
- mWeakPlayerProxy = null;
- } else {
- mWeakPlayerProxy = new WeakReference<PlayerProxy>(playerProxy);
- mPlayerProxy = null;
- }
- mWeakPlayerBase = null;
mId = applyPlayer(configuration, new Operation.Builder().defer().build());
}
@@ -155,10 +124,6 @@
if (mWeakPlayerBase != null) {
mWeakPlayerBase.clear();
}
- if (mWeakPlayerProxy != null) {
- mWeakPlayerProxy.clear();
- }
- mPlayerProxy = null;
}
@Override
@@ -177,20 +142,7 @@
@NonNull VolumeShaper.Configuration configuration,
@NonNull VolumeShaper.Operation operation) {
final int id;
- if (mPlayerProxy != null || mWeakPlayerProxy != null) {
- // The PlayerProxy accepts only one way transactions so
- // the Configuration must have an id set to one of the system
- // ids (a positive value less than 16).
- PlayerProxy player = mWeakPlayerProxy != null ? mWeakPlayerProxy.get() : mPlayerProxy;
- if (player == null) {
- throw new IllegalStateException("player deallocated");
- }
- id = configuration.getId();
- if (id < 0) {
- throw new IllegalArgumentException("proxy requires configuration with id");
- }
- player.applyVolumeShaper(configuration, operation);
- } else if (mWeakPlayerBase != null) {
+ if (mWeakPlayerBase != null) {
PlayerBase player = mWeakPlayerBase.get();
if (player == null) {
throw new IllegalStateException("player deallocated");
@@ -220,9 +172,7 @@
*/
private @NonNull VolumeShaper.State getStatePlayer(int id) {
final VolumeShaper.State state;
- if (mPlayerProxy != null || mWeakPlayerProxy != null) {
- throw new IllegalStateException("getStatePlayer not permitted through proxy");
- } else if (mWeakPlayerBase != null) {
+ if (mWeakPlayerBase != null) {
PlayerBase player = mWeakPlayerBase.get();
if (player == null) {
throw new IllegalStateException("player deallocated");
@@ -510,6 +460,7 @@
};
/**
+ * @hide
* Constructs a volume shaper from an id.
*
* This is an opaque handle for controlling a {@code VolumeShaper} that has
@@ -522,7 +473,7 @@
* @param id
* @throws IllegalArgumentException if id is negative.
*/
- private Configuration(int id) {
+ public Configuration(int id) {
if (id < 0) {
throw new IllegalArgumentException("negative id " + id);
}
@@ -1039,6 +990,13 @@
*/
private static final int FLAG_DEFER = 1 << 3;
+ /**
+ * Use the id specified in the configuration, creating
+ * VolumeShaper as needed; the configuration should be
+ * TYPE_SCALE.
+ */
+ private static final int FLAG_CREATE_IF_NEEDED = 1 << 4;
+
private static final int FLAG_PUBLIC_ALL = FLAG_REVERSE | FLAG_TERMINATE;
private final int mFlags;
@@ -1175,6 +1133,17 @@
}
/**
+ * Use the id specified in the configuration, creating
+ * VolumeShaper as needed; the configuration should be
+ * TYPE_SCALE.
+ * @return the same Builder instance.
+ */
+ public @NonNull Builder createIfNeeded() {
+ mFlags |= FLAG_CREATE_IF_NEEDED;
+ return this;
+ }
+
+ /**
* Sets the operation flag. Do not call this directly but one of the
* other builder methods.
*
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index e8ff510..d648dd8 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -51,14 +51,36 @@
private final static boolean DEBUG = false;
private final static int VOLUME_SHAPER_SYSTEM_DUCK_ID = 1;
- private ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>();
+ private final VolumeShaper.Configuration DUCK_VSHAPE =
+ new VolumeShaper.Configuration.Builder()
+ .setId(VOLUME_SHAPER_SYSTEM_DUCK_ID)
+ .setCurve(new float[] { 0.f, 1.f } /* times */,
+ new float[] { 1.f, 0.2f } /* volumes */)
+ .setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
+ .setDurationMs(MediaFocusControl.getFocusRampTimeMs(
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
+ new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION)
+ .build()))
+ .build();
+ private final VolumeShaper.Configuration DUCK_ID =
+ new VolumeShaper.Configuration(VOLUME_SHAPER_SYSTEM_DUCK_ID);
+ private final VolumeShaper.Operation PLAY_CREATE_IF_NEEDED =
+ new VolumeShaper.Operation.Builder(VolumeShaper.Operation.PLAY)
+ .createIfNeeded()
+ .build();
+ private final VolumeShaper.Operation TERMINATE =
+ new VolumeShaper.Operation.Builder()
+ .terminate()
+ .build();
+
+ private final ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>();
// a public client is one that needs an anonymized version of the playback configurations, we
// keep track of whether there is at least one to know when we need to create the list of
// playback configurations that do not contain uid/pid/package name information.
private boolean mHasPublicClients = false;
private final Object mPlayerLock = new Object();
- private HashMap<Integer, AudioPlaybackConfiguration> mPlayers =
+ private final HashMap<Integer, AudioPlaybackConfiguration> mPlayers =
new HashMap<Integer, AudioPlaybackConfiguration>();
PlaybackActivityMonitor() {
@@ -130,12 +152,10 @@
synchronized(mPlayerLock) {
final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
if (checkConfigurationCaller(piid, apc, binderUid)) {
+ apc.getPlayerProxy().applyVolumeShaper(
+ DUCK_ID,
+ TERMINATE);
mPlayers.remove(new Integer(piid));
- final VolumeShaper vs = mDuckVolumeShapers.get(new Integer(piid));
- if (vs != null) {
- vs.release();
- mDuckVolumeShapers.remove(new Integer(piid));
- }
} else {
Log.e(TAG, "Error releasing player " + piid);
}
@@ -252,20 +272,6 @@
private final ArrayList<Integer> mDuckedPlayers = new ArrayList<Integer>();
private final ArrayList<Integer> mMutedPlayers = new ArrayList<Integer>();
- private final VolumeShaper.Configuration DUCK_VSHAPE =
- new VolumeShaper.Configuration.Builder()
- .setId(VOLUME_SHAPER_SYSTEM_DUCK_ID)
- .setCurve(new float[] { 0.f, 1.f } /* times */,
- new float[] { 1.f, 0.2f } /* volumes */)
- .setDurationMs(MediaFocusControl.getFocusRampTimeMs(
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
- new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION)
- .build()))
- .build();
-
- private final HashMap<Integer, VolumeShaper> mDuckVolumeShapers =
- new HashMap<Integer, VolumeShaper>();
-
@Override
public boolean duckPlayers(FocusRequester winner, FocusRequester loser) {
if (DEBUG) {
@@ -302,17 +308,9 @@
} else {
try {
if (DEBUG) { Log.v(TAG, "ducking player " + piid); }
- final VolumeShaper ducker;
- if (mDuckVolumeShapers.containsKey(new Integer(piid))) {
- ducker = mDuckVolumeShapers.get(new Integer(piid));
- } else {
- ducker = new VolumeShaper(
- DUCK_VSHAPE,
- apc.getPlayerProxy(),
- true /* keepReference */);
- mDuckVolumeShapers.put(new Integer(piid), ducker);
- }
- ducker.apply(VolumeShaper.Operation.PLAY); // duck
+ apc.getPlayerProxy().applyVolumeShaper(
+ DUCK_VSHAPE,
+ PLAY_CREATE_IF_NEEDED);
mDuckedPlayers.add(piid);
} catch (Exception e) {
Log.e(TAG, "Error ducking player " + piid, e);
@@ -341,10 +339,9 @@
try {
if (DEBUG) { Log.v(TAG, "unducking player" + piid); }
mDuckedPlayers.remove(new Integer(piid));
- if (mDuckVolumeShapers.containsKey(new Integer(piid))) {
- final VolumeShaper ducker = mDuckVolumeShapers.get(new Integer(piid));
- ducker.apply(VolumeShaper.Operation.REVERSE); // unduck
- }
+ apc.getPlayerProxy().applyVolumeShaper(
+ DUCK_ID,
+ VolumeShaper.Operation.REVERSE);
} catch (Exception e) {
Log.e(TAG, "Error unducking player " + piid, e);
}