Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92ed7bf4 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi
Browse files

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
parent 214baa03
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -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);
}
+14 −0
Original line number Diff line number Diff line
@@ -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 */);
        }
    }

    //==========================================================================================
+54 −2
Original line number Diff line number Diff line
@@ -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();
        }
    }