Add AudioDeviceAttributes as argument to AudioManager API

NoNonSdkCheck: This CL changes the arguments of an existing API that was
annotated already.
Bug: 199846845
Test: atest AidlConversionUnitTests

Change-Id: I90a24c0428d9c77ccd45dff65bbdad198aa81fb2
This commit is contained in:
Nathalie Le Clair 2021-10-15 14:22:41 +02:00
parent 4e27963e60
commit 517a1327ca
16 changed files with 657 additions and 144 deletions

View File

@ -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"
// ----------------------------------------------------------------------------
@ -578,18 +579,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;
}
@ -2830,7 +2839,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},

View File

@ -166,10 +166,21 @@ public final class AudioDeviceAttributes implements Parcelable {
* @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 = "";
mName = name;
mNativeType = nativeType;
mAudioProfiles = new ArrayList<>();
mAudioDescriptors = new ArrayList<>();

View File

@ -5851,7 +5851,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
@ -5860,10 +5860,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();

View File

@ -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;
@ -1542,9 +1544,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);

View File

@ -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);

View File

@ -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(

View File

@ -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;
}
}

View File

@ -499,12 +499,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);
}
}
@ -1012,11 +1011,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*/);
}
}

View File

@ -219,19 +219,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;
}
}
@ -269,11 +265,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);
}
}
@ -508,41 +503,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();
}
@ -561,12 +560,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();
}
@ -696,16 +695,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
@ -732,9 +732,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)
@ -751,9 +750,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();
@ -930,13 +928,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;
}
}
@ -944,8 +942,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);
}
@ -961,8 +958,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.
@ -1019,8 +1017,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(
@ -1058,8 +1057,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),
@ -1069,8 +1069,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));
@ -1083,8 +1084,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),
@ -1106,8 +1108,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));
@ -1124,14 +1127,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);
@ -1152,8 +1155,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));
}

View File

@ -6377,23 +6377,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) */

View File

@ -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();
}
}

View File

@ -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);
}
/**

View File

@ -586,8 +586,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,
@ -595,13 +596,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;
}

View File

@ -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.BtProfileConnectionInfo;
@ -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*/);
}
}

View File

@ -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;
}

View File

@ -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;
@ -203,24 +204,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) {