Merge "CEC: Implement getSupportedShortAudioDescriptor method." am: b65741930f am: b1f73213b6 am: c8beeff74c
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2081683 Change-Id: If6d54566facaaff90d223ebc4ab9b11bf8a3eec9 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -71,6 +71,9 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
|
|||||||
private static final String TAG = "HdmiCecLocalDeviceAudioSystem";
|
private static final String TAG = "HdmiCecLocalDeviceAudioSystem";
|
||||||
|
|
||||||
private static final boolean WAKE_ON_HOTPLUG = false;
|
private static final boolean WAKE_ON_HOTPLUG = false;
|
||||||
|
private static final int MAX_CHANNELS = 8;
|
||||||
|
private static final HashMap<Integer, List<Integer>> AUDIO_CODECS_MAP =
|
||||||
|
mapAudioCodecWithAudioFormat();
|
||||||
|
|
||||||
// Whether the System Audio Control feature is enabled or not. True by default.
|
// Whether the System Audio Control feature is enabled or not. True by default.
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
@@ -485,17 +488,17 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@AudioCodec int[] audioFormatCodes = parseAudioFormatCodes(message.getParams());
|
@AudioCodec int[] audioCodecs = parseAudioCodecs(message.getParams());
|
||||||
byte[] sadBytes;
|
byte[] sadBytes;
|
||||||
if (config != null && config.size() > 0) {
|
if (config != null && config.size() > 0) {
|
||||||
sadBytes = getSupportedShortAudioDescriptorsFromConfig(config, audioFormatCodes);
|
sadBytes = getSupportedShortAudioDescriptorsFromConfig(config, audioCodecs);
|
||||||
} else {
|
} else {
|
||||||
AudioDeviceInfo deviceInfo = getSystemAudioDeviceInfo();
|
AudioDeviceInfo deviceInfo = getSystemAudioDeviceInfo();
|
||||||
if (deviceInfo == null) {
|
if (deviceInfo == null) {
|
||||||
return Constants.ABORT_UNABLE_TO_DETERMINE;
|
return Constants.ABORT_UNABLE_TO_DETERMINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
sadBytes = getSupportedShortAudioDescriptors(deviceInfo, audioFormatCodes);
|
sadBytes = getSupportedShortAudioDescriptors(deviceInfo, audioCodecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sadBytes.length == 0) {
|
if (sadBytes.length == 0) {
|
||||||
@@ -508,11 +511,12 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getSupportedShortAudioDescriptors(
|
@VisibleForTesting
|
||||||
AudioDeviceInfo deviceInfo, @AudioCodec int[] audioFormatCodes) {
|
byte[] getSupportedShortAudioDescriptors(
|
||||||
ArrayList<byte[]> sads = new ArrayList<>(audioFormatCodes.length);
|
AudioDeviceInfo deviceInfo, @AudioCodec int[] audioCodecs) {
|
||||||
for (@AudioCodec int audioFormatCode : audioFormatCodes) {
|
ArrayList<byte[]> sads = new ArrayList<>(audioCodecs.length);
|
||||||
byte[] sad = getSupportedShortAudioDescriptor(deviceInfo, audioFormatCode);
|
for (@AudioCodec int audioCodec : audioCodecs) {
|
||||||
|
byte[] sad = getSupportedShortAudioDescriptor(deviceInfo, audioCodec);
|
||||||
if (sad != null) {
|
if (sad != null) {
|
||||||
if (sad.length == 3) {
|
if (sad.length == 3) {
|
||||||
|
|
||||||
@@ -520,7 +524,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
|
|||||||
} else {
|
} else {
|
||||||
HdmiLogger.warning(
|
HdmiLogger.warning(
|
||||||
"Dropping Short Audio Descriptor with length %d for requested codec %x",
|
"Dropping Short Audio Descriptor with length %d for requested codec %x",
|
||||||
sad.length, audioFormatCode);
|
sad.length, audioCodec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -528,7 +532,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getSupportedShortAudioDescriptorsFromConfig(
|
private byte[] getSupportedShortAudioDescriptorsFromConfig(
|
||||||
List<DeviceConfig> deviceConfig, @AudioCodec int[] audioFormatCodes) {
|
List<DeviceConfig> deviceConfig, @AudioCodec int[] audioCodecs) {
|
||||||
DeviceConfig deviceConfigToUse = null;
|
DeviceConfig deviceConfigToUse = null;
|
||||||
String audioDeviceName = SystemProperties.get(
|
String audioDeviceName = SystemProperties.get(
|
||||||
Constants.PROPERTY_SYSTEM_AUDIO_MODE_AUDIO_PORT,
|
Constants.PROPERTY_SYSTEM_AUDIO_MODE_AUDIO_PORT,
|
||||||
@@ -544,13 +548,13 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
|
|||||||
return new byte[0];
|
return new byte[0];
|
||||||
}
|
}
|
||||||
HashMap<Integer, byte[]> map = new HashMap<>();
|
HashMap<Integer, byte[]> map = new HashMap<>();
|
||||||
ArrayList<byte[]> sads = new ArrayList<>(audioFormatCodes.length);
|
ArrayList<byte[]> sads = new ArrayList<>(audioCodecs.length);
|
||||||
for (CodecSad codecSad : deviceConfigToUse.supportedCodecs) {
|
for (CodecSad codecSad : deviceConfigToUse.supportedCodecs) {
|
||||||
map.put(codecSad.audioCodec, codecSad.sad);
|
map.put(codecSad.audioCodec, codecSad.sad);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < audioFormatCodes.length; i++) {
|
for (int i = 0; i < audioCodecs.length; i++) {
|
||||||
if (map.containsKey(audioFormatCodes[i])) {
|
if (map.containsKey(audioCodecs[i])) {
|
||||||
byte[] sad = map.get(audioFormatCodes[i]);
|
byte[] sad = map.get(audioCodecs[i]);
|
||||||
if (sad != null && sad.length == 3) {
|
if (sad != null && sad.length == 3) {
|
||||||
sads.add(sad);
|
sads.add(sad);
|
||||||
}
|
}
|
||||||
@@ -572,42 +576,171 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a 3 byte short audio descriptor as described in CEC 1.4 table 29 or null if the
|
* Returns a 3 byte short audio descriptor as described in CEC 1.4 table 29 or null if the
|
||||||
* audioFormatCode is not supported.
|
* audioCodec is not supported.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
private byte[] getSupportedShortAudioDescriptor(
|
@VisibleForTesting
|
||||||
AudioDeviceInfo deviceInfo, @AudioCodec int audioFormatCode) {
|
byte[] getSupportedShortAudioDescriptor(
|
||||||
switch (audioFormatCode) {
|
AudioDeviceInfo deviceInfo, @AudioCodec int audioCodec) {
|
||||||
case Constants.AUDIO_CODEC_NONE: {
|
byte[] shortAudioDescriptor = new byte[3];
|
||||||
return null;
|
|
||||||
}
|
int[] deviceSupportedAudioFormats = deviceInfo.getEncodings();
|
||||||
case Constants.AUDIO_CODEC_LPCM: {
|
// Return null when audioCodec or device does not support any audio formats.
|
||||||
return getLpcmShortAudioDescriptor(deviceInfo);
|
if (!AUDIO_CODECS_MAP.containsKey(audioCodec) || deviceSupportedAudioFormats.length == 0) {
|
||||||
}
|
return null;
|
||||||
// TODO(b/80297701): implement the rest of the codecs
|
}
|
||||||
case Constants.AUDIO_CODEC_DD:
|
List<Integer> audioCodecSupportedAudioFormats = AUDIO_CODECS_MAP.get(audioCodec);
|
||||||
case Constants.AUDIO_CODEC_MPEG1:
|
|
||||||
case Constants.AUDIO_CODEC_MP3:
|
for (int supportedAudioFormat : deviceSupportedAudioFormats) {
|
||||||
case Constants.AUDIO_CODEC_MPEG2:
|
if (audioCodecSupportedAudioFormats.contains(supportedAudioFormat)) {
|
||||||
case Constants.AUDIO_CODEC_AAC:
|
// Initialise the first two bytes of short audio descriptor.
|
||||||
case Constants.AUDIO_CODEC_DTS:
|
shortAudioDescriptor[0] = getFirstByteOfSAD(deviceInfo, audioCodec);
|
||||||
case Constants.AUDIO_CODEC_ATRAC:
|
shortAudioDescriptor[1] = getSecondByteOfSAD(deviceInfo);
|
||||||
case Constants.AUDIO_CODEC_ONEBITAUDIO:
|
switch (audioCodec) {
|
||||||
case Constants.AUDIO_CODEC_DDP:
|
case Constants.AUDIO_CODEC_NONE: {
|
||||||
case Constants.AUDIO_CODEC_DTSHD:
|
return null;
|
||||||
case Constants.AUDIO_CODEC_TRUEHD:
|
}
|
||||||
case Constants.AUDIO_CODEC_DST:
|
case Constants.AUDIO_CODEC_LPCM: {
|
||||||
case Constants.AUDIO_CODEC_WMAPRO:
|
if (supportedAudioFormat == AudioFormat.ENCODING_PCM_16BIT) {
|
||||||
default: {
|
shortAudioDescriptor[2] = (byte) 0x01;
|
||||||
return null;
|
} else if (supportedAudioFormat
|
||||||
|
== AudioFormat.ENCODING_PCM_24BIT_PACKED) {
|
||||||
|
shortAudioDescriptor[2] = (byte) 0x04;
|
||||||
|
} else {
|
||||||
|
// Since no bit is reserved for these audio formats in LPCM codec.
|
||||||
|
shortAudioDescriptor[2] = (byte) 0x00;
|
||||||
|
}
|
||||||
|
return shortAudioDescriptor;
|
||||||
|
}
|
||||||
|
case Constants.AUDIO_CODEC_DD:
|
||||||
|
case Constants.AUDIO_CODEC_MPEG1:
|
||||||
|
case Constants.AUDIO_CODEC_MP3:
|
||||||
|
case Constants.AUDIO_CODEC_MPEG2:
|
||||||
|
case Constants.AUDIO_CODEC_AAC:
|
||||||
|
case Constants.AUDIO_CODEC_DTS: {
|
||||||
|
shortAudioDescriptor[2] = getThirdSadByteForCodecs2Through8(deviceInfo);
|
||||||
|
return shortAudioDescriptor;
|
||||||
|
}
|
||||||
|
case Constants.AUDIO_CODEC_DDP:
|
||||||
|
case Constants.AUDIO_CODEC_DTSHD:
|
||||||
|
case Constants.AUDIO_CODEC_TRUEHD: {
|
||||||
|
// Default value is 0x0 unless defined by Audio Codec Vendor.
|
||||||
|
shortAudioDescriptor[2] = (byte) 0x00;
|
||||||
|
return shortAudioDescriptor;
|
||||||
|
}
|
||||||
|
case Constants.AUDIO_CODEC_ATRAC:
|
||||||
|
case Constants.AUDIO_CODEC_ONEBITAUDIO:
|
||||||
|
case Constants.AUDIO_CODEC_DST:
|
||||||
|
case Constants.AUDIO_CODEC_WMAPRO:
|
||||||
|
// Not supported.
|
||||||
|
default: {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private static HashMap<Integer, List<Integer>> mapAudioCodecWithAudioFormat() {
|
||||||
private byte[] getLpcmShortAudioDescriptor(AudioDeviceInfo deviceInfo) {
|
// Mapping the values of @AudioCodec audio codecs with @AudioFormat audio formats.
|
||||||
// TODO(b/80297701): implement
|
HashMap<Integer, List<Integer>> audioCodecsMap = new HashMap<Integer, List<Integer>>();
|
||||||
return null;
|
|
||||||
|
audioCodecsMap.put(Constants.AUDIO_CODEC_NONE, List.of(AudioFormat.ENCODING_DEFAULT));
|
||||||
|
audioCodecsMap.put(
|
||||||
|
Constants.AUDIO_CODEC_LPCM,
|
||||||
|
List.of(
|
||||||
|
AudioFormat.ENCODING_PCM_8BIT,
|
||||||
|
AudioFormat.ENCODING_PCM_16BIT,
|
||||||
|
AudioFormat.ENCODING_PCM_FLOAT,
|
||||||
|
AudioFormat.ENCODING_PCM_24BIT_PACKED,
|
||||||
|
AudioFormat.ENCODING_PCM_32BIT));
|
||||||
|
audioCodecsMap.put(Constants.AUDIO_CODEC_DD, List.of(AudioFormat.ENCODING_AC3));
|
||||||
|
audioCodecsMap.put(Constants.AUDIO_CODEC_MPEG1, List.of(AudioFormat.ENCODING_AAC_HE_V1));
|
||||||
|
audioCodecsMap.put(Constants.AUDIO_CODEC_MPEG2, List.of(AudioFormat.ENCODING_AAC_HE_V2));
|
||||||
|
audioCodecsMap.put(Constants.AUDIO_CODEC_MP3, List.of(AudioFormat.ENCODING_MP3));
|
||||||
|
audioCodecsMap.put(Constants.AUDIO_CODEC_AAC, List.of(AudioFormat.ENCODING_AAC_LC));
|
||||||
|
audioCodecsMap.put(Constants.AUDIO_CODEC_DTS, List.of(AudioFormat.ENCODING_DTS));
|
||||||
|
audioCodecsMap.put(
|
||||||
|
Constants.AUDIO_CODEC_DDP,
|
||||||
|
List.of(AudioFormat.ENCODING_E_AC3, AudioFormat.ENCODING_E_AC3_JOC));
|
||||||
|
audioCodecsMap.put(Constants.AUDIO_CODEC_DTSHD, List.of(AudioFormat.ENCODING_DTS_HD));
|
||||||
|
audioCodecsMap.put(
|
||||||
|
Constants.AUDIO_CODEC_TRUEHD,
|
||||||
|
List.of(AudioFormat.ENCODING_DOLBY_TRUEHD, AudioFormat.ENCODING_DOLBY_MAT));
|
||||||
|
|
||||||
|
return audioCodecsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte getFirstByteOfSAD(AudioDeviceInfo deviceInfo, @AudioCodec int audioCodec) {
|
||||||
|
byte firstByte = 0;
|
||||||
|
int maxNumberOfChannels = getMaxNumberOfChannels(deviceInfo);
|
||||||
|
|
||||||
|
// Fill bits 0-2 of the first byte.
|
||||||
|
firstByte |= (maxNumberOfChannels - 1);
|
||||||
|
|
||||||
|
// Fill bits 3-6 of the first byte.
|
||||||
|
firstByte |= (audioCodec << 3);
|
||||||
|
|
||||||
|
return firstByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte getSecondByteOfSAD(AudioDeviceInfo deviceInfo) {
|
||||||
|
ArrayList<Integer> samplingRates =
|
||||||
|
new ArrayList<Integer>(Arrays.asList(32, 44, 48, 88, 96, 176, 192));
|
||||||
|
|
||||||
|
// samplingRatesdevicesupports is guaranteed to be not null
|
||||||
|
int[] samplingRatesDeviceSupports = deviceInfo.getSampleRates();
|
||||||
|
if (samplingRatesDeviceSupports.length == 0) {
|
||||||
|
Slog.e(TAG, "Device supports arbitrary rates");
|
||||||
|
// Since device supports arbitrary rates, we will return 0x7f since bit 7 is reserved.
|
||||||
|
return (byte) 0x7f;
|
||||||
|
}
|
||||||
|
byte secondByte = 0;
|
||||||
|
for (int supportedSampleRate : samplingRatesDeviceSupports) {
|
||||||
|
if (samplingRates.contains(supportedSampleRate)) {
|
||||||
|
int index = samplingRates.indexOf(supportedSampleRate);
|
||||||
|
// Setting the bit of a sample rate which is being supported.
|
||||||
|
secondByte |= (1 << index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return secondByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty array from deviceInfo.getChannelCounts() implies device supports arbitrary channel
|
||||||
|
* counts and hence we assume max channels are supported by the device.
|
||||||
|
*/
|
||||||
|
private int getMaxNumberOfChannels(AudioDeviceInfo deviceInfo) {
|
||||||
|
int maxNumberOfChannels = MAX_CHANNELS;
|
||||||
|
int[] channelCounts = deviceInfo.getChannelCounts();
|
||||||
|
if (channelCounts.length != 0) {
|
||||||
|
maxNumberOfChannels = channelCounts[channelCounts.length - 1];
|
||||||
|
maxNumberOfChannels =
|
||||||
|
(maxNumberOfChannels > MAX_CHANNELS ? MAX_CHANNELS : maxNumberOfChannels);
|
||||||
|
}
|
||||||
|
return maxNumberOfChannels;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte getThirdSadByteForCodecs2Through8(AudioDeviceInfo deviceInfo) {
|
||||||
|
/*
|
||||||
|
* Here, we are assuming that max bit rate is closely equals to the max sampling rate the
|
||||||
|
* device supports.
|
||||||
|
*/
|
||||||
|
int maxSamplingRate = 0;
|
||||||
|
int[] samplingRatesDeviceSupports = deviceInfo.getSampleRates();
|
||||||
|
if (samplingRatesDeviceSupports.length == 0) {
|
||||||
|
maxSamplingRate = 192;
|
||||||
|
} else {
|
||||||
|
for (int sampleRate : samplingRatesDeviceSupports) {
|
||||||
|
if (maxSamplingRate < sampleRate) {
|
||||||
|
maxSamplingRate = sampleRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (byte) (maxSamplingRate / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -634,14 +767,14 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@AudioCodec
|
@AudioCodec
|
||||||
private int[] parseAudioFormatCodes(byte[] params) {
|
private int[] parseAudioCodecs(byte[] params) {
|
||||||
@AudioCodec int[] audioFormatCodes = new int[params.length];
|
@AudioCodec int[] audioCodecs = new int[params.length];
|
||||||
for (int i = 0; i < params.length; i++) {
|
for (int i = 0; i < params.length; i++) {
|
||||||
byte val = params[i];
|
byte val = params[i];
|
||||||
audioFormatCodes[i] =
|
audioCodecs[i] =
|
||||||
val >= 1 && val <= Constants.AUDIO_CODEC_MAX ? val : Constants.AUDIO_CODEC_NONE;
|
val >= 1 && val <= Constants.AUDIO_CODEC_MAX ? val : Constants.AUDIO_CODEC_NONE;
|
||||||
}
|
}
|
||||||
return audioFormatCodes;
|
return audioCodecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user