/* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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: * - SDK (Java API) types from 'android.media'; * - legacy native (system/audio.h) types. * * Methods that convert between AIDL and SDK types are called * using the following pattern: * * aidl2api_AIDL-type-name_SDK-type-name * api2aidl_SDK-type-name_AIDL-type-name * * Since the range of the SDK values is generally narrower than * the range of AIDL values, when a match can't be found, the * conversion function returns a corresponding 'INVALID' value. * * Methods that convert between AIDL and legacy types are called * using the following pattern: * * aidl2legacy_AIDL-type-name_native-type-name * legacy2aidl_native-type-name_AIDL-type-name * * In general, there is a 1:1 mapping between AIDL and framework * types, and a failure to convert a value indicates a programming * error. Thus, the conversion functions may throw an IllegalArgumentException. * * @hide */ @VisibleForTesting public class AidlConversion { /** Convert from AIDL AudioChannelLayout to legacy audio_channel_mask_t. */ public static int /*audio_channel_mask_t*/ aidl2legacy_AudioChannelLayout_audio_channel_mask_t( @NonNull AudioChannelLayout aidl, boolean isInput) { Parcel out = Parcel.obtain(); aidl.writeToParcel(out, 0); out.setDataPosition(0); try { return aidl2legacy_AudioChannelLayout_Parcel_audio_channel_mask_t(out, isInput); } finally { out.recycle(); } } /** Convert from legacy audio_channel_mask_t to AIDL AudioChannelLayout. */ public static AudioChannelLayout legacy2aidl_audio_channel_mask_t_AudioChannelLayout( int /*audio_channel_mask_t*/ legacy, boolean isInput) { Parcel in = legacy2aidl_audio_channel_mask_t_AudioChannelLayout_Parcel(legacy, isInput); if (in != null) { try { return AudioChannelLayout.CREATOR.createFromParcel(in); } finally { in.recycle(); } } throw new IllegalArgumentException("Failed to convert legacy audio " + (isInput ? "input" : "output") + " audio_channel_mask_t " + legacy + " value"); } /** Convert from AIDL AudioFormatDescription to legacy audio_format_t. */ public static int /*audio_format_t*/ aidl2legacy_AudioFormatDescription_audio_format_t( @NonNull AudioFormatDescription aidl) { Parcel out = Parcel.obtain(); aidl.writeToParcel(out, 0); out.setDataPosition(0); try { return aidl2legacy_AudioFormatDescription_Parcel_audio_format_t(out); } finally { out.recycle(); } } /** Convert from legacy audio_format_t to AIDL AudioFormatDescription. */ public static @NonNull AudioFormatDescription legacy2aidl_audio_format_t_AudioFormatDescription( int /*audio_format_t*/ legacy) { Parcel in = legacy2aidl_audio_format_t_AudioFormatDescription_Parcel(legacy); if (in != null) { try { return AudioFormatDescription.CREATOR.createFromParcel(in); } finally { in.recycle(); } } throw new IllegalArgumentException( "Failed to convert legacy audio_format_t value " + legacy); } /** Convert from AIDL AudioEncapsulationMode to legacy audio_encapsulation_mode_t. */ public static native int aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t( int /*AudioEncapsulationMode.* */ aidl); /** Convert from legacy audio_encapsulation_mode_t to AIDL AudioEncapsulationMode. */ public static native int legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode( int /*audio_encapsulation_mode_t*/ legacy); /** Convert from AIDL AudioStreamType to legacy audio_stream_type_t. */ public static native int aidl2legacy_AudioStreamType_audio_stream_type_t( int /*AudioStreamType.* */ aidl); /** Convert from legacy audio_stream_type_t to AIDL AudioStreamType. */ public static native int legacy2aidl_audio_stream_type_t_AudioStreamType( int /*audio_stream_type_t*/ legacy); /** Convert from AIDL AudioUsage to legacy audio_usage_t. */ public static native int aidl2legacy_AudioUsage_audio_usage_t(int /*AudioUsage.* */ aidl); /** 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) { switch (aidlMask.getTag()) { case AudioChannelLayout.none: return isInput ? AudioFormat.CHANNEL_IN_DEFAULT : AudioFormat.CHANNEL_OUT_DEFAULT; case AudioChannelLayout.invalid: return AudioFormat.CHANNEL_INVALID; case AudioChannelLayout.indexMask: // Note that for a proper building of SDK AudioFormat one must // call either 'setChannelMask' or 'setChannelIndexMask' depending // on the variant of AudioChannelLayout. The integer representations // of positional and indexed channel masks are indistinguishable in // the SDK. return aidlMask.getIndexMask(); case AudioChannelLayout.layoutMask: if (isInput) { switch (aidlMask.getLayoutMask()) { case AudioChannelLayout.LAYOUT_MONO: return AudioFormat.CHANNEL_IN_MONO; case AudioChannelLayout.LAYOUT_STEREO: return AudioFormat.CHANNEL_IN_STEREO; case AudioChannelLayout.LAYOUT_FRONT_BACK: return AudioFormat.CHANNEL_IN_FRONT_BACK; 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()) { case AudioChannelLayout.LAYOUT_MONO: return AudioFormat.CHANNEL_OUT_MONO; case AudioChannelLayout.LAYOUT_STEREO: return AudioFormat.CHANNEL_OUT_STEREO; case AudioChannelLayout.LAYOUT_2POINT1: return AudioFormat.CHANNEL_OUT_FRONT_LEFT | AudioFormat.CHANNEL_OUT_FRONT_RIGHT | AudioFormat.CHANNEL_OUT_LOW_FREQUENCY; case AudioChannelLayout.LAYOUT_TRI: return AudioFormat.CHANNEL_OUT_FRONT_LEFT | AudioFormat.CHANNEL_OUT_FRONT_RIGHT | AudioFormat.CHANNEL_OUT_FRONT_CENTER; case AudioChannelLayout.LAYOUT_TRI_BACK: return AudioFormat.CHANNEL_OUT_FRONT_LEFT | AudioFormat.CHANNEL_OUT_FRONT_RIGHT | AudioFormat.CHANNEL_OUT_BACK_CENTER; case AudioChannelLayout.LAYOUT_3POINT1: return AudioFormat.CHANNEL_OUT_FRONT_LEFT | AudioFormat.CHANNEL_OUT_FRONT_RIGHT | AudioFormat.CHANNEL_OUT_FRONT_CENTER | AudioFormat.CHANNEL_OUT_LOW_FREQUENCY; case AudioChannelLayout.LAYOUT_2POINT0POINT2: return AudioFormat.CHANNEL_OUT_FRONT_LEFT | AudioFormat.CHANNEL_OUT_FRONT_RIGHT | AudioFormat.CHANNEL_OUT_TOP_SIDE_LEFT | AudioFormat.CHANNEL_OUT_TOP_SIDE_RIGHT; case AudioChannelLayout.LAYOUT_2POINT1POINT2: return AudioFormat.CHANNEL_OUT_FRONT_LEFT | AudioFormat.CHANNEL_OUT_FRONT_RIGHT | AudioFormat.CHANNEL_OUT_TOP_SIDE_LEFT | AudioFormat.CHANNEL_OUT_TOP_SIDE_RIGHT | AudioFormat.CHANNEL_OUT_LOW_FREQUENCY; case AudioChannelLayout.LAYOUT_3POINT0POINT2: return AudioFormat.CHANNEL_OUT_FRONT_LEFT | AudioFormat.CHANNEL_OUT_FRONT_RIGHT | AudioFormat.CHANNEL_OUT_FRONT_CENTER | AudioFormat.CHANNEL_OUT_TOP_SIDE_LEFT | AudioFormat.CHANNEL_OUT_TOP_SIDE_RIGHT; case AudioChannelLayout.LAYOUT_3POINT1POINT2: return AudioFormat.CHANNEL_OUT_FRONT_LEFT | AudioFormat.CHANNEL_OUT_FRONT_RIGHT | AudioFormat.CHANNEL_OUT_FRONT_CENTER | AudioFormat.CHANNEL_OUT_TOP_SIDE_LEFT | AudioFormat.CHANNEL_OUT_TOP_SIDE_RIGHT | AudioFormat.CHANNEL_OUT_LOW_FREQUENCY; case AudioChannelLayout.LAYOUT_QUAD: return AudioFormat.CHANNEL_OUT_QUAD; case AudioChannelLayout.LAYOUT_QUAD_SIDE: return AudioFormat.CHANNEL_OUT_QUAD_SIDE; case AudioChannelLayout.LAYOUT_SURROUND: return AudioFormat.CHANNEL_OUT_SURROUND; case AudioChannelLayout.LAYOUT_PENTA: return AudioFormat.CHANNEL_OUT_QUAD | AudioFormat.CHANNEL_OUT_FRONT_CENTER; case AudioChannelLayout.LAYOUT_5POINT1: return AudioFormat.CHANNEL_OUT_5POINT1; case AudioChannelLayout.LAYOUT_5POINT1_SIDE: return AudioFormat.CHANNEL_OUT_5POINT1_SIDE; case AudioChannelLayout.LAYOUT_5POINT1POINT2: return AudioFormat.CHANNEL_OUT_5POINT1POINT2; case AudioChannelLayout.LAYOUT_5POINT1POINT4: return AudioFormat.CHANNEL_OUT_5POINT1POINT4; case AudioChannelLayout.LAYOUT_6POINT1: return AudioFormat.CHANNEL_OUT_6POINT1; case AudioChannelLayout.LAYOUT_7POINT1: return AudioFormat.CHANNEL_OUT_7POINT1_SURROUND; case AudioChannelLayout.LAYOUT_7POINT1POINT2: return AudioFormat.CHANNEL_OUT_7POINT1POINT2; case AudioChannelLayout.LAYOUT_7POINT1POINT4: return AudioFormat.CHANNEL_OUT_7POINT1POINT4; case AudioChannelLayout.LAYOUT_9POINT1POINT4: return AudioFormat.CHANNEL_OUT_9POINT1POINT4; case AudioChannelLayout.LAYOUT_9POINT1POINT6: return AudioFormat.CHANNEL_OUT_9POINT1POINT6; case AudioChannelLayout.LAYOUT_13POINT_360RA: return AudioFormat.CHANNEL_OUT_13POINT_360RA; case AudioChannelLayout.LAYOUT_22POINT2: return AudioFormat.CHANNEL_OUT_22POINT2; case AudioChannelLayout.LAYOUT_MONO_HAPTIC_A: return AudioFormat.CHANNEL_OUT_MONO | AudioFormat.CHANNEL_OUT_HAPTIC_A; case AudioChannelLayout.LAYOUT_STEREO_HAPTIC_A: return AudioFormat.CHANNEL_OUT_STEREO | AudioFormat.CHANNEL_OUT_HAPTIC_A; case AudioChannelLayout.LAYOUT_HAPTIC_AB: return AudioFormat.CHANNEL_OUT_HAPTIC_A | AudioFormat.CHANNEL_OUT_HAPTIC_B; case AudioChannelLayout.LAYOUT_MONO_HAPTIC_AB: return AudioFormat.CHANNEL_OUT_MONO | AudioFormat.CHANNEL_OUT_HAPTIC_A | AudioFormat.CHANNEL_OUT_HAPTIC_B; case AudioChannelLayout.LAYOUT_STEREO_HAPTIC_AB: return AudioFormat.CHANNEL_OUT_STEREO | AudioFormat.CHANNEL_OUT_HAPTIC_A | AudioFormat.CHANNEL_OUT_HAPTIC_B; case AudioChannelLayout.LAYOUT_FRONT_BACK: return AudioFormat.CHANNEL_OUT_FRONT_CENTER | AudioFormat.CHANNEL_OUT_BACK_CENTER; 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()) { // AudioFormat input masks match legacy native masks directly, // thus we add AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO here. case AudioChannelLayout.VOICE_UPLINK_MONO: return AudioFormat.CHANNEL_IN_VOICE_UPLINK | AudioFormat.CHANNEL_IN_MONO; case AudioChannelLayout.VOICE_DNLINK_MONO: return AudioFormat.CHANNEL_IN_VOICE_DNLINK | AudioFormat.CHANNEL_IN_MONO; case AudioChannelLayout.VOICE_CALL_MONO: return AudioFormat.CHANNEL_IN_VOICE_UPLINK | AudioFormat.CHANNEL_IN_VOICE_DNLINK | AudioFormat.CHANNEL_IN_MONO; } } return AudioFormat.CHANNEL_INVALID; default: return AudioFormat.CHANNEL_INVALID; } } /** Convert from AIDL AudioConfig to SDK AudioFormat. */ public static @NonNull AudioFormat aidl2api_AudioConfig_AudioFormat( @NonNull AudioConfig aidl, boolean isInput) { // Only information from the encapsulated AudioConfigBase is used. return aidl2api_AudioConfigBase_AudioFormat(aidl.base, isInput); } /** Convert from AIDL AudioConfigBase to SDK AudioFormat. */ public static @NonNull AudioFormat aidl2api_AudioConfigBase_AudioFormat( @NonNull AudioConfigBase aidl, boolean isInput) { AudioFormat.Builder apiBuilder = new AudioFormat.Builder(); apiBuilder.setSampleRate(aidl.sampleRate); if (aidl.channelMask.getTag() != AudioChannelLayout.indexMask) { apiBuilder.setChannelMask(aidl2api_AudioChannelLayout_AudioFormatChannelMask( aidl.channelMask, isInput)); } else { apiBuilder.setChannelIndexMask(aidl2api_AudioChannelLayout_AudioFormatChannelMask( aidl.channelMask, isInput)); } apiBuilder.setEncoding(aidl2api_AudioFormat_AudioFormatEncoding(aidl.format)); return apiBuilder.build(); } /** Convert from AIDL AudioFormat to SDK AudioFormat.ENCODING_*. */ public static int aidl2api_AudioFormat_AudioFormatEncoding( @NonNull AudioFormatDescription aidl) { switch (aidl.type) { case AudioFormatType.PCM: switch (aidl.pcm) { case PcmType.UINT_8_BIT: return AudioFormat.ENCODING_PCM_8BIT; case PcmType.INT_16_BIT: return AudioFormat.ENCODING_PCM_16BIT; case PcmType.INT_32_BIT: return AudioFormat.ENCODING_PCM_32BIT; case PcmType.FIXED_Q_8_24: case PcmType.FLOAT_32_BIT: return AudioFormat.ENCODING_PCM_FLOAT; case PcmType.INT_24_BIT: return AudioFormat.ENCODING_PCM_24BIT_PACKED; default: return AudioFormat.ENCODING_INVALID; } case AudioFormatType.NON_PCM: // same as DEFAULT if (aidl.encoding != null && !aidl.encoding.isEmpty()) { if (MediaFormat.MIMETYPE_AUDIO_AC3.equals(aidl.encoding)) { return AudioFormat.ENCODING_AC3; } else if (MediaFormat.MIMETYPE_AUDIO_EAC3.equals(aidl.encoding)) { return AudioFormat.ENCODING_E_AC3; } else if (MediaFormat.MIMETYPE_AUDIO_DTS.equals(aidl.encoding)) { return AudioFormat.ENCODING_DTS; } else if (MediaFormat.MIMETYPE_AUDIO_DTS_HD.equals(aidl.encoding)) { return AudioFormat.ENCODING_DTS_HD; } else if (MediaFormat.MIMETYPE_AUDIO_MPEG.equals(aidl.encoding)) { return AudioFormat.ENCODING_MP3; } else if (MediaFormat.MIMETYPE_AUDIO_AAC_LC.equals(aidl.encoding)) { return AudioFormat.ENCODING_AAC_LC; } else if (MediaFormat.MIMETYPE_AUDIO_AAC_HE_V1.equals(aidl.encoding)) { return AudioFormat.ENCODING_AAC_HE_V1; } else if (MediaFormat.MIMETYPE_AUDIO_AAC_HE_V2.equals(aidl.encoding)) { return AudioFormat.ENCODING_AAC_HE_V2; } else if (MediaFormat.MIMETYPE_AUDIO_IEC61937.equals(aidl.encoding) && aidl.pcm == PcmType.INT_16_BIT) { return AudioFormat.ENCODING_IEC61937; } else if (MediaFormat.MIMETYPE_AUDIO_DOLBY_TRUEHD.equals( aidl.encoding)) { return AudioFormat.ENCODING_DOLBY_TRUEHD; } else if (MediaFormat.MIMETYPE_AUDIO_AAC_ELD.equals(aidl.encoding)) { return AudioFormat.ENCODING_AAC_ELD; } else if (MediaFormat.MIMETYPE_AUDIO_AAC_XHE.equals(aidl.encoding)) { return AudioFormat.ENCODING_AAC_XHE; } else if (MediaFormat.MIMETYPE_AUDIO_AC4.equals(aidl.encoding)) { return AudioFormat.ENCODING_AC4; } else if (MediaFormat.MIMETYPE_AUDIO_EAC3_JOC.equals(aidl.encoding)) { return AudioFormat.ENCODING_E_AC3_JOC; } else if (MediaFormat.MIMETYPE_AUDIO_DOLBY_MAT.equals(aidl.encoding) || aidl.encoding.startsWith( MediaFormat.MIMETYPE_AUDIO_DOLBY_MAT + ".")) { return AudioFormat.ENCODING_DOLBY_MAT; } else if (MediaFormat.MIMETYPE_AUDIO_OPUS.equals(aidl.encoding)) { return AudioFormat.ENCODING_OPUS; } else if (MediaFormat.MIMETYPE_AUDIO_MPEGH_BL_L3.equals(aidl.encoding)) { return AudioFormat.ENCODING_MPEGH_BL_L3; } else if (MediaFormat.MIMETYPE_AUDIO_MPEGH_BL_L4.equals(aidl.encoding)) { return AudioFormat.ENCODING_MPEGH_BL_L4; } else if (MediaFormat.MIMETYPE_AUDIO_MPEGH_LC_L3.equals(aidl.encoding)) { return AudioFormat.ENCODING_MPEGH_LC_L3; } else if (MediaFormat.MIMETYPE_AUDIO_MPEGH_LC_L4.equals(aidl.encoding)) { return AudioFormat.ENCODING_MPEGH_LC_L4; } else if (MediaFormat.MIMETYPE_AUDIO_DTS_UHD.equals(aidl.encoding)) { return AudioFormat.ENCODING_DTS_UHD_P1; } else if (MediaFormat.MIMETYPE_AUDIO_DRA.equals(aidl.encoding)) { return AudioFormat.ENCODING_DRA; } else { return AudioFormat.ENCODING_INVALID; } } else { return AudioFormat.ENCODING_DEFAULT; } case AudioFormatType.SYS_RESERVED_INVALID: default: return AudioFormat.ENCODING_INVALID; } } /** * 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_SADB: return AudioStandard.SADB; case AudioDescriptor.STANDARD_VSADB: return AudioStandard.VSADB; 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.SADB: return AudioDescriptor.STANDARD_SADB; case AudioStandard.VSADB: return AudioDescriptor.STANDARD_VSADB; 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_PCM: return AudioEncapsulationType.PCM; 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.PCM: return android.media.AudioProfile.AUDIO_ENCAPSULATION_TYPE_PCM; 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_OUT_BLE_BROADCAST: aidl.type = AudioDeviceType.OUT_BROADCAST; 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( int legacy, boolean isInput); private static native int aidl2legacy_AudioFormatDescription_Parcel_audio_format_t( Parcel aidl); private static native Parcel legacy2aidl_audio_format_t_AudioFormatDescription_Parcel( int legacy); }