Skip to content
Snippets Groups Projects
Commit 8922f5db authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Audio focus enforcement: use VolumeShaper for ducking"

parents 6955665c dce82ab7
No related branches found
No related tags found
No related merge requests found
......@@ -37,8 +37,9 @@ import java.util.Objects;
public final class VolumeShaper {
/* member variables */
private int mId;
private final WeakReference<PlayerBase> mPlayerBase;
private final WeakReference<PlayerProxy> mPlayerProxy;
private final WeakReference<PlayerBase> mWeakPlayerBase;
private final WeakReference<PlayerProxy> mWeakPlayerProxy;
private PlayerProxy mPlayerProxy;
/**
* Constructs a {@code VolumeShaper} from a {@link VolumeShaper.Configuration} and an
......@@ -64,14 +65,14 @@ public final class VolumeShaper {
/* package */ VolumeShaper(
@NonNull Configuration configuration, @NonNull PlayerBase playerBase) {
mPlayerBase = new WeakReference<PlayerBase>(playerBase);
mWeakPlayerBase = new WeakReference<PlayerBase>(playerBase);
mPlayerProxy = null;
mWeakPlayerProxy = null;
mId = applyPlayer(configuration, new Operation.Builder().defer().build());
}
/**
* @hide
* TODO SystemApi
* 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).
......@@ -80,12 +81,20 @@ public final class VolumeShaper {
* @param playerProxy
*/
public VolumeShaper(
@NonNull Configuration configuration, @NonNull PlayerProxy playerProxy) {
@NonNull Configuration configuration,
@NonNull PlayerProxy playerProxy,
boolean keepReference) {
if (configuration.getId() < 0) {
throw new IllegalArgumentException("playerProxy configuration id must be specified");
}
mPlayerProxy = new WeakReference<PlayerProxy>(playerProxy);
mPlayerBase = null;
if (keepReference) {
mPlayerProxy = playerProxy;
mWeakPlayerProxy = null;
} else {
mWeakPlayerProxy = new WeakReference<PlayerProxy>(playerProxy);
mPlayerProxy = null;
}
mWeakPlayerBase = null;
mId = applyPlayer(configuration, new Operation.Builder().defer().build());
}
......@@ -143,12 +152,13 @@ public final class VolumeShaper {
} catch (IllegalStateException ise) {
; // ok
}
if (mPlayerBase != null) {
mPlayerBase.clear();
if (mWeakPlayerBase != null) {
mWeakPlayerBase.clear();
}
if (mPlayerProxy != null) {
mPlayerProxy.clear();
if (mWeakPlayerProxy != null) {
mWeakPlayerProxy.clear();
}
mPlayerProxy = null;
}
@Override
......@@ -167,11 +177,11 @@ public final class VolumeShaper {
@NonNull VolumeShaper.Configuration configuration,
@NonNull VolumeShaper.Operation operation) {
final int id;
if (mPlayerProxy != null) {
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 = mPlayerProxy.get();
PlayerProxy player = mWeakPlayerProxy != null ? mWeakPlayerProxy.get() : mPlayerProxy;
if (player == null) {
throw new IllegalStateException("player deallocated");
}
......@@ -180,8 +190,8 @@ public final class VolumeShaper {
throw new IllegalArgumentException("proxy requires configuration with id");
}
player.applyVolumeShaper(configuration, operation);
} else if (mPlayerBase != null) {
PlayerBase player = mPlayerBase.get();
} else if (mWeakPlayerBase != null) {
PlayerBase player = mWeakPlayerBase.get();
if (player == null) {
throw new IllegalStateException("player deallocated");
}
......@@ -210,14 +220,10 @@ public final class VolumeShaper {
*/
private @NonNull VolumeShaper.State getStatePlayer(int id) {
final VolumeShaper.State state;
if (mPlayerProxy != null) {
PlayerProxy player = mPlayerProxy.get();
if (player == null) {
throw new IllegalStateException("player deallocated");
}
if (mPlayerProxy != null || mWeakPlayerProxy != null) {
throw new IllegalStateException("getStatePlayer not permitted through proxy");
} else if (mPlayerBase != null) {
PlayerBase player = mPlayerBase.get();
} else if (mWeakPlayerBase != null) {
PlayerBase player = mWeakPlayerBase.get();
if (player == null) {
throw new IllegalStateException("player deallocated");
}
......
......@@ -437,7 +437,7 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
* @param attr attributes of the sound about to start playing
* @return time in ms
*/
protected int getFocusRampTimeMs(int focusGain, AudioAttributes attr) {
protected static int getFocusRampTimeMs(int focusGain, AudioAttributes attr) {
switch (attr.getUsage()) {
case AudioAttributes.USAGE_MEDIA:
case AudioAttributes.USAGE_GAME:
......
......@@ -25,6 +25,7 @@ import android.media.AudioSystem;
import android.media.IPlaybackConfigDispatcher;
import android.media.MediaRecorder;
import android.media.PlayerBase;
import android.media.VolumeShaper;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
......@@ -47,6 +48,7 @@ public final class PlaybackActivityMonitor
public final static String TAG = "AudioService.PlaybackActivityMonitor";
private final static boolean DEBUG = false;
private final static int VOLUME_SHAPER_SYSTEM_DUCK_ID = 1;
private ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>();
// a public client is one that needs an anonymized version of the playback configurations, we
......@@ -126,6 +128,11 @@ public final class PlaybackActivityMonitor
final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
if (checkConfigurationCaller(piid, apc, binderUid)) {
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);
}
......@@ -242,6 +249,20 @@ public final class PlaybackActivityMonitor
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) {
......@@ -268,11 +289,24 @@ public final class PlaybackActivityMonitor
// the player is speaking, ducking will make the speech unintelligible
// so let the app handle it instead
return false;
} else if (apc.getPlayerType()
== AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) {
// TODO support ducking of SoundPool players
return false;
} else {
try {
if (DEBUG) { Log.v(TAG, "ducking player " + piid); }
//FIXME just a test before we have VolumeShape
apc.getPlayerProxy().setPan(-1.0f);
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
mDuckedPlayers.add(piid);
} catch (Exception e) {
Log.e(TAG, "Error ducking player " + piid, e);
......@@ -301,8 +335,10 @@ public final class PlaybackActivityMonitor
try {
if (DEBUG) { Log.v(TAG, "unducking player" + piid); }
mDuckedPlayers.remove(new Integer(piid));
//FIXME just a test before we have VolumeShape
apc.getPlayerProxy().setPan(0.0f);
if (mDuckVolumeShapers.containsKey(new Integer(piid))) {
final VolumeShaper ducker = mDuckVolumeShapers.get(new Integer(piid));
ducker.apply(VolumeShaper.Operation.REVERSE); // unduck
}
} catch (Exception e) {
Log.e(TAG, "Error unducking player " + piid, e);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment