summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--media/java/android/media/AudioManager.java32
-rw-r--r--media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioManagerTest.java36
-rw-r--r--services/core/java/com/android/server/audio/AudioManagerShellCommand.java13
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java41
4 files changed, 103 insertions, 19 deletions
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index aa3dbda374be..71013f7f4e34 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -22,6 +22,7 @@ import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.media.audio.Flags.autoPublicVolumeApiHardening;
import static android.media.audio.Flags.automaticBtDeviceType;
import static android.media.audio.Flags.cacheGetStreamMinMaxVolume;
+import static android.media.audio.Flags.cacheGetStreamVolume;
import static android.media.audio.Flags.FLAG_DEPRECATE_STREAM_BT_SCO;
import static android.media.audio.Flags.FLAG_FOCUS_EXCLUSIVE_WITH_RECORDING;
import static android.media.audio.Flags.FLAG_FOCUS_FREEZE_TEST_API;
@@ -1241,7 +1242,12 @@ public class AudioManager {
* @hide
**/
public static final String VOLUME_MAX_CACHING_API = "getStreamMaxVolume";
- private static final int VOLUME_MIN_MAX_CACHING_SIZE = 16;
+ /**
+ * API string for caching the volume for each stream
+ * @hide
+ **/
+ public static final String VOLUME_CACHING_API = "getStreamVolume";
+ private static final int VOLUME_CACHING_SIZE = 16;
private final IpcDataCache.QueryHandler<VolumeCacheQuery, Integer> mVolQuery =
new IpcDataCache.QueryHandler<>() {
@@ -1252,6 +1258,7 @@ public class AudioManager {
return switch (query.queryCommand) {
case QUERY_VOL_MIN -> service.getStreamMinVolume(query.stream);
case QUERY_VOL_MAX -> service.getStreamMaxVolume(query.stream);
+ case QUERY_VOL -> service.getStreamVolume(query.stream);
default -> {
Log.w(TAG, "Not a valid volume cache query: " + query);
yield null;
@@ -1265,29 +1272,40 @@ public class AudioManager {
};
private final IpcDataCache<VolumeCacheQuery, Integer> mVolMinCache =
- new IpcDataCache<>(VOLUME_MIN_MAX_CACHING_SIZE, IpcDataCache.MODULE_SYSTEM,
+ new IpcDataCache<>(VOLUME_CACHING_SIZE, IpcDataCache.MODULE_SYSTEM,
VOLUME_MIN_CACHING_API, VOLUME_MIN_CACHING_API, mVolQuery);
private final IpcDataCache<VolumeCacheQuery, Integer> mVolMaxCache =
- new IpcDataCache<>(VOLUME_MIN_MAX_CACHING_SIZE, IpcDataCache.MODULE_SYSTEM,
+ new IpcDataCache<>(VOLUME_CACHING_SIZE, IpcDataCache.MODULE_SYSTEM,
VOLUME_MAX_CACHING_API, VOLUME_MAX_CACHING_API, mVolQuery);
+ private final IpcDataCache<VolumeCacheQuery, Integer> mVolCache =
+ new IpcDataCache<>(VOLUME_CACHING_SIZE, IpcDataCache.MODULE_SYSTEM,
+ VOLUME_CACHING_API, VOLUME_CACHING_API, mVolQuery);
+
/**
* Used to invalidate the cache for the given API
* @hide
**/
public static void clearVolumeCache(String api) {
- if (cacheGetStreamMinMaxVolume()) {
+ if (cacheGetStreamMinMaxVolume() && (VOLUME_MAX_CACHING_API.equals(api)
+ || VOLUME_MIN_CACHING_API.equals(api))) {
+ IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM, api);
+ } else if (cacheGetStreamVolume() && VOLUME_CACHING_API.equals(api)) {
IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM, api);
+ } else {
+ Log.w(TAG, "invalid clearVolumeCache for api " + api);
}
}
private static final int QUERY_VOL_MIN = 1;
private static final int QUERY_VOL_MAX = 2;
+ private static final int QUERY_VOL = 3;
/** @hide */
@IntDef(prefix = "QUERY_VOL", value = {
QUERY_VOL_MIN,
- QUERY_VOL_MAX}
+ QUERY_VOL_MAX,
+ QUERY_VOL}
)
@Retention(RetentionPolicy.SOURCE)
private @interface QueryVolCommand {}
@@ -1297,6 +1315,7 @@ public class AudioManager {
return switch (queryCommand) {
case QUERY_VOL_MIN -> "getStreamMinVolume";
case QUERY_VOL_MAX -> "getStreamMaxVolume";
+ case QUERY_VOL -> "getStreamVolume";
default -> "invalid command";
};
}
@@ -1373,6 +1392,9 @@ public class AudioManager {
* @see #setStreamVolume(int, int, int)
*/
public int getStreamVolume(int streamType) {
+ if (cacheGetStreamVolume()) {
+ return mVolCache.query(new VolumeCacheQuery(streamType, QUERY_VOL));
+ }
final IAudioService service = getService();
try {
return service.getStreamVolume(streamType);
diff --git a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioManagerTest.java b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioManagerTest.java
index 017a1029d35c..209734ca4a53 100644
--- a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioManagerTest.java
+++ b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioManagerTest.java
@@ -67,6 +67,17 @@ public class AudioManagerTest {
private AudioManager mAudioManager;
+ private static final int[] PUBLIC_STREAM_TYPES = {
+ STREAM_VOICE_CALL,
+ STREAM_SYSTEM,
+ STREAM_RING,
+ STREAM_MUSIC,
+ STREAM_ALARM,
+ STREAM_NOTIFICATION,
+ STREAM_DTMF,
+ STREAM_ACCESSIBILITY,
+ };
+
@Rule
public final AudioVolumesTestRule rule = new AudioVolumesTestRule();
@@ -226,18 +237,8 @@ public class AudioManagerTest {
public void getStreamMinMaxVolume_consistentWithAs() throws Exception {
IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
IAudioService service = IAudioService.Stub.asInterface(b);
- final int[] streamTypes = {
- STREAM_VOICE_CALL,
- STREAM_SYSTEM,
- STREAM_RING,
- STREAM_MUSIC,
- STREAM_ALARM,
- STREAM_NOTIFICATION,
- STREAM_DTMF,
- STREAM_ACCESSIBILITY,
- };
-
- for (int streamType : streamTypes) {
+
+ for (int streamType : PUBLIC_STREAM_TYPES) {
assertEquals(service.getStreamMinVolume(streamType),
mAudioManager.getStreamMinVolume(streamType));
assertEquals(service.getStreamMaxVolume(streamType),
@@ -245,6 +246,17 @@ public class AudioManagerTest {
}
}
+ @Test
+ public void getStreamVolume_consistentWithAs() throws Exception {
+ IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+ IAudioService service = IAudioService.Stub.asInterface(b);
+
+ for (int streamType : PUBLIC_STREAM_TYPES) {
+ assertEquals(service.getStreamVolume(streamType),
+ mAudioManager.getStreamVolume(streamType));
+ }
+ }
+
//-----------------------------------------------------------------
// Test Volume per Attributes setter/getters
//-----------------------------------------------------------------
diff --git a/services/core/java/com/android/server/audio/AudioManagerShellCommand.java b/services/core/java/com/android/server/audio/AudioManagerShellCommand.java
index c35f4fca6edd..fece7a899f0a 100644
--- a/services/core/java/com/android/server/audio/AudioManagerShellCommand.java
+++ b/services/core/java/com/android/server/audio/AudioManagerShellCommand.java
@@ -69,6 +69,8 @@ class AudioManagerShellCommand extends ShellCommand {
return getMinVolume();
case "get-max-volume":
return getMaxVolume();
+ case "get-stream-volume":
+ return getStreamVolume();
case "set-device-volume":
return setDeviceVolume();
case "adj-mute":
@@ -114,6 +116,8 @@ class AudioManagerShellCommand extends ShellCommand {
pw.println(" Gets the min volume for STREAM_TYPE");
pw.println(" get-max-volume STREAM_TYPE");
pw.println(" Gets the max volume for STREAM_TYPE");
+ pw.println(" get-stream-volume STREAM_TYPE");
+ pw.println(" Gets the volume for STREAM_TYPE");
pw.println(" set-device-volume STREAM_TYPE VOLUME_INDEX NATIVE_DEVICE_TYPE");
pw.println(" Sets for NATIVE_DEVICE_TYPE the STREAM_TYPE volume to VOLUME_INDEX");
pw.println(" adj-mute STREAM_TYPE");
@@ -322,6 +326,15 @@ class AudioManagerShellCommand extends ShellCommand {
return 0;
}
+ private int getStreamVolume() {
+ final Context context = mService.mContext;
+ final AudioManager am = context.getSystemService(AudioManager.class);
+ final int stream = readIntArg();
+ final int result = am.getStreamVolume(stream);
+ getOutPrintWriter().println("AudioManager.getStreamVolume(" + stream + ") -> " + result);
+ return 0;
+ }
+
private int setDeviceVolume() {
final Context context = mService.mContext;
final AudioDeviceVolumeManager advm = (AudioDeviceVolumeManager) context.getSystemService(
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 1baded86705e..ddce8c7051ea 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -50,6 +50,7 @@ import static android.media.AudioManager.STREAM_SYSTEM;
import static android.media.audio.Flags.autoPublicVolumeApiHardening;
import static android.media.audio.Flags.automaticBtDeviceType;
import static android.media.audio.Flags.cacheGetStreamMinMaxVolume;
+import static android.media.audio.Flags.cacheGetStreamVolume;
import static android.media.audio.Flags.concurrentAudioRecordBypassPermission;
import static android.media.audio.Flags.featureSpatialAudioHeadtrackingLowLatency;
import static android.media.audio.Flags.focusFreezeTestApi;
@@ -1890,6 +1891,12 @@ public class AudioService extends IAudioService.Stub
mSpatializerHelper.onRoutingUpdated();
}
checkMuteAwaitConnection();
+ if (cacheGetStreamVolume()) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Clear volume cache after routing update");
+ }
+ AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
+ }
}
//-----------------------------------------------------------------
@@ -4968,6 +4975,8 @@ public class AudioService extends IAudioService.Stub
+ concurrentAudioRecordBypassPermission());
pw.println("\tandroid.media.audio.Flags.cacheGetStreamMinMaxVolume:"
+ cacheGetStreamMinMaxVolume());
+ pw.println("\tandroid.media.audio.Flags.cacheGetStreamVolume:"
+ + cacheGetStreamVolume());
}
private void dumpAudioMode(PrintWriter pw) {
@@ -7034,6 +7043,13 @@ public class AudioService extends IAudioService.Stub
streamState.mIsMuted = false;
}
}
+ if (cacheGetStreamVolume()) {
+ if (DEBUG_VOL) {
+ Log.d(TAG,
+ "Clear volume cache after possibly changing mute in readAudioSettings");
+ }
+ AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
+ }
}
readVolumeGroupsSettings(userSwitch);
@@ -9254,11 +9270,23 @@ public class AudioService extends IAudioService.Stub
public void put(int key, int value) {
super.put(key, value);
record("put", key, value);
+ if (cacheGetStreamVolume()) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Clear volume cache after update index map");
+ }
+ AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
+ }
}
@Override
public void setValueAt(int index, int value) {
super.setValueAt(index, value);
record("setValueAt", keyAt(index), value);
+ if (cacheGetStreamVolume()) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Clear volume cache after update index map");
+ }
+ AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
+ }
}
// Record all changes in the VolumeStreamState
@@ -9988,8 +10016,9 @@ public class AudioService extends IAudioService.Stub
* @return true if the mute state was changed
*/
public boolean mute(boolean state, boolean apply, String src) {
+ boolean changed;
synchronized (VolumeStreamState.class) {
- boolean changed = state != mIsMuted;
+ changed = state != mIsMuted;
if (changed) {
sMuteLogger.enqueue(
new AudioServiceEvents.StreamMuteEvent(mStreamType, state, src));
@@ -10007,8 +10036,16 @@ public class AudioService extends IAudioService.Stub
doMute();
}
}
- return changed;
}
+
+ if (cacheGetStreamVolume() && changed) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "Clear volume cache after changing mute state");
+ }
+ AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
+ }
+
+ return changed;
}
public void doMute() {