AudioService: internal API for disabling audio playback for a UID
Internal API, available through AudioManagerInternal, to flag a UID as having lost the ability to play audio. When that happens, all players associated with this UID are paused, and future players are immediately paused when they report they started. Users of this API must "enable" a previously banned UID when it is no longer in use. Test: upcoming manual test with background apps Bug: 34471029 Change-Id: Ic1c103aabe8f3897072b3ce938d84cb949540e23
This commit is contained in:
@@ -59,4 +59,15 @@ public abstract class AudioManagerInternal {
|
||||
|
||||
int getRingerModeAffectedStreams(int streams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable or restore the ability to play audio for a given UID.
|
||||
* When a UID isn't meant to be tracked anymore (e.g. client died), re-enable audio for this UID
|
||||
* to prevent disabling audio for future UIDs that would reuse the same value.
|
||||
* This operation is asynchronous.
|
||||
* @param disable when true, prevents playback of audio streams from the given uid. If false,
|
||||
* restores the ability to play, or no-op if playback hadn't been disabled before.
|
||||
* @param uid the client UID whose ability to play will be affected.
|
||||
*/
|
||||
public abstract void disableAudioForUid(boolean disable, int uid);
|
||||
}
|
||||
|
||||
@@ -239,6 +239,7 @@ public class AudioService extends IAudioService.Stub
|
||||
private static final int MSG_SET_A2DP_SRC_CONNECTION_STATE = 101;
|
||||
private static final int MSG_SET_A2DP_SINK_CONNECTION_STATE = 102;
|
||||
private static final int MSG_A2DP_DEVICE_CONFIG_CHANGE = 103;
|
||||
private static final int MSG_DISABLE_AUDIO_FOR_UID = 104;
|
||||
// end of messages handled under wakelock
|
||||
|
||||
private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000;
|
||||
@@ -4871,6 +4872,12 @@ public class AudioService extends IAudioService.Stub
|
||||
mAudioEventWakeLock.release();
|
||||
break;
|
||||
|
||||
case MSG_DISABLE_AUDIO_FOR_UID:
|
||||
mPlaybackMonitor.disableAudioForUid( msg.arg1 == 1 /* disable */,
|
||||
msg.arg2 /* uid */);
|
||||
mAudioEventWakeLock.release();
|
||||
break;
|
||||
|
||||
case MSG_REPORT_NEW_ROUTES: {
|
||||
int N = mRoutesObservers.beginBroadcast();
|
||||
if (N > 0) {
|
||||
@@ -6591,6 +6598,13 @@ public class AudioService extends IAudioService.Stub
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableAudioForUid(boolean disable, int uid) {
|
||||
queueMsgUnderWakeLock(mAudioHandler, MSG_DISABLE_AUDIO_FOR_UID,
|
||||
disable ? 1 : 0 /* arg1 */, uid /* arg2 */,
|
||||
null /* obj */, 0 /* delay */);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
|
||||
@@ -86,6 +86,43 @@ public final class PlaybackActivityMonitor
|
||||
AudioPlaybackConfiguration.sPlayerDeathMonitor = this;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
private final ArrayList<Integer> mBannedUids = new ArrayList<Integer>();
|
||||
|
||||
// see AudioManagerInternal.disableAudioForUid(boolean disable, int uid)
|
||||
public void disableAudioForUid(boolean disable, int uid) {
|
||||
synchronized(mPlayerLock) {
|
||||
final int index = mBannedUids.indexOf(new Integer(uid));
|
||||
if (index >= 0) {
|
||||
if (!disable) {
|
||||
mBannedUids.remove(index);
|
||||
// nothing else to do, future playback requests from this uid are ok
|
||||
} // no else to handle, uid already present, so disabling again is no-op
|
||||
} else {
|
||||
if (disable) {
|
||||
for (AudioPlaybackConfiguration apc : mPlayers.values()) {
|
||||
checkBanPlayer(apc, uid);
|
||||
}
|
||||
mBannedUids.add(new Integer(uid));
|
||||
} // no else to handle, uid already not in list, so enabling again is no-op
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkBanPlayer(@NonNull AudioPlaybackConfiguration apc, int uid) {
|
||||
final boolean toBan = (apc.getClientUid() == uid);
|
||||
if (toBan) {
|
||||
final int piid = apc.getPlayerInterfaceId();
|
||||
try {
|
||||
Log.v(TAG, "banning player " + piid + " uid:" + uid);
|
||||
apc.getPlayerProxy().pause();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "error banning player " + piid + " uid:" + uid, e);
|
||||
}
|
||||
}
|
||||
return toBan;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
// Track players and their states
|
||||
// methods playerAttributes, playerEvent, releasePlayer are all oneway calls
|
||||
@@ -129,6 +166,14 @@ public final class PlaybackActivityMonitor
|
||||
if (apc == null) {
|
||||
return;
|
||||
}
|
||||
if (event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
|
||||
for (Integer uidInteger: mBannedUids) {
|
||||
if (checkBanPlayer(apc, uidInteger.intValue())) {
|
||||
// player was banned, do not update its state
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (apc.getPlayerType() == AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) {
|
||||
// FIXME SoundPool not ready for state reporting
|
||||
return;
|
||||
@@ -178,10 +223,17 @@ public final class PlaybackActivityMonitor
|
||||
pw.println("\n ducked players:");
|
||||
mDuckingManager.dump(pw);
|
||||
// players muted due to the device ringing or being in a call
|
||||
pw.println("\n muted player piids:");
|
||||
pw.print("\n muted player piids:");
|
||||
for (int piid : mMutedPlayers) {
|
||||
pw.println(" " + piid);
|
||||
pw.print(" " + piid);
|
||||
}
|
||||
pw.println();
|
||||
// banned players:
|
||||
pw.print("\n banned uids:");
|
||||
for (int uid : mBannedUids) {
|
||||
pw.print(" " + uid);
|
||||
}
|
||||
pw.println();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user