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

Commit 2ed92e02 authored by Wenyu Zhang's avatar Wenyu Zhang
Browse files

Persist input gain in settings

Creates InputDeviceVolumeHelper to maintain a map of input device to its
gain index. Plug it into AudioService to allow persist input gain and
call lower stack to apply the gain.
Expose APIs in AudioDeviceVolumeManager to set/get device input gain,
get max/min input gain, get isInputGainFixed.

Design doc: go/audio-system-settings-gain-control

Change-Id: Ib69793348cad3af145391b43d396fcc729d92244
Bug:b/364923030
Test:AudioServiceTest
Flag:com.android.media.flags.enable_audio_input_device_routing_and_volume_control
parent 69e38b08
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -5471,6 +5471,14 @@ public final class Settings {
        @Readable
        public static final String VOLUME_MASTER = "volume_master";
        /**
         * The mapping of input device to its input gain index.
         *
         * @hide
         */
        @Readable
        public static final String INPUT_GAIN_INDEX_SETTINGS = "input_gain_index_settings";
        /**
         * Master mono (int 1 = mono, 0 = normal).
         *
@@ -8390,7 +8398,6 @@ public final class Settings {
        @Readable
        public static final String LOCK_SCREEN_LOCK_AFTER_TIMEOUT = "lock_screen_lock_after_timeout";
        /**
         * This preference contains the string that shows for owner info on LockScreen.
         * @hide
+80 −0
Original line number Diff line number Diff line
@@ -16,8 +16,11 @@

package android.media;

import static com.android.media.flags.Flags.FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL;

import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -432,6 +435,83 @@ public class AudioDeviceVolumeManager {
        return VolumeInfo.getDefaultVolumeInfo();
    }

    /**
     * @hide
     * Sets the input gain index for a particular AudioDeviceAttributes.
     * TODO(b/364923030): create InputVolumeInfo on top of VolumeInfo rather than using index to
     * handle volume information, to solve issues e.g. gain index ranges might be different for
     * different categories of devices.
     */
    @FlaggedApi(FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL)
    @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED)
    public void setInputGainIndex(@NonNull AudioDeviceAttributes ada, int index) {
        try {
            getService().setInputGainIndex(ada, index);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @hide
     * Gets the input gain index for a particular AudioDeviceAttributes.
     */
    @FlaggedApi(FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL)
    @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED)
    public int getInputGainIndex(@NonNull AudioDeviceAttributes ada) {
        try {
            return getService().getInputGainIndex(ada);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @hide
     * Gets the maximum input gain index for input device.
     */
    @FlaggedApi(FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL)
    @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED)
    public int getMaxInputGainIndex() {
        try {
            return getService().getMaxInputGainIndex();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @hide
     * Gets the minimum input gain index for input device.
     */
    @FlaggedApi(FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL)
    @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED)
    public int getMinInputGainIndex() {
        try {
            return getService().getMinInputGainIndex();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @hide
     * Indicates if an input device does not support input gain control.
     *     <p>The following APIs have no effect when input gain is fixed:
     *     <ul>
     *       <li>{@link #setInputGainIndex(AudioDeviceAttributes, int)}
     *     </ul>
     */
    @FlaggedApi(FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL)
    @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED)
    public boolean isInputGainFixed(@NonNull AudioDeviceAttributes ada) {
        try {
            return getService().isInputGainFixed(ada);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @hide
     * Return human-readable name for volume behavior
+15 −0
Original line number Diff line number Diff line
@@ -189,6 +189,21 @@ interface IAudioService {

    void setMicrophoneMute(boolean on, String callingPackage, int userId, in String attributionTag);

    @EnforcePermission("MODIFY_AUDIO_SETTINGS_PRIVILEGED")
    void setInputGainIndex(in AudioDeviceAttributes ada, int index);

    @EnforcePermission("MODIFY_AUDIO_SETTINGS_PRIVILEGED")
    int getInputGainIndex(in AudioDeviceAttributes ada);

    @EnforcePermission("MODIFY_AUDIO_SETTINGS_PRIVILEGED")
    int getMaxInputGainIndex();

    @EnforcePermission("MODIFY_AUDIO_SETTINGS_PRIVILEGED")
    int getMinInputGainIndex();

    @EnforcePermission("MODIFY_AUDIO_SETTINGS_PRIVILEGED")
    boolean isInputGainFixed(in AudioDeviceAttributes ada);

    oneway void setMicrophoneMuteFromSwitch(boolean on);

    void setRingerModeExternal(int ringerMode, String caller);
+2 −2
Original line number Diff line number Diff line
@@ -903,8 +903,8 @@ public class SettingsBackupTest {
                        Settings.System.EGG_MODE, // I am the lolrus
                        Settings.System.END_BUTTON_BEHAVIOR, // bug?
                        Settings.System.DEFAULT_DEVICE_FONT_SCALE, // Non configurable
                        Settings.System
                                .HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY,
                        Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY,
                        Settings.System.INPUT_GAIN_INDEX_SETTINGS,
                        // candidate for backup?
                        Settings.System.LOCKSCREEN_DISABLED, // ?
                        Settings.System.MEDIA_BUTTON_RECEIVER, // candidate for backup?
+127 −1
Original line number Diff line number Diff line
@@ -68,10 +68,11 @@ import static com.android.media.audio.Flags.audioserverPermissions;
import static com.android.media.audio.Flags.disablePrescaleAbsoluteVolume;
import static com.android.media.audio.Flags.equalScoLeaVcIndexRange;
import static com.android.media.audio.Flags.replaceStreamBtSco;
import static com.android.media.audio.Flags.ringerModeAffectsAlarm;
import static com.android.media.audio.Flags.ringMyCar;
import static com.android.media.audio.Flags.ringerModeAffectsAlarm;
import static com.android.media.audio.Flags.setStreamVolumeOrder;
import static com.android.media.audio.Flags.vgsVssSyncMuteOrder;
import static com.android.media.flags.Flags.enableAudioInputDeviceRoutingAndVolumeControl;
import static com.android.server.audio.SoundDoseHelper.ACTION_CHECK_MUSIC_ACTIVE;
import static com.android.server.utils.EventLogger.Event.ALOGE;
import static com.android.server.utils.EventLogger.Event.ALOGI;
@@ -491,6 +492,10 @@ public class AudioService extends IAudioService.Stub
    private static final int MSG_INIT_SPATIALIZER = 102;
    private static final int MSG_INIT_ADI_DEVICE_STATES = 103;
    private static final int MSG_INIT_INPUT_GAINS = 104;
    private static final int MSG_SET_INPUT_GAIN_INDEX = 105;
    private static final int MSG_PERSIST_INPUT_GAIN_INDEX = 106;
    // end of messages handled under wakelock
    // retry delay in case of failure to indicate system ready to AudioFlinger
@@ -512,6 +517,11 @@ public class AudioService extends IAudioService.Stub
     **/
    private SparseArray<VolumeStreamState> mStreamStates;
    /**
     * @see InputDeviceVolumeHelper
     */
    private InputDeviceVolumeHelper mInputDeviceVolumeHelper;
    /*package*/ int getVssVolumeForDevice(int stream, int device) {
        final VolumeStreamState streamState = mStreamStates.get(stream);
        return streamState != null ? streamState.getIndex(device) : -1;
@@ -1501,6 +1511,15 @@ public class AudioService extends IAudioService.Stub
                0 /* arg1 */, 0 /* arg2 */, null /* obj */, 0 /* delay */);
        queueMsgUnderWakeLock(mAudioHandler, MSG_INIT_SPATIALIZER,
                0 /* arg1 */, 0 /* arg2 */, null /* obj */, 0 /* delay */);
        if (enableAudioInputDeviceRoutingAndVolumeControl()) {
            queueMsgUnderWakeLock(
                    mAudioHandler,
                    MSG_INIT_INPUT_GAINS,
                    0 /* arg1 */,
                    0 /* arg2 */,
                    null /* obj */,
                    0 /* delay */);
        }
        mDisplayManager = context.getSystemService(DisplayManager.class);
@@ -1594,6 +1613,16 @@ public class AudioService extends IAudioService.Stub
        }
    }
    /** Called by handling of MSG_INIT_INPUT_GAINS */
    private void onInitInputGains() {
        mInputDeviceVolumeHelper =
                new InputDeviceVolumeHelper(
                        mSettings,
                        mContentResolver,
                        mSettingsLock,
                        System.INPUT_GAIN_INDEX_SETTINGS);
    }
    private SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionChangedListener =
            new SubscriptionManager.OnSubscriptionsChangedListener() {
                @Override
@@ -5742,6 +5771,90 @@ public class AudioService extends IAudioService.Stub
                : aliasStreamType == sStreamVolumeAlias.get(AudioSystem.STREAM_SYSTEM);
    }
    /**
     * @see AudioDeviceVolumeManager#setInputGainIndex(AudioDeviceAttributes, int)
     */
    @Override
    @android.annotation.EnforcePermission(MODIFY_AUDIO_SETTINGS_PRIVILEGED)
    public void setInputGainIndex(@NonNull AudioDeviceAttributes ada, int index) {
        super.setInputGainIndex_enforcePermission();
        if (mInputDeviceVolumeHelper.setInputGainIndex(ada, index)) {
            // Post message to set system volume (it in turn will post a message
            // to persist).
            sendMsg(
                    mAudioHandler,
                    MSG_SET_INPUT_GAIN_INDEX,
                    SENDMSG_QUEUE,
                    /*arg1*/ index,
                    /*arg2*/ 0,
                    /*obj*/ ada,
                    /*delay*/ 0);
        }
    }
    private void setInputGainIndexInt(@NonNull AudioDeviceAttributes ada, int index) {
        // TODO(b/364923030): call AudioSystem to apply input gain in native layer.
        // Post a persist input gain msg.
        sendMsg(
                mAudioHandler,
                MSG_PERSIST_INPUT_GAIN_INDEX,
                SENDMSG_QUEUE,
                /*arg1*/ index,
                /*arg2*/ 0,
                /*obj*/ ada,
                PERSIST_DELAY);
    }
    private void persistInputGainIndex(@NonNull AudioDeviceAttributes ada, int index) {
        mInputDeviceVolumeHelper.persistInputGainIndex(ada, index);
    }
    /**
     * @see AudioDeviceVolumeManager#getInputGainIndex(AudioDeviceAttributes)
     */
    @Override
    @android.annotation.EnforcePermission(MODIFY_AUDIO_SETTINGS_PRIVILEGED)
    public int getInputGainIndex(@NonNull AudioDeviceAttributes ada) {
        super.getInputGainIndex_enforcePermission();
        return mInputDeviceVolumeHelper.getInputGainIndex(ada);
    }
    /**
     * @see AudioDeviceVolumeManager#getMaxInputGainIndex()
     */
    @Override
    @android.annotation.EnforcePermission(MODIFY_AUDIO_SETTINGS_PRIVILEGED)
    public int getMaxInputGainIndex() {
        super.getMaxInputGainIndex_enforcePermission();
        return mInputDeviceVolumeHelper.getMaxInputGainIndex();
    }
    /**
     * @see AudioDeviceVolumeManager#getMinInputGainIndex()
     */
    @Override
    @android.annotation.EnforcePermission(MODIFY_AUDIO_SETTINGS_PRIVILEGED)
    public int getMinInputGainIndex() {
        super.getMinInputGainIndex_enforcePermission();
        return mInputDeviceVolumeHelper.getMinInputGainIndex();
    }
    /**
     * @see AudioDeviceVolumeManager#isInputGainFixed(AudioDeviceAttributes)
     */
    @Override
    @android.annotation.EnforcePermission(MODIFY_AUDIO_SETTINGS_PRIVILEGED)
    public boolean isInputGainFixed(@NonNull AudioDeviceAttributes ada) {
        super.isInputGainFixed_enforcePermission();
        return mInputDeviceVolumeHelper.isInputGainFixed(ada);
    }
    /** @see AudioManager#setMicrophoneMute(boolean) */
    @Override
    public void setMicrophoneMute(boolean on, String callingPackage, int userId,
@@ -10077,6 +10190,14 @@ public class AudioService extends IAudioService.Stub
                    vgs.persistVolumeGroup(msg.arg1);
                    break;
                case MSG_SET_INPUT_GAIN_INDEX:
                    setInputGainIndexInt((AudioDeviceAttributes) msg.obj, msg.arg1);
                    break;
                case MSG_PERSIST_INPUT_GAIN_INDEX:
                    persistInputGainIndex((AudioDeviceAttributes) msg.obj, msg.arg1);
                    break;
                case MSG_PERSIST_RINGER_MODE:
                    // note that the value persisted is the current ringer mode, not the
                    // value of ringer mode as of the time the request was made to persist
@@ -10147,6 +10268,11 @@ public class AudioService extends IAudioService.Stub
                    mAudioEventWakeLock.release();
                    break;
                case MSG_INIT_INPUT_GAINS:
                    onInitInputGains();
                    mAudioEventWakeLock.release();
                    break;
                case MSG_INIT_ADI_DEVICE_STATES:
                    onInitAdiDeviceStates();
                    mAudioEventWakeLock.release();
Loading