Merge "Use device set for getDevicesForStream" into tm-dev
This commit is contained in:
@@ -828,13 +828,6 @@ android_media_AudioSystem_getMasterBalance(JNIEnv *env, jobject thiz)
|
||||
return balance;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -360,7 +360,7 @@ interface IAudioService {
|
||||
|
||||
boolean isMusicActive(in boolean remotely);
|
||||
|
||||
int getDevicesForStream(in int streamType);
|
||||
int getDeviceMaskForStream(in int streamType);
|
||||
|
||||
int[] getAvailableCommunicationDeviceIds();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
@@ -143,60 +134,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
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user