Merge changes from topics "AudioDeviceAttributes_update", "ShortAudioDescriptors"
* changes: Inform AudioManager about ARC SADs Add AudioDeviceAttributes as argument to AudioManager API Add fields to AudioDeviceAttributes class
This commit is contained in:
committed by
Android (Google) Code Review
commit
dbad339f5f
@@ -19679,10 +19679,13 @@ package android.media {
|
||||
method public android.media.AudioAttributes.Builder setUsage(int);
|
||||
}
|
||||
|
||||
public class AudioDescriptor {
|
||||
public class AudioDescriptor implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public byte[] getDescriptor();
|
||||
method public int getEncapsulationType();
|
||||
method public int getStandard();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.media.AudioDescriptor> CREATOR;
|
||||
field public static final int STANDARD_EDID = 1; // 0x1
|
||||
field public static final int STANDARD_NONE = 0; // 0x0
|
||||
}
|
||||
@@ -20198,14 +20201,17 @@ package android.media {
|
||||
method @NonNull public android.media.AudioPresentation.Builder setProgramId(int);
|
||||
}
|
||||
|
||||
public class AudioProfile {
|
||||
public class AudioProfile implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public int[] getChannelIndexMasks();
|
||||
method @NonNull public int[] getChannelMasks();
|
||||
method public int getEncapsulationType();
|
||||
method public int getFormat();
|
||||
method @NonNull public int[] getSampleRates();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field public static final int AUDIO_ENCAPSULATION_TYPE_IEC61937 = 1; // 0x1
|
||||
field public static final int AUDIO_ENCAPSULATION_TYPE_NONE = 0; // 0x0
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.media.AudioProfile> CREATOR;
|
||||
}
|
||||
|
||||
public class AudioRecord implements android.media.AudioRecordingMonitor android.media.AudioRouting android.media.MicrophoneDirection {
|
||||
|
||||
@@ -5933,11 +5933,20 @@ package android.media {
|
||||
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioAttributes.Builder setSystemUsage(int);
|
||||
}
|
||||
|
||||
public class AudioDescriptor implements android.os.Parcelable {
|
||||
ctor public AudioDescriptor(int, int, @NonNull byte[]);
|
||||
}
|
||||
|
||||
public final class AudioDeviceAttributes implements android.os.Parcelable {
|
||||
ctor public AudioDeviceAttributes(@NonNull android.media.AudioDeviceInfo);
|
||||
ctor public AudioDeviceAttributes(int, int, @NonNull String);
|
||||
ctor public AudioDeviceAttributes(int, int, @NonNull String, @NonNull String, @NonNull java.util.List<android.media.AudioProfile>, @NonNull java.util.List<android.media.AudioDescriptor>);
|
||||
method public int describeContents();
|
||||
method public boolean equalTypeAddress(@Nullable Object);
|
||||
method @NonNull public String getAddress();
|
||||
method @NonNull public java.util.List<android.media.AudioDescriptor> getAudioDescriptors();
|
||||
method @NonNull public java.util.List<android.media.AudioProfile> getAudioProfiles();
|
||||
method @NonNull public String getName();
|
||||
method public int getRole();
|
||||
method public int getType();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
@@ -6094,6 +6103,10 @@ package android.media {
|
||||
field public static final int PLAYER_TYPE_UNKNOWN = -1; // 0xffffffff
|
||||
}
|
||||
|
||||
public class AudioProfile implements android.os.Parcelable {
|
||||
ctor public AudioProfile(int, @NonNull int[], @NonNull int[], @NonNull int[], int);
|
||||
}
|
||||
|
||||
public class AudioRecord implements android.media.AudioRecordingMonitor android.media.AudioRouting android.media.MicrophoneDirection {
|
||||
ctor @RequiresPermission(android.Manifest.permission.RECORD_AUDIO) public AudioRecord(android.media.AudioAttributes, android.media.AudioFormat, int, int) throws java.lang.IllegalArgumentException;
|
||||
method public static long getMaxSharedAudioHistoryMillis();
|
||||
|
||||
@@ -18,25 +18,25 @@
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#define LOG_TAG "AudioSystem-JNI"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <jni.h>
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
#include "core_jni_helpers.h"
|
||||
|
||||
#include <android/media/AudioVibratorInfo.h>
|
||||
#include <android/media/INativeSpatializerCallback.h>
|
||||
#include <android/media/ISpatializer.h>
|
||||
#include <android_os_Parcel.h>
|
||||
#include <audiomanager/AudioManager.h>
|
||||
#include <jni.h>
|
||||
#include <media/AudioContainers.h>
|
||||
#include <media/AudioPolicy.h>
|
||||
#include <media/AudioSystem.h>
|
||||
#include <media/MicrophoneInfo.h>
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
#include <nativehelper/ScopedLocalRef.h>
|
||||
#include <system/audio.h>
|
||||
#include <system/audio_policy.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "android_media_AudioAttributes.h"
|
||||
#include "android_media_AudioDescriptor.h"
|
||||
#include "android_media_AudioDeviceAttributes.h"
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "android_media_AudioProfile.h"
|
||||
#include "android_media_MicrophoneInfo.h"
|
||||
#include "android_util_Binder.h"
|
||||
#include "core_jni_helpers.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -584,18 +585,26 @@ android_media_AudioSystem_routing_callback()
|
||||
env->DeleteLocalRef(clazz);
|
||||
}
|
||||
|
||||
static jint
|
||||
android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name,
|
||||
jint codec)
|
||||
{
|
||||
const char *c_address = env->GetStringUTFChars(device_address, NULL);
|
||||
const char *c_name = env->GetStringUTFChars(device_name, NULL);
|
||||
int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),
|
||||
static_cast <audio_policy_dev_state_t>(state),
|
||||
c_address, c_name,
|
||||
static_cast <audio_format_t>(codec)));
|
||||
env->ReleaseStringUTFChars(device_address, c_address);
|
||||
env->ReleaseStringUTFChars(device_name, c_name);
|
||||
static jint android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz,
|
||||
jint state, jobject jParcel,
|
||||
jint codec) {
|
||||
int status;
|
||||
if (Parcel *parcel = parcelForJavaObject(env, jParcel); parcel != nullptr) {
|
||||
android::media::audio::common::AudioPort port{};
|
||||
if (status_t statusOfParcel = port.readFromParcel(parcel); statusOfParcel == OK) {
|
||||
status = check_AudioSystem_Command(
|
||||
AudioSystem::setDeviceConnectionState(static_cast<audio_policy_dev_state_t>(
|
||||
state),
|
||||
port,
|
||||
static_cast<audio_format_t>(codec)));
|
||||
} else {
|
||||
ALOGE("Failed to read from parcel: %s", statusToString(statusOfParcel).c_str());
|
||||
status = kAudioStatusError;
|
||||
}
|
||||
} else {
|
||||
ALOGE("Failed to retrieve the native parcel from Java parcel");
|
||||
status = kAudioStatusError;
|
||||
}
|
||||
return (jint) status;
|
||||
}
|
||||
|
||||
@@ -2912,7 +2921,7 @@ static const JNINativeMethod gMethods[] =
|
||||
{"newAudioSessionId", "()I", (void *)android_media_AudioSystem_newAudioSessionId},
|
||||
{"newAudioPlayerId", "()I", (void *)android_media_AudioSystem_newAudioPlayerId},
|
||||
{"newAudioRecorderId", "()I", (void *)android_media_AudioSystem_newAudioRecorderId},
|
||||
{"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;I)I",
|
||||
{"setDeviceConnectionState", "(ILandroid/os/Parcel;I)I",
|
||||
(void *)android_media_AudioSystem_setDeviceConnectionState},
|
||||
{"getDeviceConnectionState", "(ILjava/lang/String;)I",
|
||||
(void *)android_media_AudioSystem_getDeviceConnectionState},
|
||||
|
||||
@@ -18,16 +18,21 @@ package android.media;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SystemApi;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* The AudioDescriptor contains the information to describe the audio playback/capture
|
||||
* capabilities. The capabilities are described by a byte array, which is defined by a
|
||||
* particular standard. This is used when the format is unrecognized to the platform.
|
||||
*/
|
||||
public class AudioDescriptor {
|
||||
public class AudioDescriptor implements Parcelable {
|
||||
/**
|
||||
* The audio standard is not specified.
|
||||
*/
|
||||
@@ -49,7 +54,15 @@ public class AudioDescriptor {
|
||||
private final byte[] mDescriptor;
|
||||
private final int mEncapsulationType;
|
||||
|
||||
AudioDescriptor(int standard, int encapsulationType, @NonNull byte[] descriptor) {
|
||||
/**
|
||||
* @hide
|
||||
* Constructor from standard, encapsulation type and descriptor
|
||||
* @param standard the standard of the audio descriptor
|
||||
* @param encapsulationType the encapsulation type of the audio descriptor
|
||||
* @param descriptor the audio descriptor
|
||||
*/
|
||||
@SystemApi
|
||||
public AudioDescriptor(int standard, int encapsulationType, @NonNull byte[] descriptor) {
|
||||
mStandard = standard;
|
||||
mEncapsulationType = encapsulationType;
|
||||
mDescriptor = descriptor;
|
||||
@@ -87,4 +100,66 @@ public class AudioDescriptor {
|
||||
public @AudioProfile.EncapsulationType int getEncapsulationType() {
|
||||
return mEncapsulationType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mStandard, mEncapsulationType, Arrays.hashCode(mDescriptor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
AudioDescriptor that = (AudioDescriptor) o;
|
||||
return ((mStandard == that.mStandard)
|
||||
&& (mEncapsulationType == that.mEncapsulationType)
|
||||
&& (Arrays.equals(mDescriptor, that.mDescriptor)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("{");
|
||||
sb.append("standard=" + mStandard);
|
||||
sb.append(", encapsulation type=" + mEncapsulationType);
|
||||
if (mDescriptor != null && mDescriptor.length > 0) {
|
||||
sb.append(", descriptor=").append(Arrays.toString(mDescriptor));
|
||||
}
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeInt(mStandard);
|
||||
dest.writeInt(mEncapsulationType);
|
||||
dest.writeByteArray(mDescriptor);
|
||||
}
|
||||
|
||||
private AudioDescriptor(@NonNull Parcel in) {
|
||||
mStandard = in.readInt();
|
||||
mEncapsulationType = in.readInt();
|
||||
mDescriptor = in.createByteArray();
|
||||
}
|
||||
|
||||
public static final @NonNull Parcelable.Creator<AudioDescriptor> CREATOR =
|
||||
new Parcelable.Creator<AudioDescriptor>() {
|
||||
/**
|
||||
* Rebuilds an AudioDescriptor previously stored with writeToParcel().
|
||||
* @param p Parcel object to read the AudioDescriptor from
|
||||
* @return a new AudioDescriptor created from the data in the parcel
|
||||
*/
|
||||
public AudioDescriptor createFromParcel(Parcel p) {
|
||||
return new AudioDescriptor(p);
|
||||
}
|
||||
|
||||
public AudioDescriptor[] newArray(int size) {
|
||||
return new AudioDescriptor[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -18,12 +18,16 @@ package android.media;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -65,16 +69,27 @@ public final class AudioDeviceAttributes implements Parcelable {
|
||||
* The unique address of the device. Some devices don't have addresses, only an empty string.
|
||||
*/
|
||||
private final @NonNull String mAddress;
|
||||
|
||||
/**
|
||||
* The non-unique name of the device. Some devices don't have names, only an empty string.
|
||||
* Should not be used as a unique identifier for a device.
|
||||
*/
|
||||
private final @NonNull String mName;
|
||||
/**
|
||||
* Is input or output device
|
||||
*/
|
||||
private final @Role int mRole;
|
||||
|
||||
/**
|
||||
* The internal audio device type
|
||||
*/
|
||||
private final int mNativeType;
|
||||
/**
|
||||
* List of AudioProfiles supported by the device
|
||||
*/
|
||||
private final @NonNull List<AudioProfile> mAudioProfiles;
|
||||
/**
|
||||
* List of AudioDescriptors supported by the device
|
||||
*/
|
||||
private final @NonNull List<AudioDescriptor> mAudioDescriptors;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
@@ -88,7 +103,10 @@ public final class AudioDeviceAttributes implements Parcelable {
|
||||
mRole = deviceInfo.isSink() ? ROLE_OUTPUT : ROLE_INPUT;
|
||||
mType = deviceInfo.getType();
|
||||
mAddress = deviceInfo.getAddress();
|
||||
mName = String.valueOf(deviceInfo.getProductName());
|
||||
mNativeType = deviceInfo.getInternalType();
|
||||
mAudioProfiles = deviceInfo.getAudioProfiles();
|
||||
mAudioDescriptors = deviceInfo.getAudioDescriptors();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +118,24 @@ public final class AudioDeviceAttributes implements Parcelable {
|
||||
*/
|
||||
@SystemApi
|
||||
public AudioDeviceAttributes(@Role int role, @AudioDeviceInfo.AudioDeviceType int type,
|
||||
@NonNull String address) {
|
||||
@NonNull String address) {
|
||||
this(role, type, address, "", new ArrayList<>(), new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Constructor with specification of all attributes
|
||||
* @param role indicates input or output role
|
||||
* @param type the device type, as defined in {@link AudioDeviceInfo}
|
||||
* @param address the address of the device, or an empty string for devices without one
|
||||
* @param name the name of the device, or an empty string for devices without one
|
||||
* @param profiles the list of AudioProfiles supported by the device
|
||||
* @param descriptors the list of AudioDescriptors supported by the device
|
||||
*/
|
||||
@SystemApi
|
||||
public AudioDeviceAttributes(@Role int role, @AudioDeviceInfo.AudioDeviceType int type,
|
||||
@NonNull String address, @NonNull String name, @NonNull List<AudioProfile> profiles,
|
||||
@NonNull List<AudioDescriptor> descriptors) {
|
||||
Objects.requireNonNull(address);
|
||||
if (role != ROLE_OUTPUT && role != ROLE_INPUT) {
|
||||
throw new IllegalArgumentException("Invalid role " + role);
|
||||
@@ -118,19 +153,37 @@ public final class AudioDeviceAttributes implements Parcelable {
|
||||
mRole = role;
|
||||
mType = type;
|
||||
mAddress = address;
|
||||
mName = name;
|
||||
mAudioProfiles = profiles;
|
||||
mAudioDescriptors = descriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Constructor from internal device type and address
|
||||
* @param type the internal device type, as defined in {@link AudioSystem}
|
||||
* Constructor called from AudioSystem JNI when creating an AudioDeviceAttributes from a native
|
||||
* AudioDeviceTypeAddr instance.
|
||||
* @param nativeType the internal device type, as defined in {@link AudioSystem}
|
||||
* @param address the address of the device, or an empty string for devices without one
|
||||
*/
|
||||
public AudioDeviceAttributes(int nativeType, @NonNull String address) {
|
||||
this(nativeType, address, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Constructor called from BtHelper to connect or disconnect a Bluetooth device.
|
||||
* @param nativeType the internal device type, as defined in {@link AudioSystem}
|
||||
* @param address the address of the device, or an empty string for devices without one
|
||||
* @param name the name of the device, or an empty string for devices without one
|
||||
*/
|
||||
public AudioDeviceAttributes(int nativeType, @NonNull String address, @NonNull String name) {
|
||||
mRole = (nativeType & AudioSystem.DEVICE_BIT_IN) != 0 ? ROLE_INPUT : ROLE_OUTPUT;
|
||||
mType = AudioDeviceInfo.convertInternalDeviceToDeviceType(nativeType);
|
||||
mAddress = address;
|
||||
mName = name;
|
||||
mNativeType = nativeType;
|
||||
mAudioProfiles = new ArrayList<>();
|
||||
mAudioDescriptors = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,6 +216,16 @@ public final class AudioDeviceAttributes implements Parcelable {
|
||||
return mAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Returns the name of the audio device, or an empty string for devices without one
|
||||
* @return the device name
|
||||
*/
|
||||
@SystemApi
|
||||
public @NonNull String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Returns the internal device type of a device
|
||||
@@ -172,9 +235,29 @@ public final class AudioDeviceAttributes implements Parcelable {
|
||||
return mNativeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Returns the list of AudioProfiles supported by the device
|
||||
* @return the list of AudioProfiles
|
||||
*/
|
||||
@SystemApi
|
||||
public @NonNull List<AudioProfile> getAudioProfiles() {
|
||||
return mAudioProfiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Returns the list of AudioDescriptors supported by the device
|
||||
* @return the list of AudioDescriptors
|
||||
*/
|
||||
@SystemApi
|
||||
public @NonNull List<AudioDescriptor> getAudioDescriptors() {
|
||||
return mAudioDescriptors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mRole, mType, mAddress);
|
||||
return Objects.hash(mRole, mType, mAddress, mName, mAudioProfiles, mAudioDescriptors);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -182,6 +265,25 @@ public final class AudioDeviceAttributes implements Parcelable {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
AudioDeviceAttributes that = (AudioDeviceAttributes) o;
|
||||
return ((mRole == that.mRole)
|
||||
&& (mType == that.mType)
|
||||
&& mAddress.equals(that.mAddress)
|
||||
&& mName.equals(that.mName)
|
||||
&& mAudioProfiles.equals(that.mAudioProfiles)
|
||||
&& mAudioDescriptors.equals(that.mAudioDescriptors));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the role, type and address are equal. Called to compare with an
|
||||
* AudioDeviceAttributes that was created from a native AudioDeviceTypeAddr instance.
|
||||
* @param o object to compare with
|
||||
* @return whether role, type and address are equal
|
||||
*/
|
||||
public boolean equalTypeAddress(@Nullable Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
AudioDeviceAttributes that = (AudioDeviceAttributes) o;
|
||||
return ((mRole == that.mRole)
|
||||
&& (mType == that.mType)
|
||||
@@ -199,7 +301,10 @@ public final class AudioDeviceAttributes implements Parcelable {
|
||||
+ " role:" + roleToString(mRole)
|
||||
+ " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName(mNativeType)
|
||||
: AudioSystem.getInputDeviceName(mNativeType))
|
||||
+ " addr:" + mAddress);
|
||||
+ " addr:" + mAddress
|
||||
+ " name:" + mName
|
||||
+ " profiles:" + mAudioProfiles.toString()
|
||||
+ " descriptors:" + mAudioDescriptors.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -212,14 +317,26 @@ public final class AudioDeviceAttributes implements Parcelable {
|
||||
dest.writeInt(mRole);
|
||||
dest.writeInt(mType);
|
||||
dest.writeString(mAddress);
|
||||
dest.writeString(mName);
|
||||
dest.writeInt(mNativeType);
|
||||
dest.writeParcelableArray(
|
||||
mAudioProfiles.toArray(new AudioProfile[mAudioProfiles.size()]), flags);
|
||||
dest.writeParcelableArray(
|
||||
mAudioDescriptors.toArray(new AudioDescriptor[mAudioDescriptors.size()]), flags);
|
||||
}
|
||||
|
||||
private AudioDeviceAttributes(@NonNull Parcel in) {
|
||||
mRole = in.readInt();
|
||||
mType = in.readInt();
|
||||
mAddress = in.readString();
|
||||
mName = in.readString();
|
||||
mNativeType = in.readInt();
|
||||
AudioProfile[] audioProfilesArray =
|
||||
in.readParcelableArray(AudioProfile.class.getClassLoader(), AudioProfile.class);
|
||||
mAudioProfiles = new ArrayList<AudioProfile>(Arrays.asList(audioProfilesArray));
|
||||
AudioDescriptor[] audioDescriptorsArray = in.readParcelableArray(
|
||||
AudioDescriptor.class.getClassLoader(), AudioDescriptor.class);
|
||||
mAudioDescriptors = new ArrayList<AudioDescriptor>(Arrays.asList(audioDescriptorsArray));
|
||||
}
|
||||
|
||||
public static final @NonNull Parcelable.Creator<AudioDeviceAttributes> CREATOR =
|
||||
|
||||
@@ -421,7 +421,7 @@ public final class AudioDeviceInfo {
|
||||
*/
|
||||
public CharSequence getProductName() {
|
||||
String portName = mPort.name();
|
||||
return portName.length() != 0 ? portName : android.os.Build.MODEL;
|
||||
return (portName != null && portName.length() != 0) ? portName : android.os.Build.MODEL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5874,7 +5874,7 @@ public class AudioManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Indicate wired accessory connection state change.
|
||||
* @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx)
|
||||
* @param state new connection state: 1 connected, 0 disconnected
|
||||
@@ -5883,10 +5883,29 @@ public class AudioManager {
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
|
||||
public void setWiredDeviceConnectionState(int type, int state, String address, String name) {
|
||||
public void setWiredDeviceConnectionState(int device, int state, String address,
|
||||
String name) {
|
||||
final IAudioService service = getService();
|
||||
int role = isOutputDevice(device)
|
||||
? AudioDeviceAttributes.ROLE_OUTPUT : AudioDeviceAttributes.ROLE_INPUT;
|
||||
AudioDeviceAttributes attributes = new AudioDeviceAttributes(
|
||||
role, AudioDeviceInfo.convertInternalDeviceToDeviceType(device), address,
|
||||
name, new ArrayList<>()/*mAudioProfiles*/, new ArrayList<>()/*mAudioDescriptors*/);
|
||||
setWiredDeviceConnectionState(attributes, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate wired accessory connection state change and attributes.
|
||||
* @param state new connection state: 1 connected, 0 disconnected
|
||||
* @param attributes attributes of the connected device
|
||||
* {@hide}
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
|
||||
public void setWiredDeviceConnectionState(AudioDeviceAttributes attributes, int state) {
|
||||
final IAudioService service = getService();
|
||||
try {
|
||||
service.setWiredDeviceConnectionState(type, state, address, name,
|
||||
service.setWiredDeviceConnectionState(attributes, state,
|
||||
mApplicationContext.getOpPackageName());
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
|
||||
@@ -18,10 +18,14 @@ package android.media;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SystemApi;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -33,7 +37,7 @@ import java.util.stream.Collectors;
|
||||
* be reported in different audio profiles. The application can choose any of the encapsulation
|
||||
* types.
|
||||
*/
|
||||
public class AudioProfile {
|
||||
public class AudioProfile implements Parcelable {
|
||||
/**
|
||||
* No encapsulation type is specified.
|
||||
*/
|
||||
@@ -57,9 +61,19 @@ public class AudioProfile {
|
||||
private final int[] mChannelIndexMasks;
|
||||
private final int mEncapsulationType;
|
||||
|
||||
AudioProfile(int format, @NonNull int[] samplingRates, @NonNull int[] channelMasks,
|
||||
@NonNull int[] channelIndexMasks,
|
||||
int encapsulationType) {
|
||||
/**
|
||||
* @hide
|
||||
* Constructor from format, sampling rates, channel masks, channel index masks and
|
||||
* encapsulation type.
|
||||
* @param format the audio format
|
||||
* @param samplingRates the supported sampling rates
|
||||
* @param channelMasks the supported channel masks
|
||||
* @param channelIndexMasks the supported channel index masks
|
||||
* @param encapsulationType the encapsulation type of the encoding format
|
||||
*/
|
||||
@SystemApi
|
||||
public AudioProfile(int format, @NonNull int[] samplingRates, @NonNull int[] channelMasks,
|
||||
@NonNull int[] channelIndexMasks, int encapsulationType) {
|
||||
mFormat = format;
|
||||
mSamplingRates = samplingRates;
|
||||
mChannelMasks = channelMasks;
|
||||
@@ -113,6 +127,26 @@ public class AudioProfile {
|
||||
return mEncapsulationType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mFormat, Arrays.hashCode(mSamplingRates),
|
||||
Arrays.hashCode(mChannelMasks), Arrays.hashCode(mChannelIndexMasks),
|
||||
mEncapsulationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
AudioProfile that = (AudioProfile) o;
|
||||
return ((mFormat == that.mFormat)
|
||||
&& (hasIdenticalElements(mSamplingRates, that.mSamplingRates))
|
||||
&& (hasIdenticalElements(mChannelMasks, that.mChannelMasks))
|
||||
&& (hasIdenticalElements(mChannelIndexMasks, that.mChannelIndexMasks))
|
||||
&& (mEncapsulationType == that.mEncapsulationType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("{");
|
||||
@@ -126,6 +160,7 @@ public class AudioProfile {
|
||||
if (mChannelIndexMasks != null && mChannelIndexMasks.length > 0) {
|
||||
sb.append(", channel index masks=").append(Arrays.toString(mChannelIndexMasks));
|
||||
}
|
||||
sb.append(", encapsulation type=" + mEncapsulationType);
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -137,4 +172,50 @@ public class AudioProfile {
|
||||
return Arrays.stream(ints).mapToObj(anInt -> String.format("0x%02X", anInt))
|
||||
.collect(Collectors.joining(", "));
|
||||
}
|
||||
|
||||
private static boolean hasIdenticalElements(int[] array1, int[] array2) {
|
||||
int[] sortedArray1 = Arrays.copyOf(array1, array1.length);
|
||||
Arrays.sort(sortedArray1);
|
||||
int[] sortedArray2 = Arrays.copyOf(array2, array2.length);
|
||||
Arrays.sort(sortedArray2);
|
||||
return Arrays.equals(sortedArray1, sortedArray2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeInt(mFormat);
|
||||
dest.writeIntArray(mSamplingRates);
|
||||
dest.writeIntArray(mChannelMasks);
|
||||
dest.writeIntArray(mChannelIndexMasks);
|
||||
dest.writeInt(mEncapsulationType);
|
||||
}
|
||||
|
||||
private AudioProfile(@NonNull Parcel in) {
|
||||
mFormat = in.readInt();
|
||||
mSamplingRates = in.createIntArray();
|
||||
mChannelMasks = in.createIntArray();
|
||||
mChannelIndexMasks = in.createIntArray();
|
||||
mEncapsulationType = in.readInt();
|
||||
}
|
||||
|
||||
public static final @NonNull Parcelable.Creator<AudioProfile> CREATOR =
|
||||
new Parcelable.Creator<AudioProfile>() {
|
||||
/**
|
||||
* Rebuilds an AudioProfile previously stored with writeToParcel().
|
||||
* @param p Parcel object to read the AudioProfile from
|
||||
* @return a new AudioProfile created from the data in the parcel
|
||||
*/
|
||||
public AudioProfile createFromParcel(Parcel p) {
|
||||
return new AudioProfile(p);
|
||||
}
|
||||
|
||||
public AudioProfile[] newArray(int size) {
|
||||
return new AudioProfile[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -26,10 +26,12 @@ import android.bluetooth.BluetoothLeAudioCodecConfig;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.audio.common.AidlConversion;
|
||||
import android.media.audiofx.AudioEffect;
|
||||
import android.media.audiopolicy.AudioMix;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
import android.os.Vibrator;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
@@ -1555,9 +1557,24 @@ public class AudioSystem
|
||||
* {@link #AUDIO_STATUS_ERROR} or {@link #AUDIO_STATUS_SERVER_DIED}
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
public static native int setDeviceConnectionState(int device, int state,
|
||||
String device_address, String device_name,
|
||||
int codecFormat);
|
||||
public static int setDeviceConnectionState(AudioDeviceAttributes attributes, int state,
|
||||
int codecFormat) {
|
||||
android.media.audio.common.AudioPort port =
|
||||
AidlConversion.api2aidl_AudioDeviceAttributes_AudioPort(attributes);
|
||||
Parcel parcel = Parcel.obtain();
|
||||
port.writeToParcel(parcel, 0);
|
||||
parcel.setDataPosition(0);
|
||||
try {
|
||||
return setDeviceConnectionState(state, parcel, codecFormat);
|
||||
} finally {
|
||||
parcel.recycle();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
public static native int setDeviceConnectionState(int state, Parcel parcel, int codecFormat);
|
||||
/** @hide */
|
||||
@UnsupportedAppUsage
|
||||
public static native int getDeviceConnectionState(int device, String device_address);
|
||||
|
||||
@@ -215,8 +215,7 @@ interface IAudioService {
|
||||
IRingtonePlayer getRingtonePlayer();
|
||||
int getUiSoundsStreamType();
|
||||
|
||||
void setWiredDeviceConnectionState(int type, int state, String address, String name,
|
||||
String caller);
|
||||
void setWiredDeviceConnectionState(in AudioDeviceAttributes aa, int state, String caller);
|
||||
|
||||
@UnsupportedAppUsage
|
||||
AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer);
|
||||
|
||||
@@ -17,12 +17,17 @@
|
||||
package android.media.audio.common;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.media.AudioDescriptor;
|
||||
import android.media.AudioDeviceAttributes;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.AudioSystem;
|
||||
import android.media.MediaFormat;
|
||||
import android.os.Parcel;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* This class provides utility functions for converting between
|
||||
* the AIDL types defined in 'android.media.audio.common' and:
|
||||
@@ -525,6 +530,351 @@ public class AidlConversion {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from SDK AudioDeviceAttributes to AIDL AudioPort.
|
||||
*/
|
||||
public static AudioPort api2aidl_AudioDeviceAttributes_AudioPort(
|
||||
@NonNull AudioDeviceAttributes attributes) {
|
||||
AudioPort port = new AudioPort();
|
||||
port.name = attributes.getName();
|
||||
// TO DO: b/211611504 Convert attributes.getAudioProfiles() to AIDL as well.
|
||||
port.profiles = new AudioProfile[]{};
|
||||
port.extraAudioDescriptors = attributes.getAudioDescriptors().stream()
|
||||
.map(descriptor -> api2aidl_AudioDescriptor_ExtraAudioDescriptor(descriptor))
|
||||
.collect(Collectors.toList()).toArray(ExtraAudioDescriptor[]::new);
|
||||
port.flags = new AudioIoFlags();
|
||||
port.gains = new AudioGain[]{};
|
||||
AudioPortDeviceExt deviceExt = new AudioPortDeviceExt();
|
||||
deviceExt.device = new AudioDevice();
|
||||
deviceExt.encodedFormats = new AudioFormatDescription[]{};
|
||||
deviceExt.device.type =
|
||||
api2aidl_NativeType_AudioDeviceDescription(attributes.getInternalType());
|
||||
deviceExt.device.address = AudioDeviceAddress.id(attributes.getAddress());
|
||||
port.ext = AudioPortExt.device(deviceExt);
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from SDK AudioDescriptor to AIDL ExtraAudioDescriptor.
|
||||
*/
|
||||
public static ExtraAudioDescriptor api2aidl_AudioDescriptor_ExtraAudioDescriptor(
|
||||
@NonNull AudioDescriptor descriptor) {
|
||||
ExtraAudioDescriptor extraDescriptor = new ExtraAudioDescriptor();
|
||||
extraDescriptor.standard =
|
||||
api2aidl_AudioDescriptorStandard_AudioStandard(descriptor.getStandard());
|
||||
extraDescriptor.audioDescriptor = descriptor.getDescriptor();
|
||||
extraDescriptor.encapsulationType =
|
||||
api2aidl_AudioProfileEncapsulationType_AudioEncapsulationType(
|
||||
descriptor.getEncapsulationType());
|
||||
return extraDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from SDK AudioDescriptor to AIDL ExtraAudioDescriptor.
|
||||
*/
|
||||
public static @NonNull AudioDescriptor aidl2api_ExtraAudioDescriptor_AudioDescriptor(
|
||||
@NonNull ExtraAudioDescriptor extraDescriptor) {
|
||||
AudioDescriptor descriptor = new AudioDescriptor(
|
||||
aidl2api_AudioStandard_AudioDescriptorStandard(extraDescriptor.standard),
|
||||
aidl2api_AudioEncapsulationType_AudioProfileEncapsulationType(
|
||||
extraDescriptor.encapsulationType),
|
||||
extraDescriptor.audioDescriptor);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from SDK AudioDescriptor#mStandard to AIDL AudioStandard
|
||||
*/
|
||||
@AudioStandard
|
||||
public static int api2aidl_AudioDescriptorStandard_AudioStandard(
|
||||
@AudioDescriptor.AudioDescriptorStandard int standard) {
|
||||
switch (standard) {
|
||||
case AudioDescriptor.STANDARD_EDID:
|
||||
return AudioStandard.EDID;
|
||||
case AudioDescriptor.STANDARD_NONE:
|
||||
default:
|
||||
return AudioStandard.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from AIDL AudioStandard to SDK AudioDescriptor#mStandard
|
||||
*/
|
||||
@AudioDescriptor.AudioDescriptorStandard
|
||||
public static int aidl2api_AudioStandard_AudioDescriptorStandard(@AudioStandard int standard) {
|
||||
switch (standard) {
|
||||
case AudioStandard.EDID:
|
||||
return AudioDescriptor.STANDARD_EDID;
|
||||
case AudioStandard.NONE:
|
||||
default:
|
||||
return AudioDescriptor.STANDARD_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from SDK AudioProfile.EncapsulationType to AIDL AudioEncapsulationType
|
||||
*/
|
||||
@AudioEncapsulationType
|
||||
public static int api2aidl_AudioProfileEncapsulationType_AudioEncapsulationType(
|
||||
@android.media.AudioProfile.EncapsulationType int type) {
|
||||
switch (type) {
|
||||
case android.media.AudioProfile.AUDIO_ENCAPSULATION_TYPE_IEC61937:
|
||||
return AudioEncapsulationType.IEC61937;
|
||||
case android.media.AudioProfile.AUDIO_ENCAPSULATION_TYPE_NONE:
|
||||
default:
|
||||
return AudioEncapsulationType.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from AIDL AudioEncapsulationType to SDK AudioProfile.EncapsulationType
|
||||
*/
|
||||
@android.media.AudioProfile.EncapsulationType
|
||||
public static int aidl2api_AudioEncapsulationType_AudioProfileEncapsulationType(
|
||||
@AudioEncapsulationType int type) {
|
||||
switch (type) {
|
||||
case AudioEncapsulationType.IEC61937:
|
||||
return android.media.AudioProfile.AUDIO_ENCAPSULATION_TYPE_IEC61937;
|
||||
case AudioEncapsulationType.NONE:
|
||||
default:
|
||||
return android.media.AudioProfile.AUDIO_ENCAPSULATION_TYPE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from SDK native type to AIDL AudioDeviceDescription
|
||||
*/
|
||||
public static AudioDeviceDescription api2aidl_NativeType_AudioDeviceDescription(
|
||||
int nativeType) {
|
||||
AudioDeviceDescription aidl = new AudioDeviceDescription();
|
||||
aidl.connection = "";
|
||||
switch (nativeType) {
|
||||
case AudioSystem.DEVICE_OUT_EARPIECE:
|
||||
aidl.type = AudioDeviceType.OUT_SPEAKER_EARPIECE;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_SPEAKER:
|
||||
aidl.type = AudioDeviceType.OUT_SPEAKER;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_WIRED_HEADPHONE:
|
||||
aidl.type = AudioDeviceType.OUT_HEADPHONE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_ANALOG;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_BLUETOOTH_SCO:
|
||||
aidl.type = AudioDeviceType.OUT_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_BT_SCO;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
|
||||
aidl.type = AudioDeviceType.OUT_CARKIT;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_BT_SCO;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
|
||||
aidl.type = AudioDeviceType.OUT_HEADPHONE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_BT_A2DP;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
|
||||
aidl.type = AudioDeviceType.OUT_SPEAKER;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_BT_A2DP;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_TELEPHONY_TX:
|
||||
aidl.type = AudioDeviceType.OUT_TELEPHONY_TX;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_AUX_LINE:
|
||||
aidl.type = AudioDeviceType.OUT_LINE_AUX;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_SPEAKER_SAFE:
|
||||
aidl.type = AudioDeviceType.OUT_SPEAKER_SAFE;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_HEARING_AID:
|
||||
aidl.type = AudioDeviceType.OUT_HEARING_AID;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_WIRELESS;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_ECHO_CANCELLER:
|
||||
aidl.type = AudioDeviceType.OUT_ECHO_CANCELLER;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_BLE_SPEAKER:
|
||||
aidl.type = AudioDeviceType.OUT_SPEAKER;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_BT_LE;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_BUILTIN_MIC:
|
||||
aidl.type = AudioDeviceType.IN_MICROPHONE;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_BACK_MIC:
|
||||
aidl.type = AudioDeviceType.IN_MICROPHONE_BACK;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_TELEPHONY_RX:
|
||||
aidl.type = AudioDeviceType.IN_TELEPHONY_RX;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_TV_TUNER:
|
||||
aidl.type = AudioDeviceType.IN_TV_TUNER;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_LOOPBACK:
|
||||
aidl.type = AudioDeviceType.IN_LOOPBACK;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_BLUETOOTH_BLE:
|
||||
aidl.type = AudioDeviceType.IN_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_BT_LE;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_ECHO_REFERENCE:
|
||||
aidl.type = AudioDeviceType.IN_ECHO_REFERENCE;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_WIRED_HEADSET:
|
||||
aidl.type = AudioDeviceType.IN_HEADSET;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_ANALOG;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_WIRED_HEADSET:
|
||||
aidl.type = AudioDeviceType.OUT_HEADSET;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_ANALOG;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET:
|
||||
aidl.type = AudioDeviceType.IN_HEADSET;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_BT_SCO;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
|
||||
aidl.type = AudioDeviceType.OUT_HEADSET;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_BT_SCO;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_HDMI:
|
||||
aidl.type = AudioDeviceType.IN_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_HDMI;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_HDMI:
|
||||
aidl.type = AudioDeviceType.OUT_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_HDMI;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_REMOTE_SUBMIX:
|
||||
aidl.type = AudioDeviceType.IN_SUBMIX;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_REMOTE_SUBMIX:
|
||||
aidl.type = AudioDeviceType.OUT_SUBMIX;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET:
|
||||
aidl.type = AudioDeviceType.IN_DOCK;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_ANALOG;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET:
|
||||
aidl.type = AudioDeviceType.OUT_DOCK;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_ANALOG;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET:
|
||||
aidl.type = AudioDeviceType.IN_DOCK;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_USB;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET:
|
||||
aidl.type = AudioDeviceType.OUT_DOCK;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_USB;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_USB_ACCESSORY:
|
||||
aidl.type = AudioDeviceType.IN_ACCESSORY;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_USB;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_USB_ACCESSORY:
|
||||
aidl.type = AudioDeviceType.OUT_ACCESSORY;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_USB;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_USB_DEVICE:
|
||||
aidl.type = AudioDeviceType.IN_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_USB;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_USB_DEVICE:
|
||||
aidl.type = AudioDeviceType.OUT_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_USB;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_FM_TUNER:
|
||||
aidl.type = AudioDeviceType.IN_FM_TUNER;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_FM:
|
||||
aidl.type = AudioDeviceType.OUT_FM;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_LINE:
|
||||
aidl.type = AudioDeviceType.IN_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_ANALOG;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_LINE:
|
||||
aidl.type = AudioDeviceType.OUT_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_ANALOG;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_SPDIF:
|
||||
aidl.type = AudioDeviceType.IN_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_SPDIF;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_SPDIF:
|
||||
aidl.type = AudioDeviceType.OUT_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_SPDIF;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_BLUETOOTH_A2DP:
|
||||
aidl.type = AudioDeviceType.IN_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_BT_A2DP;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP:
|
||||
aidl.type = AudioDeviceType.OUT_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_BT_A2DP;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_IP:
|
||||
aidl.type = AudioDeviceType.IN_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_IP_V4;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_IP:
|
||||
aidl.type = AudioDeviceType.OUT_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_IP_V4;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_BUS:
|
||||
aidl.type = AudioDeviceType.IN_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_BUS;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_BUS:
|
||||
aidl.type = AudioDeviceType.OUT_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_BUS;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_PROXY:
|
||||
aidl.type = AudioDeviceType.IN_AFE_PROXY;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_PROXY:
|
||||
aidl.type = AudioDeviceType.OUT_AFE_PROXY;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_USB_HEADSET:
|
||||
aidl.type = AudioDeviceType.IN_HEADSET;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_USB;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_USB_HEADSET:
|
||||
aidl.type = AudioDeviceType.OUT_HEADSET;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_USB;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_HDMI_ARC:
|
||||
aidl.type = AudioDeviceType.IN_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_HDMI_ARC;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_HDMI_ARC:
|
||||
aidl.type = AudioDeviceType.OUT_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_HDMI_ARC;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_HDMI_EARC:
|
||||
aidl.type = AudioDeviceType.IN_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_HDMI_EARC;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_HDMI_EARC:
|
||||
aidl.type = AudioDeviceType.OUT_DEVICE;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_HDMI_EARC;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_BLE_HEADSET:
|
||||
aidl.type = AudioDeviceType.IN_HEADSET;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_BT_LE;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_BLE_HEADSET:
|
||||
aidl.type = AudioDeviceType.OUT_HEADSET;
|
||||
aidl.connection = AudioDeviceDescription.CONNECTION_BT_LE;
|
||||
break;
|
||||
case AudioSystem.DEVICE_IN_DEFAULT:
|
||||
aidl.type = AudioDeviceType.IN_DEFAULT;
|
||||
break;
|
||||
case AudioSystem.DEVICE_OUT_DEFAULT:
|
||||
aidl.type = AudioDeviceType.OUT_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
aidl.type = AudioDeviceType.NONE;
|
||||
}
|
||||
return aidl;
|
||||
}
|
||||
|
||||
private static native int aidl2legacy_AudioChannelLayout_Parcel_audio_channel_mask_t(
|
||||
Parcel aidl, boolean isInput);
|
||||
private static native Parcel legacy2aidl_audio_channel_mask_t_AudioChannelLayout_Parcel(
|
||||
|
||||
@@ -16,8 +16,18 @@
|
||||
|
||||
package android.media.audio.common;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.media.AudioAttributes;
|
||||
import android.media.AudioDescriptor;
|
||||
import android.media.AudioDeviceAttributes;
|
||||
import android.media.AudioDeviceInfo;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.AudioProfile;
|
||||
import android.media.AudioSystem;
|
||||
import android.media.AudioTrack;
|
||||
import android.media.MediaFormat;
|
||||
@@ -25,11 +35,12 @@ import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Unit tests for AidlConversion utilities.
|
||||
*
|
||||
@@ -417,10 +428,102 @@ public final class AidlConversionUnitTests {
|
||||
() -> AidlConversion.legacy2aidl_audio_usage_t_AudioUsage(sInvalidValue));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAudioDescriptorConversion_Default() {
|
||||
ExtraAudioDescriptor aidl = createDefaultDescriptor();
|
||||
AudioDescriptor audioDescriptor =
|
||||
AidlConversion.aidl2api_ExtraAudioDescriptor_AudioDescriptor(aidl);
|
||||
assertEquals(AudioDescriptor.STANDARD_NONE, audioDescriptor.getStandard());
|
||||
assertEquals(
|
||||
AudioProfile.AUDIO_ENCAPSULATION_TYPE_NONE, audioDescriptor.getEncapsulationType());
|
||||
assertTrue(Arrays.equals(new byte[]{}, audioDescriptor.getDescriptor()));
|
||||
|
||||
ExtraAudioDescriptor reconstructedExtraDescriptor =
|
||||
AidlConversion.api2aidl_AudioDescriptor_ExtraAudioDescriptor(audioDescriptor);
|
||||
assertEquals(aidl, reconstructedExtraDescriptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAudioDescriptorConversion() {
|
||||
ExtraAudioDescriptor aidl = createEncapsulationDescriptor(new byte[]{0x05, 0x18, 0x4A});
|
||||
AudioDescriptor audioDescriptor =
|
||||
AidlConversion.aidl2api_ExtraAudioDescriptor_AudioDescriptor(aidl);
|
||||
assertEquals(AudioDescriptor.STANDARD_EDID, audioDescriptor.getStandard());
|
||||
assertEquals(AudioProfile.AUDIO_ENCAPSULATION_TYPE_IEC61937,
|
||||
audioDescriptor.getEncapsulationType());
|
||||
assertTrue(Arrays.equals(new byte[]{0x05, 0x18, 0x4A}, audioDescriptor.getDescriptor()));
|
||||
|
||||
ExtraAudioDescriptor reconstructedExtraDescriptor =
|
||||
AidlConversion.api2aidl_AudioDescriptor_ExtraAudioDescriptor(audioDescriptor);
|
||||
assertEquals(aidl, reconstructedExtraDescriptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAudioDeviceAttributesConversion_Default() {
|
||||
AudioDeviceAttributes attributes =
|
||||
new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_DEFAULT, "myAddress");
|
||||
AudioPort port = AidlConversion.api2aidl_AudioDeviceAttributes_AudioPort(attributes);
|
||||
assertEquals("", port.name);
|
||||
assertEquals(0, port.extraAudioDescriptors.length);
|
||||
assertEquals("myAddress", port.ext.getDevice().device.address.getId());
|
||||
assertEquals("", port.ext.getDevice().device.type.connection);
|
||||
assertEquals(AudioDeviceType.OUT_DEFAULT, port.ext.getDevice().device.type.type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAudioDeviceAttributesConversion() {
|
||||
AudioDescriptor audioDescriptor1 =
|
||||
AidlConversion.aidl2api_ExtraAudioDescriptor_AudioDescriptor(
|
||||
createEncapsulationDescriptor(new byte[]{0x05, 0x18, 0x4A}));
|
||||
|
||||
AudioDescriptor audioDescriptor2 =
|
||||
AidlConversion.aidl2api_ExtraAudioDescriptor_AudioDescriptor(
|
||||
createDefaultDescriptor());
|
||||
|
||||
AudioDeviceAttributes attributes =
|
||||
new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT,
|
||||
AudioDeviceInfo.TYPE_HDMI_ARC, "myAddress", "myName", new ArrayList<>(),
|
||||
new ArrayList<>(Arrays.asList(audioDescriptor1, audioDescriptor2)));
|
||||
AudioPort port = AidlConversion.api2aidl_AudioDeviceAttributes_AudioPort(
|
||||
attributes);
|
||||
assertEquals("myName", port.name);
|
||||
assertEquals(2, port.extraAudioDescriptors.length);
|
||||
assertEquals(AudioStandard.EDID, port.extraAudioDescriptors[0].standard);
|
||||
assertEquals(AudioEncapsulationType.IEC61937,
|
||||
port.extraAudioDescriptors[0].encapsulationType);
|
||||
assertTrue(Arrays.equals(new byte[]{0x05, 0x18, 0x4A},
|
||||
port.extraAudioDescriptors[0].audioDescriptor));
|
||||
assertEquals(AudioStandard.NONE, port.extraAudioDescriptors[1].standard);
|
||||
assertEquals(AudioEncapsulationType.NONE,
|
||||
port.extraAudioDescriptors[1].encapsulationType);
|
||||
assertTrue(Arrays.equals(new byte[]{},
|
||||
port.extraAudioDescriptors[1].audioDescriptor));
|
||||
assertEquals("myAddress", port.ext.getDevice().device.address.getId());
|
||||
assertEquals(AudioDeviceDescription.CONNECTION_HDMI_ARC,
|
||||
port.ext.getDevice().device.type.connection);
|
||||
assertEquals(AudioDeviceType.OUT_DEVICE, port.ext.getDevice().device.type.type);
|
||||
}
|
||||
|
||||
private static AudioFormatDescription createPcm16FormatAidl() {
|
||||
final AudioFormatDescription aidl = new AudioFormatDescription();
|
||||
aidl.type = AudioFormatType.PCM;
|
||||
aidl.pcm = PcmType.INT_16_BIT;
|
||||
return aidl;
|
||||
}
|
||||
|
||||
private static ExtraAudioDescriptor createDefaultDescriptor() {
|
||||
ExtraAudioDescriptor extraDescriptor = new ExtraAudioDescriptor();
|
||||
extraDescriptor.standard = AudioStandard.NONE;
|
||||
extraDescriptor.encapsulationType = AudioEncapsulationType.NONE;
|
||||
extraDescriptor.audioDescriptor = new byte[]{};
|
||||
return extraDescriptor;
|
||||
}
|
||||
|
||||
private static ExtraAudioDescriptor createEncapsulationDescriptor(byte[] audioDescriptor) {
|
||||
ExtraAudioDescriptor extraDescriptor = new ExtraAudioDescriptor();
|
||||
extraDescriptor.standard = AudioStandard.EDID;
|
||||
extraDescriptor.encapsulationType = AudioEncapsulationType.IEC61937;
|
||||
extraDescriptor.audioDescriptor = audioDescriptor;
|
||||
return extraDescriptor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,12 +500,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
}
|
||||
}
|
||||
|
||||
/*package*/ void setWiredDeviceConnectionState(int type,
|
||||
@AudioService.ConnectionState int state, String address, String name,
|
||||
String caller) {
|
||||
/*package*/ void setWiredDeviceConnectionState(AudioDeviceAttributes attributes,
|
||||
@AudioService.ConnectionState int state, String caller) {
|
||||
//TODO move logging here just like in setBluetooth* methods
|
||||
synchronized (mDeviceStateLock) {
|
||||
mDeviceInventory.setWiredDeviceConnectionState(type, state, address, name, caller);
|
||||
mDeviceInventory.setWiredDeviceConnectionState(attributes, state, caller);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1013,11 +1012,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
}
|
||||
}
|
||||
|
||||
/*package*/ boolean handleDeviceConnection(boolean connect, int device, String address,
|
||||
String deviceName) {
|
||||
/*package*/ boolean handleDeviceConnection(AudioDeviceAttributes attributes, boolean connect) {
|
||||
synchronized (mDeviceStateLock) {
|
||||
return mDeviceInventory.handleDeviceConnection(connect, device, address, deviceName,
|
||||
false /*for test*/);
|
||||
return mDeviceInventory.handleDeviceConnection(attributes, connect, false /*for test*/);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -230,19 +230,15 @@ public class AudioDeviceInventory {
|
||||
* A class just for packaging up a set of connection parameters.
|
||||
*/
|
||||
/*package*/ class WiredDeviceConnectionState {
|
||||
public final int mType;
|
||||
public final AudioDeviceAttributes mAttributes;
|
||||
public final @AudioService.ConnectionState int mState;
|
||||
public final String mAddress;
|
||||
public final String mName;
|
||||
public final String mCaller;
|
||||
public boolean mForTest = false;
|
||||
|
||||
/*package*/ WiredDeviceConnectionState(int type, @AudioService.ConnectionState int state,
|
||||
String address, String name, String caller) {
|
||||
mType = type;
|
||||
/*package*/ WiredDeviceConnectionState(AudioDeviceAttributes attributes,
|
||||
@AudioService.ConnectionState int state, String caller) {
|
||||
mAttributes = attributes;
|
||||
mState = state;
|
||||
mAddress = address;
|
||||
mName = name;
|
||||
mCaller = caller;
|
||||
}
|
||||
}
|
||||
@@ -280,11 +276,10 @@ public class AudioDeviceInventory {
|
||||
synchronized (mDevicesLock) {
|
||||
//TODO iterate on mApmConnectedDevices instead once it handles all device types
|
||||
for (DeviceInfo di : mConnectedDevices.values()) {
|
||||
mAudioSystem.setDeviceConnectionState(
|
||||
di.mDeviceType,
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE,
|
||||
mAudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(di.mDeviceType,
|
||||
di.mDeviceAddress,
|
||||
di.mDeviceName,
|
||||
di.mDeviceName),
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE,
|
||||
di.mDeviceCodecFormat);
|
||||
}
|
||||
}
|
||||
@@ -519,41 +514,45 @@ public class AudioDeviceInventory {
|
||||
|
||||
/*package*/ void onSetWiredDeviceConnectionState(
|
||||
AudioDeviceInventory.WiredDeviceConnectionState wdcs) {
|
||||
int type = wdcs.mAttributes.getInternalType();
|
||||
|
||||
AudioService.sDeviceLogger.log(new AudioServiceEvents.WiredDevConnectEvent(wdcs));
|
||||
|
||||
MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId
|
||||
+ "onSetWiredDeviceConnectionState")
|
||||
.set(MediaMetrics.Property.ADDRESS, wdcs.mAddress)
|
||||
.set(MediaMetrics.Property.DEVICE, AudioSystem.getDeviceName(wdcs.mType))
|
||||
.set(MediaMetrics.Property.ADDRESS, wdcs.mAttributes.getAddress())
|
||||
.set(MediaMetrics.Property.DEVICE,
|
||||
AudioSystem.getDeviceName(type))
|
||||
.set(MediaMetrics.Property.STATE,
|
||||
wdcs.mState == AudioService.CONNECTION_STATE_DISCONNECTED
|
||||
? MediaMetrics.Value.DISCONNECTED : MediaMetrics.Value.CONNECTED);
|
||||
synchronized (mDevicesLock) {
|
||||
if ((wdcs.mState == AudioService.CONNECTION_STATE_DISCONNECTED)
|
||||
&& DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(wdcs.mType)) {
|
||||
&& DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(type)) {
|
||||
mDeviceBroker.setBluetoothA2dpOnInt(true, false /*fromA2dp*/,
|
||||
"onSetWiredDeviceConnectionState state DISCONNECTED");
|
||||
}
|
||||
|
||||
if (!handleDeviceConnection(wdcs.mState == AudioService.CONNECTION_STATE_CONNECTED,
|
||||
wdcs.mType, wdcs.mAddress, wdcs.mName, wdcs.mForTest)) {
|
||||
if (!handleDeviceConnection(wdcs.mAttributes,
|
||||
wdcs.mState == AudioService.CONNECTION_STATE_CONNECTED, wdcs.mForTest)) {
|
||||
// change of connection state failed, bailout
|
||||
mmi.set(MediaMetrics.Property.EARLY_RETURN, "change of connection state failed")
|
||||
.record();
|
||||
return;
|
||||
}
|
||||
if (wdcs.mState != AudioService.CONNECTION_STATE_DISCONNECTED) {
|
||||
if (DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(wdcs.mType)) {
|
||||
if (DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(type)) {
|
||||
mDeviceBroker.setBluetoothA2dpOnInt(false, false /*fromA2dp*/,
|
||||
"onSetWiredDeviceConnectionState state not DISCONNECTED");
|
||||
}
|
||||
mDeviceBroker.checkMusicActive(wdcs.mType, wdcs.mCaller);
|
||||
mDeviceBroker.checkMusicActive(type, wdcs.mCaller);
|
||||
}
|
||||
if (wdcs.mType == AudioSystem.DEVICE_OUT_HDMI) {
|
||||
if (type == AudioSystem.DEVICE_OUT_HDMI) {
|
||||
mDeviceBroker.checkVolumeCecOnHdmiConnection(wdcs.mState, wdcs.mCaller);
|
||||
}
|
||||
sendDeviceConnectionIntent(wdcs.mType, wdcs.mState, wdcs.mAddress, wdcs.mName);
|
||||
updateAudioRoutes(wdcs.mType, wdcs.mState);
|
||||
sendDeviceConnectionIntent(type, wdcs.mState,
|
||||
wdcs.mAttributes.getAddress(), wdcs.mAttributes.getName());
|
||||
updateAudioRoutes(type, wdcs.mState);
|
||||
}
|
||||
mmi.record();
|
||||
}
|
||||
@@ -572,12 +571,12 @@ public class AudioDeviceInventory {
|
||||
return;
|
||||
}
|
||||
// Toggle HDMI to retrigger broadcast with proper formats.
|
||||
setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
|
||||
AudioSystem.DEVICE_STATE_UNAVAILABLE, "", "",
|
||||
"android"); // disconnect
|
||||
setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE, "", "",
|
||||
"android"); // reconnect
|
||||
setWiredDeviceConnectionState(
|
||||
new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_HDMI, ""),
|
||||
AudioSystem.DEVICE_STATE_UNAVAILABLE, "android"); // disconnect
|
||||
setWiredDeviceConnectionState(
|
||||
new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_HDMI, ""),
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE, "android"); // reconnect
|
||||
}
|
||||
mmi.record();
|
||||
}
|
||||
@@ -707,16 +706,17 @@ public class AudioDeviceInventory {
|
||||
|
||||
/**
|
||||
* Implements the communication with AudioSystem to (dis)connect a device in the native layers
|
||||
* @param attributes the attributes of the device
|
||||
* @param connect true if connection
|
||||
* @param device the device type
|
||||
* @param address the address of the device
|
||||
* @param deviceName human-readable name of device
|
||||
* @param isForTesting if true, not calling AudioSystem for the connection as this is
|
||||
* just for testing
|
||||
* @return false if an error was reported by AudioSystem
|
||||
*/
|
||||
/*package*/ boolean handleDeviceConnection(boolean connect, int device, String address,
|
||||
String deviceName, boolean isForTesting) {
|
||||
/*package*/ boolean handleDeviceConnection(AudioDeviceAttributes attributes, boolean connect,
|
||||
boolean isForTesting) {
|
||||
int device = attributes.getInternalType();
|
||||
String address = attributes.getAddress();
|
||||
String deviceName = attributes.getName();
|
||||
if (AudioService.DEBUG_DEVICES) {
|
||||
Slog.i(TAG, "handleDeviceConnection(" + connect + " dev:"
|
||||
+ Integer.toHexString(device) + " address:" + address
|
||||
@@ -743,9 +743,8 @@ public class AudioDeviceInventory {
|
||||
if (isForTesting) {
|
||||
res = AudioSystem.AUDIO_STATUS_OK;
|
||||
} else {
|
||||
res = mAudioSystem.setDeviceConnectionState(device,
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE, address, deviceName,
|
||||
AudioSystem.AUDIO_FORMAT_DEFAULT);
|
||||
res = mAudioSystem.setDeviceConnectionState(attributes,
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE, AudioSystem.AUDIO_FORMAT_DEFAULT);
|
||||
}
|
||||
if (res != AudioSystem.AUDIO_STATUS_OK) {
|
||||
final String reason = "not connecting device 0x" + Integer.toHexString(device)
|
||||
@@ -762,9 +761,8 @@ public class AudioDeviceInventory {
|
||||
mmi.set(MediaMetrics.Property.STATE, MediaMetrics.Value.CONNECTED).record();
|
||||
return true;
|
||||
} else if (!connect && isConnected) {
|
||||
mAudioSystem.setDeviceConnectionState(device,
|
||||
AudioSystem.DEVICE_STATE_UNAVAILABLE, address, deviceName,
|
||||
AudioSystem.AUDIO_FORMAT_DEFAULT);
|
||||
mAudioSystem.setDeviceConnectionState(attributes,
|
||||
AudioSystem.DEVICE_STATE_UNAVAILABLE, AudioSystem.AUDIO_FORMAT_DEFAULT);
|
||||
// always remove even if disconnection failed
|
||||
mConnectedDevices.remove(deviceKey);
|
||||
mmi.set(MediaMetrics.Property.STATE, MediaMetrics.Value.CONNECTED).record();
|
||||
@@ -941,13 +939,13 @@ public class AudioDeviceInventory {
|
||||
return delay;
|
||||
}
|
||||
|
||||
/*package*/ int setWiredDeviceConnectionState(int type, @AudioService.ConnectionState int state,
|
||||
String address, String name, String caller) {
|
||||
/*package*/ int setWiredDeviceConnectionState(AudioDeviceAttributes attributes,
|
||||
@AudioService.ConnectionState int state, String caller) {
|
||||
synchronized (mDevicesLock) {
|
||||
int delay = checkSendBecomingNoisyIntentInt(type, state, AudioSystem.DEVICE_NONE);
|
||||
int delay = checkSendBecomingNoisyIntentInt(
|
||||
attributes.getInternalType(), state, AudioSystem.DEVICE_NONE);
|
||||
mDeviceBroker.postSetWiredDeviceConnectionState(
|
||||
new WiredDeviceConnectionState(type, state, address, name, caller),
|
||||
delay);
|
||||
new WiredDeviceConnectionState(attributes, state, caller), delay);
|
||||
return delay;
|
||||
}
|
||||
}
|
||||
@@ -955,8 +953,7 @@ public class AudioDeviceInventory {
|
||||
/*package*/ void setTestDeviceConnectionState(@NonNull AudioDeviceAttributes device,
|
||||
@AudioService.ConnectionState int state) {
|
||||
final WiredDeviceConnectionState connection = new WiredDeviceConnectionState(
|
||||
device.getInternalType(), state, device.getAddress(),
|
||||
"test device", "com.android.server.audio");
|
||||
device, state, "com.android.server.audio");
|
||||
connection.mForTest = true;
|
||||
onSetWiredDeviceConnectionState(connection);
|
||||
}
|
||||
@@ -972,8 +969,9 @@ public class AudioDeviceInventory {
|
||||
mDeviceBroker.setBluetoothA2dpOnInt(true, true /*fromA2dp*/, eventSource);
|
||||
// at this point there could be another A2DP device already connected in APM, but it
|
||||
// doesn't matter as this new one will overwrite the previous one
|
||||
final int res = mAudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE, address, name, a2dpCodec);
|
||||
final int res = mAudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
|
||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address, name),
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE, a2dpCodec);
|
||||
|
||||
// TODO: log in MediaMetrics once distinction between connection failure and
|
||||
// double connection is made.
|
||||
@@ -1035,8 +1033,9 @@ public class AudioDeviceInventory {
|
||||
|
||||
// device to remove was visible by APM, update APM
|
||||
mDeviceBroker.clearAvrcpAbsoluteVolumeSupported();
|
||||
final int res = mAudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
||||
AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "", a2dpCodec);
|
||||
final int res = mAudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
|
||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address),
|
||||
AudioSystem.DEVICE_STATE_UNAVAILABLE, a2dpCodec);
|
||||
|
||||
if (res != AudioSystem.AUDIO_STATUS_OK) {
|
||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
||||
@@ -1074,8 +1073,9 @@ public class AudioDeviceInventory {
|
||||
|
||||
@GuardedBy("mDevicesLock")
|
||||
private void makeA2dpSrcAvailable(String address) {
|
||||
mAudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE, address, "",
|
||||
mAudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
|
||||
AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address),
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE,
|
||||
AudioSystem.AUDIO_FORMAT_DEFAULT);
|
||||
mConnectedDevices.put(
|
||||
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address),
|
||||
@@ -1085,8 +1085,9 @@ public class AudioDeviceInventory {
|
||||
|
||||
@GuardedBy("mDevicesLock")
|
||||
private void makeA2dpSrcUnavailable(String address) {
|
||||
mAudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
|
||||
AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "",
|
||||
mAudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
|
||||
AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address),
|
||||
AudioSystem.DEVICE_STATE_UNAVAILABLE,
|
||||
AudioSystem.AUDIO_FORMAT_DEFAULT);
|
||||
mConnectedDevices.remove(
|
||||
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address));
|
||||
@@ -1099,8 +1100,9 @@ public class AudioDeviceInventory {
|
||||
AudioSystem.DEVICE_OUT_HEARING_AID);
|
||||
mDeviceBroker.postSetHearingAidVolumeIndex(hearingAidVolIndex, streamType);
|
||||
|
||||
mAudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE, address, name,
|
||||
mAudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
|
||||
AudioSystem.DEVICE_OUT_HEARING_AID, address, name),
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE,
|
||||
AudioSystem.AUDIO_FORMAT_DEFAULT);
|
||||
mConnectedDevices.put(
|
||||
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address),
|
||||
@@ -1122,8 +1124,9 @@ public class AudioDeviceInventory {
|
||||
|
||||
@GuardedBy("mDevicesLock")
|
||||
private void makeHearingAidDeviceUnavailable(String address) {
|
||||
mAudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
|
||||
AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "",
|
||||
mAudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
|
||||
AudioSystem.DEVICE_OUT_HEARING_AID, address),
|
||||
AudioSystem.DEVICE_STATE_UNAVAILABLE,
|
||||
AudioSystem.AUDIO_FORMAT_DEFAULT);
|
||||
mConnectedDevices.remove(
|
||||
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address));
|
||||
@@ -1140,14 +1143,14 @@ public class AudioDeviceInventory {
|
||||
private void makeLeAudioDeviceAvailable(String address, String name, int streamType, int device,
|
||||
String eventSource) {
|
||||
if (device != AudioSystem.DEVICE_NONE) {
|
||||
|
||||
/* Audio Policy sees Le Audio similar to A2DP. Let's make sure
|
||||
* AUDIO_POLICY_FORCE_NO_BT_A2DP is not set
|
||||
*/
|
||||
mDeviceBroker.setBluetoothA2dpOnInt(true, false /*fromA2dp*/, eventSource);
|
||||
|
||||
AudioSystem.setDeviceConnectionState(device, AudioSystem.DEVICE_STATE_AVAILABLE,
|
||||
address, name, AudioSystem.AUDIO_FORMAT_DEFAULT);
|
||||
AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(device, address, name),
|
||||
AudioSystem.DEVICE_STATE_AVAILABLE,
|
||||
AudioSystem.AUDIO_FORMAT_DEFAULT);
|
||||
mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address),
|
||||
new DeviceInfo(device, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT));
|
||||
mDeviceBroker.postAccessoryPlugMediaUnmute(device);
|
||||
@@ -1168,8 +1171,9 @@ public class AudioDeviceInventory {
|
||||
@GuardedBy("mDevicesLock")
|
||||
private void makeLeAudioDeviceUnavailable(String address, int device) {
|
||||
if (device != AudioSystem.DEVICE_NONE) {
|
||||
AudioSystem.setDeviceConnectionState(device, AudioSystem.DEVICE_STATE_UNAVAILABLE,
|
||||
address, "", AudioSystem.AUDIO_FORMAT_DEFAULT);
|
||||
AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(device, address),
|
||||
AudioSystem.DEVICE_STATE_UNAVAILABLE,
|
||||
AudioSystem.AUDIO_FORMAT_DEFAULT);
|
||||
mConnectedDevices.remove(DeviceInfo.makeDeviceListKey(device, address));
|
||||
}
|
||||
|
||||
|
||||
@@ -6371,23 +6371,23 @@ public class AudioService extends IAudioService.Stub
|
||||
/**
|
||||
* see AudioManager.setWiredDeviceConnectionState()
|
||||
*/
|
||||
public void setWiredDeviceConnectionState(int type,
|
||||
@ConnectionState int state, String address, String name,
|
||||
String caller) {
|
||||
public void setWiredDeviceConnectionState(AudioDeviceAttributes attributes,
|
||||
@ConnectionState int state, String caller) {
|
||||
enforceModifyAudioRoutingPermission();
|
||||
if (state != CONNECTION_STATE_CONNECTED
|
||||
&& state != CONNECTION_STATE_DISCONNECTED) {
|
||||
throw new IllegalArgumentException("Invalid state " + state);
|
||||
}
|
||||
new MediaMetrics.Item(mMetricsId + "setWiredDeviceConnectionState")
|
||||
.set(MediaMetrics.Property.ADDRESS, address)
|
||||
.set(MediaMetrics.Property.ADDRESS, attributes.getAddress())
|
||||
.set(MediaMetrics.Property.CLIENT_NAME, caller)
|
||||
.set(MediaMetrics.Property.DEVICE, AudioSystem.getDeviceName(type))
|
||||
.set(MediaMetrics.Property.NAME, name)
|
||||
.set(MediaMetrics.Property.DEVICE,
|
||||
AudioSystem.getDeviceName(attributes.getInternalType()))
|
||||
.set(MediaMetrics.Property.NAME, attributes.getName())
|
||||
.set(MediaMetrics.Property.STATE,
|
||||
state == CONNECTION_STATE_CONNECTED ? "connected" : "disconnected")
|
||||
.record();
|
||||
mDeviceBroker.setWiredDeviceConnectionState(type, state, address, name, caller);
|
||||
mDeviceBroker.setWiredDeviceConnectionState(attributes, state, caller);
|
||||
}
|
||||
|
||||
/** @see AudioManager#setTestDeviceConnectionState(AudioDeviceAttributes, boolean) */
|
||||
|
||||
@@ -116,10 +116,11 @@ public class AudioServiceEvents {
|
||||
@Override
|
||||
public String eventToString() {
|
||||
return new StringBuilder("setWiredDeviceConnectionState(")
|
||||
.append(" type:").append(Integer.toHexString(mState.mType))
|
||||
.append(" type:").append(
|
||||
Integer.toHexString(mState.mAttributes.getInternalType()))
|
||||
.append(" state:").append(AudioSystem.deviceStateToString(mState.mState))
|
||||
.append(" addr:").append(mState.mAddress)
|
||||
.append(" name:").append(mState.mName)
|
||||
.append(" addr:").append(mState.mAttributes.getAddress())
|
||||
.append(" name:").append(mState.mAttributes.getName())
|
||||
.append(") from ").append(mState.mCaller).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,19 +258,16 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback {
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link AudioSystem#setDeviceConnectionState(int, int, String, String, int)}
|
||||
* @param device
|
||||
* Same as {@link AudioSystem#setDeviceConnectionState(AudioDeviceAttributes, int, int)}
|
||||
* @param attributes
|
||||
* @param state
|
||||
* @param deviceAddress
|
||||
* @param deviceName
|
||||
* @param codecFormat
|
||||
* @return
|
||||
*/
|
||||
public int setDeviceConnectionState(int device, int state, String deviceAddress,
|
||||
String deviceName, int codecFormat) {
|
||||
public int setDeviceConnectionState(AudioDeviceAttributes attributes, int state,
|
||||
int codecFormat) {
|
||||
invalidateRoutingCache();
|
||||
return AudioSystem.setDeviceConnectionState(device, state, deviceAddress, deviceName,
|
||||
codecFormat);
|
||||
return AudioSystem.setDeviceConnectionState(attributes, state, codecFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -595,8 +595,9 @@ public class BtHelper {
|
||||
String btDeviceName = getName(btDevice);
|
||||
boolean result = false;
|
||||
if (isActive) {
|
||||
result |= mDeviceBroker.handleDeviceConnection(isActive, audioDevice.getInternalType(),
|
||||
audioDevice.getAddress(), btDeviceName);
|
||||
result |= mDeviceBroker.handleDeviceConnection(new AudioDeviceAttributes(
|
||||
audioDevice.getInternalType(), audioDevice.getAddress(), btDeviceName),
|
||||
isActive);
|
||||
} else {
|
||||
int[] outDeviceTypes = {
|
||||
AudioSystem.DEVICE_OUT_BLUETOOTH_SCO,
|
||||
@@ -604,13 +605,15 @@ public class BtHelper {
|
||||
AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT
|
||||
};
|
||||
for (int outDeviceType : outDeviceTypes) {
|
||||
result |= mDeviceBroker.handleDeviceConnection(
|
||||
isActive, outDeviceType, audioDevice.getAddress(), btDeviceName);
|
||||
result |= mDeviceBroker.handleDeviceConnection(new AudioDeviceAttributes(
|
||||
outDeviceType, audioDevice.getAddress(), btDeviceName),
|
||||
isActive);
|
||||
}
|
||||
}
|
||||
// handleDeviceConnection() && result to make sure the method get executed
|
||||
result = mDeviceBroker.handleDeviceConnection(
|
||||
isActive, inDevice, audioDevice.getAddress(), btDeviceName) && result;
|
||||
result = mDeviceBroker.handleDeviceConnection(new AudioDeviceAttributes(
|
||||
inDevice, audioDevice.getAddress(), btDeviceName),
|
||||
isActive) && result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,10 @@ import android.hardware.hdmi.HdmiRecordSources;
|
||||
import android.hardware.hdmi.HdmiTimerRecordSources;
|
||||
import android.hardware.hdmi.IHdmiControlCallback;
|
||||
import android.hardware.tv.cec.V1_0.SendMessageResult;
|
||||
import android.media.AudioSystem;
|
||||
import android.media.AudioDescriptor;
|
||||
import android.media.AudioDeviceAttributes;
|
||||
import android.media.AudioDeviceInfo;
|
||||
import android.media.AudioProfile;
|
||||
import android.media.tv.TvInputInfo;
|
||||
import android.media.tv.TvInputManager.TvInputCallback;
|
||||
import android.util.Slog;
|
||||
@@ -58,6 +61,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Represent a logical device of type TV residing in Android system.
|
||||
@@ -816,12 +820,23 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
|
||||
HdmiLogger.debug("Set Arc Status[old:%b new:%b]", mArcEstablished, enabled);
|
||||
boolean oldStatus = mArcEstablished;
|
||||
// 1. Enable/disable ARC circuit.
|
||||
enableAudioReturnChannel(enabled);
|
||||
// 2. Notify arc status to audio service.
|
||||
notifyArcStatusToAudioService(enabled);
|
||||
// 3. Update arc status;
|
||||
mArcEstablished = enabled;
|
||||
if (enabled) {
|
||||
RequestSadAction action = new RequestSadAction(
|
||||
this, Constants.ADDR_AUDIO_SYSTEM,
|
||||
new RequestSadAction.RequestSadCallback() {
|
||||
@Override
|
||||
public void onRequestSadDone(List<byte[]> supportedSads) {
|
||||
enableAudioReturnChannel(enabled);
|
||||
notifyArcStatusToAudioService(enabled, supportedSads);
|
||||
mArcEstablished = enabled;
|
||||
}
|
||||
});
|
||||
addAndStartAction(action);
|
||||
} else {
|
||||
enableAudioReturnChannel(enabled);
|
||||
notifyArcStatusToAudioService(enabled, new ArrayList<>());
|
||||
mArcEstablished = enabled;
|
||||
}
|
||||
return oldStatus;
|
||||
}
|
||||
|
||||
@@ -843,11 +858,15 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
return mService.isConnected(portId);
|
||||
}
|
||||
|
||||
private void notifyArcStatusToAudioService(boolean enabled) {
|
||||
private void notifyArcStatusToAudioService(boolean enabled, List<byte[]> supportedSads) {
|
||||
// Note that we don't set any name to ARC.
|
||||
mService.getAudioManager().setWiredDeviceConnectionState(
|
||||
AudioSystem.DEVICE_OUT_HDMI_ARC,
|
||||
enabled ? 1 : 0, "", "");
|
||||
AudioDeviceAttributes attributes = new AudioDeviceAttributes(
|
||||
AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_HDMI_ARC, "", "",
|
||||
new ArrayList<AudioProfile>(), supportedSads.stream()
|
||||
.map(sad -> new AudioDescriptor(AudioDescriptor.STANDARD_EDID,
|
||||
AudioProfile.AUDIO_ENCAPSULATION_TYPE_NONE, sad))
|
||||
.collect(Collectors.toList()));
|
||||
mService.getAudioManager().setWiredDeviceConnectionState(attributes, enabled ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.media.AudioDeviceAttributes;
|
||||
import android.media.AudioManager;
|
||||
import android.media.AudioSystem;
|
||||
import android.media.BluetoothProfileConnectionInfo;
|
||||
@@ -186,8 +187,9 @@ public class AudioDeviceBrokerTest {
|
||||
doNothing().when(mSpySystemServer).broadcastStickyIntentToCurrentProfileGroup(
|
||||
any(Intent.class));
|
||||
|
||||
mSpyDevInventory.setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
|
||||
AudioService.CONNECTION_STATE_CONNECTED, address, name, caller);
|
||||
mSpyDevInventory.setWiredDeviceConnectionState(new AudioDeviceAttributes(
|
||||
AudioSystem.DEVICE_OUT_WIRED_HEADSET, address, name),
|
||||
AudioService.CONNECTION_STATE_CONNECTED, caller);
|
||||
Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS);
|
||||
|
||||
// Verify that the sticky intent is broadcasted
|
||||
@@ -246,11 +248,11 @@ public class AudioDeviceBrokerTest {
|
||||
*/
|
||||
private void checkSingleSystemConnection(BluetoothDevice btDevice) throws Exception {
|
||||
final String expectedName = btDevice.getName() == null ? "" : btDevice.getName();
|
||||
AudioDeviceAttributes expected = new AudioDeviceAttributes(
|
||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, btDevice.getAddress(), expectedName);
|
||||
verify(mSpyAudioSystem, times(1)).setDeviceConnectionState(
|
||||
ArgumentMatchers.eq(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP),
|
||||
ArgumentMatchers.argThat(x -> x.equalTypeAddress(expected)),
|
||||
ArgumentMatchers.eq(AudioSystem.DEVICE_STATE_AVAILABLE),
|
||||
ArgumentMatchers.eq(btDevice.getAddress()),
|
||||
ArgumentMatchers.eq(expectedName),
|
||||
anyInt() /*codec*/);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,11 +48,10 @@ public class NoOpAudioSystemAdapter extends AudioSystemAdapter {
|
||||
//-----------------------------------------------------------------
|
||||
// Overrides of AudioSystemAdapter
|
||||
@Override
|
||||
public int setDeviceConnectionState(int device, int state, String deviceAddress,
|
||||
String deviceName, int codecFormat) {
|
||||
Log.i(TAG, String.format("setDeviceConnectionState(0x%s, %d, %s, %s, 0x%s",
|
||||
Integer.toHexString(device), state, deviceAddress, deviceName,
|
||||
Integer.toHexString(codecFormat)));
|
||||
public int setDeviceConnectionState(AudioDeviceAttributes attributes, int state,
|
||||
int codecFormat) {
|
||||
Log.i(TAG, String.format("setDeviceConnectionState(0x%s, %d, 0x%s",
|
||||
attributes.toString(), state, Integer.toHexString(codecFormat)));
|
||||
return AudioSystem.AUDIO_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,23 @@ import java.util.concurrent.TimeUnit;
|
||||
public class HdmiCecLocalDeviceTvTest {
|
||||
private static final int TIMEOUT_MS = HdmiConfig.TIMEOUT_MS + 1;
|
||||
|
||||
private static final String[] SADS_NOT_TO_QUERY = new String[]{
|
||||
HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MPEG1,
|
||||
HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_AAC,
|
||||
HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DTS,
|
||||
HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_ATRAC,
|
||||
HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_ONEBITAUDIO,
|
||||
HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DDP,
|
||||
HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DTSHD,
|
||||
HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_TRUEHD,
|
||||
HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_DST,
|
||||
HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_WMAPRO,
|
||||
HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MAX};
|
||||
private static final HdmiCecMessage SAD_QUERY =
|
||||
HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(ADDR_TV, ADDR_AUDIO_SYSTEM,
|
||||
new int[]{Constants.AUDIO_CODEC_LPCM, Constants.AUDIO_CODEC_DD,
|
||||
Constants.AUDIO_CODEC_MP3, Constants.AUDIO_CODEC_MPEG2});
|
||||
|
||||
private HdmiControlService mHdmiControlService;
|
||||
private HdmiCecController mHdmiCecController;
|
||||
private HdmiCecLocalDeviceTv mHdmiCecLocalDeviceTv;
|
||||
@@ -136,6 +153,10 @@ public class HdmiCecLocalDeviceTvTest {
|
||||
mNativeWrapper.setPhysicalAddress(mTvPhysicalAddress);
|
||||
mTestLooper.dispatchAll();
|
||||
mTvLogicalAddress = mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress();
|
||||
for (String sad : SADS_NOT_TO_QUERY) {
|
||||
mHdmiControlService.getHdmiCecConfig().setIntValue(
|
||||
sad, HdmiControlManager.QUERY_SAD_DISABLED);
|
||||
}
|
||||
mNativeWrapper.clearResultMessages();
|
||||
}
|
||||
|
||||
@@ -442,6 +463,7 @@ public class HdmiCecLocalDeviceTvTest {
|
||||
ADDR_TV,
|
||||
ADDR_AUDIO_SYSTEM);
|
||||
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated);
|
||||
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(SAD_QUERY);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -463,6 +485,7 @@ public class HdmiCecLocalDeviceTvTest {
|
||||
ADDR_TV,
|
||||
ADDR_AUDIO_SYSTEM);
|
||||
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated);
|
||||
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(SAD_QUERY);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -485,6 +508,7 @@ public class HdmiCecLocalDeviceTvTest {
|
||||
ADDR_TV,
|
||||
ADDR_AUDIO_SYSTEM);
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.usb;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.media.AudioDeviceAttributes;
|
||||
import android.media.AudioSystem;
|
||||
import android.media.IAudioService;
|
||||
import android.os.RemoteException;
|
||||
@@ -213,24 +214,25 @@ public final class UsbAlsaDevice {
|
||||
int outputState = (enable && connected) ? 1 : 0;
|
||||
if (outputState != mOutputState) {
|
||||
mOutputState = outputState;
|
||||
mAudioService.setWiredDeviceConnectionState(device, outputState,
|
||||
alsaCardDeviceString,
|
||||
mDeviceName, TAG);
|
||||
AudioDeviceAttributes attributes = new AudioDeviceAttributes(device,
|
||||
alsaCardDeviceString, mDeviceName);
|
||||
mAudioService.setWiredDeviceConnectionState(attributes, outputState, TAG);
|
||||
}
|
||||
}
|
||||
|
||||
// Input Device
|
||||
if (mHasInput) {
|
||||
int device = mIsInputHeadset ? AudioSystem.DEVICE_IN_USB_HEADSET
|
||||
int device = mIsInputHeadset
|
||||
? AudioSystem.DEVICE_IN_USB_HEADSET
|
||||
: AudioSystem.DEVICE_IN_USB_DEVICE;
|
||||
boolean connected = isInputJackConnected();
|
||||
Slog.i(TAG, "INPUT JACK connected: " + connected);
|
||||
int inputState = (enable && connected) ? 1 : 0;
|
||||
if (inputState != mInputState) {
|
||||
mInputState = inputState;
|
||||
mAudioService.setWiredDeviceConnectionState(
|
||||
device, inputState, alsaCardDeviceString,
|
||||
mDeviceName, TAG);
|
||||
AudioDeviceAttributes attributes = new AudioDeviceAttributes(device,
|
||||
alsaCardDeviceString, mDeviceName);
|
||||
mAudioService.setWiredDeviceConnectionState(attributes, inputState, TAG);
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
|
||||
Reference in New Issue
Block a user