From 37839213235b20231b21388f034c421c55267ede Mon Sep 17 00:00:00 2001 From: kholoud mohamed Date: Mon, 15 Mar 2021 16:49:06 +0000 Subject: [PATCH] Created a new testAPI isFullVolumeDevice in AudioManager * Created isFullVolumeDevice to replace usage of dumpsys audio in cts tests. * Added a new permission QUERY_AUDIO_STATE to the newly created API and the existing API that it depends on: - getDevicesForAttributes - getDeviceVolumeBehavior Test: The new API is accessible from cts tests Bug: 182260585 Change-Id: I9d6bd24695ae306930b2518b1b12288aca46ebe9 --- core/api/system-current.txt | 4 +-- core/api/test-current.txt | 1 + media/java/android/media/AudioManager.java | 32 +++++++++++++++++-- .../android/server/audio/AudioService.java | 14 ++++++-- 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 54c666314f985..102636ed28a07 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -5050,8 +5050,8 @@ package android.media { method @IntRange(from=0) public long getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List getAudioProductStrategies(); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List getAudioVolumeGroups(); - method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getDeviceVolumeBehavior(@NonNull android.media.AudioDeviceAttributes); - method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List getDevicesForAttributes(@NonNull android.media.AudioAttributes); + method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE"}) public int getDeviceVolumeBehavior(@NonNull android.media.AudioDeviceAttributes); + method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE"}) public java.util.List getDevicesForAttributes(@NonNull android.media.AudioAttributes); method @IntRange(from=0) public long getMaxAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo); method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); diff --git a/core/api/test-current.txt b/core/api/test-current.txt index e486fa2c2e29f..9892c361b7117 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1329,6 +1329,7 @@ package android.media { public class AudioManager { method @Nullable public static android.media.AudioDeviceInfo getDeviceInfoFromType(int); method public boolean hasRegisteredDynamicPolicy(); + method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, android.Manifest.permission.QUERY_AUDIO_STATE}) public boolean isFullVolumeDevice(); } public static final class AudioRecord.MetricsConstants { diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index e8e263147c6e7..9e9d02e4eebfe 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -5287,7 +5287,10 @@ public class AudioManager { * otherwise (typically one device, except for duplicated paths). */ @SystemApi - @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + @RequiresPermission(anyOf = { + android.Manifest.permission.MODIFY_AUDIO_ROUTING, + android.Manifest.permission.QUERY_AUDIO_STATE + }) public @NonNull List getDevicesForAttributes( @NonNull AudioAttributes attributes) { Objects.requireNonNull(attributes); @@ -5426,7 +5429,10 @@ public class AudioManager { * @return the volume behavior for the device */ @SystemApi - @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + @RequiresPermission(anyOf = { + android.Manifest.permission.MODIFY_AUDIO_ROUTING, + android.Manifest.permission.QUERY_AUDIO_STATE + }) public @DeviceVolumeBehavior int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device) { // verify arguments (validity of device type is enforced in server) @@ -5440,6 +5446,28 @@ public class AudioManager { } } + /** + * @hide + * Returns {@code true} if the volume device behavior is {@link #DEVICE_VOLUME_BEHAVIOR_FULL}. + */ + @TestApi + @RequiresPermission(anyOf = { + android.Manifest.permission.MODIFY_AUDIO_ROUTING, + android.Manifest.permission.QUERY_AUDIO_STATE + }) + public boolean isFullVolumeDevice() { + final AudioAttributes attributes = new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_MEDIA) + .build(); + final List devices = getDevicesForAttributes(attributes); + for (AudioDeviceAttributes device : devices) { + if (getDeviceVolumeBehavior(device) == DEVICE_VOLUME_BEHAVIOR_FULL) { + return true; + } + } + return false; + } + /** * Indicate wired accessory connection state change. * @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx) diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 1950710a36e0a..0a6847515137f 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -2258,7 +2258,7 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#getDevicesForAttributes(AudioAttributes) */ public @NonNull ArrayList getDevicesForAttributes( @NonNull AudioAttributes attributes) { - enforceModifyAudioRoutingPermission(); + enforceQueryStateOrModifyRoutingPermission(); return getDevicesForAttributesInt(attributes); } @@ -2900,6 +2900,16 @@ public class AudioService extends IAudioService.Stub } } + private void enforceQueryStateOrModifyRoutingPermission() { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + != PackageManager.PERMISSION_GRANTED + && mContext.checkCallingOrSelfPermission(Manifest.permission.QUERY_AUDIO_STATE) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException( + "Missing MODIFY_AUDIO_ROUTING or QUERY_AUDIO_STATE permissions"); + } + } + /** @see AudioManager#setVolumeIndexForAttributes(attr, int, int) */ public void setVolumeIndexForAttributes(@NonNull AudioAttributes attr, int index, int flags, String callingPackage) { @@ -5814,7 +5824,7 @@ public class AudioService extends IAudioService.Stub public @AudioManager.DeviceVolumeBehavior int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device) { // verify permissions - enforceModifyAudioRoutingPermission(); + enforceQueryStateOrModifyRoutingPermission(); // translate Java device type to native device type (for the devices masks for full / fixed) final int audioSystemDeviceOut = AudioDeviceInfo.convertDeviceTypeToInternalDevice(