Enhance channel masks conversion between AIDL and SDK
Provide conversion for layouts not listed in AudioChannelLayout::LAYOUT_* constants. In this case the conversion is performed on bit-by-bit correspondence between AudioChannelLayout::CHANNEL_* constants and SDK channel bits from AudioFormat. Added missing input channel bits to AudioFormat to match native. Currently hidden, since we would need to update docs if we reveal these bits and masks to apps. Bug: 198812639 Bug: 204362366 Test: atest AidlConversionUnitTests Change-Id: I7cb80fef2bfe9513f16dc632b22ef81b1e0f0526
This commit is contained in:
@@ -675,8 +675,44 @@ public final class AudioFormat implements Parcelable {
|
||||
public static final int CHANNEL_IN_Z_AXIS = 0x2000;
|
||||
public static final int CHANNEL_IN_VOICE_UPLINK = 0x4000;
|
||||
public static final int CHANNEL_IN_VOICE_DNLINK = 0x8000;
|
||||
// CHANNEL_IN_BACK_LEFT to TOP_RIGHT are not microphone positions
|
||||
// but surround channels which are used when dealing with multi-channel inputs,
|
||||
// e.g. via HDMI input on TV.
|
||||
/** @hide */
|
||||
public static final int CHANNEL_IN_BACK_LEFT = 0x10000;
|
||||
/** @hide */
|
||||
public static final int CHANNEL_IN_BACK_RIGHT = 0x20000;
|
||||
/** @hide */
|
||||
public static final int CHANNEL_IN_CENTER = 0x40000;
|
||||
/** @hide */
|
||||
public static final int CHANNEL_IN_LOW_FREQUENCY = 0x100000;
|
||||
/** @hide */
|
||||
public static final int CHANNEL_IN_TOP_LEFT = 0x200000;
|
||||
/** @hide */
|
||||
public static final int CHANNEL_IN_TOP_RIGHT = 0x400000;
|
||||
public static final int CHANNEL_IN_MONO = CHANNEL_IN_FRONT;
|
||||
public static final int CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT);
|
||||
// Surround channel masks corresponding to output masks, used for
|
||||
// surround sound inputs.
|
||||
/** @hide */
|
||||
public static final int CHANNEL_IN_2POINT0POINT2 = (
|
||||
CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT | CHANNEL_IN_TOP_LEFT | CHANNEL_IN_TOP_RIGHT);
|
||||
/** @hide */
|
||||
public static final int CHANNEL_IN_2POINT1POINT2 = (
|
||||
CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT | CHANNEL_IN_TOP_LEFT | CHANNEL_IN_TOP_RIGHT
|
||||
| CHANNEL_IN_LOW_FREQUENCY);
|
||||
/** @hide */
|
||||
public static final int CHANNEL_IN_3POINT0POINT2 = (
|
||||
CHANNEL_IN_LEFT | CHANNEL_IN_CENTER | CHANNEL_IN_RIGHT | CHANNEL_IN_TOP_LEFT
|
||||
| CHANNEL_IN_TOP_RIGHT);
|
||||
/** @hide */
|
||||
public static final int CHANNEL_IN_3POINT1POINT2 = (
|
||||
CHANNEL_IN_LEFT | CHANNEL_IN_CENTER | CHANNEL_IN_RIGHT | CHANNEL_IN_TOP_LEFT
|
||||
| CHANNEL_IN_TOP_RIGHT | CHANNEL_IN_LOW_FREQUENCY);
|
||||
/** @hide */
|
||||
public static final int CHANNEL_IN_5POINT1 = (
|
||||
CHANNEL_IN_LEFT | CHANNEL_IN_CENTER | CHANNEL_IN_RIGHT | CHANNEL_IN_BACK_LEFT
|
||||
| CHANNEL_IN_BACK_RIGHT | CHANNEL_IN_LOW_FREQUENCY);
|
||||
/** @hide */
|
||||
public static final int CHANNEL_IN_FRONT_BACK = CHANNEL_IN_FRONT | CHANNEL_IN_BACK;
|
||||
// CHANNEL_IN_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_IN_ALL
|
||||
|
||||
@@ -131,6 +131,124 @@ public class AidlConversion {
|
||||
/** Convert from legacy audio_usage_t to AIDL AudioUsage. */
|
||||
public static native int legacy2aidl_audio_usage_t_AudioUsage(int /*audio_usage_t*/ legacy);
|
||||
|
||||
/** Convert from a channel bit of AIDL AudioChannelLayout to SDK AudioFormat.CHANNEL_* bit. */
|
||||
private static int aidl2api_AudioChannelLayoutBit_AudioFormatChannel(
|
||||
int aidlBit, boolean isInput) {
|
||||
if (isInput) {
|
||||
switch (aidlBit) {
|
||||
case AudioChannelLayout.CHANNEL_FRONT_LEFT:
|
||||
return AudioFormat.CHANNEL_IN_LEFT;
|
||||
case AudioChannelLayout.CHANNEL_FRONT_RIGHT:
|
||||
return AudioFormat.CHANNEL_IN_RIGHT;
|
||||
case AudioChannelLayout.CHANNEL_FRONT_CENTER:
|
||||
return AudioFormat.CHANNEL_IN_CENTER;
|
||||
case AudioChannelLayout.CHANNEL_BACK_CENTER:
|
||||
return AudioFormat.CHANNEL_IN_BACK;
|
||||
// CHANNEL_IN_*_PROCESSED not supported
|
||||
// CHANNEL_IN_PRESSURE not supported
|
||||
// CHANNEL_IN_*_AXIS not supported
|
||||
// CHANNEL_IN_VOICE_* not supported
|
||||
case AudioChannelLayout.CHANNEL_BACK_LEFT:
|
||||
return AudioFormat.CHANNEL_IN_BACK_LEFT;
|
||||
case AudioChannelLayout.CHANNEL_BACK_RIGHT:
|
||||
return AudioFormat.CHANNEL_IN_BACK_RIGHT;
|
||||
case AudioChannelLayout.CHANNEL_LOW_FREQUENCY:
|
||||
return AudioFormat.CHANNEL_IN_LOW_FREQUENCY;
|
||||
case AudioChannelLayout.CHANNEL_TOP_SIDE_LEFT:
|
||||
return AudioFormat.CHANNEL_IN_TOP_LEFT;
|
||||
case AudioChannelLayout.CHANNEL_TOP_SIDE_RIGHT:
|
||||
return AudioFormat.CHANNEL_IN_TOP_RIGHT;
|
||||
default:
|
||||
return AudioFormat.CHANNEL_INVALID;
|
||||
}
|
||||
} else {
|
||||
switch (aidlBit) {
|
||||
case AudioChannelLayout.CHANNEL_FRONT_LEFT:
|
||||
return AudioFormat.CHANNEL_OUT_FRONT_LEFT;
|
||||
case AudioChannelLayout.CHANNEL_FRONT_RIGHT:
|
||||
return AudioFormat.CHANNEL_OUT_FRONT_RIGHT;
|
||||
case AudioChannelLayout.CHANNEL_FRONT_CENTER:
|
||||
return AudioFormat.CHANNEL_OUT_FRONT_CENTER;
|
||||
case AudioChannelLayout.CHANNEL_LOW_FREQUENCY:
|
||||
return AudioFormat.CHANNEL_OUT_LOW_FREQUENCY;
|
||||
case AudioChannelLayout.CHANNEL_BACK_LEFT:
|
||||
return AudioFormat.CHANNEL_OUT_BACK_LEFT;
|
||||
case AudioChannelLayout.CHANNEL_BACK_RIGHT:
|
||||
return AudioFormat.CHANNEL_OUT_BACK_RIGHT;
|
||||
case AudioChannelLayout.CHANNEL_FRONT_LEFT_OF_CENTER:
|
||||
return AudioFormat.CHANNEL_OUT_FRONT_LEFT_OF_CENTER;
|
||||
case AudioChannelLayout.CHANNEL_FRONT_RIGHT_OF_CENTER:
|
||||
return AudioFormat.CHANNEL_OUT_FRONT_RIGHT_OF_CENTER;
|
||||
case AudioChannelLayout.CHANNEL_BACK_CENTER:
|
||||
return AudioFormat.CHANNEL_OUT_BACK_CENTER;
|
||||
case AudioChannelLayout.CHANNEL_SIDE_LEFT:
|
||||
return AudioFormat.CHANNEL_OUT_SIDE_LEFT;
|
||||
case AudioChannelLayout.CHANNEL_SIDE_RIGHT:
|
||||
return AudioFormat.CHANNEL_OUT_SIDE_RIGHT;
|
||||
case AudioChannelLayout.CHANNEL_TOP_CENTER:
|
||||
return AudioFormat.CHANNEL_OUT_TOP_CENTER;
|
||||
case AudioChannelLayout.CHANNEL_TOP_FRONT_LEFT:
|
||||
return AudioFormat.CHANNEL_OUT_TOP_FRONT_LEFT;
|
||||
case AudioChannelLayout.CHANNEL_TOP_FRONT_CENTER:
|
||||
return AudioFormat.CHANNEL_OUT_TOP_FRONT_CENTER;
|
||||
case AudioChannelLayout.CHANNEL_TOP_FRONT_RIGHT:
|
||||
return AudioFormat.CHANNEL_OUT_TOP_FRONT_RIGHT;
|
||||
case AudioChannelLayout.CHANNEL_TOP_BACK_LEFT:
|
||||
return AudioFormat.CHANNEL_OUT_TOP_BACK_LEFT;
|
||||
case AudioChannelLayout.CHANNEL_TOP_BACK_CENTER:
|
||||
return AudioFormat.CHANNEL_OUT_TOP_BACK_CENTER;
|
||||
case AudioChannelLayout.CHANNEL_TOP_BACK_RIGHT:
|
||||
return AudioFormat.CHANNEL_OUT_TOP_BACK_RIGHT;
|
||||
case AudioChannelLayout.CHANNEL_TOP_SIDE_LEFT:
|
||||
return AudioFormat.CHANNEL_OUT_TOP_SIDE_LEFT;
|
||||
case AudioChannelLayout.CHANNEL_TOP_SIDE_RIGHT:
|
||||
return AudioFormat.CHANNEL_OUT_TOP_SIDE_RIGHT;
|
||||
case AudioChannelLayout.CHANNEL_BOTTOM_FRONT_LEFT:
|
||||
return AudioFormat.CHANNEL_OUT_BOTTOM_FRONT_LEFT;
|
||||
case AudioChannelLayout.CHANNEL_BOTTOM_FRONT_CENTER:
|
||||
return AudioFormat.CHANNEL_OUT_BOTTOM_FRONT_CENTER;
|
||||
case AudioChannelLayout.CHANNEL_BOTTOM_FRONT_RIGHT:
|
||||
return AudioFormat.CHANNEL_OUT_BOTTOM_FRONT_RIGHT;
|
||||
case AudioChannelLayout.CHANNEL_LOW_FREQUENCY_2:
|
||||
return AudioFormat.CHANNEL_OUT_LOW_FREQUENCY_2;
|
||||
case AudioChannelLayout.CHANNEL_FRONT_WIDE_LEFT:
|
||||
return AudioFormat.CHANNEL_OUT_FRONT_WIDE_LEFT;
|
||||
case AudioChannelLayout.CHANNEL_FRONT_WIDE_RIGHT:
|
||||
return AudioFormat.CHANNEL_OUT_FRONT_WIDE_RIGHT;
|
||||
case AudioChannelLayout.CHANNEL_HAPTIC_A:
|
||||
return AudioFormat.CHANNEL_OUT_HAPTIC_A;
|
||||
case AudioChannelLayout.CHANNEL_HAPTIC_B:
|
||||
return AudioFormat.CHANNEL_OUT_HAPTIC_B;
|
||||
default:
|
||||
return AudioFormat.CHANNEL_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from a channel bitmask of AIDL AudioChannelLayout to
|
||||
* SDK AudioFormat.CHANNEL_* bitmask.
|
||||
*/
|
||||
private static int aidl2api_AudioChannelLayoutBitMask_AudioFormatChannelMask(
|
||||
int aidlBitMask, boolean isInput) {
|
||||
int apiMask = 0;
|
||||
for (int bit = 1 << 31; bit != 0; bit >>>= 1) {
|
||||
if ((aidlBitMask & bit) == bit) {
|
||||
int apiBit = aidl2api_AudioChannelLayoutBit_AudioFormatChannel(bit, isInput);
|
||||
if (apiBit != AudioFormat.CHANNEL_INVALID) {
|
||||
apiMask |= apiBit;
|
||||
aidlBitMask &= ~bit;
|
||||
if (aidlBitMask == 0) {
|
||||
return apiMask;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return AudioFormat.CHANNEL_INVALID;
|
||||
}
|
||||
|
||||
/** Convert from AIDL AudioChannelLayout to SDK AudioFormat.CHANNEL_*. */
|
||||
public static int aidl2api_AudioChannelLayout_AudioFormatChannelMask(
|
||||
@NonNull AudioChannelLayout aidlMask, boolean isInput) {
|
||||
@@ -155,8 +273,17 @@ public class AidlConversion {
|
||||
return AudioFormat.CHANNEL_IN_STEREO;
|
||||
case AudioChannelLayout.LAYOUT_FRONT_BACK:
|
||||
return AudioFormat.CHANNEL_IN_FRONT_BACK;
|
||||
default:
|
||||
return AudioFormat.CHANNEL_INVALID;
|
||||
case AudioChannelLayout.LAYOUT_2POINT0POINT2:
|
||||
return AudioFormat.CHANNEL_IN_2POINT0POINT2;
|
||||
case AudioChannelLayout.LAYOUT_2POINT1POINT2:
|
||||
return AudioFormat.CHANNEL_IN_2POINT1POINT2;
|
||||
case AudioChannelLayout.LAYOUT_3POINT0POINT2:
|
||||
return AudioFormat.CHANNEL_IN_3POINT0POINT2;
|
||||
case AudioChannelLayout.LAYOUT_3POINT1POINT2:
|
||||
return AudioFormat.CHANNEL_IN_3POINT1POINT2;
|
||||
case AudioChannelLayout.LAYOUT_5POINT1:
|
||||
return AudioFormat.CHANNEL_IN_5POINT1;
|
||||
default: // fall through
|
||||
}
|
||||
} else {
|
||||
switch (aidlMask.getLayoutMask()) {
|
||||
@@ -264,10 +391,12 @@ public class AidlConversion {
|
||||
case AudioChannelLayout.LAYOUT_FRONT_BACK:
|
||||
return AudioFormat.CHANNEL_OUT_FRONT_CENTER
|
||||
| AudioFormat.CHANNEL_OUT_BACK_CENTER;
|
||||
default:
|
||||
return AudioFormat.CHANNEL_INVALID;
|
||||
default: // fall through
|
||||
}
|
||||
}
|
||||
// If a match for a predefined layout wasn't found, make a custom one from bits.
|
||||
return aidl2api_AudioChannelLayoutBitMask_AudioFormatChannelMask(
|
||||
aidlMask.getLayoutMask(), isInput);
|
||||
case AudioChannelLayout.voiceMask:
|
||||
if (isInput) {
|
||||
switch (aidlMask.getVoiceMask()) {
|
||||
|
||||
@@ -66,6 +66,19 @@ public final class AidlConversionUnitTests {
|
||||
assertEquals(AudioFormat.CHANNEL_OUT_MONO, api);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAudioChannelConversionApiOutputMask() {
|
||||
final AudioChannelLayout aidl = AudioChannelLayout.layoutMask(
|
||||
AudioChannelLayout.CHANNEL_FRONT_LEFT | AudioChannelLayout.CHANNEL_FRONT_RIGHT
|
||||
| AudioChannelLayout.CHANNEL_FRONT_WIDE_LEFT
|
||||
| AudioChannelLayout.CHANNEL_FRONT_WIDE_RIGHT);
|
||||
final int api = AidlConversion.aidl2api_AudioChannelLayout_AudioFormatChannelMask(
|
||||
aidl, false /*isInput*/);
|
||||
assertEquals(AudioFormat.CHANNEL_OUT_FRONT_LEFT | AudioFormat.CHANNEL_OUT_FRONT_RIGHT
|
||||
| AudioFormat.CHANNEL_OUT_FRONT_WIDE_LEFT
|
||||
| AudioFormat.CHANNEL_OUT_FRONT_WIDE_RIGHT, api);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAudioChannelConversionApiInput() {
|
||||
final AudioChannelLayout aidl = AudioChannelLayout.layoutMask(
|
||||
@@ -75,6 +88,20 @@ public final class AidlConversionUnitTests {
|
||||
assertEquals(AudioFormat.CHANNEL_IN_MONO, api);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAudioChannelConversionApiInputMask() {
|
||||
final AudioChannelLayout aidl = AudioChannelLayout.layoutMask(
|
||||
AudioChannelLayout.CHANNEL_FRONT_LEFT | AudioChannelLayout.CHANNEL_FRONT_RIGHT
|
||||
| AudioChannelLayout.CHANNEL_TOP_SIDE_LEFT
|
||||
| AudioChannelLayout.CHANNEL_TOP_SIDE_RIGHT);
|
||||
final int api = AidlConversion.aidl2api_AudioChannelLayout_AudioFormatChannelMask(
|
||||
aidl, true /*isInput*/);
|
||||
assertEquals(AudioFormat.CHANNEL_IN_LEFT | AudioFormat.CHANNEL_IN_RIGHT
|
||||
// | AudioFormat.CHANNEL_IN_TOP_LEFT | AudioFormat.CHANNEL_IN_TOP_RIGHT,
|
||||
| 0x200000 | 0x400000, // TODO: Replace with names when revealed.
|
||||
api);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAudioChannelConversionApiIndex() {
|
||||
final AudioChannelLayout aidl = AudioChannelLayout.indexMask(
|
||||
|
||||
Reference in New Issue
Block a user