From 0ddd0d71326f606a16e37ddd19b7bc7e5fbbaa37 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Thu, 21 Jan 2021 17:18:29 -0800 Subject: [PATCH] AudioService: cache routing queries by AudioAttributes Add support for caching the result of getDevicesForAttributes in the AudioSystem adapter class, as well as stats and debug mode. Bug: 162448412 Test: atest com.google.android.gts.audioservice.AudioServiceHostTest#testDevicesForAttributes Change-Id: I7b45fd0c4c6f2f00c1c3bf6fde02dbf5624c91d8 --- .../server/audio/AudioSystemAdapter.java | 74 ++++++++++++++++--- 1 file changed, 64 insertions(+), 10 deletions(-) diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java index ff84505e59a95..973fbd2bba179 100644 --- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java +++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java @@ -56,6 +56,8 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { private static final boolean USE_CACHE_FOR_GETDEVICES = true; private ConcurrentHashMap mDevicesForStreamCache; + private ConcurrentHashMap> + mDevicesForAttrCache; private int[] mMethodCacheHit; /** @@ -87,7 +89,9 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { AudioSystem.setRoutingCallback(sSingletonDefaultAdapter); if (USE_CACHE_FOR_GETDEVICES) { sSingletonDefaultAdapter.mDevicesForStreamCache = - new ConcurrentHashMap(AudioSystem.getNumStreamTypes()); + new ConcurrentHashMap<>(AudioSystem.getNumStreamTypes()); + sSingletonDefaultAdapter.mDevicesForAttrCache = + new ConcurrentHashMap<>(AudioSystem.getNumStreamTypes()); sSingletonDefaultAdapter.mMethodCacheHit = new int[NB_MEASUREMENTS]; } if (ENABLE_GETDEVICES_STATS) { @@ -102,11 +106,15 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { if (DEBUG_CACHE) { Log.d(TAG, "---- clearing cache ----------"); } - if (mDevicesForStreamCache == null) { - return; + if (mDevicesForStreamCache != null) { + synchronized (mDevicesForStreamCache) { + mDevicesForStreamCache.clear(); + } } - synchronized (mDevicesForStreamCache) { - mDevicesForStreamCache.clear(); + if (mDevicesForAttrCache != null) { + synchronized (mDevicesForAttrCache) { + mDevicesForAttrCache.clear(); + } } } @@ -135,7 +143,8 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { res = AudioSystem.getDevicesForStream(stream); mDevicesForStreamCache.put(stream, res); if (DEBUG_CACHE) { - Log.d(TAG, " stream=" + stream + " dev=0x" + Integer.toHexString(res)); + Log.d(TAG, mMethodNames[METHOD_GETDEVICESFORSTREAM] + + streamDeviceToDebugString(stream, res)); } return res; } @@ -144,19 +153,25 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { if (DEBUG_CACHE) { final int real = AudioSystem.getDevicesForStream(stream); if (res == real) { - Log.d(TAG, " stream=" + stream + " dev=0x" + Integer.toHexString(res) - + " CACHE"); + Log.d(TAG, mMethodNames[METHOD_GETDEVICESFORSTREAM] + + streamDeviceToDebugString(stream, res) + " CACHE"); } else { - Log.e(TAG, " stream=" + stream + " dev=0x" + Integer.toHexString(res) + Log.e(TAG, mMethodNames[METHOD_GETDEVICESFORSTREAM] + + streamDeviceToDebugString(stream, res) + " CACHE ERROR real dev=0x" + Integer.toHexString(real)); } } } return res; } + // not using cache return AudioSystem.getDevicesForStream(stream); } + private static String streamDeviceToDebugString(int stream, int dev) { + return " stream=" + stream + " dev=0x" + Integer.toHexString(dev); + } + /** * Same as {@link AudioSystem#getDevicesForAttributes(AudioAttributes)} * @param attributes the attributes for which the routing is queried @@ -176,10 +191,49 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { private @NonNull ArrayList getDevicesForAttributesImpl( @NonNull AudioAttributes attributes) { - // TODO implement caching for attributes-based routing + if (USE_CACHE_FOR_GETDEVICES) { + ArrayList res; + synchronized (mDevicesForAttrCache) { + res = mDevicesForAttrCache.get(attributes); + if (res == null) { + res = AudioSystem.getDevicesForAttributes(attributes); + mDevicesForAttrCache.put(attributes, res); + if (DEBUG_CACHE) { + Log.d(TAG, mMethodNames[METHOD_GETDEVICESFORATTRIBUTES] + + attrDeviceToDebugString(attributes, res)); + } + return res; + } + // cache hit + mMethodCacheHit[METHOD_GETDEVICESFORATTRIBUTES]++; + if (DEBUG_CACHE) { + final ArrayList real = + AudioSystem.getDevicesForAttributes(attributes); + if (res.equals(real)) { + Log.d(TAG, mMethodNames[METHOD_GETDEVICESFORATTRIBUTES] + + attrDeviceToDebugString(attributes, res) + " CACHE"); + } else { + Log.e(TAG, mMethodNames[METHOD_GETDEVICESFORATTRIBUTES] + + attrDeviceToDebugString(attributes, res) + + " CACHE ERROR real:" + attrDeviceToDebugString(attributes, real)); + } + } + } + return res; + } + // not using cache return AudioSystem.getDevicesForAttributes(attributes); } + private static String attrDeviceToDebugString(@NonNull AudioAttributes attr, + @NonNull ArrayList devices) { + String ds = " attrUsage=" + attr.getSystemUsage(); + for (AudioDeviceAttributes ada : devices) { + ds = ds.concat(" dev=0x" + Integer.toHexString(ada.getInternalType())); + } + return ds; + } + /** * Same as {@link AudioSystem#setDeviceConnectionState(int, int, String, String, int)} * @param device