diff options
| -rw-r--r-- | core/jni/android_media_AudioSystem.cpp | 8 | ||||
| -rw-r--r-- | media/java/android/media/AudioManager.java | 40 | ||||
| -rw-r--r-- | media/java/android/media/AudioSystem.java | 81 | ||||
| -rwxr-xr-x | media/java/android/media/IAudioService.aidl | 2 | ||||
| -rw-r--r-- | services/core/java/com/android/server/audio/AudioDeviceBroker.java | 11 | ||||
| -rw-r--r-- | services/core/java/com/android/server/audio/AudioService.java | 156 | ||||
| -rw-r--r-- | services/core/java/com/android/server/audio/AudioSystemAdapter.java | 104 |
7 files changed, 225 insertions, 177 deletions
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 90b272ccd127..e7817606aae9 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -829,13 +829,6 @@ android_media_AudioSystem_getMasterBalance(JNIEnv *env, jobject thiz) } static jint -android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream) -{ - return (jint)deviceTypesToBitMask( - AudioSystem::getDevicesForStream(static_cast<audio_stream_type_t>(stream))); -} - -static jint android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz) { return (jint) AudioSystem::getPrimaryOutputSamplingRate(); @@ -2959,7 +2952,6 @@ static const JNINativeMethod gMethods[] = {"getMasterMono", "()Z", (void *)android_media_AudioSystem_getMasterMono}, {"setMasterBalance", "(F)I", (void *)android_media_AudioSystem_setMasterBalance}, {"getMasterBalance", "()F", (void *)android_media_AudioSystem_getMasterBalance}, - {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream}, {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate}, {"getPrimaryOutputFrameCount", "()I", diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 6c99a0734e3e..3a2f0d9194f5 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -5624,27 +5624,33 @@ public class AudioManager { * Note that the information may be imprecise when the implementation * cannot distinguish whether a particular device is enabled. * - * {@hide} + * @deprecated on {@link android.os.Build.VERSION_CODES#T} as new devices + * will have multi-bit device types. + * Prefer to use {@link #getDevicesForAttributes()} instead, + * noting that getDevicesForStream() has a few small discrepancies + * for better volume handling. + * @hide */ @UnsupportedAppUsage + @Deprecated public int getDevicesForStream(int streamType) { switch (streamType) { - case STREAM_VOICE_CALL: - case STREAM_SYSTEM: - case STREAM_RING: - case STREAM_MUSIC: - case STREAM_ALARM: - case STREAM_NOTIFICATION: - case STREAM_DTMF: - case STREAM_ACCESSIBILITY: - final IAudioService service = getService(); - try { - return service.getDevicesForStream(streamType); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - default: - return 0; + case STREAM_VOICE_CALL: + case STREAM_SYSTEM: + case STREAM_RING: + case STREAM_MUSIC: + case STREAM_ALARM: + case STREAM_NOTIFICATION: + case STREAM_DTMF: + case STREAM_ACCESSIBILITY: + final IAudioService service = getService(); + try { + return service.getDeviceMaskForStream(streamType); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + default: + return 0; } } diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 210f3e5e4499..acb34b527e06 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -29,6 +29,7 @@ import android.content.pm.PackageManager; import android.media.audio.common.AidlConversion; import android.media.audiofx.AudioEffect; import android.media.audiopolicy.AudioMix; +import android.media.audiopolicy.AudioProductStrategy; import android.os.Build; import android.os.IBinder; import android.os.Parcel; @@ -47,6 +48,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.TreeSet; /* IF YOU CHANGE ANY OF THE CONSTANTS IN THIS FILE, DO NOT FORGET * TO UPDATE THE CORRESPONDING NATIVE GLUE AND AudioManager.java. @@ -1655,9 +1657,63 @@ public class AudioSystem /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static native boolean getMasterMute(); - /** @hide */ + /** @hide + * Only used (unsupported) for legacy apps. + * @deprecated on {@link android.os.Build.VERSION_CODES#T} as new devices + * will have multi-bit device types. + * Use {@link AudioManager#getDevicesForAttributes(AudioAttributes)} instead. + */ @UnsupportedAppUsage - public static native int getDevicesForStream(int stream); + @Deprecated + public static int getDevicesForStream(int stream) { + final AudioAttributes attr = + AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType(stream); + return getDeviceMaskFromSet(generateAudioDeviceTypesSet( + getDevicesForAttributes(attr, true /* forVolume */))); + } + + /** @hide + * Conversion from a device set to a bit mask. + * + * Legacy compatibility method (use a device list instead of a bit mask). + * Conversion to bit mask skips multi-bit (S and later) internal device types + * (e.g. AudioSystem.DEVICE_OUT* or AudioManager.DEVICE_OUT*) for legacy + * compatibility reasons. Legacy apps will not understand these new device types + * and it will raise false matches with old device types. + */ + public static int getDeviceMaskFromSet(@NonNull Set<Integer> deviceSet) { + int deviceMask = DEVICE_NONE; // zero. + int deviceInChecksum = DEVICE_BIT_IN; + for (Integer device : deviceSet) { + if ((device & (device - 1) & ~DEVICE_BIT_IN) != 0) { + Log.v(TAG, "getDeviceMaskFromSet skipping multi-bit device value " + device); + continue; + } + deviceMask |= device; + deviceInChecksum &= device; + } + // Validate that deviceSet is either ALL input devices or ALL output devices. + // We check that the "OR" of all the DEVICE_BIT_INs == the "AND" of all DEVICE_BIT_INs. + if (!deviceSet.isEmpty() && deviceInChecksum != (deviceMask & DEVICE_BIT_IN)) { + Log.e(TAG, "getDeviceMaskFromSet: Invalid set: " + deviceSetToString(deviceSet)); + } + return deviceMask; + } + + /** @hide */ + @NonNull + public static String deviceSetToString(@NonNull Set<Integer> devices) { + int n = 0; + StringBuilder sb = new StringBuilder(); + for (Integer device : devices) { + if (n++ > 0) { + sb.append(", "); + } + sb.append(AudioSystem.getDeviceName(device)); + sb.append("(" + Integer.toHexString(device) + ")"); + } + return sb.toString(); + } /** * @hide @@ -2252,18 +2308,15 @@ public class AudioSystem /** * @hide - * Return a set of audio device types from a bit mask audio device type, which may + * Return a set of audio device types from a list of audio device attributes, which may * represent multiple audio device types. - * FIXME: Remove this when getting ride of bit mask usage of audio device types. - */ - public static Set<Integer> generateAudioDeviceTypesSet(int types) { - Set<Integer> deviceTypes = new HashSet<>(); - Set<Integer> allDeviceTypes = - (types & DEVICE_BIT_IN) == 0 ? DEVICE_OUT_ALL_SET : DEVICE_IN_ALL_SET; - for (int deviceType : allDeviceTypes) { - if ((types & deviceType) == deviceType) { - deviceTypes.add(deviceType); - } + */ + @NonNull + public static Set<Integer> generateAudioDeviceTypesSet( + @NonNull List<AudioDeviceAttributes> deviceList) { + Set<Integer> deviceTypes = new TreeSet<>(); + for (AudioDeviceAttributes device : deviceList) { + deviceTypes.add(device.getInternalType()); } return deviceTypes; } @@ -2274,7 +2327,7 @@ public class AudioSystem */ public static Set<Integer> intersectionAudioDeviceTypes( @NonNull Set<Integer> a, @NonNull Set<Integer> b) { - Set<Integer> intersection = new HashSet<>(a); + Set<Integer> intersection = new TreeSet<>(a); intersection.retainAll(b); return intersection; } diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index d702eb9aef57..fa3057a4ead1 100755 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -360,7 +360,7 @@ interface IAudioService { boolean isMusicActive(in boolean remotely); - int getDevicesForStream(in int streamType); + int getDeviceMaskForStream(in int streamType); int[] getAvailableCommunicationDeviceIds(); diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index ff7557a0eb6b..270a61b32390 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -1565,6 +1565,13 @@ import java.util.concurrent.atomic.AtomicBoolean; private AtomicBoolean mMusicMuted = new AtomicBoolean(false); + private static <T> boolean hasIntersection(Set<T> a, Set<T> b) { + for (T e : a) { + if (b.contains(e)) return true; + } + return false; + } + boolean messageMutesMusic(int message) { if (message == 0) { return false; @@ -1574,8 +1581,8 @@ import java.util.concurrent.atomic.AtomicBoolean; || message == MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT || message == MSG_L_A2DP_DEVICE_CONFIG_CHANGE) && AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) - && mDeviceInventory.DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains( - mAudioService.getDevicesForStream(AudioSystem.STREAM_MUSIC))) { + && hasIntersection(mDeviceInventory.DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET, + mAudioService.getDeviceSetForStream(AudioSystem.STREAM_MUSIC))) { return false; } return true; diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 0ff8a93ce175..1f9ca8a304c2 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -195,6 +195,7 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Set; +import java.util.TreeSet; import java.util.UUID; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; @@ -1822,6 +1823,7 @@ public class AudioService extends IAudioService.Stub } // Check if device to be updated is routed for the given audio stream + // This may include devices such as SPEAKER_SAFE. List<AudioDeviceAttributes> devicesForAttributes = getDevicesForAttributesInt( new AudioAttributes.Builder().setInternalLegacyStreamType(streamType).build(), true /* forVolume */); @@ -3693,8 +3695,7 @@ public class AudioService extends IAudioService.Stub int streamType = getBluetoothContextualVolumeStream(newMode); - final Set<Integer> deviceTypes = AudioSystem.generateAudioDeviceTypesSet( - mAudioSystem.getDevicesForStream(streamType)); + final Set<Integer> deviceTypes = getDeviceSetForStreamDirect(streamType); final Set<Integer> absVolumeMultiModeCaseDevices = AudioSystem.intersectionAudioDeviceTypes( mAbsVolumeMultiModeCaseDevices, deviceTypes); if (absVolumeMultiModeCaseDevices.isEmpty()) { @@ -6258,55 +6259,104 @@ public class AudioService extends IAudioService.Stub } } - /** only public for mocking/spying, do not call outside of AudioService */ + /** + * Returns device associated with the stream volume. + * + * Only public for mocking/spying, do not call outside of AudioService. + * Device volume aliasing means DEVICE_OUT_SPEAKER may be returned for + * DEVICE_OUT_SPEAKER_SAFE. + */ @VisibleForTesting public int getDeviceForStream(int stream) { - int device = getDevicesForStreamInt(stream); - if ((device & (device - 1)) != 0) { + return selectOneAudioDevice(getDeviceSetForStream(stream)); + } + + /* + * Must match native apm_extract_one_audio_device() used in getDeviceForVolume() + * or the wrong device volume may be adjusted. + */ + private int selectOneAudioDevice(Set<Integer> deviceSet) { + if (deviceSet.isEmpty()) { + return AudioSystem.DEVICE_NONE; + } else if (deviceSet.size() == 1) { + return deviceSet.iterator().next(); + } else { // Multiple device selection is either: // - speaker + one other device: give priority to speaker in this case. // - one A2DP device + another device: happens with duplicated output. In this case // retain the device on the A2DP output as the other must not correspond to an active // selection if not the speaker. // - HDMI-CEC system audio mode only output: give priority to available item in order. - // FIXME: Haven't applied audio device type refactor to this API - // as it is going to be deprecated. - if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) { - device = AudioSystem.DEVICE_OUT_SPEAKER; - } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) { - // FIXME(b/184944421): DEVICE_OUT_HDMI_EARC has two bits set, - // so it must be handled correctly as it aliases - // with DEVICE_OUT_HDMI_ARC | DEVICE_OUT_EARPIECE. - device = AudioSystem.DEVICE_OUT_HDMI_ARC; - } else if ((device & AudioSystem.DEVICE_OUT_SPDIF) != 0) { - device = AudioSystem.DEVICE_OUT_SPDIF; - } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) { - device = AudioSystem.DEVICE_OUT_AUX_LINE; + + if (deviceSet.contains(AudioSystem.DEVICE_OUT_SPEAKER)) { + return AudioSystem.DEVICE_OUT_SPEAKER; + } else if (deviceSet.contains(AudioSystem.DEVICE_OUT_SPEAKER_SAFE)) { + // Note: DEVICE_OUT_SPEAKER_SAFE not present in getDeviceSetForStreamDirect + return AudioSystem.DEVICE_OUT_SPEAKER_SAFE; + } else if (deviceSet.contains(AudioSystem.DEVICE_OUT_HDMI_ARC)) { + return AudioSystem.DEVICE_OUT_HDMI_ARC; + } else if (deviceSet.contains(AudioSystem.DEVICE_OUT_HDMI_EARC)) { + return AudioSystem.DEVICE_OUT_HDMI_EARC; + } else if (deviceSet.contains(AudioSystem.DEVICE_OUT_SPDIF)) { + return AudioSystem.DEVICE_OUT_SPDIF; + } else if (deviceSet.contains(AudioSystem.DEVICE_OUT_AUX_LINE)) { + return AudioSystem.DEVICE_OUT_AUX_LINE; } else { for (int deviceType : AudioSystem.DEVICE_OUT_ALL_A2DP_SET) { - if ((deviceType & device) == deviceType) { + if (deviceSet.contains(deviceType)) { return deviceType; } } } } - return device; + Log.w(TAG, "selectOneAudioDevice returning DEVICE_NONE from invalid device combination " + + AudioSystem.deviceSetToString(deviceSet)); + return AudioSystem.DEVICE_NONE; } /** * @see AudioManager#getDevicesForStream(int) + * @deprecated on {@link android.os.Build.VERSION_CODES#T} as new devices + * will have multi-bit device types since S. + * Use {@link #getDevicesForAttributes()} instead. */ - public int getDevicesForStream(int streamType) { + @Override + @Deprecated + public int getDeviceMaskForStream(int streamType) { ensureValidStreamType(streamType); + // no permission required final long token = Binder.clearCallingIdentity(); try { - return mAudioSystem.getDevicesForStream(streamType); + return AudioSystem.getDeviceMaskFromSet( + getDeviceSetForStreamDirect(streamType)); } finally { Binder.restoreCallingIdentity(token); } } - private int getDevicesForStreamInt(int stream) { + /** + * Returns the devices associated with a stream type. + * + * SPEAKER_SAFE will alias to SPEAKER. + */ + @NonNull + private Set<Integer> getDeviceSetForStreamDirect(int stream) { + final AudioAttributes attr = + AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType(stream); + Set<Integer> deviceSet = + AudioSystem.generateAudioDeviceTypesSet( + getDevicesForAttributesInt(attr, true /* forVolume */)); + return deviceSet; + } + + /** + * Returns a reference to the list of devices for the stream, do not modify. + * + * The device returned may be aliased to the actual device whose volume curve + * will be used. For example DEVICE_OUT_SPEAKER_SAFE aliases to DEVICE_OUT_SPEAKER. + */ + @NonNull + public Set<Integer> getDeviceSetForStream(int stream) { ensureValidStreamType(stream); synchronized (VolumeStreamState.class) { return mStreamStates[stream].observeDevicesForStream_syncVSS(true); @@ -6318,11 +6368,10 @@ public class AudioService extends IAudioService.Stub synchronized (VolumeStreamState.class) { for (int stream = 0; stream < mStreamStates.length; stream++) { if (stream != skipStream) { - int devices = mStreamStates[stream].observeDevicesForStream_syncVSS( - false /*checkOthers*/); - - Set<Integer> devicesSet = AudioSystem.generateAudioDeviceTypesSet(devices); - for (Integer device : devicesSet) { + Set<Integer> deviceSet = + mStreamStates[stream].observeDevicesForStream_syncVSS( + false /*checkOthers*/); + for (Integer device : deviceSet) { // Update volume states for devices routed for the stream updateVolumeStates(device, stream, "AudioService#onObserveDevicesForAllStreams"); @@ -6643,7 +6692,7 @@ public class AudioService extends IAudioService.Stub && DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.contains(newDevice) && mStreamStates[AudioSystem.STREAM_MUSIC].mIsMuted && mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(newDevice) != 0 - && (newDevice & mAudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0) { + && getDeviceSetForStreamDirect(AudioSystem.STREAM_MUSIC).contains(newDevice)) { if (DEBUG_VOL) { Log.i(TAG, String.format("onAccessoryPlugMediaUnmute unmuting device=%d [%s]", newDevice, AudioSystem.getOutputDeviceName(newDevice))); @@ -7031,7 +7080,7 @@ public class AudioService extends IAudioService.Stub private boolean mIsMuted; private boolean mIsMutedInternally; private String mVolumeIndexSettingName; - private int mObservedDevices; + @NonNull private Set<Integer> mObservedDeviceSet = new TreeSet<>(); private final SparseIntArray mIndexMap = new SparseIntArray(8) { @Override @@ -7098,17 +7147,30 @@ public class AudioService extends IAudioService.Stub } } + /** + * Returns a list of devices associated with the stream type. + * + * This is a reference to the local list, do not modify. + */ @GuardedBy("VolumeStreamState.class") - public int observeDevicesForStream_syncVSS(boolean checkOthers) { + @NonNull + public Set<Integer> observeDevicesForStream_syncVSS( + boolean checkOthers) { if (!mSystemServer.isPrivileged()) { - return AudioSystem.DEVICE_NONE; + return new TreeSet<Integer>(); } - final int devices = mAudioSystem.getDevicesForStream(mStreamType); - if (devices == mObservedDevices) { - return devices; + final Set<Integer> deviceSet = + getDeviceSetForStreamDirect(mStreamType); + if (deviceSet.equals(mObservedDeviceSet)) { + return mObservedDeviceSet; } - final int prevDevices = mObservedDevices; - mObservedDevices = devices; + + // Use legacy bit masks for message signalling. + // TODO(b/185386781): message needs update since it uses devices bit-mask. + final int devices = AudioSystem.getDeviceMaskFromSet(deviceSet); + final int prevDevices = AudioSystem.getDeviceMaskFromSet(mObservedDeviceSet); + + mObservedDeviceSet = deviceSet; if (checkOthers) { // one stream's devices have changed, check the others postObserveDevicesForAllStreams(mStreamType); @@ -7124,7 +7186,7 @@ public class AudioService extends IAudioService.Stub SENDMSG_QUEUE, prevDevices /*arg1*/, devices /*arg2*/, // ok to send reference to this object, it is final mStreamDevicesChanged /*obj*/, 0 /*delay*/); - return devices; + return mObservedDeviceSet; } public @Nullable String getSettingNameForDevice(int device) { @@ -7555,19 +7617,7 @@ public class AudioService extends IAudioService.Stub } pw.println(); pw.print(" Devices: "); - final int devices = getDevicesForStreamInt(mStreamType); - int device, i = 0, n = 0; - // iterate all devices from 1 to DEVICE_OUT_DEFAULT exclusive - // (the default device is not returned by getDevicesForStreamInt) - while ((device = 1 << i) != AudioSystem.DEVICE_OUT_DEFAULT) { - if ((devices & device) != 0) { - if (n++ > 0) { - pw.print(", "); - } - pw.print(AudioSystem.getOutputDeviceName(device)); - } - i++; - } + pw.print(AudioSystem.deviceSetToString(getDeviceSetForStream(mStreamType))); } } @@ -9324,7 +9374,9 @@ public class AudioService extends IAudioService.Stub mDeviceBroker.setForceUse_Async(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, config, "setHdmiSystemAudioSupported"); } - device = getDevicesForStreamInt(AudioSystem.STREAM_MUSIC); + // TODO(b/185386781): Update AudioManager API to use device list. + // So far, this value appears to be advisory for debug log. + device = getDeviceMaskForStream(AudioSystem.STREAM_MUSIC); } } return device; diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java index 6ef8e876a10d..1429b3cf2041 100644 --- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java +++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java @@ -52,15 +52,13 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { * in measured methods */ private static final boolean ENABLE_GETDEVICES_STATS = false; - private static final int NB_MEASUREMENTS = 2; - private static final int METHOD_GETDEVICESFORSTREAM = 0; - private static final int METHOD_GETDEVICESFORATTRIBUTES = 1; + private static final int NB_MEASUREMENTS = 1; + private static final int METHOD_GETDEVICESFORATTRIBUTES = 0; private long[] mMethodTimeNs; private int[] mMethodCallCounter; - private String[] mMethodNames = {"getDevicesForStream", "getDevicesForAttributes"}; + private String[] mMethodNames = {"getDevicesForAttributes"}; private static final boolean USE_CACHE_FOR_GETDEVICES = true; - private ConcurrentHashMap<Integer, Integer> mDevicesForStreamCache; private ConcurrentHashMap<Pair<AudioAttributes, Boolean>, ArrayList<AudioDeviceAttributes>> mDevicesForAttrCache; private int[] mMethodCacheHit; @@ -113,8 +111,6 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { sSingletonDefaultAdapter = new AudioSystemAdapter(); AudioSystem.setRoutingCallback(sSingletonDefaultAdapter); if (USE_CACHE_FOR_GETDEVICES) { - sSingletonDefaultAdapter.mDevicesForStreamCache = - new ConcurrentHashMap<>(AudioSystem.getNumStreamTypes()); sSingletonDefaultAdapter.mDevicesForAttrCache = new ConcurrentHashMap<>(AudioSystem.getNumStreamTypes()); sSingletonDefaultAdapter.mMethodCacheHit = new int[NB_MEASUREMENTS]; @@ -131,11 +127,6 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { if (DEBUG_CACHE) { Log.d(TAG, "---- clearing cache ----------"); } - if (mDevicesForStreamCache != null) { - synchronized (mDevicesForStreamCache) { - mDevicesForStreamCache.clear(); - } - } if (mDevicesForAttrCache != null) { synchronized (mDevicesForAttrCache) { mDevicesForAttrCache.clear(); @@ -144,60 +135,6 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { } /** - * Same as {@link AudioSystem#getDevicesForStream(int)} - * @param stream a valid stream type - * @return a mask of device types - */ - public int getDevicesForStream(int stream) { - if (!ENABLE_GETDEVICES_STATS) { - return getDevicesForStreamImpl(stream); - } - mMethodCallCounter[METHOD_GETDEVICESFORSTREAM]++; - final long startTime = SystemClock.uptimeNanos(); - final int res = getDevicesForStreamImpl(stream); - mMethodTimeNs[METHOD_GETDEVICESFORSTREAM] += SystemClock.uptimeNanos() - startTime; - return res; - } - - private int getDevicesForStreamImpl(int stream) { - if (USE_CACHE_FOR_GETDEVICES) { - Integer res; - synchronized (mDevicesForStreamCache) { - res = mDevicesForStreamCache.get(stream); - if (res == null) { - res = AudioSystem.getDevicesForStream(stream); - mDevicesForStreamCache.put(stream, res); - if (DEBUG_CACHE) { - Log.d(TAG, mMethodNames[METHOD_GETDEVICESFORSTREAM] - + streamDeviceToDebugString(stream, res)); - } - return res; - } - // cache hit - mMethodCacheHit[METHOD_GETDEVICESFORSTREAM]++; - if (DEBUG_CACHE) { - final int real = AudioSystem.getDevicesForStream(stream); - if (res == real) { - Log.d(TAG, mMethodNames[METHOD_GETDEVICESFORSTREAM] - + streamDeviceToDebugString(stream, res) + " CACHE"); - } else { - 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 * @return the devices that the stream with the given attributes would be routed to @@ -253,12 +190,9 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { } private static String attrDeviceToDebugString(@NonNull AudioAttributes attr, - @NonNull ArrayList<AudioDeviceAttributes> devices) { - String ds = " attrUsage=" + attr.getSystemUsage(); - for (AudioDeviceAttributes ada : devices) { - ds = ds.concat(" dev=0x" + Integer.toHexString(ada.getInternalType())); - } - return ds; + @NonNull List<AudioDeviceAttributes> devices) { + return " attrUsage=" + attr.getSystemUsage() + " " + + AudioSystem.deviceSetToString(AudioSystem.generateAudioDeviceTypesSet(devices)); } /** @@ -518,20 +452,23 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { */ public void dump(PrintWriter pw) { pw.println("\nAudioSystemAdapter:"); - pw.println(" mDevicesForStreamCache:"); - if (mDevicesForStreamCache != null) { - for (Integer stream : mDevicesForStreamCache.keySet()) { - pw.println("\t stream:" + stream + " device:" - + AudioSystem.getOutputDeviceName(mDevicesForStreamCache.get(stream))); - } - } pw.println(" mDevicesForAttrCache:"); if (mDevicesForAttrCache != null) { for (Map.Entry<Pair<AudioAttributes, Boolean>, ArrayList<AudioDeviceAttributes>> entry : mDevicesForAttrCache.entrySet()) { - pw.println("\t" + entry.getKey().first + " forVolume: " + entry.getKey().second); - for (AudioDeviceAttributes devAttr : entry.getValue()) { - pw.println("\t\t" + devAttr); + final AudioAttributes attributes = entry.getKey().first; + try { + final int stream = attributes.getVolumeControlStream(); + pw.println("\t" + attributes + " forVolume: " + entry.getKey().second + + " stream: " + + AudioSystem.STREAM_NAMES[stream] + "(" + stream + ")"); + for (AudioDeviceAttributes devAttr : entry.getValue()) { + pw.println("\t\t" + devAttr); + } + } catch (IllegalArgumentException e) { + // dump could fail if attributes do not map to a stream. + pw.println("\t dump failed for attributes: " + attributes); + Log.e(TAG, "dump failed", e); } } } @@ -545,7 +482,8 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback { + ": counter=" + mMethodCallCounter[i] + " time(ms)=" + (mMethodTimeNs[i] / 1E6) + (USE_CACHE_FOR_GETDEVICES - ? (" FScacheHit=" + mMethodCacheHit[METHOD_GETDEVICESFORSTREAM]) : "")); + ? (" FScacheHit=" + mMethodCacheHit[METHOD_GETDEVICESFORATTRIBUTES]) + : "")); } pw.println("\n"); } |