Loading services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +28 −19 Original line number Original line Diff line number Diff line Loading @@ -67,6 +67,10 @@ public final class PlaybackActivityMonitor .createIfNeeded() .createIfNeeded() .build(); .build(); // like a PLAY_CREATE_IF_NEEDED operation but with a skip to the end of the ramp private static final VolumeShaper.Operation PLAY_SKIP_RAMP = new VolumeShaper.Operation.Builder(PLAY_CREATE_IF_NEEDED).setXOffset(1.0f).build(); private final ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>(); private final ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>(); // a public client is one that needs an anonymized version of the playback configurations, we // 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 // keep track of whether there is at least one to know when we need to create the list of Loading Loading @@ -487,17 +491,19 @@ public final class PlaybackActivityMonitor private static final class DuckingManager { private static final class DuckingManager { private final HashMap<Integer, DuckedApp> mDuckers = new HashMap<Integer, DuckedApp>(); private final HashMap<Integer, DuckedApp> mDuckers = new HashMap<Integer, DuckedApp>(); void duckUid(int uid, ArrayList<AudioPlaybackConfiguration> apcsToDuck) { synchronized void duckUid(int uid, ArrayList<AudioPlaybackConfiguration> apcsToDuck) { if (DEBUG) { Log.v(TAG, "DuckingManager: duckUid() uid:"+ uid); } if (!mDuckers.containsKey(uid)) { if (!mDuckers.containsKey(uid)) { mDuckers.put(uid, new DuckedApp(uid)); mDuckers.put(uid, new DuckedApp(uid)); } } final DuckedApp da = mDuckers.get(uid); final DuckedApp da = mDuckers.get(uid); for (AudioPlaybackConfiguration apc : apcsToDuck) { for (AudioPlaybackConfiguration apc : apcsToDuck) { da.addDuck(apc); da.addDuck(apc, false /*skipRamp*/); } } } } void unduckUid(int uid, HashMap<Integer, AudioPlaybackConfiguration> players) { synchronized void unduckUid(int uid, HashMap<Integer, AudioPlaybackConfiguration> players) { if (DEBUG) { Log.v(TAG, "DuckingManager: unduckUid() uid:"+ uid); } final DuckedApp da = mDuckers.remove(uid); final DuckedApp da = mDuckers.remove(uid); if (da == null) { if (da == null) { return; return; Loading @@ -506,25 +512,27 @@ public final class PlaybackActivityMonitor } } // pre-condition: apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED // pre-condition: apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED void checkDuck(@NonNull AudioPlaybackConfiguration apc) { synchronized void checkDuck(@NonNull AudioPlaybackConfiguration apc) { if (DEBUG) { Log.v(TAG, "DuckingManager: checkDuck() player piid:" + apc.getPlayerInterfaceId()+ " uid:"+ apc.getClientUid()); } final DuckedApp da = mDuckers.get(apc.getClientUid()); final DuckedApp da = mDuckers.get(apc.getClientUid()); if (da == null) { if (da == null) { return; return; } } // FIXME here the player needs to be put in a state that is the same as if it da.addDuck(apc, true /*skipRamp*/); // had been ducked as it starts. At the moment, this works already for linked // players, as is the case in gapless playback. da.addDuck(apc); } } void dump(PrintWriter pw) { synchronized void dump(PrintWriter pw) { for (DuckedApp da : mDuckers.values()) { for (DuckedApp da : mDuckers.values()) { da.dump(pw); da.dump(pw); } } } } void removeReleased(@NonNull AudioPlaybackConfiguration apc) { synchronized void removeReleased(@NonNull AudioPlaybackConfiguration apc) { final DuckedApp da = mDuckers.get(apc.getClientUid()); final int uid = apc.getClientUid(); if (DEBUG) { Log.v(TAG, "DuckingManager: removedReleased() player piid: " + apc.getPlayerInterfaceId() + " uid:" + uid); } final DuckedApp da = mDuckers.get(uid); if (da == null) { if (da == null) { return; return; } } Loading @@ -550,20 +558,21 @@ public final class PlaybackActivityMonitor // pre-conditions: // pre-conditions: // * apc != null // * apc != null // * apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED // * apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED void addDuck(@NonNull AudioPlaybackConfiguration apc) { void addDuck(@NonNull AudioPlaybackConfiguration apc, boolean skipRamp) { final int piid = new Integer(apc.getPlayerInterfaceId()); final int piid = new Integer(apc.getPlayerInterfaceId()); if (mDuckedPlayers.contains(piid)) { if (mDuckedPlayers.contains(piid)) { if (DEBUG) { Log.v(TAG, "player " + piid + " already ducked"); } if (DEBUG) { Log.v(TAG, "player piid:" + piid + " already ducked"); } return; return; } } try { try { Log.v(TAG, "ducking player " + apc.getPlayerInterfaceId() + " uid:" + mUid); Log.v(TAG, "ducking (skipRamp=" + skipRamp + ") player piid:" + apc.getPlayerInterfaceId() + " uid:" + mUid); apc.getPlayerProxy().applyVolumeShaper( apc.getPlayerProxy().applyVolumeShaper( DUCK_VSHAPE, DUCK_VSHAPE, PLAY_CREATE_IF_NEEDED); skipRamp ? PLAY_SKIP_RAMP : PLAY_CREATE_IF_NEEDED); mDuckedPlayers.add(piid); mDuckedPlayers.add(piid); } catch (Exception e) { } catch (Exception e) { Log.e(TAG, "Error ducking player " + piid + " uid:" + mUid, e); Log.e(TAG, "Error ducking player piid:" + piid + " uid:" + mUid, e); } } } } Loading @@ -577,13 +586,13 @@ public final class PlaybackActivityMonitor DUCK_ID, DUCK_ID, VolumeShaper.Operation.REVERSE); VolumeShaper.Operation.REVERSE); } catch (Exception e) { } catch (Exception e) { Log.e(TAG, "Error unducking player " + piid + " uid:" + mUid, e); Log.e(TAG, "Error unducking player piid:" + piid + " uid:" + mUid, e); } } } else { } else { // this piid was in the list of ducked players, but wasn't found // this piid was in the list of ducked players, but wasn't found if (DEBUG) { if (DEBUG) { Log.v(TAG, "Error unducking player " + piid + ", player not found for" Log.v(TAG, "Error unducking player piid:" + piid + " uid " + mUid); + ", player not found for uid " + mUid); } } } } } } Loading Loading
services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +28 −19 Original line number Original line Diff line number Diff line Loading @@ -67,6 +67,10 @@ public final class PlaybackActivityMonitor .createIfNeeded() .createIfNeeded() .build(); .build(); // like a PLAY_CREATE_IF_NEEDED operation but with a skip to the end of the ramp private static final VolumeShaper.Operation PLAY_SKIP_RAMP = new VolumeShaper.Operation.Builder(PLAY_CREATE_IF_NEEDED).setXOffset(1.0f).build(); private final ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>(); private final ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>(); // a public client is one that needs an anonymized version of the playback configurations, we // 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 // keep track of whether there is at least one to know when we need to create the list of Loading Loading @@ -487,17 +491,19 @@ public final class PlaybackActivityMonitor private static final class DuckingManager { private static final class DuckingManager { private final HashMap<Integer, DuckedApp> mDuckers = new HashMap<Integer, DuckedApp>(); private final HashMap<Integer, DuckedApp> mDuckers = new HashMap<Integer, DuckedApp>(); void duckUid(int uid, ArrayList<AudioPlaybackConfiguration> apcsToDuck) { synchronized void duckUid(int uid, ArrayList<AudioPlaybackConfiguration> apcsToDuck) { if (DEBUG) { Log.v(TAG, "DuckingManager: duckUid() uid:"+ uid); } if (!mDuckers.containsKey(uid)) { if (!mDuckers.containsKey(uid)) { mDuckers.put(uid, new DuckedApp(uid)); mDuckers.put(uid, new DuckedApp(uid)); } } final DuckedApp da = mDuckers.get(uid); final DuckedApp da = mDuckers.get(uid); for (AudioPlaybackConfiguration apc : apcsToDuck) { for (AudioPlaybackConfiguration apc : apcsToDuck) { da.addDuck(apc); da.addDuck(apc, false /*skipRamp*/); } } } } void unduckUid(int uid, HashMap<Integer, AudioPlaybackConfiguration> players) { synchronized void unduckUid(int uid, HashMap<Integer, AudioPlaybackConfiguration> players) { if (DEBUG) { Log.v(TAG, "DuckingManager: unduckUid() uid:"+ uid); } final DuckedApp da = mDuckers.remove(uid); final DuckedApp da = mDuckers.remove(uid); if (da == null) { if (da == null) { return; return; Loading @@ -506,25 +512,27 @@ public final class PlaybackActivityMonitor } } // pre-condition: apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED // pre-condition: apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED void checkDuck(@NonNull AudioPlaybackConfiguration apc) { synchronized void checkDuck(@NonNull AudioPlaybackConfiguration apc) { if (DEBUG) { Log.v(TAG, "DuckingManager: checkDuck() player piid:" + apc.getPlayerInterfaceId()+ " uid:"+ apc.getClientUid()); } final DuckedApp da = mDuckers.get(apc.getClientUid()); final DuckedApp da = mDuckers.get(apc.getClientUid()); if (da == null) { if (da == null) { return; return; } } // FIXME here the player needs to be put in a state that is the same as if it da.addDuck(apc, true /*skipRamp*/); // had been ducked as it starts. At the moment, this works already for linked // players, as is the case in gapless playback. da.addDuck(apc); } } void dump(PrintWriter pw) { synchronized void dump(PrintWriter pw) { for (DuckedApp da : mDuckers.values()) { for (DuckedApp da : mDuckers.values()) { da.dump(pw); da.dump(pw); } } } } void removeReleased(@NonNull AudioPlaybackConfiguration apc) { synchronized void removeReleased(@NonNull AudioPlaybackConfiguration apc) { final DuckedApp da = mDuckers.get(apc.getClientUid()); final int uid = apc.getClientUid(); if (DEBUG) { Log.v(TAG, "DuckingManager: removedReleased() player piid: " + apc.getPlayerInterfaceId() + " uid:" + uid); } final DuckedApp da = mDuckers.get(uid); if (da == null) { if (da == null) { return; return; } } Loading @@ -550,20 +558,21 @@ public final class PlaybackActivityMonitor // pre-conditions: // pre-conditions: // * apc != null // * apc != null // * apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED // * apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED void addDuck(@NonNull AudioPlaybackConfiguration apc) { void addDuck(@NonNull AudioPlaybackConfiguration apc, boolean skipRamp) { final int piid = new Integer(apc.getPlayerInterfaceId()); final int piid = new Integer(apc.getPlayerInterfaceId()); if (mDuckedPlayers.contains(piid)) { if (mDuckedPlayers.contains(piid)) { if (DEBUG) { Log.v(TAG, "player " + piid + " already ducked"); } if (DEBUG) { Log.v(TAG, "player piid:" + piid + " already ducked"); } return; return; } } try { try { Log.v(TAG, "ducking player " + apc.getPlayerInterfaceId() + " uid:" + mUid); Log.v(TAG, "ducking (skipRamp=" + skipRamp + ") player piid:" + apc.getPlayerInterfaceId() + " uid:" + mUid); apc.getPlayerProxy().applyVolumeShaper( apc.getPlayerProxy().applyVolumeShaper( DUCK_VSHAPE, DUCK_VSHAPE, PLAY_CREATE_IF_NEEDED); skipRamp ? PLAY_SKIP_RAMP : PLAY_CREATE_IF_NEEDED); mDuckedPlayers.add(piid); mDuckedPlayers.add(piid); } catch (Exception e) { } catch (Exception e) { Log.e(TAG, "Error ducking player " + piid + " uid:" + mUid, e); Log.e(TAG, "Error ducking player piid:" + piid + " uid:" + mUid, e); } } } } Loading @@ -577,13 +586,13 @@ public final class PlaybackActivityMonitor DUCK_ID, DUCK_ID, VolumeShaper.Operation.REVERSE); VolumeShaper.Operation.REVERSE); } catch (Exception e) { } catch (Exception e) { Log.e(TAG, "Error unducking player " + piid + " uid:" + mUid, e); Log.e(TAG, "Error unducking player piid:" + piid + " uid:" + mUid, e); } } } else { } else { // this piid was in the list of ducked players, but wasn't found // this piid was in the list of ducked players, but wasn't found if (DEBUG) { if (DEBUG) { Log.v(TAG, "Error unducking player " + piid + ", player not found for" Log.v(TAG, "Error unducking player piid:" + piid + " uid " + mUid); + ", player not found for uid " + mUid); } } } } } } Loading