Add adjust-only absolute volume behavior.

Adjust-only behavior (DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY)
is a variant of absolute behavior (DEVICE_VOLUME_BEHAVIOR_ABSOLUTE).
Like ABSOLUTE, ADJUST_ONLY may be adopted by calling a hidden API in
AudioDeviceVolumeManager and providing a listener for volume changes.

The difference with ADJUST_ONLY behavior is that setting volume via
AudioManager#setStreamVolume does not necessarily have an effect.
However, the listener is still notified of setStreamVolume calls
in case there's a slow or less reliable method of setting volume.

ADJUST_ONLY behavior may be returned by getDeviceVolumeBehavior for
SDK level U or higher. For lower SDK levels, FULL volume behavior is
returned in its place, as it is a similar but less powerful behavior.

Bug: 240663182
Test: atest AbsoluteVolumeBehaviorTest

Change-Id: I389bdd650dee717c4b249c989f4a9ee21c4eded7
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index a4d5606..659e3e6 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -6231,6 +6231,15 @@
     @SystemApi
     public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE = 4;
 
+    /**
+     * @hide
+     * A variant of {@link #DEVICE_VOLUME_BEHAVIOR_ABSOLUTE} where the host cannot reliably set
+     * the volume percentage of the audio device. Specifically, {@link #setStreamVolume} will have
+     * no effect, or an unreliable effect.
+     */
+    @SystemApi
+    public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY = 5;
+
     /** @hide */
     @IntDef({
             DEVICE_VOLUME_BEHAVIOR_VARIABLE,
@@ -6238,6 +6247,7 @@
             DEVICE_VOLUME_BEHAVIOR_FIXED,
             DEVICE_VOLUME_BEHAVIOR_ABSOLUTE,
             DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE,
+            DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface DeviceVolumeBehavior {}
@@ -6250,11 +6260,23 @@
             DEVICE_VOLUME_BEHAVIOR_FIXED,
             DEVICE_VOLUME_BEHAVIOR_ABSOLUTE,
             DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE,
+            DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface DeviceVolumeBehaviorState {}
 
     /**
+     * Variants of absolute volume behavior that are set in {@link AudioDeviceVolumeManager}.
+     * @hide
+     */
+    @IntDef({
+            DEVICE_VOLUME_BEHAVIOR_ABSOLUTE,
+            DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AbsoluteDeviceVolumeBehavior {}
+
+    /**
      * @hide
      * Throws IAE on an invalid volume behavior value
      * @param volumeBehavior behavior value to check
@@ -6266,6 +6288,7 @@
             case DEVICE_VOLUME_BEHAVIOR_FIXED:
             case DEVICE_VOLUME_BEHAVIOR_ABSOLUTE:
             case DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE:
+            case DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY:
                 return;
             default:
                 throw new IllegalArgumentException("Illegal volume behavior " + volumeBehavior);
@@ -6305,6 +6328,16 @@
 
     /**
      * @hide
+     * Controls whether DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY may be returned by
+     * getDeviceVolumeBehavior. If this is disabled, DEVICE_VOLUME_BEHAVIOR_FULL is returned
+     * in its place.
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    public static final long RETURN_DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY = 240663182L;
+
+    /**
+     * @hide
      * Returns the volume device behavior for the given audio device
      * @param device the audio device
      * @return the volume behavior for the device
@@ -6322,7 +6355,12 @@
         // communicate with service
         final IAudioService service = getService();
         try {
-            return service.getDeviceVolumeBehavior(device);
+            int behavior = service.getDeviceVolumeBehavior(device);
+            if (!CompatChanges.isChangeEnabled(RETURN_DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY)
+                    && behavior == DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY) {
+                return AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL;
+            }
+            return behavior;
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }