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

This commit is contained in:
Nadav Bar
2020-03-05 11:58:53 +00:00
committed by Android (Google) Code Review
5 changed files with 165 additions and 13 deletions

View File

@@ -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;

View File

@@ -1507,23 +1507,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
@@ -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;
}
//====================================================================

View File

@@ -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.
}

View File

@@ -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
//======================

View File

@@ -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());
}
}
}
/**