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

Commit f1f04649 authored by Nadav Bar's avatar Nadav Bar Committed by Android (Google) Code Review
Browse files

Merge "Set/get allowed capture policy via AudioService." into qt-qpr1-dev

parents 24b81758 55e8fd23
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -1251,7 +1251,10 @@ public final class AudioAttributes implements Parcelable {
        }
    }

    static int capturePolicyToFlags(@CapturePolicy int capturePolicy, int flags) {
    /**
     * @hide
     */
    public static int capturePolicyToFlags(@CapturePolicy int capturePolicy, int flags) {
        switch (capturePolicy) {
            case ALLOW_CAPTURE_BY_NONE:
                flags |= FLAG_NO_MEDIA_PROJECTION | FLAG_NO_SYSTEM_CAPTURE;
+17 −12
Original line number Diff line number Diff line
@@ -1507,22 +1507,21 @@ public class AudioManager {
     *     {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL},
     *     {@link AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM},
     *     {@link AudioAttributes#ALLOW_CAPTURE_BY_NONE}.
     * @throws IllegalArgumentException if the argument is not a valid value.
     * @throws RuntimeException if the argument is not a valid value.
     */
    public void setAllowedCapturePolicy(@AudioAttributes.CapturePolicy int capturePolicy) {
        int flags = AudioAttributes.capturePolicyToFlags(capturePolicy, 0x0);
        // TODO: got trough AudioService and save a cache to restore in case of AP crash
        // TODO: also pass the package in case multiple packages have the same UID
        int result = AudioSystem.setAllowedCapturePolicy(Process.myUid(), flags);
        final IAudioService service = getService();
        try {
            int result = service.setAllowedCapturePolicy(capturePolicy);
            if (result != AudioSystem.AUDIO_STATUS_OK) {
                Log.e(TAG, "Could not setAllowedCapturePolicy: " + result);
                return;
            }
        mCapturePolicy = capturePolicy;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    @AudioAttributes.CapturePolicy
    private int mCapturePolicy = AudioAttributes.ALLOW_CAPTURE_BY_ALL;

    /**
     * Return the capture policy.
@@ -1531,7 +1530,13 @@ public class AudioManager {
     */
    @AudioAttributes.CapturePolicy
    public int getAllowedCapturePolicy() {
        return mCapturePolicy;
        int result = AudioAttributes.ALLOW_CAPTURE_BY_ALL;
        try {
            result = getService().getAllowedCapturePolicy();
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to query allowed capture policy: " + e);
        }
        return result;
    }

    //====================================================================
+4 −0
Original line number Diff line number Diff line
@@ -259,6 +259,10 @@ interface IAudioService {

    boolean hasHapticChannels(in Uri uri);

    int setAllowedCapturePolicy(in int capturePolicy);

    int getAllowedCapturePolicy();

    // WARNING: read warning at top of file, new methods that need to be used by native
    // code via IAudioManager.h need to be added to the top section.
}
+58 −0
Original line number Diff line number Diff line
@@ -1041,6 +1041,27 @@ public class AudioService extends IAudioService.Stub
            }
        }

        // Restore capture policies
        synchronized (mPlaybackMonitor) {
            HashMap<Integer, Integer> allowedCapturePolicies =
                    mPlaybackMonitor.getAllAllowedCapturePolicies();
            for (HashMap.Entry<Integer, Integer> entry : allowedCapturePolicies.entrySet()) {
                int result = AudioSystem.setAllowedCapturePolicy(
                        entry.getKey(),
                        AudioAttributes.capturePolicyToFlags(entry.getValue(), 0x0));
                if (result != AudioSystem.AUDIO_STATUS_OK) {
                    Log.e(TAG, "Failed to restore capture policy, uid: "
                            + entry.getKey() + ", capture policy: " + entry.getValue()
                            + ", result: " + result);
                    // When restoring capture policy failed, set the capture policy as
                    // ALLOW_CAPTURE_BY_ALL, which will result in removing the cached
                    // capture policy in PlaybackActivityMonitor.
                    mPlaybackMonitor.setAllowedCapturePolicy(
                            entry.getKey(), AudioAttributes.ALLOW_CAPTURE_BY_ALL);
                }
            }
        }

        onIndicateSystemReady();
        // indicate the end of reconfiguration phase to audio HAL
        AudioSystem.setParameters("restarting=false");
@@ -7250,6 +7271,43 @@ public class AudioService extends IAudioService.Stub
        mPlaybackMonitor.releasePlayer(piid, Binder.getCallingUid());
    }

    /**
     * Specifies whether the audio played by this app may or may not be captured by other apps or
     * the system.
     *
     * @param capturePolicy one of
     *     {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL},
     *     {@link AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM},
     *     {@link AudioAttributes#ALLOW_CAPTURE_BY_NONE}.
     * @return AudioSystem.AUDIO_STATUS_OK if set allowed capture policy succeed.
     * @throws IllegalArgumentException if the argument is not a valid value.
     */
    public int setAllowedCapturePolicy(int capturePolicy) {
        int callingUid = Binder.getCallingUid();
        int flags = AudioAttributes.capturePolicyToFlags(capturePolicy, 0x0);
        final long identity = Binder.clearCallingIdentity();
        synchronized (mPlaybackMonitor) {
            int result = AudioSystem.setAllowedCapturePolicy(callingUid, flags);
            if (result == AudioSystem.AUDIO_STATUS_OK) {
                mPlaybackMonitor.setAllowedCapturePolicy(callingUid, capturePolicy);
            }
            Binder.restoreCallingIdentity(identity);
            return result;
        }
    }

    /**
     * Return the capture policy.
     * @return the cached capture policy for the calling uid.
     */
    public int getAllowedCapturePolicy() {
        int callingUid = Binder.getCallingUid();
        final long identity = Binder.clearCallingIdentity();
        int capturePolicy = mPlaybackMonitor.getAllowedCapturePolicy(callingUid);
        Binder.restoreCallingIdentity(identity);
        return capturePolicy;
    }

    //======================
    // Audio device management
    //======================
+82 −0
Original line number Diff line number Diff line
@@ -160,6 +160,12 @@ public final class PlaybackActivityMonitor
                new AudioPlaybackConfiguration(pic, newPiid,
                        Binder.getCallingUid(), Binder.getCallingPid());
        apc.init();
        synchronized (mAllowedCapturePolicies) {
            int uid = apc.getClientUid();
            if (mAllowedCapturePolicies.containsKey(uid)) {
                updateAllowedCapturePolicy(apc, mAllowedCapturePolicies.get(uid));
            }
        }
        sEventLogger.log(new NewPlayerEvent(apc));
        synchronized(mPlayerLock) {
            mPlayers.put(newPiid, apc);
@@ -169,6 +175,13 @@ public final class PlaybackActivityMonitor

    public void playerAttributes(int piid, @NonNull AudioAttributes attr, int binderUid) {
        final boolean change;
        synchronized (mAllowedCapturePolicies) {
            if (mAllowedCapturePolicies.containsKey(binderUid)
                    && attr.getAllowedCapturePolicy() < mAllowedCapturePolicies.get(binderUid)) {
                attr = new AudioAttributes.Builder(attr)
                        .setAllowedCapturePolicy(mAllowedCapturePolicies.get(binderUid)).build();
            }
        }
        synchronized(mPlayerLock) {
            final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
            if (checkConfigurationCaller(piid, apc, binderUid)) {
@@ -284,6 +297,69 @@ public final class PlaybackActivityMonitor
        }
    }

    /**
     * A map of uid to capture policy.
     */
    private final HashMap<Integer, Integer> mAllowedCapturePolicies =
            new HashMap<Integer, Integer>();

    /**
     * Cache allowed capture policy, which specifies whether the audio played by the app may or may
     * not be captured by other apps or the system.
     *
     * @param uid the uid of requested app
     * @param capturePolicy one of
     *     {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL},
     *     {@link AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM},
     *     {@link AudioAttributes#ALLOW_CAPTURE_BY_NONE}.
     */
    public void setAllowedCapturePolicy(int uid, int capturePolicy) {
        synchronized (mAllowedCapturePolicies) {
            if (capturePolicy == AudioAttributes.ALLOW_CAPTURE_BY_ALL) {
                // When the capture policy is ALLOW_CAPTURE_BY_ALL, it is okay to
                // remove it from cached capture policy as it is the default value.
                mAllowedCapturePolicies.remove(uid);
                return;
            } else {
                mAllowedCapturePolicies.put(uid, capturePolicy);
            }
        }
        synchronized (mPlayerLock) {
            for (AudioPlaybackConfiguration apc : mPlayers.values()) {
                if (apc.getClientUid() == uid) {
                    updateAllowedCapturePolicy(apc, capturePolicy);
                }
            }
        }
    }

    /**
     * Return the capture policy for given uid.
     * @param uid the uid to query its cached capture policy.
     * @return cached capture policy for given uid or AudioAttributes.ALLOW_CAPTURE_BY_ALL
     *         if there is not cached capture policy.
     */
    public int getAllowedCapturePolicy(int uid) {
        return mAllowedCapturePolicies.getOrDefault(uid, AudioAttributes.ALLOW_CAPTURE_BY_ALL);
    }

    /**
     * Return all cached capture policies.
     */
    public HashMap<Integer, Integer> getAllAllowedCapturePolicies() {
        return mAllowedCapturePolicies;
    }

    private void updateAllowedCapturePolicy(AudioPlaybackConfiguration apc, int capturePolicy) {
        AudioAttributes attr = apc.getAudioAttributes();
        if (attr.getAllowedCapturePolicy() >= capturePolicy) {
            return;
        }
        apc.handleAudioAttributesEvent(
                new AudioAttributes.Builder(apc.getAudioAttributes())
                        .setAllowedCapturePolicy(capturePolicy).build());
    }

    // Implementation of AudioPlaybackConfiguration.PlayerDeathMonitor
    @Override
    public void playerDeath(int piid) {
@@ -331,6 +407,12 @@ public final class PlaybackActivityMonitor
            // log
            sEventLogger.dump(pw);
        }
        synchronized (mAllowedCapturePolicies) {
            pw.println("\n  allowed capture policies:");
            for (HashMap.Entry<Integer, Integer> entry : mAllowedCapturePolicies.entrySet()) {
                pw.println("  uid: " + entry.getKey() + " policy: " + entry.getValue());
            }
        }
    }

    /**