Loading api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -23279,6 +23279,7 @@ package android.media { method @Deprecated public boolean registerRemoteController(android.media.RemoteController); method @Deprecated public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int); method public int requestAudioFocus(@NonNull android.media.AudioFocusRequest); method public void setAllowedCapturePolicy(int); method @Deprecated public void setBluetoothA2dpOn(boolean); method public void setBluetoothScoOn(boolean); method public void setMicrophoneMute(boolean); core/jni/android_media_AudioSystem.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -2229,6 +2229,11 @@ android_media_AudioSystem_isHapticPlaybackSupported(JNIEnv *env, jobject thiz) return AudioSystem::isHapticPlaybackSupported(); } static jint android_media_AudioSystem_setAllowedCapturePolicy(JNIEnv *env, jobject thiz, jint uid, jint flags) { return AudioSystem::setAllowedCapturePolicy(uid, flags); } // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { Loading Loading @@ -2304,6 +2309,7 @@ static const JNINativeMethod gMethods[] = { {"isHapticPlaybackSupported", "()Z", (void *)android_media_AudioSystem_isHapticPlaybackSupported}, {"getHwOffloadEncodingFormatsSupportedForA2DP", "(Ljava/util/ArrayList;)I", (void*)android_media_AudioSystem_getHwOffloadEncodingFormatsSupportedForA2DP}, {"setAllowedCapturePolicy", "(II)I", (void *)android_media_AudioSystem_setAllowedCapturePolicy}, }; static const JNINativeMethod gEventHandlerMethods[] = { Loading media/java/android/media/AudioAttributes.java +19 −14 Original line number Diff line number Diff line Loading @@ -710,20 +710,7 @@ public final class AudioAttributes implements Parcelable { * @throws IllegalArgumentException if the argument is not a valid value. */ public @NonNull Builder setAllowedCapturePolicy(@CapturePolicy int capturePolicy) { switch (capturePolicy) { case ALLOW_CAPTURE_BY_NONE: mFlags |= FLAG_NO_MEDIA_PROJECTION | FLAG_NO_SYSTEM_CAPTURE; break; case ALLOW_CAPTURE_BY_SYSTEM: mFlags |= FLAG_NO_MEDIA_PROJECTION; mFlags &= ~FLAG_NO_SYSTEM_CAPTURE; break; case ALLOW_CAPTURE_BY_ALL: mFlags &= ~FLAG_NO_SYSTEM_CAPTURE & ~FLAG_NO_MEDIA_PROJECTION; break; default: throw new IllegalArgumentException("Unknown allow playback capture policy"); } mFlags = capturePolicyToFlags(capturePolicy, mFlags); return this; } Loading Loading @@ -1219,6 +1206,24 @@ public final class AudioAttributes implements Parcelable { } } static int capturePolicyToFlags(@CapturePolicy int capturePolicy, int flags) { switch (capturePolicy) { case ALLOW_CAPTURE_BY_NONE: flags |= FLAG_NO_MEDIA_PROJECTION | FLAG_NO_SYSTEM_CAPTURE; break; case ALLOW_CAPTURE_BY_SYSTEM: flags |= FLAG_NO_MEDIA_PROJECTION; flags &= ~FLAG_NO_SYSTEM_CAPTURE; break; case ALLOW_CAPTURE_BY_ALL: flags &= ~FLAG_NO_SYSTEM_CAPTURE & ~FLAG_NO_MEDIA_PROJECTION; break; default: throw new IllegalArgumentException("Unknown allow playback capture policy"); } return flags; } /** @hide */ @IntDef({ USAGE_UNKNOWN, Loading media/java/android/media/AudioManager.java +24 −0 Original line number Diff line number Diff line Loading @@ -1478,6 +1478,30 @@ public class AudioManager { } } /** * Specifying if this audio may or may not be captured by other apps or the system. * * The default is {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL}. * * Note that each audio track can also set its policy, in which case the most * restrictive policy is always applied. * * @param capturePolicy one of * {@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. */ 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); } } //==================================================================== // Offload query /** Loading media/java/android/media/AudioPlaybackCaptureConfiguration.java +9 −5 Original line number Diff line number Diff line Loading @@ -29,13 +29,17 @@ import com.android.internal.util.Preconditions; * Configuration for capturing audio played by other apps. * * Only the following audio can be captured: * - usage MUST be UNKNOWN or GAME or MEDIA. All other usages CAN NOT be capturable. * - audio attributes MUST NOT have the FLAG_NO_CAPTURE * - usage MUST be {@link AudioAttributes#USAGE_UNKNOWN} or {@link AudioAttributes#USAGE_GAME} * or {@link AudioAttributes#USAGE_MEDIA}. All other usages CAN NOT be captured. * - audio attributes MUST have its ${@link AudioAttributes.Builder#setAllowedCapturePolicy} * to {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL}. * - played by apps that MUST be in the same user profile as the capturing app * (eg work profile can not capture user profile apps and vice-versa). * - played by apps that MUST NOT have in their manifest.xml the application * attribute android:allowAudioPlaybackCapture="false" * - played by apps that MUST have a targetSdkVersion higher or equal to 29 (Q). * - played by apps for which the attribute allowAudioPlaybackCapture in their manifest * MUST either be: * * set to "true" * * not set, and their targetSdkVersion MUST be equal or higher to * {@link android.os.Build.VERSION_CODES#Q}. * * <p>An example for creating a capture configuration for capturing all media playback: * Loading Loading
api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -23279,6 +23279,7 @@ package android.media { method @Deprecated public boolean registerRemoteController(android.media.RemoteController); method @Deprecated public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int); method public int requestAudioFocus(@NonNull android.media.AudioFocusRequest); method public void setAllowedCapturePolicy(int); method @Deprecated public void setBluetoothA2dpOn(boolean); method public void setBluetoothScoOn(boolean); method public void setMicrophoneMute(boolean);
core/jni/android_media_AudioSystem.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -2229,6 +2229,11 @@ android_media_AudioSystem_isHapticPlaybackSupported(JNIEnv *env, jobject thiz) return AudioSystem::isHapticPlaybackSupported(); } static jint android_media_AudioSystem_setAllowedCapturePolicy(JNIEnv *env, jobject thiz, jint uid, jint flags) { return AudioSystem::setAllowedCapturePolicy(uid, flags); } // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { Loading Loading @@ -2304,6 +2309,7 @@ static const JNINativeMethod gMethods[] = { {"isHapticPlaybackSupported", "()Z", (void *)android_media_AudioSystem_isHapticPlaybackSupported}, {"getHwOffloadEncodingFormatsSupportedForA2DP", "(Ljava/util/ArrayList;)I", (void*)android_media_AudioSystem_getHwOffloadEncodingFormatsSupportedForA2DP}, {"setAllowedCapturePolicy", "(II)I", (void *)android_media_AudioSystem_setAllowedCapturePolicy}, }; static const JNINativeMethod gEventHandlerMethods[] = { Loading
media/java/android/media/AudioAttributes.java +19 −14 Original line number Diff line number Diff line Loading @@ -710,20 +710,7 @@ public final class AudioAttributes implements Parcelable { * @throws IllegalArgumentException if the argument is not a valid value. */ public @NonNull Builder setAllowedCapturePolicy(@CapturePolicy int capturePolicy) { switch (capturePolicy) { case ALLOW_CAPTURE_BY_NONE: mFlags |= FLAG_NO_MEDIA_PROJECTION | FLAG_NO_SYSTEM_CAPTURE; break; case ALLOW_CAPTURE_BY_SYSTEM: mFlags |= FLAG_NO_MEDIA_PROJECTION; mFlags &= ~FLAG_NO_SYSTEM_CAPTURE; break; case ALLOW_CAPTURE_BY_ALL: mFlags &= ~FLAG_NO_SYSTEM_CAPTURE & ~FLAG_NO_MEDIA_PROJECTION; break; default: throw new IllegalArgumentException("Unknown allow playback capture policy"); } mFlags = capturePolicyToFlags(capturePolicy, mFlags); return this; } Loading Loading @@ -1219,6 +1206,24 @@ public final class AudioAttributes implements Parcelable { } } static int capturePolicyToFlags(@CapturePolicy int capturePolicy, int flags) { switch (capturePolicy) { case ALLOW_CAPTURE_BY_NONE: flags |= FLAG_NO_MEDIA_PROJECTION | FLAG_NO_SYSTEM_CAPTURE; break; case ALLOW_CAPTURE_BY_SYSTEM: flags |= FLAG_NO_MEDIA_PROJECTION; flags &= ~FLAG_NO_SYSTEM_CAPTURE; break; case ALLOW_CAPTURE_BY_ALL: flags &= ~FLAG_NO_SYSTEM_CAPTURE & ~FLAG_NO_MEDIA_PROJECTION; break; default: throw new IllegalArgumentException("Unknown allow playback capture policy"); } return flags; } /** @hide */ @IntDef({ USAGE_UNKNOWN, Loading
media/java/android/media/AudioManager.java +24 −0 Original line number Diff line number Diff line Loading @@ -1478,6 +1478,30 @@ public class AudioManager { } } /** * Specifying if this audio may or may not be captured by other apps or the system. * * The default is {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL}. * * Note that each audio track can also set its policy, in which case the most * restrictive policy is always applied. * * @param capturePolicy one of * {@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. */ 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); } } //==================================================================== // Offload query /** Loading
media/java/android/media/AudioPlaybackCaptureConfiguration.java +9 −5 Original line number Diff line number Diff line Loading @@ -29,13 +29,17 @@ import com.android.internal.util.Preconditions; * Configuration for capturing audio played by other apps. * * Only the following audio can be captured: * - usage MUST be UNKNOWN or GAME or MEDIA. All other usages CAN NOT be capturable. * - audio attributes MUST NOT have the FLAG_NO_CAPTURE * - usage MUST be {@link AudioAttributes#USAGE_UNKNOWN} or {@link AudioAttributes#USAGE_GAME} * or {@link AudioAttributes#USAGE_MEDIA}. All other usages CAN NOT be captured. * - audio attributes MUST have its ${@link AudioAttributes.Builder#setAllowedCapturePolicy} * to {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL}. * - played by apps that MUST be in the same user profile as the capturing app * (eg work profile can not capture user profile apps and vice-versa). * - played by apps that MUST NOT have in their manifest.xml the application * attribute android:allowAudioPlaybackCapture="false" * - played by apps that MUST have a targetSdkVersion higher or equal to 29 (Q). * - played by apps for which the attribute allowAudioPlaybackCapture in their manifest * MUST either be: * * set to "true" * * not set, and their targetSdkVersion MUST be equal or higher to * {@link android.os.Build.VERSION_CODES#Q}. * * <p>An example for creating a capture configuration for capturing all media playback: * Loading