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

Commit 8f819190 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi Committed by Android (Google) Code Review
Browse files

Merge "AudioService: internal API for disabling audio playback for a UID" into oc-dr1-dev

parents 01eb7111 92ed7bf4
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
@@ -94,6 +94,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
@@ -137,6 +174,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;
@@ -186,10 +231,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();
        }
    }