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
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 764570e..725af34 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5472,6 +5472,14 @@
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).
*
* @hide
@@ -8390,7 +8398,6 @@
@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
diff --git a/media/java/android/media/AudioDeviceVolumeManager.java b/media/java/android/media/AudioDeviceVolumeManager.java
index 13876ad..e1fbfea 100644
--- a/media/java/android/media/AudioDeviceVolumeManager.java
+++ b/media/java/android/media/AudioDeviceVolumeManager.java
@@ -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;
@@ -434,6 +437,83 @@
/**
* @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
* @param behavior one of the volume behaviors defined in AudioManager
* @return a string for the given behavior
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index c22b674..9fd3f5b 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -189,6 +189,21 @@
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);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index d39b564..1659c9e 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -903,8 +903,8 @@
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?
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 78a1fa7..bfef685 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -68,10 +68,11 @@
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 @@
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 @@
**/
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 @@
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 @@
}
}
+ /** 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 @@
: 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 @@
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 @@
mAudioEventWakeLock.release();
break;
+ case MSG_INIT_INPUT_GAINS:
+ onInitInputGains();
+ mAudioEventWakeLock.release();
+ break;
+
case MSG_INIT_ADI_DEVICE_STATES:
onInitAdiDeviceStates();
mAudioEventWakeLock.release();
diff --git a/services/core/java/com/android/server/audio/InputDeviceVolumeHelper.java b/services/core/java/com/android/server/audio/InputDeviceVolumeHelper.java
new file mode 100644
index 0000000..d83dca6
--- /dev/null
+++ b/services/core/java/com/android/server/audio/InputDeviceVolumeHelper.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.audio;
+
+import static android.media.AudioManager.GET_DEVICES_INPUTS;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.media.AudioDeviceAttributes;
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
+import android.media.AudioSystem;
+import android.os.UserHandle;
+import android.util.IntArray;
+import android.util.SparseIntArray;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/** Maintains the current state of input gains. */
+/*package*/ class InputDeviceVolumeHelper {
+ private static final String TAG = "InputDeviceVolumeHelper";
+
+ // TODO(b/364923030): retrieve these constants from AudioPolicyManager.
+ private final int INDEX_MIN = 0;
+ private final int INDEX_MAX = 100;
+ private final int INDEX_DEFAULT = 50;
+
+ private final SettingsAdapter mSettings;
+ private final ContentResolver mContentResolver;
+ private final Object mSettingsLock;
+ private final String mInputGainIndexSettingsName;
+
+ // A map between device internal type (e.g. AudioSystem.DEVICE_IN_BUILTIN_MIC) to its input gain
+ // index.
+ private final SparseIntArray mInputGainIndexMap;
+ private final Set<Integer> mSupportedDeviceTypes;
+
+ InputDeviceVolumeHelper(
+ SettingsAdapter settings,
+ ContentResolver contentResolver,
+ Object settingsLock,
+ String settingsName) {
+ mSettings = settings;
+ mContentResolver = contentResolver;
+ mSettingsLock = settingsLock;
+ mInputGainIndexSettingsName = settingsName;
+
+ IntArray internalDeviceTypes = new IntArray();
+ int status = AudioSystem.getSupportedDeviceTypes(GET_DEVICES_INPUTS, internalDeviceTypes);
+ mInputGainIndexMap =
+ new SparseIntArray(
+ status == AudioManager.SUCCESS
+ ? internalDeviceTypes.size()
+ : AudioSystem.DEVICE_IN_ALL_SET.size());
+
+ if (status == AudioManager.SUCCESS) {
+ Set<Integer> supportedDeviceTypes = new HashSet<>();
+ for (int i = 0; i < internalDeviceTypes.size(); i++) {
+ supportedDeviceTypes.add(internalDeviceTypes.get(i));
+ }
+ mSupportedDeviceTypes = supportedDeviceTypes;
+ } else {
+ mSupportedDeviceTypes = AudioSystem.DEVICE_IN_ALL_SET;
+ }
+
+ readSettings();
+ }
+
+ public void readSettings() {
+ synchronized (InputDeviceVolumeHelper.class) {
+ for (int inputDeviceType : mSupportedDeviceTypes) {
+ // Retrieve current input gain for device. If no input gain stored for current
+ // device, use default input gain.
+ int index;
+ if (!hasValidSettingsName()) {
+ index = INDEX_DEFAULT;
+ } else {
+ String name = getSettingNameForDevice(inputDeviceType);
+ index =
+ mSettings.getSystemIntForUser(
+ mContentResolver, name, INDEX_DEFAULT, UserHandle.USER_CURRENT);
+ }
+
+ mInputGainIndexMap.put(inputDeviceType, getValidIndex(index));
+ }
+ }
+ }
+
+ public boolean hasValidSettingsName() {
+ return mInputGainIndexSettingsName != null && !mInputGainIndexSettingsName.isEmpty();
+ }
+
+ public @Nullable String getSettingNameForDevice(int inputDeviceType) {
+ if (!hasValidSettingsName()) {
+ return null;
+ }
+ final String suffix = AudioSystem.getInputDeviceName(inputDeviceType);
+ if (suffix.isEmpty()) {
+ return mInputGainIndexSettingsName;
+ }
+ return mInputGainIndexSettingsName + "_" + suffix;
+ }
+
+ private int getValidIndex(int index) {
+ if (index < INDEX_MIN) {
+ return INDEX_MIN;
+ }
+ if (index > INDEX_MAX) {
+ return INDEX_MAX;
+ }
+ return index;
+ }
+
+ public int getInputGainIndex(@NonNull AudioDeviceAttributes ada) {
+ int inputDeviceType = AudioDeviceInfo.convertDeviceTypeToInternalInputDevice(ada.getType());
+ ensureValidInputDeviceType(inputDeviceType);
+
+ synchronized (InputDeviceVolumeHelper.class) {
+ return mInputGainIndexMap.get(inputDeviceType, INDEX_DEFAULT);
+ }
+ }
+
+ public int getMaxInputGainIndex() {
+ return INDEX_MAX;
+ }
+
+ public int getMinInputGainIndex() {
+ return INDEX_MIN;
+ }
+
+ public boolean isInputGainFixed(@NonNull AudioDeviceAttributes ada) {
+ int inputDeviceType = AudioDeviceInfo.convertDeviceTypeToInternalInputDevice(ada.getType());
+ ensureValidInputDeviceType(inputDeviceType);
+
+ // For simplicity, all devices have non fixed input gain. This might change
+ // when more input devices are supported and some do not support input gain control.
+ return false;
+ }
+
+ public boolean setInputGainIndex(@NonNull AudioDeviceAttributes ada, int index) {
+ int inputDeviceType = AudioDeviceInfo.convertDeviceTypeToInternalInputDevice(ada.getType());
+ ensureValidInputDeviceType(inputDeviceType);
+
+ int oldIndex;
+ synchronized (mSettingsLock) {
+ synchronized (InputDeviceVolumeHelper.class) {
+ oldIndex = getInputGainIndex(ada);
+ index = getValidIndex(index);
+
+ if (oldIndex == index) {
+ return false;
+ }
+
+ mInputGainIndexMap.put(inputDeviceType, index);
+ return true;
+ }
+ }
+ }
+
+ public void persistInputGainIndex(@NonNull AudioDeviceAttributes ada, int index) {
+ int inputDeviceType = AudioDeviceInfo.convertDeviceTypeToInternalInputDevice(ada.getType());
+ ensureValidInputDeviceType(inputDeviceType);
+
+ if (hasValidSettingsName()) {
+ mSettings.putSystemIntForUser(
+ mContentResolver,
+ getSettingNameForDevice(inputDeviceType),
+ index,
+ UserHandle.USER_CURRENT);
+ }
+ }
+
+ public boolean isValidInputDeviceType(int inputDeviceType) {
+ return mSupportedDeviceTypes.contains(inputDeviceType);
+ }
+
+ private void ensureValidInputDeviceType(int inputDeviceType) {
+ if (!isValidInputDeviceType(inputDeviceType)) {
+ throw new IllegalArgumentException("Bad input device type " + inputDeviceType);
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/audio/AudioServiceTest.java b/services/tests/servicestests/src/com/android/server/audio/AudioServiceTest.java
index b7100ea..c9e9f00 100644
--- a/services/tests/servicestests/src/com/android/server/audio/AudioServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/AudioServiceTest.java
@@ -15,6 +15,8 @@
*/
package com.android.server.audio;
+import static android.media.AudioDeviceInfo.TYPE_BUILTIN_MIC;
+
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
@@ -27,16 +29,20 @@
import android.app.AppOpsManager;
import android.content.Context;
+import android.media.AudioDeviceAttributes;
import android.media.AudioSystem;
import android.os.Looper;
import android.os.PermissionEnforcer;
import android.os.UserHandle;
+import android.platform.test.annotations.EnableFlags;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.media.flags.Flags;
+
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
@@ -53,6 +59,7 @@
private static final String TAG = "AudioServiceTest";
private static final int MAX_MESSAGE_HANDLING_DELAY_MS = 100;
+ private static final int DEFAULT_INPUT_GAIN_INDEX = 50;
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();
@@ -202,4 +209,29 @@
reset(mSpySystemServer);
}
}
+
+ /** Test input gain index setter and getter */
+ @EnableFlags(Flags.FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL)
+ @Test
+ public void testInputGainIndex() throws Exception {
+ Log.i(TAG, "running testInputGainIndex");
+ Assert.assertNotNull(mAudioService);
+ Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS); // wait for full AudioService initialization
+
+ AudioDeviceAttributes ada =
+ new AudioDeviceAttributes(
+ AudioDeviceAttributes.ROLE_INPUT, TYPE_BUILTIN_MIC, /* address= */ "");
+
+ Assert.assertEquals(
+ "default input gain index reporting wrong value",
+ DEFAULT_INPUT_GAIN_INDEX,
+ mAudioService.getInputGainIndex(ada));
+
+ int inputGainIndex = 20;
+ mAudioService.setInputGainIndex(ada, inputGainIndex);
+ Assert.assertEquals(
+ "input gain index reporting wrong value",
+ inputGainIndex,
+ mAudioService.getInputGainIndex(ada));
+ }
}