diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 669bfc5a1b32d..7d5c18c9ec4e6 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -96,8 +96,6 @@ public class AudioManager { private Context mOriginalContext; private Context mApplicationContext; private long mVolumeKeyUpTime; - private boolean mUseFixedVolumeInitialized; - private boolean mUseFixedVolume; private static final String TAG = "AudioManager"; private static final boolean DEBUG = false; private static final AudioPortEventHandler sAudioPortEventHandler = new AudioPortEventHandler(); @@ -893,19 +891,13 @@ public class AudioManager { * */ public boolean isVolumeFixed() { - synchronized (this) { - try { - if (!mUseFixedVolumeInitialized) { - mUseFixedVolume = getContext().getResources().getBoolean( - com.android.internal.R.bool.config_useFixedVolume); - } - } catch (Exception e) { - } finally { - // only ever try once, so always consider initialized even if query failed - mUseFixedVolumeInitialized = true; - } + boolean res = false; + try { + res = getService().isVolumeFixed(); + } catch (RemoteException e) { + Log.e(TAG, "Error querying isVolumeFixed", e); } - return mUseFixedVolume; + return res; } /** diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 067f8215829c4..2f4e1fd2e801c 100755 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -456,4 +456,6 @@ interface IAudioService { void registerSpatializerOutputCallback(in ISpatializerOutputCallback cb); void unregisterSpatializerOutputCallback(in ISpatializerOutputCallback cb); + + boolean isVolumeFixed(); } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index e8b0e08ed710b..f6f605fc4c088 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -6185,9 +6185,15 @@ public class AudioService extends IAudioService.Stub */ public @AudioManager.DeviceVolumeBehavior int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device) { + Objects.requireNonNull(device); // verify permissions enforceQueryStateOrModifyRoutingPermission(); + return getDeviceVolumeBehaviorInt(device); + } + + private @AudioManager.DeviceVolumeBehavior + int getDeviceVolumeBehaviorInt(@NonNull AudioDeviceAttributes device) { // translate Java device type to native device type (for the devices masks for full / fixed) final int audioSystemDeviceOut = AudioDeviceInfo.convertDeviceTypeToInternalDevice( device.getType()); @@ -6215,6 +6221,29 @@ public class AudioService extends IAudioService.Stub return AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE; } + /** + * @see AudioManager#isVolumeFixed() + * Note there are no permission checks on this operation, as this is part of API 21 + * @return true if the current device's volume behavior for media is + * DEVICE_VOLUME_BEHAVIOR_FIXED + */ + public boolean isVolumeFixed() { + if (mUseFixedVolume) { + return true; + } + final AudioAttributes attributes = new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_MEDIA) + .build(); + // calling getDevice*Int to bypass permission check + final List devices = getDevicesForAttributesInt(attributes); + for (AudioDeviceAttributes device : devices) { + if (getDeviceVolumeBehaviorInt(device) == AudioManager.DEVICE_VOLUME_BEHAVIOR_FIXED) { + return true; + } + } + return false; + } + /*package*/ static final int CONNECTION_STATE_DISCONNECTED = 0; /*package*/ static final int CONNECTION_STATE_CONNECTED = 1; /**