Loading media/java/android/media/VolumeShaper.java +28 −22 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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). Loading @@ -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()); } Loading Loading @@ -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 Loading @@ -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"); } Loading @@ -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"); } Loading Loading @@ -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"); } Loading services/core/java/com/android/server/audio/MediaFocusControl.java +1 −1 Original line number Diff line number Diff line Loading @@ -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: Loading services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +40 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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); } Loading Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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); } Loading Loading
media/java/android/media/VolumeShaper.java +28 −22 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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). Loading @@ -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()); } Loading Loading @@ -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 Loading @@ -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"); } Loading @@ -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"); } Loading Loading @@ -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"); } Loading
services/core/java/com/android/server/audio/MediaFocusControl.java +1 −1 Original line number Diff line number Diff line Loading @@ -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: Loading
services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +40 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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); } Loading Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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); } Loading