Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9be43ad8 authored by Yan Han's avatar Yan Han Committed by Android (Google) Code Review
Browse files

Merge changes from topic "abs-vol-adjust-only"

* changes:
  Add adjust-only absolute volume behavior.
  Fix incorrect return value from getDeviceVolumeBehavior
parents 85f33be5 6f96eec9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6757,6 +6757,7 @@ package android.media {
    field public static final int AUDIOFOCUS_FLAG_LOCK = 4; // 0x4
    field public static final int AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS = 2; // 0x2
    field public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE = 3; // 0x3
    field public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY = 5; // 0x5
    field public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE = 4; // 0x4
    field public static final int DEVICE_VOLUME_BEHAVIOR_FIXED = 2; // 0x2
    field public static final int DEVICE_VOLUME_BEHAVIOR_FULL = 1; // 0x1
+80 −3
Original line number Diff line number Diff line
@@ -146,13 +146,16 @@ public class AudioDeviceVolumeManager {
         * @param register true for registering, false for unregistering
         * @param device device for which volume is monitored
         */
        @RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING,
                android.Manifest.permission.BLUETOOTH_PRIVILEGED })
        public void register(boolean register, @NonNull AudioDeviceAttributes device,
                @NonNull List<VolumeInfo> volumes, boolean handlesVolumeAdjustment) {
                @NonNull List<VolumeInfo> volumes, boolean handlesVolumeAdjustment,
                @AudioManager.AbsoluteDeviceVolumeBehavior int behavior) {
            try {
                getService().registerDeviceVolumeDispatcherForAbsoluteVolume(register,
                        this, mPackageName,
                        Objects.requireNonNull(device), Objects.requireNonNull(volumes),
                        handlesVolumeAdjustment);
                        handlesVolumeAdjustment, behavior);
            } catch (RemoteException e) {
                e.rethrowFromSystemServer();
            }
@@ -234,6 +237,77 @@ public class AudioDeviceVolumeManager {
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnAudioDeviceVolumeChangedListener vclistener,
            boolean handlesVolumeAdjustment) {
        baseSetDeviceAbsoluteMultiVolumeBehavior(device, volumes, executor, vclistener,
                handlesVolumeAdjustment, AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
    }

    /**
     * @hide
     * Configures a device to use absolute volume model, and registers a listener for receiving
     * volume updates to apply on that device.
     *
     * Should be used instead of {@link #setDeviceAbsoluteVolumeBehavior} when there is no reliable
     * way to set the device's volume to a percentage.
     *
     * @param device the audio device set to absolute volume mode
     * @param volume the type of volume this device responds to
     * @param executor the Executor used for receiving volume updates through the listener
     * @param vclistener the callback for volume updates
     */
    @RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING,
            android.Manifest.permission.BLUETOOTH_PRIVILEGED })
    public void setDeviceAbsoluteVolumeAdjustOnlyBehavior(
            @NonNull AudioDeviceAttributes device,
            @NonNull VolumeInfo volume,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnAudioDeviceVolumeChangedListener vclistener,
            boolean handlesVolumeAdjustment) {
        final ArrayList<VolumeInfo> volumes = new ArrayList<>(1);
        volumes.add(volume);
        setDeviceAbsoluteMultiVolumeAdjustOnlyBehavior(device, volumes, executor, vclistener,
                handlesVolumeAdjustment);
    }

    /**
     * @hide
     * Configures a device to use absolute volume model applied to different volume types, and
     * registers a listener for receiving volume updates to apply on that device.
     *
     * Should be used instead of {@link #setDeviceAbsoluteMultiVolumeBehavior} when there is
     * no reliable way to set the device's volume to a percentage.
     *
     * @param device the audio device set to absolute multi-volume mode
     * @param volumes the list of volumes the given device responds to
     * @param executor the Executor used for receiving volume updates through the listener
     * @param vclistener the callback for volume updates
     */
    @RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING,
            android.Manifest.permission.BLUETOOTH_PRIVILEGED })
    public void setDeviceAbsoluteMultiVolumeAdjustOnlyBehavior(
            @NonNull AudioDeviceAttributes device,
            @NonNull List<VolumeInfo> volumes,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnAudioDeviceVolumeChangedListener vclistener,
            boolean handlesVolumeAdjustment) {
        baseSetDeviceAbsoluteMultiVolumeBehavior(device, volumes, executor, vclistener,
                handlesVolumeAdjustment, AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY);
    }

    /**
     * Base method for configuring a device to use absolute volume behavior, or one of its variants.
     * See {@link AudioManager#AbsoluteDeviceVolumeBehavior} for a list of allowed behaviors.
     *
     * @param behavior the variant of absolute device volume behavior to adopt
     */
    @RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING,
            android.Manifest.permission.BLUETOOTH_PRIVILEGED })
    private void baseSetDeviceAbsoluteMultiVolumeBehavior(
            @NonNull AudioDeviceAttributes device,
            @NonNull List<VolumeInfo> volumes,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnAudioDeviceVolumeChangedListener vclistener,
            boolean handlesVolumeAdjustment,
            @AudioManager.AbsoluteDeviceVolumeBehavior int behavior) {
        Objects.requireNonNull(device);
        Objects.requireNonNull(volumes);
        Objects.requireNonNull(executor);
@@ -253,7 +327,8 @@ public class AudioDeviceVolumeManager {
                mDeviceVolumeListeners.removeIf(info -> info.mDevice.equalTypeAddress(device));
            }
            mDeviceVolumeListeners.add(listenerInfo);
            mDeviceVolumeDispatcherStub.register(true, device, volumes, handlesVolumeAdjustment);
            mDeviceVolumeDispatcherStub.register(true, device, volumes, handlesVolumeAdjustment,
                    behavior);
        }
    }

