Loading media/java/android/media/AudioDeviceAttributes.java +4 −4 Original line number Diff line number Diff line Loading @@ -99,11 +99,11 @@ public final class AudioDeviceAttributes implements Parcelable { if (role != ROLE_OUTPUT && role != ROLE_INPUT) { throw new IllegalArgumentException("Invalid role " + role); } if (role == ROLE_OUTPUT && !AudioDeviceInfo.isValidAudioDeviceTypeOut(type)) { throw new IllegalArgumentException("Invalid output device type " + type); if (role == ROLE_OUTPUT) { AudioDeviceInfo.enforceValidAudioDeviceTypeOut(type); } if (role == ROLE_INPUT && !AudioDeviceInfo.isValidAudioDeviceTypeIn(type)) { throw new IllegalArgumentException("Invalid input device type " + type); if (role == ROLE_INPUT) { AudioDeviceInfo.enforceValidAudioDeviceTypeIn(type); } mRole = role; Loading media/java/android/media/AudioDeviceInfo.java +22 −0 Original line number Diff line number Diff line Loading @@ -280,6 +280,28 @@ public final class AudioDeviceInfo { } } /** * @hide * Throws IAE on an invalid output device type * @param type */ public static void enforceValidAudioDeviceTypeOut(int type) { if (!isValidAudioDeviceTypeOut(type)) { throw new IllegalArgumentException("Illegal output device type " + type); } } /** * @hide * Throws IAE on an invalid input device type * @param type */ public static void enforceValidAudioDeviceTypeIn(int type) { if (!isValidAudioDeviceTypeIn(type)) { throw new IllegalArgumentException("Illegal input device type " + type); } } @Override public boolean equals(Object o) { if (this == o) return true; Loading media/java/android/media/AudioManager.java +144 −0 Original line number Diff line number Diff line Loading @@ -4571,6 +4571,150 @@ public class AudioManager { } } /** * @hide * Volume behavior for an audio device where a software attenuation is applied * @see #setDeviceVolumeBehavior(int, String, int) */ public static final int DEVICE_VOLUME_BEHAVIOR_VARIABLE = 0; /** * @hide * Volume behavior for an audio device where the volume is always set to provide no attenuation * nor gain (e.g. unit gain). * @see #setDeviceVolumeBehavior(int, String, int) */ public static final int DEVICE_VOLUME_BEHAVIOR_FULL = 1; /** * @hide * Volume behavior for an audio device where the volume is either set to muted, or to provide * no attenuation nor gain (e.g. unit gain). * @see #setDeviceVolumeBehavior(int, String, int) */ public static final int DEVICE_VOLUME_BEHAVIOR_FIXED = 2; /** * @hide * Volume behavior for an audio device where no software attenuation is applied, and * the volume is kept synchronized between the host and the device itself through a * device-specific protocol such as BT AVRCP. * @see #setDeviceVolumeBehavior(int, String, int) */ public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE = 3; /** * @hide * Volume behavior for an audio device where no software attenuation is applied, and * the volume is kept synchronized between the host and the device itself through a * device-specific protocol (such as for hearing aids), based on the audio mode (e.g. * normal vs in phone call). * @see #setMode(int) * @see #setDeviceVolumeBehavior(int, String, int) */ public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE = 4; /** @hide */ @IntDef({ DEVICE_VOLUME_BEHAVIOR_VARIABLE, DEVICE_VOLUME_BEHAVIOR_FULL, DEVICE_VOLUME_BEHAVIOR_FIXED, DEVICE_VOLUME_BEHAVIOR_ABSOLUTE, DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE, }) @Retention(RetentionPolicy.SOURCE) public @interface DeviceVolumeBehavior {} /** * @hide * Throws IAE on an invalid volume behavior value * @param volumeBehavior behavior value to check */ public static void enforceValidVolumeBehavior(int volumeBehavior) { switch (volumeBehavior) { case DEVICE_VOLUME_BEHAVIOR_VARIABLE: case DEVICE_VOLUME_BEHAVIOR_FULL: case DEVICE_VOLUME_BEHAVIOR_FIXED: case DEVICE_VOLUME_BEHAVIOR_ABSOLUTE: case DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE: return; default: throw new IllegalArgumentException("Illegal volume behavior " + volumeBehavior); } } /** * @hide * Sets the volume behavior for an audio output device. * @param deviceType the type of audio device to be affected. Currently only supports * {@link AudioDeviceInfo#TYPE_HDMI}, {@link AudioDeviceInfo#TYPE_HDMI_ARC}, * {@link AudioDeviceInfo#TYPE_LINE_DIGITAL} and {@link AudioDeviceInfo#TYPE_AUX_LINE} * @param deviceAddress the address of the device, if any * @param deviceVolumeBehavior one of the device behaviors */ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setDeviceVolumeBehavior(int deviceType, @Nullable String deviceAddress, @DeviceVolumeBehavior int deviceVolumeBehavior) { setDeviceVolumeBehavior(new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT, deviceType, deviceAddress), deviceVolumeBehavior); } /** * @hide * Sets the volume behavior for an audio output device. * @param device the device to be affected. Currently only supports devices of type * {@link AudioDeviceInfo#TYPE_HDMI}, {@link AudioDeviceInfo#TYPE_HDMI_ARC}, * {@link AudioDeviceInfo#TYPE_LINE_DIGITAL} and {@link AudioDeviceInfo#TYPE_AUX_LINE} * @param deviceVolumeBehavior one of the device behaviors */ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device, @DeviceVolumeBehavior int deviceVolumeBehavior) { // verify arguments (validity of device type is enforced in server) Objects.requireNonNull(device); enforceValidVolumeBehavior(deviceVolumeBehavior); // communicate with service final IAudioService service = getService(); try { service.setDeviceVolumeBehavior(device, deviceVolumeBehavior, mApplicationContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * @hide * Returns the volume device behavior for the given device type and address * @param deviceType an audio output device type, as defined in {@link AudioDeviceInfo} * @param deviceAddress the address of the audio device, if any. * @return the volume behavior for the device */ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public @DeviceVolumeBehavior int getDeviceVolumeBehavior(int deviceType, @Nullable String deviceAddress) { // verify arguments AudioDeviceInfo.enforceValidAudioDeviceTypeOut(deviceType); return getDeviceVolumeBehavior(new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT, deviceType, deviceAddress)); } /** * @hide * Returns the volume device behavior for the given audio device * @param device the audio device * @return the volume behavior for the device */ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public @DeviceVolumeBehavior int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device) { // verify arguments (validity of device type is enforced in server) Objects.requireNonNull(device); // communicate with service final IAudioService service = getService(); try { return service.getDeviceVolumeBehavior(device); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Indicate wired accessory connection state change. * @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx) Loading media/java/android/media/IAudioService.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -294,6 +294,11 @@ interface IAudioService { oneway void setRttEnabled(in boolean rttEnabled); void setDeviceVolumeBehavior(in AudioDeviceAttributes device, in int deviceVolumeBehavior, in String pkgName); int getDeviceVolumeBehavior(in AudioDeviceAttributes device); // 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. } services/core/java/com/android/server/audio/AudioService.java +112 −2 Original line number Diff line number Diff line Loading @@ -2332,8 +2332,7 @@ public class AudioService extends IAudioService.Stub } private void enforceModifyAudioRoutingPermission() { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.MODIFY_AUDIO_ROUTING) if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Missing MODIFY_AUDIO_ROUTING permission"); } Loading Loading @@ -4610,6 +4609,117 @@ public class AudioService extends IAudioService.Stub observeDevicesForStreams(-1); } /** * @see AudioManager#setDeviceVolumeBehavior(AudioDeviceAttributes, int) * @param device the audio device to be affected * @param deviceVolumeBehavior one of the device behaviors */ public void setDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device, @AudioManager.DeviceVolumeBehavior int deviceVolumeBehavior, @Nullable String pkgName) { // verify permissions enforceModifyAudioRoutingPermission(); // verify arguments Objects.requireNonNull(device); AudioManager.enforceValidVolumeBehavior(deviceVolumeBehavior); if (pkgName == null) { pkgName = ""; } // translate Java device type to native device type (for the devices masks for full / fixed) final int type; switch (device.getType()) { case AudioDeviceInfo.TYPE_HDMI: type = AudioSystem.DEVICE_OUT_HDMI; break; case AudioDeviceInfo.TYPE_HDMI_ARC: type = AudioSystem.DEVICE_OUT_HDMI_ARC; break; case AudioDeviceInfo.TYPE_LINE_DIGITAL: type = AudioSystem.DEVICE_OUT_SPDIF; break; case AudioDeviceInfo.TYPE_AUX_LINE: type = AudioSystem.DEVICE_OUT_LINE; break; default: // unsupported for now throw new IllegalArgumentException("Unsupported device type " + device.getType()); } // update device masks based on volume behavior switch (deviceVolumeBehavior) { case AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE: mFullVolumeDevices.remove(type); mFixedVolumeDevices.remove(type); break; case AudioManager.DEVICE_VOLUME_BEHAVIOR_FIXED: mFullVolumeDevices.remove(type); mFixedVolumeDevices.add(type); break; case AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL: mFullVolumeDevices.add(type); mFixedVolumeDevices.remove(type); break; case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE: case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE: throw new IllegalArgumentException("Absolute volume unsupported for now"); } // log event and caller sDeviceLogger.log(new AudioEventLogger.StringEvent( "Volume behavior " + deviceVolumeBehavior + " for dev=0x" + Integer.toHexString(type) + " by pkg:" + pkgName)); // make sure we have a volume entry for this device, and that volume is updated according // to volume behavior checkAddAllFixedVolumeDevices(type, "setDeviceVolumeBehavior:" + pkgName); } /** * @see AudioManager#getDeviceVolumeBehavior(AudioDeviceAttributes) * @param device the audio output device type * @return the volume behavior for the device */ public @AudioManager.DeviceVolumeBehavior int getDeviceVolumeBehavior( @NonNull AudioDeviceAttributes device) { // verify permissions enforceModifyAudioRoutingPermission(); // translate Java device type to native device type (for the devices masks for full / fixed) final int type; switch (device.getType()) { case AudioDeviceInfo.TYPE_HEARING_AID: type = AudioSystem.DEVICE_OUT_HEARING_AID; break; case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP: type = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; break; case AudioDeviceInfo.TYPE_HDMI: type = AudioSystem.DEVICE_OUT_HDMI; break; case AudioDeviceInfo.TYPE_HDMI_ARC: type = AudioSystem.DEVICE_OUT_HDMI_ARC; break; case AudioDeviceInfo.TYPE_LINE_DIGITAL: type = AudioSystem.DEVICE_OUT_SPDIF; break; case AudioDeviceInfo.TYPE_AUX_LINE: type = AudioSystem.DEVICE_OUT_LINE; break; default: // unsupported for now throw new IllegalArgumentException("Unsupported device type " + device.getType()); } if ((mFullVolumeDevices.contains(type))) { return AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL; } if ((mFixedVolumeDevices.contains(type))) { return AudioManager.DEVICE_VOLUME_BEHAVIOR_FIXED; } if ((mAbsVolumeMultiModeCaseDevices.contains(type))) { return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE; } if (type == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP && mDeviceBroker.isAvrcpAbsoluteVolumeSupported()) { return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE; } return AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE; } /*package*/ static final int CONNECTION_STATE_DISCONNECTED = 0; /*package*/ static final int CONNECTION_STATE_CONNECTED = 1; /** Loading Loading
media/java/android/media/AudioDeviceAttributes.java +4 −4 Original line number Diff line number Diff line Loading @@ -99,11 +99,11 @@ public final class AudioDeviceAttributes implements Parcelable { if (role != ROLE_OUTPUT && role != ROLE_INPUT) { throw new IllegalArgumentException("Invalid role " + role); } if (role == ROLE_OUTPUT && !AudioDeviceInfo.isValidAudioDeviceTypeOut(type)) { throw new IllegalArgumentException("Invalid output device type " + type); if (role == ROLE_OUTPUT) { AudioDeviceInfo.enforceValidAudioDeviceTypeOut(type); } if (role == ROLE_INPUT && !AudioDeviceInfo.isValidAudioDeviceTypeIn(type)) { throw new IllegalArgumentException("Invalid input device type " + type); if (role == ROLE_INPUT) { AudioDeviceInfo.enforceValidAudioDeviceTypeIn(type); } mRole = role; Loading
media/java/android/media/AudioDeviceInfo.java +22 −0 Original line number Diff line number Diff line Loading @@ -280,6 +280,28 @@ public final class AudioDeviceInfo { } } /** * @hide * Throws IAE on an invalid output device type * @param type */ public static void enforceValidAudioDeviceTypeOut(int type) { if (!isValidAudioDeviceTypeOut(type)) { throw new IllegalArgumentException("Illegal output device type " + type); } } /** * @hide * Throws IAE on an invalid input device type * @param type */ public static void enforceValidAudioDeviceTypeIn(int type) { if (!isValidAudioDeviceTypeIn(type)) { throw new IllegalArgumentException("Illegal input device type " + type); } } @Override public boolean equals(Object o) { if (this == o) return true; Loading
media/java/android/media/AudioManager.java +144 −0 Original line number Diff line number Diff line Loading @@ -4571,6 +4571,150 @@ public class AudioManager { } } /** * @hide * Volume behavior for an audio device where a software attenuation is applied * @see #setDeviceVolumeBehavior(int, String, int) */ public static final int DEVICE_VOLUME_BEHAVIOR_VARIABLE = 0; /** * @hide * Volume behavior for an audio device where the volume is always set to provide no attenuation * nor gain (e.g. unit gain). * @see #setDeviceVolumeBehavior(int, String, int) */ public static final int DEVICE_VOLUME_BEHAVIOR_FULL = 1; /** * @hide * Volume behavior for an audio device where the volume is either set to muted, or to provide * no attenuation nor gain (e.g. unit gain). * @see #setDeviceVolumeBehavior(int, String, int) */ public static final int DEVICE_VOLUME_BEHAVIOR_FIXED = 2; /** * @hide * Volume behavior for an audio device where no software attenuation is applied, and * the volume is kept synchronized between the host and the device itself through a * device-specific protocol such as BT AVRCP. * @see #setDeviceVolumeBehavior(int, String, int) */ public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE = 3; /** * @hide * Volume behavior for an audio device where no software attenuation is applied, and * the volume is kept synchronized between the host and the device itself through a * device-specific protocol (such as for hearing aids), based on the audio mode (e.g. * normal vs in phone call). * @see #setMode(int) * @see #setDeviceVolumeBehavior(int, String, int) */ public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE = 4; /** @hide */ @IntDef({ DEVICE_VOLUME_BEHAVIOR_VARIABLE, DEVICE_VOLUME_BEHAVIOR_FULL, DEVICE_VOLUME_BEHAVIOR_FIXED, DEVICE_VOLUME_BEHAVIOR_ABSOLUTE, DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE, }) @Retention(RetentionPolicy.SOURCE) public @interface DeviceVolumeBehavior {} /** * @hide * Throws IAE on an invalid volume behavior value * @param volumeBehavior behavior value to check */ public static void enforceValidVolumeBehavior(int volumeBehavior) { switch (volumeBehavior) { case DEVICE_VOLUME_BEHAVIOR_VARIABLE: case DEVICE_VOLUME_BEHAVIOR_FULL: case DEVICE_VOLUME_BEHAVIOR_FIXED: case DEVICE_VOLUME_BEHAVIOR_ABSOLUTE: case DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE: return; default: throw new IllegalArgumentException("Illegal volume behavior " + volumeBehavior); } } /** * @hide * Sets the volume behavior for an audio output device. * @param deviceType the type of audio device to be affected. Currently only supports * {@link AudioDeviceInfo#TYPE_HDMI}, {@link AudioDeviceInfo#TYPE_HDMI_ARC}, * {@link AudioDeviceInfo#TYPE_LINE_DIGITAL} and {@link AudioDeviceInfo#TYPE_AUX_LINE} * @param deviceAddress the address of the device, if any * @param deviceVolumeBehavior one of the device behaviors */ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setDeviceVolumeBehavior(int deviceType, @Nullable String deviceAddress, @DeviceVolumeBehavior int deviceVolumeBehavior) { setDeviceVolumeBehavior(new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT, deviceType, deviceAddress), deviceVolumeBehavior); } /** * @hide * Sets the volume behavior for an audio output device. * @param device the device to be affected. Currently only supports devices of type * {@link AudioDeviceInfo#TYPE_HDMI}, {@link AudioDeviceInfo#TYPE_HDMI_ARC}, * {@link AudioDeviceInfo#TYPE_LINE_DIGITAL} and {@link AudioDeviceInfo#TYPE_AUX_LINE} * @param deviceVolumeBehavior one of the device behaviors */ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device, @DeviceVolumeBehavior int deviceVolumeBehavior) { // verify arguments (validity of device type is enforced in server) Objects.requireNonNull(device); enforceValidVolumeBehavior(deviceVolumeBehavior); // communicate with service final IAudioService service = getService(); try { service.setDeviceVolumeBehavior(device, deviceVolumeBehavior, mApplicationContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * @hide * Returns the volume device behavior for the given device type and address * @param deviceType an audio output device type, as defined in {@link AudioDeviceInfo} * @param deviceAddress the address of the audio device, if any. * @return the volume behavior for the device */ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public @DeviceVolumeBehavior int getDeviceVolumeBehavior(int deviceType, @Nullable String deviceAddress) { // verify arguments AudioDeviceInfo.enforceValidAudioDeviceTypeOut(deviceType); return getDeviceVolumeBehavior(new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT, deviceType, deviceAddress)); } /** * @hide * Returns the volume device behavior for the given audio device * @param device the audio device * @return the volume behavior for the device */ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public @DeviceVolumeBehavior int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device) { // verify arguments (validity of device type is enforced in server) Objects.requireNonNull(device); // communicate with service final IAudioService service = getService(); try { return service.getDeviceVolumeBehavior(device); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Indicate wired accessory connection state change. * @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx) Loading
media/java/android/media/IAudioService.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -294,6 +294,11 @@ interface IAudioService { oneway void setRttEnabled(in boolean rttEnabled); void setDeviceVolumeBehavior(in AudioDeviceAttributes device, in int deviceVolumeBehavior, in String pkgName); int getDeviceVolumeBehavior(in AudioDeviceAttributes device); // 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. }
services/core/java/com/android/server/audio/AudioService.java +112 −2 Original line number Diff line number Diff line Loading @@ -2332,8 +2332,7 @@ public class AudioService extends IAudioService.Stub } private void enforceModifyAudioRoutingPermission() { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.MODIFY_AUDIO_ROUTING) if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Missing MODIFY_AUDIO_ROUTING permission"); } Loading Loading @@ -4610,6 +4609,117 @@ public class AudioService extends IAudioService.Stub observeDevicesForStreams(-1); } /** * @see AudioManager#setDeviceVolumeBehavior(AudioDeviceAttributes, int) * @param device the audio device to be affected * @param deviceVolumeBehavior one of the device behaviors */ public void setDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device, @AudioManager.DeviceVolumeBehavior int deviceVolumeBehavior, @Nullable String pkgName) { // verify permissions enforceModifyAudioRoutingPermission(); // verify arguments Objects.requireNonNull(device); AudioManager.enforceValidVolumeBehavior(deviceVolumeBehavior); if (pkgName == null) { pkgName = ""; } // translate Java device type to native device type (for the devices masks for full / fixed) final int type; switch (device.getType()) { case AudioDeviceInfo.TYPE_HDMI: type = AudioSystem.DEVICE_OUT_HDMI; break; case AudioDeviceInfo.TYPE_HDMI_ARC: type = AudioSystem.DEVICE_OUT_HDMI_ARC; break; case AudioDeviceInfo.TYPE_LINE_DIGITAL: type = AudioSystem.DEVICE_OUT_SPDIF; break; case AudioDeviceInfo.TYPE_AUX_LINE: type = AudioSystem.DEVICE_OUT_LINE; break; default: // unsupported for now throw new IllegalArgumentException("Unsupported device type " + device.getType()); } // update device masks based on volume behavior switch (deviceVolumeBehavior) { case AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE: mFullVolumeDevices.remove(type); mFixedVolumeDevices.remove(type); break; case AudioManager.DEVICE_VOLUME_BEHAVIOR_FIXED: mFullVolumeDevices.remove(type); mFixedVolumeDevices.add(type); break; case AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL: mFullVolumeDevices.add(type); mFixedVolumeDevices.remove(type); break; case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE: case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE: throw new IllegalArgumentException("Absolute volume unsupported for now"); } // log event and caller sDeviceLogger.log(new AudioEventLogger.StringEvent( "Volume behavior " + deviceVolumeBehavior + " for dev=0x" + Integer.toHexString(type) + " by pkg:" + pkgName)); // make sure we have a volume entry for this device, and that volume is updated according // to volume behavior checkAddAllFixedVolumeDevices(type, "setDeviceVolumeBehavior:" + pkgName); } /** * @see AudioManager#getDeviceVolumeBehavior(AudioDeviceAttributes) * @param device the audio output device type * @return the volume behavior for the device */ public @AudioManager.DeviceVolumeBehavior int getDeviceVolumeBehavior( @NonNull AudioDeviceAttributes device) { // verify permissions enforceModifyAudioRoutingPermission(); // translate Java device type to native device type (for the devices masks for full / fixed) final int type; switch (device.getType()) { case AudioDeviceInfo.TYPE_HEARING_AID: type = AudioSystem.DEVICE_OUT_HEARING_AID; break; case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP: type = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; break; case AudioDeviceInfo.TYPE_HDMI: type = AudioSystem.DEVICE_OUT_HDMI; break; case AudioDeviceInfo.TYPE_HDMI_ARC: type = AudioSystem.DEVICE_OUT_HDMI_ARC; break; case AudioDeviceInfo.TYPE_LINE_DIGITAL: type = AudioSystem.DEVICE_OUT_SPDIF; break; case AudioDeviceInfo.TYPE_AUX_LINE: type = AudioSystem.DEVICE_OUT_LINE; break; default: // unsupported for now throw new IllegalArgumentException("Unsupported device type " + device.getType()); } if ((mFullVolumeDevices.contains(type))) { return AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL; } if ((mFixedVolumeDevices.contains(type))) { return AudioManager.DEVICE_VOLUME_BEHAVIOR_FIXED; } if ((mAbsVolumeMultiModeCaseDevices.contains(type))) { return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE; } if (type == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP && mDeviceBroker.isAvrcpAbsoluteVolumeSupported()) { return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE; } return AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE; } /*package*/ static final int CONNECTION_STATE_DISCONNECTED = 0; /*package*/ static final int CONNECTION_STATE_CONNECTED = 1; /** Loading