Merge "Add SystemApi for querying audio routing"
This commit is contained in:
committed by
Android (Google) Code Review
commit
2dbacb6ca4
@@ -23663,6 +23663,7 @@ package android.media {
|
||||
field public static final int TYPE_BUILTIN_EARPIECE = 1; // 0x1
|
||||
field public static final int TYPE_BUILTIN_MIC = 15; // 0xf
|
||||
field public static final int TYPE_BUILTIN_SPEAKER = 2; // 0x2
|
||||
field public static final int TYPE_BUILTIN_SPEAKER_SAFE = 24; // 0x18
|
||||
field public static final int TYPE_BUS = 21; // 0x15
|
||||
field public static final int TYPE_DOCK = 13; // 0xd
|
||||
field public static final int TYPE_FM = 14; // 0xe
|
||||
|
||||
@@ -4063,6 +4063,10 @@ package android.media {
|
||||
field public static final int ROLE_OUTPUT = 2; // 0x2
|
||||
}
|
||||
|
||||
public final class AudioDeviceInfo {
|
||||
field public static final int TYPE_REMOTE_SUBMIX = 25; // 0x19
|
||||
}
|
||||
|
||||
public final class AudioFocusInfo implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public android.media.AudioAttributes getAttributes();
|
||||
@@ -4090,6 +4094,7 @@ package android.media {
|
||||
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
|
||||
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies();
|
||||
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioVolumeGroup> getAudioVolumeGroups();
|
||||
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAddress> getDevicesForAttributes(@NonNull android.media.AudioAttributes);
|
||||
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
|
||||
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
|
||||
method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDeviceAddress getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
|
||||
|
||||
@@ -2312,6 +2312,48 @@ android_media_AudioSystem_getPreferredDeviceForStrategy(JNIEnv *env, jobject thi
|
||||
return jStatus;
|
||||
}
|
||||
|
||||
static jint
|
||||
android_media_AudioSystem_getDevicesForAttributes(JNIEnv *env, jobject thiz,
|
||||
jobject jaa, jobjectArray jDeviceArray)
|
||||
{
|
||||
const jsize maxResultSize = env->GetArrayLength(jDeviceArray);
|
||||
// the JNI is always expected to provide us with an array capable of holding enough
|
||||
// devices i.e. the most we ever route a track to. This is preferred over receiving an ArrayList
|
||||
// with reverse JNI to make the array grow as need as this would be less efficient, and some
|
||||
// components call this method often
|
||||
if (jDeviceArray == nullptr || maxResultSize == 0) {
|
||||
ALOGE("%s invalid array to store AudioDeviceAddress", __FUNCTION__);
|
||||
return (jint)AUDIO_JAVA_BAD_VALUE;
|
||||
}
|
||||
|
||||
JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
|
||||
jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
|
||||
if (jStatus != (jint) AUDIO_JAVA_SUCCESS) {
|
||||
return jStatus;
|
||||
}
|
||||
|
||||
AudioDeviceTypeAddrVector devices;
|
||||
jStatus = check_AudioSystem_Command(
|
||||
AudioSystem::getDevicesForAttributes(*(paa.get()), &devices));
|
||||
if (jStatus != NO_ERROR) {
|
||||
return jStatus;
|
||||
}
|
||||
|
||||
if (devices.size() > maxResultSize) {
|
||||
return AUDIO_JAVA_INVALID_OPERATION;
|
||||
}
|
||||
size_t index = 0;
|
||||
jobject jAudioDeviceAddress = NULL;
|
||||
for (const auto& device : devices) {
|
||||
jStatus = createAudioDeviceAddressFromNative(env, &jAudioDeviceAddress, &device);
|
||||
if (jStatus != AUDIO_JAVA_SUCCESS) {
|
||||
return jStatus;
|
||||
}
|
||||
env->SetObjectArrayElement(jDeviceArray, index++, jAudioDeviceAddress);
|
||||
}
|
||||
return jStatus;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static const JNINativeMethod gMethods[] = {
|
||||
@@ -2395,6 +2437,7 @@ static const JNINativeMethod gMethods[] = {
|
||||
{"setPreferredDeviceForStrategy", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setPreferredDeviceForStrategy},
|
||||
{"removePreferredDeviceForStrategy", "(I)I", (void *)android_media_AudioSystem_removePreferredDeviceForStrategy},
|
||||
{"getPreferredDeviceForStrategy", "(I[Landroid/media/AudioDeviceAddress;)I", (void *)android_media_AudioSystem_getPreferredDeviceForStrategy},
|
||||
{"getDevicesForAttributes", "(Landroid/media/AudioAttributes;[Landroid/media/AudioDeviceAddress;)I", (void *)android_media_AudioSystem_getDevicesForAttributes}
|
||||
};
|
||||
|
||||
static const JNINativeMethod gEventHandlerMethods[] = {
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.media;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SystemApi;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -127,6 +128,23 @@ public final class AudioDeviceInfo {
|
||||
* A device type describing a Hearing Aid.
|
||||
*/
|
||||
public static final int TYPE_HEARING_AID = 23;
|
||||
/**
|
||||
* A device type describing the speaker system (i.e. a mono speaker or stereo speakers) built
|
||||
* in a device, that is specifically tuned for outputting sounds like notifications and alarms
|
||||
* (i.e. sounds the user couldn't necessarily anticipate).
|
||||
* <p>Note that this physical audio device may be the same as {@link #TYPE_BUILTIN_SPEAKER}
|
||||
* but is driven differently to safely accommodate the different use case.</p>
|
||||
*/
|
||||
public static final int TYPE_BUILTIN_SPEAKER_SAFE = 24;
|
||||
/**
|
||||
* @hide
|
||||
* A device type for rerouting audio within the Android framework between mixes and
|
||||
* system applications. Typically created when using
|
||||
* {@link android.media.audiopolicy.AudioPolicy} for mixes created with the
|
||||
* {@link android.media.audiopolicy.AudioMix#ROUTE_FLAG_RENDER} flag.
|
||||
*/
|
||||
@SystemApi
|
||||
public static final int TYPE_REMOTE_SUBMIX = 25;
|
||||
|
||||
/** @hide */
|
||||
@IntDef(flag = false, prefix = "TYPE", value = {
|
||||
@@ -228,6 +246,8 @@ public final class AudioDeviceInfo {
|
||||
case TYPE_IP:
|
||||
case TYPE_BUS:
|
||||
case TYPE_HEARING_AID:
|
||||
case TYPE_BUILTIN_SPEAKER_SAFE:
|
||||
case TYPE_REMOTE_SUBMIX:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -253,6 +273,7 @@ public final class AudioDeviceInfo {
|
||||
case TYPE_LINE_DIGITAL:
|
||||
case TYPE_IP:
|
||||
case TYPE_BUS:
|
||||
case TYPE_REMOTE_SUBMIX:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -449,6 +470,9 @@ public final class AudioDeviceInfo {
|
||||
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_IP, TYPE_IP);
|
||||
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BUS, TYPE_BUS);
|
||||
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_HEARING_AID, TYPE_HEARING_AID);
|
||||
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPEAKER_SAFE,
|
||||
TYPE_BUILTIN_SPEAKER_SAFE);
|
||||
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX);
|
||||
|
||||
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, TYPE_BUILTIN_MIC);
|
||||
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, TYPE_BLUETOOTH_SCO);
|
||||
@@ -468,10 +492,7 @@ public final class AudioDeviceInfo {
|
||||
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, TYPE_BLUETOOTH_A2DP);
|
||||
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_IP, TYPE_IP);
|
||||
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUS, TYPE_BUS);
|
||||
|
||||
// not covered here, legacy
|
||||
//AudioSystem.DEVICE_OUT_REMOTE_SUBMIX
|
||||
//AudioSystem.DEVICE_IN_REMOTE_SUBMIX
|
||||
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX);
|
||||
|
||||
// privileges mapping to output device
|
||||
EXT_TO_INT_DEVICE_MAPPING = new SparseIntArray();
|
||||
@@ -498,6 +519,9 @@ public final class AudioDeviceInfo {
|
||||
EXT_TO_INT_DEVICE_MAPPING.put(TYPE_IP, AudioSystem.DEVICE_OUT_IP);
|
||||
EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BUS, AudioSystem.DEVICE_OUT_BUS);
|
||||
EXT_TO_INT_DEVICE_MAPPING.put(TYPE_HEARING_AID, AudioSystem.DEVICE_OUT_HEARING_AID);
|
||||
EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BUILTIN_SPEAKER_SAFE,
|
||||
AudioSystem.DEVICE_OUT_SPEAKER_SAFE);
|
||||
EXT_TO_INT_DEVICE_MAPPING.put(TYPE_REMOTE_SUBMIX, AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4331,6 +4331,26 @@ public class AudioManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Get the audio devices that would be used for the routing of the given audio attributes.
|
||||
* @param attributes the {@link AudioAttributes} for which the routing is being queried
|
||||
* @return an empty list if there was an issue with the request, a list of audio devices
|
||||
* otherwise (typically one device, except for duplicated paths).
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
|
||||
public @NonNull List<AudioDeviceAddress> getDevicesForAttributes(
|
||||
@NonNull AudioAttributes attributes) {
|
||||
Objects.requireNonNull(attributes);
|
||||
final IAudioService service = getService();
|
||||
try {
|
||||
return service.getDevicesForAttributes(attributes);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate wired accessory connection state change.
|
||||
* @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx)
|
||||
|
||||
@@ -33,6 +33,7 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/* IF YOU CHANGE ANY OF THE CONSTANTS IN THIS FILE, DO NOT FORGET
|
||||
@@ -1077,6 +1078,41 @@ public class AudioSystem
|
||||
@UnsupportedAppUsage
|
||||
public static native int getDevicesForStream(int stream);
|
||||
|
||||
/**
|
||||
* Do not use directly, see {@link AudioManager#getDevicesForAttributes(AudioAttributes)}
|
||||
* Get the audio devices that would be used for the routing of the given audio attributes.
|
||||
* @param attributes the {@link AudioAttributes} for which the routing is being queried
|
||||
* @return an empty list if there was an issue with the request, a list of audio devices
|
||||
* otherwise (typically one device, except for duplicated paths).
|
||||
*/
|
||||
public static @NonNull ArrayList<AudioDeviceAddress> getDevicesForAttributes(
|
||||
@NonNull AudioAttributes attributes) {
|
||||
Objects.requireNonNull(attributes);
|
||||
final AudioDeviceAddress[] devices = new AudioDeviceAddress[MAX_DEVICE_ROUTING];
|
||||
final int res = getDevicesForAttributes(attributes, devices);
|
||||
final ArrayList<AudioDeviceAddress> routeDevices = new ArrayList<>();
|
||||
if (res != SUCCESS) {
|
||||
Log.e(TAG, "error " + res + " in getDevicesForAttributes for " + attributes);
|
||||
return routeDevices;
|
||||
}
|
||||
|
||||
for (AudioDeviceAddress device : devices) {
|
||||
if (device != null) {
|
||||
routeDevices.add(device);
|
||||
}
|
||||
}
|
||||
return routeDevices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum number of audio devices a track is ever routed to, determines the size of the
|
||||
* array passed to {@link #getDevicesForAttributes(AudioAttributes, AudioDeviceAddress[])}
|
||||
*/
|
||||
private static final int MAX_DEVICE_ROUTING = 4;
|
||||
|
||||
private static native int getDevicesForAttributes(@NonNull AudioAttributes aa,
|
||||
@NonNull AudioDeviceAddress[] devices);
|
||||
|
||||
/** @hide returns true if master mono is enabled. */
|
||||
public static native boolean getMasterMono();
|
||||
/** @hide enables or disables the master mono mode. */
|
||||
|
||||
@@ -272,6 +272,8 @@ interface IAudioService {
|
||||
|
||||
AudioDeviceAddress getPreferredDeviceForStrategy(in int strategy);
|
||||
|
||||
List<AudioDeviceAddress> getDevicesForAttributes(in AudioAttributes attributes);
|
||||
|
||||
// WARNING: read warning at top of file, new methods that need to be used by native
|
||||
// code via IAudioManager.h need to be added to the top section.
|
||||
}
|
||||
|
||||
@@ -1700,6 +1700,14 @@ public class AudioService extends IAudioService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/** @see AudioManager#getDevicesForAttributes(AudioAttributes) */
|
||||
public @NonNull ArrayList<AudioDeviceAddress> getDevicesForAttributes(
|
||||
@NonNull AudioAttributes attributes) {
|
||||
Objects.requireNonNull(attributes);
|
||||
enforceModifyAudioRoutingPermission();
|
||||
return AudioSystem.getDevicesForAttributes(attributes);
|
||||
}
|
||||
|
||||
|
||||
/** @see AudioManager#adjustVolume(int, int) */
|
||||
public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
|
||||
|
||||
Reference in New Issue
Block a user