Merge "Set/get allowed capture policy via AudioService." into qt-qpr1-dev
This commit is contained in:
@@ -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) {
|
switch (capturePolicy) {
|
||||||
case ALLOW_CAPTURE_BY_NONE:
|
case ALLOW_CAPTURE_BY_NONE:
|
||||||
flags |= FLAG_NO_MEDIA_PROJECTION | FLAG_NO_SYSTEM_CAPTURE;
|
flags |= FLAG_NO_MEDIA_PROJECTION | FLAG_NO_SYSTEM_CAPTURE;
|
||||||
|
|||||||
@@ -1507,23 +1507,22 @@ public class AudioManager {
|
|||||||
* {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL},
|
* {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL},
|
||||||
* {@link AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM},
|
* {@link AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM},
|
||||||
* {@link AudioAttributes#ALLOW_CAPTURE_BY_NONE}.
|
* {@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) {
|
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
|
// TODO: also pass the package in case multiple packages have the same UID
|
||||||
int result = AudioSystem.setAllowedCapturePolicy(Process.myUid(), flags);
|
final IAudioService service = getService();
|
||||||
if (result != AudioSystem.AUDIO_STATUS_OK) {
|
try {
|
||||||
Log.e(TAG, "Could not setAllowedCapturePolicy: " + result);
|
int result = service.setAllowedCapturePolicy(capturePolicy);
|
||||||
return;
|
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.
|
||||||
* @return the capture policy set by {@link #setAllowedCapturePolicy(int)} or
|
* @return the capture policy set by {@link #setAllowedCapturePolicy(int)} or
|
||||||
@@ -1531,7 +1530,13 @@ public class AudioManager {
|
|||||||
*/
|
*/
|
||||||
@AudioAttributes.CapturePolicy
|
@AudioAttributes.CapturePolicy
|
||||||
public int getAllowedCapturePolicy() {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
//====================================================================
|
//====================================================================
|
||||||
|
|||||||
@@ -259,6 +259,10 @@ interface IAudioService {
|
|||||||
|
|
||||||
boolean hasHapticChannels(in Uri uri);
|
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
|
// 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.
|
// code via IAudioManager.h need to be added to the top section.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
onIndicateSystemReady();
|
||||||
// indicate the end of reconfiguration phase to audio HAL
|
// indicate the end of reconfiguration phase to audio HAL
|
||||||
AudioSystem.setParameters("restarting=false");
|
AudioSystem.setParameters("restarting=false");
|
||||||
@@ -7250,6 +7271,43 @@ public class AudioService extends IAudioService.Stub
|
|||||||
mPlaybackMonitor.releasePlayer(piid, Binder.getCallingUid());
|
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
|
// Audio device management
|
||||||
//======================
|
//======================
|
||||||
|
|||||||
@@ -160,6 +160,12 @@ public final class PlaybackActivityMonitor
|
|||||||
new AudioPlaybackConfiguration(pic, newPiid,
|
new AudioPlaybackConfiguration(pic, newPiid,
|
||||||
Binder.getCallingUid(), Binder.getCallingPid());
|
Binder.getCallingUid(), Binder.getCallingPid());
|
||||||
apc.init();
|
apc.init();
|
||||||
|
synchronized (mAllowedCapturePolicies) {
|
||||||
|
int uid = apc.getClientUid();
|
||||||
|
if (mAllowedCapturePolicies.containsKey(uid)) {
|
||||||
|
updateAllowedCapturePolicy(apc, mAllowedCapturePolicies.get(uid));
|
||||||
|
}
|
||||||
|
}
|
||||||
sEventLogger.log(new NewPlayerEvent(apc));
|
sEventLogger.log(new NewPlayerEvent(apc));
|
||||||
synchronized(mPlayerLock) {
|
synchronized(mPlayerLock) {
|
||||||
mPlayers.put(newPiid, apc);
|
mPlayers.put(newPiid, apc);
|
||||||
@@ -169,6 +175,13 @@ public final class PlaybackActivityMonitor
|
|||||||
|
|
||||||
public void playerAttributes(int piid, @NonNull AudioAttributes attr, int binderUid) {
|
public void playerAttributes(int piid, @NonNull AudioAttributes attr, int binderUid) {
|
||||||
final boolean change;
|
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) {
|
synchronized(mPlayerLock) {
|
||||||
final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
|
final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
|
||||||
if (checkConfigurationCaller(piid, apc, binderUid)) {
|
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
|
// Implementation of AudioPlaybackConfiguration.PlayerDeathMonitor
|
||||||
@Override
|
@Override
|
||||||
public void playerDeath(int piid) {
|
public void playerDeath(int piid) {
|
||||||
@@ -331,6 +407,12 @@ public final class PlaybackActivityMonitor
|
|||||||
// log
|
// log
|
||||||
sEventLogger.dump(pw);
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user