diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 46abd33453353..d97e2cc51708e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2030,6 +2030,10 @@
STREAM_MUSIC as if it's on TV platform. -->
false
+
+ true
+
true
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ad02128db613e..8258aa416cc0b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -273,6 +273,7 @@
+
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 02648c4da76f6..43d77ab32371f 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -275,6 +275,25 @@ public class AudioService extends IAudioService.Stub
// indicates whether the system maps all streams to a single stream.
private final boolean mIsSingleVolume;
+ /**
+ * indicates whether STREAM_NOTIFICATION is aliased to STREAM_RING
+ * not final due to test method, see {@link #setNotifAliasRingForTest(boolean)}.
+ */
+ private boolean mNotifAliasRing;
+
+ /**
+ * Test method to temporarily override whether STREAM_NOTIFICATION is aliased to STREAM_RING,
+ * volumes will be updated in case of a change.
+ * @param alias if true, STREAM_NOTIFICATION is aliased to STREAM_RING
+ */
+ /*package*/ void setNotifAliasRingForTest(boolean alias) {
+ boolean update = (mNotifAliasRing != alias);
+ mNotifAliasRing = alias;
+ if (update) {
+ updateStreamVolumeAlias(true, "AudioServiceTest");
+ }
+ }
+
/*package*/ boolean isPlatformVoice() {
return mPlatformType == AudioSystem.PLATFORM_VOICE;
}
@@ -942,10 +961,25 @@ public class AudioService extends IAudioService.Stub
*/
public AudioService(Context context, AudioSystemAdapter audioSystem,
SystemServerAdapter systemServer, SettingsAdapter settings, @Nullable Looper looper) {
+ this (context, audioSystem, systemServer, settings, looper,
+ context.getSystemService(AppOpsManager.class));
+ }
+
+ /**
+ * @param context
+ * @param audioSystem Adapter for {@link AudioSystem}
+ * @param systemServer Adapter for privilieged functionality for system server components
+ * @param settings Adapter for {@link Settings}
+ * @param looper Looper to use for the service's message handler. If this is null, an
+ * {@link AudioSystemThread} is created as the messaging thread instead.
+ */
+ public AudioService(Context context, AudioSystemAdapter audioSystem,
+ SystemServerAdapter systemServer, SettingsAdapter settings, @Nullable Looper looper,
+ AppOpsManager appOps) {
sLifecycleLogger.log(new AudioEventLogger.StringEvent("AudioService()"));
mContext = context;
mContentResolver = context.getContentResolver();
- mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
+ mAppOps = appOps;
mAudioSystem = audioSystem;
mSystemServer = systemServer;
@@ -976,6 +1010,9 @@ public class AudioService extends IAudioService.Stub
mUseVolumeGroupAliases = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_handleVolumeAliasesUsingVolumeGroups);
+ mNotifAliasRing = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_alias_ring_notif_stream_types);
+
// Initialize volume
// Priority 1 - Android Property
// Priority 2 - Audio Policy Service
@@ -2008,7 +2045,13 @@ public class AudioService extends IAudioService.Stub
pw.println("\nStream volumes (device: index)");
int numStreamTypes = AudioSystem.getNumStreamTypes();
for (int i = 0; i < numStreamTypes; i++) {
- pw.println("- " + AudioSystem.STREAM_NAMES[i] + ":");
+ StringBuilder alias = new StringBuilder();
+ if (mStreamVolumeAlias[i] != i) {
+ alias.append(" (aliased to: ")
+ .append(AudioSystem.STREAM_NAMES[mStreamVolumeAlias[i]])
+ .append(")");
+ }
+ pw.println("- " + AudioSystem.STREAM_NAMES[i] + alias + ":");
mStreamStates[i].dump(pw);
pw.println("");
}
@@ -2040,6 +2083,10 @@ public class AudioService extends IAudioService.Stub
mStreamVolumeAlias = STREAM_VOLUME_ALIAS_DEFAULT;
dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
}
+ if (!mNotifAliasRing) {
+ mStreamVolumeAlias[AudioSystem.STREAM_NOTIFICATION] =
+ AudioSystem.STREAM_NOTIFICATION;
+ }
}
if (mIsSingleVolume) {
@@ -9888,6 +9935,7 @@ public class AudioService extends IAudioService.Stub
pw.print(" mBtScoOnByApp="); pw.println(mBtScoOnByApp);
pw.print(" mIsSingleVolume="); pw.println(mIsSingleVolume);
pw.print(" mUseFixedVolume="); pw.println(mUseFixedVolume);
+ 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(
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 91c45b4f8b603..adcbe6bb12c0b 100644
--- a/services/tests/servicestests/src/com/android/server/audio/AudioServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/AudioServiceTest.java
@@ -15,12 +15,18 @@
*/
package com.android.server.audio;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.app.AppOpsManager;
import android.content.Context;
+import android.media.AudioSystem;
import android.os.Looper;
import android.os.UserHandle;
import android.util.Log;
@@ -33,6 +39,7 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.Spy;
@MediumTest
@@ -46,6 +53,7 @@ public class AudioServiceTest {
private AudioSystemAdapter mAudioSystem;
@Spy private SystemServerAdapter mSpySystemServer;
private SettingsAdapter mSettingsAdapter;
+ @Mock private AppOpsManager mMockAppOpsManager;
// the class being unit-tested here
private AudioService mAudioService;
@@ -61,8 +69,11 @@ public class AudioServiceTest {
mAudioSystem = new NoOpAudioSystemAdapter();
mSpySystemServer = spy(new NoOpSystemServerAdapter());
mSettingsAdapter = new NoOpSettingsAdapter();
+ mMockAppOpsManager = mock(AppOpsManager.class);
+ when(mMockAppOpsManager.noteOp(anyInt(), anyInt(), anyString(), anyString(), anyString()))
+ .thenReturn(AppOpsManager.MODE_ALLOWED);
mAudioService = new AudioService(mContext, mAudioSystem, mSpySystemServer,
- mSettingsAdapter, null);
+ mSettingsAdapter, null, mMockAppOpsManager);
}
/**
@@ -113,4 +124,33 @@ public class AudioServiceTest {
reset(mSpySystemServer);
}
}
+
+ @Test
+ public void testRingNotifAlias() throws Exception {
+ Log.i(TAG, "running testRingNotifAlias");
+ Assert.assertNotNull(mAudioService);
+ // TODO add initialization message that can be caught here instead of sleeping
+ Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS); // wait for full AudioService initialization
+
+ // test with aliasing RING and NOTIFICATION
+ mAudioService.setNotifAliasRingForTest(true);
+ final int ringMaxVol = mAudioService.getStreamMaxVolume(AudioSystem.STREAM_RING);
+ final int ringMinVol = mAudioService.getStreamMinVolume(AudioSystem.STREAM_RING);
+ final int ringVol = ringMinVol + 1;
+ // set a value for NOTIFICATION so it's not at the target test value (ringMaxVol)
+ mAudioService.setStreamVolume(AudioSystem.STREAM_NOTIFICATION,
+ ringVol, 0, "bla");
+ mAudioService.setStreamVolume(AudioSystem.STREAM_RING, ringMaxVol, 0, "bla");
+ Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS);
+ Assert.assertEquals(ringMaxVol,
+ mAudioService.getStreamVolume(AudioSystem.STREAM_NOTIFICATION));
+
+ // test with no aliasing between RING and NOTIFICATION
+ mAudioService.setNotifAliasRingForTest(false);
+ mAudioService.setStreamVolume(AudioSystem.STREAM_RING, ringVol, 0, "bla");
+ mAudioService.setStreamVolume(AudioSystem.STREAM_NOTIFICATION, ringMaxVol, 0, "bla");
+ Assert.assertEquals(ringVol, mAudioService.getStreamVolume(AudioSystem.STREAM_RING));
+ Assert.assertEquals(ringMaxVol, mAudioService.getStreamVolume(
+ AudioSystem.STREAM_NOTIFICATION));
+ }
}