@@ -375,6 +450,8 @@ public class AudioDeviceVolumeManager {
                return "DEVICE_VOLUME_BEHAVIOR_ABSOLUTE";
            case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE:
                return "DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE";
            case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY:
                return "DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY";
            default:
                return "invalid volume behavior " + behavior;
        }
+39 −1
Original line number Diff line number Diff line
@@ -6231,6 +6231,15 @@ public class AudioManager {
    @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 @@ public class AudioManager {
            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,10 +6260,22 @@ public class AudioManager {
            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
@@ -6266,6 +6288,7 @@ public class AudioManager {
            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);
@@ -6303,6 +6326,16 @@ public class AudioManager {
        }
    }

    /**
     * @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
@@ -6322,7 +6355,12 @@ public class AudioManager {
        // 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();
        }
+3 −2
Original line number Diff line number Diff line
@@ -629,12 +629,13 @@ interface IAudioService {
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)")
    int[] getActiveAssistantServiceUids();

    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)")
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    void registerDeviceVolumeDispatcherForAbsoluteVolume(boolean register,
            in IAudioDeviceVolumeDispatcher cb,
            in String packageName,
            in AudioDeviceAttributes device, in List<VolumeInfo> volumes,
            boolean handlesvolumeAdjustment);
            boolean handlesvolumeAdjustment,
            int volumeBehavior);

    AudioHalVersionInfo getHalVersion();

+55 −27
Original line number Diff line number Diff line
@@ -692,6 +692,7 @@ public class AudioService extends IAudioService.Stub
    // Devices where the framework sends a full scale audio signal, and controls the volume of
    // the external audio system separately.
    // For possible volume behaviors, see {@link AudioManager.AbsoluteDeviceVolumeBehavior}.
    Map<Integer, AbsoluteVolumeDeviceInfo> mAbsoluteVolumeDeviceInfoMap = new ArrayMap<>();
    /**
@@ -702,13 +703,19 @@ public class AudioService extends IAudioService.Stub
        private final List<VolumeInfo> mVolumeInfos;
        private final IAudioDeviceVolumeDispatcher mCallback;
        private final boolean mHandlesVolumeAdjustment;
        private AbsoluteVolumeDeviceInfo(AudioDeviceAttributes device, List<VolumeInfo> volumeInfos,
                IAudioDeviceVolumeDispatcher callback, boolean handlesVolumeAdjustment) {
        private @AudioManager.AbsoluteDeviceVolumeBehavior int mDeviceVolumeBehavior;
        private AbsoluteVolumeDeviceInfo(
                AudioDeviceAttributes device,
                List<VolumeInfo> volumeInfos,
                IAudioDeviceVolumeDispatcher callback,
                boolean handlesVolumeAdjustment,
                @AudioManager.AbsoluteDeviceVolumeBehavior int behavior) {
            this.mDevice = device;
            this.mVolumeInfos = volumeInfos;
            this.mCallback = callback;
            this.mHandlesVolumeAdjustment = handlesVolumeAdjustment;
            this.mDeviceVolumeBehavior = behavior;
        }
        /**
@@ -7057,7 +7064,8 @@ public class AudioService extends IAudioService.Stub
    public void registerDeviceVolumeDispatcherForAbsoluteVolume(boolean register,
            IAudioDeviceVolumeDispatcher cb, String packageName,
            AudioDeviceAttributes device, List<VolumeInfo> volumes,
            boolean handlesVolumeAdjustment) {
            boolean handlesVolumeAdjustment,
            @AudioManager.AbsoluteDeviceVolumeBehavior int deviceVolumeBehavior) {
        // verify permissions
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
                != PackageManager.PERMISSION_GRANTED
@@ -7073,13 +7081,16 @@ public class AudioService extends IAudioService.Stub
        int deviceOut = device.getInternalType();
        if (register) {
            AbsoluteVolumeDeviceInfo info = new AbsoluteVolumeDeviceInfo(
                    device, volumes, cb, handlesVolumeAdjustment);
            boolean volumeBehaviorChanged =
                    removeAudioSystemDeviceOutFromFullVolumeDevices(deviceOut)
                    | removeAudioSystemDeviceOutFromFixedVolumeDevices(deviceOut)
                    | (addAudioSystemDeviceOutToAbsVolumeDevices(deviceOut, info) == null);
                    device, volumes, cb, handlesVolumeAdjustment, deviceVolumeBehavior);
            AbsoluteVolumeDeviceInfo oldInfo = mAbsoluteVolumeDeviceInfoMap.get(deviceOut);
            boolean volumeBehaviorChanged = (oldInfo == null)
                    || (oldInfo.mDeviceVolumeBehavior != deviceVolumeBehavior);
            if (volumeBehaviorChanged) {
                dispatchDeviceVolumeBehavior(device, AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
                removeAudioSystemDeviceOutFromFullVolumeDevices(deviceOut);
                removeAudioSystemDeviceOutFromFixedVolumeDevices(deviceOut);
                addAudioSystemDeviceOutToAbsVolumeDevices(deviceOut, info);
                dispatchDeviceVolumeBehavior(device, deviceVolumeBehavior);
            }
            // Update stream volumes to the given device, if specified in a VolumeInfo.
            // Mute state is not updated because it is stream-wide - the only way to mute a
@@ -7171,6 +7182,7 @@ public class AudioService extends IAudioService.Stub
                                != null);
                break;
            case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE:
            case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY:
            case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE:
                throw new IllegalArgumentException("Absolute volume unsupported for now");
        }
@@ -7214,11 +7226,6 @@ public class AudioService extends IAudioService.Stub
        // AudioDeviceInfo.convertDeviceTypeToInternalDevice()
        final int audioSystemDeviceOut = device.getInternalType();
        int setDeviceVolumeBehavior = retrieveStoredDeviceVolumeBehavior(audioSystemDeviceOut);
        if (setDeviceVolumeBehavior != AudioManager.DEVICE_VOLUME_BEHAVIOR_UNSET) {
            return setDeviceVolumeBehavior;
        }
        // setDeviceVolumeBehavior has not been explicitly called for the device type. Deduce the
        // current volume behavior.
        if (mFullVolumeDevices.contains(audioSystemDeviceOut)) {
@@ -7230,8 +7237,11 @@ public class AudioService extends IAudioService.Stub
        if (mAbsVolumeMultiModeCaseDevices.contains(audioSystemDeviceOut)) {
            return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE;
        }
        if (isAbsoluteVolumeDevice(audioSystemDeviceOut)
                || isA2dpAbsoluteVolumeDevice(audioSystemDeviceOut)
        if (mAbsoluteVolumeDeviceInfoMap.containsKey(audioSystemDeviceOut)) {
            return mAbsoluteVolumeDeviceInfoMap.get(audioSystemDeviceOut).mDeviceVolumeBehavior;
        }
        if (isA2dpAbsoluteVolumeDevice(audioSystemDeviceOut)
                || AudioSystem.isLeAudioDeviceType(audioSystemDeviceOut)) {
            return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE;
        }
@@ -10680,6 +10690,13 @@ public class AudioService extends IAudioService.Stub
        pw.println();
    }
    private Set<Integer> getAbsoluteVolumeDevicesWithBehavior(int behavior) {
        return mAbsoluteVolumeDeviceInfoMap.entrySet().stream()
                .filter(entry -> entry.getValue().mDeviceVolumeBehavior == behavior)
                .map(Map.Entry::getKey)
                .collect(Collectors.toSet());
    }
    private String dumpDeviceTypes(@NonNull Set<Integer> deviceTypes) {
        Iterator<Integer> it = deviceTypes.iterator();
        if (!it.hasNext()) {
@@ -10728,14 +10745,20 @@ public class AudioService extends IAudioService.Stub
        pw.print("  mNotifAliasRing="); pw.println(mNotifAliasRing);
        pw.print("  mFixedVolumeDevices="); pw.println(dumpDeviceTypes(mFixedVolumeDevices));
        pw.print("  mFullVolumeDevices="); pw.println(dumpDeviceTypes(mFullVolumeDevices));
        pw.print("  mAbsoluteVolumeDevices.keySet()="); pw.println(dumpDeviceTypes(
                mAbsoluteVolumeDeviceInfoMap.keySet()));
        pw.print("  absolute volume devices="); pw.println(dumpDeviceTypes(
                getAbsoluteVolumeDevicesWithBehavior(
                        AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE)));
        pw.print("  adjust-only absolute volume devices="); pw.println(dumpDeviceTypes(
                getAbsoluteVolumeDevicesWithBehavior(
                        AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY)));
        pw.print("  mExtVolumeController="); pw.println(mExtVolumeController);
        pw.print("  mHdmiAudioSystemClient="); pw.println(mHdmiAudioSystemClient);
        pw.print("  mHdmiPlaybackClient="); pw.println(mHdmiPlaybackClient);
        pw.print("  mHdmiTvClient="); pw.println(mHdmiTvClient);
        pw.print("  mHdmiSystemAudioSupported="); pw.println(mHdmiSystemAudioSupported);
        synchronized (mHdmiClientLock) {
            pw.print("  mHdmiCecVolumeControlEnabled="); pw.println(mHdmiCecVolumeControlEnabled);
        }
        pw.print("  mIsCallScreeningModeSupported="); pw.println(mIsCallScreeningModeSupported);
        pw.print("  mic mute FromSwitch=" + mMicMuteFromSwitch
                        + " FromRestrictions=" + mMicMuteFromRestrictions
@@ -12780,8 +12803,11 @@ public class AudioService extends IAudioService.Stub
    }
    /**
     * Returns whether the input device uses absolute volume behavior. This is distinct
     * from Bluetooth A2DP absolute volume behavior ({@link #isA2dpAbsoluteVolumeDevice}).
     * Returns whether the input device uses absolute volume behavior, including its variants.
     * For included volume behaviors, see {@link AudioManager.AbsoluteDeviceVolumeBehavior}.
     *
     * This is distinct from Bluetooth A2DP absolute volume behavior
     * ({@link #isA2dpAbsoluteVolumeDevice}).
     */
    private boolean isAbsoluteVolumeDevice(int deviceType) {
        return mAbsoluteVolumeDeviceInfoMap.containsKey(deviceType);
@@ -12888,13 +12914,15 @@ public class AudioService extends IAudioService.Stub
        return mFullVolumeDevices.remove(audioSystemDeviceOut);
    }
    private AbsoluteVolumeDeviceInfo addAudioSystemDeviceOutToAbsVolumeDevices(
            int audioSystemDeviceOut, AbsoluteVolumeDeviceInfo info) {
    private void addAudioSystemDeviceOutToAbsVolumeDevices(int audioSystemDeviceOut,
            AbsoluteVolumeDeviceInfo info) {
        if (DEBUG_VOL) {
            Log.d(TAG, "Adding DeviceType: 0x" + Integer.toHexString(audioSystemDeviceOut)
                    + " from mAbsoluteVolumeDeviceInfoMap");
                    + " to mAbsoluteVolumeDeviceInfoMap with behavior "
                    + AudioDeviceVolumeManager.volumeBehaviorName(info.mDeviceVolumeBehavior)
            );
        }
        return mAbsoluteVolumeDeviceInfoMap.put(audioSystemDeviceOut, info);
        mAbsoluteVolumeDeviceInfoMap.put(audioSystemDeviceOut, info);
    }
    private AbsoluteVolumeDeviceInfo removeAudioSystemDeviceOutFromAbsVolumeDevices(
Loading