diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 302ac3cad65d0..8dc56ed15d6f3 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -1946,7 +1946,7 @@ static jint convertAudioMixToNative(JNIEnv *env, jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule); jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria); - nAudioMix->mAllowPrivilegedPlaybackCapture = + nAudioMix->mAllowPrivilegedMediaPlaybackCapture = env->GetBooleanField(jRule, gAudioMixingRuleFields.mAllowPrivilegedPlaybackCapture); nAudioMix->mVoiceCommunicationCaptureAllowed = env->GetBooleanField(jRule, gAudioMixingRuleFields.mVoiceCommunicationCaptureAllowed); diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java index 221147dcad8f3..0c733482b2b56 100644 --- a/media/java/android/media/audiopolicy/AudioMix.java +++ b/media/java/android/media/audiopolicy/AudioMix.java @@ -218,7 +218,7 @@ public class AudioMix { /** @return an error string if the format would not allow Privileged playbackCapture * null otherwise * @hide */ - public static String canBeUsedForPrivilegedCapture(AudioFormat format) { + public static String canBeUsedForPrivilegedMediaCapture(AudioFormat format) { int sampleRate = format.getSampleRate(); if (sampleRate > PRIVILEDGED_CAPTURE_MAX_SAMPLE_RATE || sampleRate <= 0) { return "Privileged audio capture sample rate " + sampleRate @@ -448,8 +448,8 @@ public class AudioMix { } } } - if (mRule.allowPrivilegedPlaybackCapture()) { - String error = AudioMix.canBeUsedForPrivilegedCapture(mFormat); + if (mRule.allowPrivilegedMediaPlaybackCapture()) { + String error = AudioMix.canBeUsedForPrivilegedMediaCapture(mFormat); if (error != null) { throw new IllegalArgumentException(error); } diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java index de153135eeb91..1f07705a4d94d 100644 --- a/media/java/android/media/audiopolicy/AudioMixingRule.java +++ b/media/java/android/media/audiopolicy/AudioMixingRule.java @@ -46,11 +46,11 @@ import java.util.Objects; public class AudioMixingRule { private AudioMixingRule(int mixType, ArrayList criteria, - boolean allowPrivilegedPlaybackCapture, + boolean allowPrivilegedMediaPlaybackCapture, boolean voiceCommunicationCaptureAllowed) { mCriteria = criteria; mTargetMixType = mixType; - mAllowPrivilegedPlaybackCapture = allowPrivilegedPlaybackCapture; + mAllowPrivilegedPlaybackCapture = allowPrivilegedMediaPlaybackCapture; mVoiceCommunicationCaptureAllowed = voiceCommunicationCaptureAllowed; } @@ -204,13 +204,17 @@ public class AudioMixingRule { private final ArrayList mCriteria; /** @hide */ public ArrayList getCriteria() { return mCriteria; } + /** Indicates that this rule is intended to capture media or game playback by a system component + * with permission CAPTURE_MEDIA_OUTPUT or CAPTURE_AUDIO_OUTPUT. + */ + //TODO b/177061175: rename to mAllowPrivilegedMediaPlaybackCapture @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private boolean mAllowPrivilegedPlaybackCapture = false; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private boolean mVoiceCommunicationCaptureAllowed = false; /** @hide */ - public boolean allowPrivilegedPlaybackCapture() { + public boolean allowPrivilegedMediaPlaybackCapture() { return mAllowPrivilegedPlaybackCapture; } @@ -311,7 +315,7 @@ public class AudioMixingRule { public static class Builder { private ArrayList mCriteria; private int mTargetMixType = AudioMix.MIX_TYPE_INVALID; - private boolean mAllowPrivilegedPlaybackCapture = false; + private boolean mAllowPrivilegedMediaPlaybackCapture = false; // This value should be set internally according to a permission check private boolean mVoiceCommunicationCaptureAllowed = false; @@ -434,7 +438,7 @@ public class AudioMixingRule { * @return the same Builder instance. */ public @NonNull Builder allowPrivilegedPlaybackCapture(boolean allow) { - mAllowPrivilegedPlaybackCapture = allow; + mAllowPrivilegedMediaPlaybackCapture = allow; return this; } @@ -639,7 +643,7 @@ public class AudioMixingRule { */ public AudioMixingRule build() { return new AudioMixingRule(mTargetMixType, mCriteria, - mAllowPrivilegedPlaybackCapture, mVoiceCommunicationCaptureAllowed); + mAllowPrivilegedMediaPlaybackCapture, mVoiceCommunicationCaptureAllowed); } } } diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java index 697d80c6b78e5..ede68bd5022b7 100644 --- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java +++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java @@ -97,7 +97,7 @@ public class AudioPolicyConfig implements Parcelable { dest.writeInt(mix.getFormat().getEncoding()); dest.writeInt(mix.getFormat().getChannelMask()); // write opt-out respect - dest.writeBoolean(mix.getRule().allowPrivilegedPlaybackCapture()); + dest.writeBoolean(mix.getRule().allowPrivilegedMediaPlaybackCapture()); // write voice communication capture allowed flag dest.writeBoolean(mix.getRule().voiceCommunicationCaptureAllowed()); // write mix rules @@ -172,7 +172,7 @@ public class AudioPolicyConfig implements Parcelable { textDump += " channels=0x"; textDump += Integer.toHexString(mix.getFormat().getChannelMask()).toUpperCase() + "\n"; textDump += " ignore playback capture opt out=" - + mix.getRule().allowPrivilegedPlaybackCapture() + "\n"; + + mix.getRule().allowPrivilegedMediaPlaybackCapture() + "\n"; textDump += " allow voice communication capture=" + mix.getRule().voiceCommunicationCaptureAllowed() + "\n"; // write mix rules diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 08eeda20b4baa..17627fa23a96c 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -8454,28 +8454,29 @@ public class AudioService extends IAudioService.Stub } for (AudioMix mix : policyConfig.getMixes()) { // If mix is requesting privileged capture - if (mix.getRule().allowPrivilegedPlaybackCapture()) { - // then it must have CAPTURE_MEDIA_OUTPUT or CAPTURE_AUDIO_OUTPUT permission - requireCaptureAudioOrMediaOutputPerm |= true; - - // and its format must be low quality enough - String error = mix.canBeUsedForPrivilegedCapture(mix.getFormat()); - if (error != null) { - Log.e(TAG, error); + if (mix.getRule().allowPrivilegedMediaPlaybackCapture()) { + // then its format must be low quality enough + String privilegedMediaCaptureError = + mix.canBeUsedForPrivilegedMediaCapture(mix.getFormat()); + if (privilegedMediaCaptureError != null) { + Log.e(TAG, privilegedMediaCaptureError); return false; } + // and it must have CAPTURE_MEDIA_OUTPUT or CAPTURE_AUDIO_OUTPUT permission + requireCaptureAudioOrMediaOutputPerm |= true; - // If mix is trying to excplicitly capture USAGE_VOICE_COMMUNICATION - if (mix.containsMatchAttributeRuleForUsage( - AudioAttributes.USAGE_VOICE_COMMUNICATION)) { - // then it must have CAPTURE_USAGE_VOICE_COMMUNICATION_OUTPUT permission - // Note that for UID, USERID or EXCLDUE rules, the capture will be silenced - // in AudioPolicyMix - if (voiceCommunicationCaptureMixes == null) { - voiceCommunicationCaptureMixes = new ArrayList(); - } - voiceCommunicationCaptureMixes.add(mix); + } + // If mix is trying to explicitly capture USAGE_VOICE_COMMUNICATION + if (mix.containsMatchAttributeRuleForUsage( + AudioAttributes.USAGE_VOICE_COMMUNICATION) + && (mix.getRouteFlags() == mix.ROUTE_FLAG_LOOP_BACK_RENDER)) { + // It must have CAPTURE_USAGE_VOICE_COMMUNICATION_OUTPUT permission + // Note that for UID, USERID or EXCLDUE rules, the capture will be silenced + // in AudioPolicyMix + if (voiceCommunicationCaptureMixes == null) { + voiceCommunicationCaptureMixes = new ArrayList(); } + voiceCommunicationCaptureMixes.add(mix); } // If mix is RENDER|LOOPBACK, then an audio MediaProjection is enough @@ -8498,7 +8499,7 @@ public class AudioService extends IAudioService.Stub if (voiceCommunicationCaptureMixes != null && voiceCommunicationCaptureMixes.size() > 0) { if (!callerHasPermission( android.Manifest.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT)) { - Log.e(TAG, "Privileged audio capture for voice communication requires " + Log.e(TAG, "Audio capture for voice communication requires " + "CAPTURE_VOICE_COMMUNICATION_OUTPUT system permission"); return false; }