summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--media/java/android/media/AudioAttributes.java5
-rw-r--r--media/java/android/media/AudioManager.java29
-rw-r--r--media/java/android/media/IAudioService.aidl4
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java58
-rw-r--r--services/core/java/com/android/server/audio/PlaybackActivityMonitor.java82
5 files changed, 165 insertions, 13 deletions
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 114c0f1f6bf3..fe0c2d21d442 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -1427,7 +1427,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;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 861b76d2b153..7b17f9f764fb 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1547,23 +1547,22 @@ 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);
- if (result != AudioSystem.AUDIO_STATUS_OK) {
- Log.e(TAG, "Could not setAllowedCapturePolicy: " + result);
- return;
+ final IAudioService service = getService();
+ try {
+ int result = service.setAllowedCapturePolicy(capturePolicy);
+ if (result != AudioSystem.AUDIO_STATUS_OK) {
+ Log.e(TAG, "Could not setAllowedCapturePolicy: " + result);
+ return;
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- mCapturePolicy = capturePolicy;
}
- @AudioAttributes.CapturePolicy
- private int mCapturePolicy = AudioAttributes.ALLOW_CAPTURE_BY_ALL;
-
/**
* Return the capture policy.
* @return the capture policy set by {@link #setAllowedCapturePolicy(int)} or
@@ -1571,7 +1570,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;
}
//====================================================================
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 1f97be5c3f4d..64c5c05b5621 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -282,6 +282,10 @@ interface IAudioService {
List<AudioDeviceAddress> getDevicesForAttributes(in AudioAttributes attributes);
+ 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.
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 8f6bd212da19..b2548af0f576 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1068,6 +1068,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");
@@ -7298,6 +7319,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
//======================
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index f8ba55bcd092..98f409ea98e7 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -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());
+ }
+ }
}
/**