diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioDeviceConfiguration.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioDeviceConfiguration.aidl new file mode 100644 index 0000000000..2685f58485 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioDeviceConfiguration.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AudioDeviceConfiguration { + android.hardware.automotive.audiocontrol.RoutingDeviceConfiguration routingConfig; + boolean useCoreAudioVolume; + boolean useHalDuckingSignals; + boolean useCarVolumeGroupMuting; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFadeConfiguration.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFadeConfiguration.aidl new file mode 100644 index 0000000000..0a3c677036 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFadeConfiguration.aidl @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AudioFadeConfiguration { + String name; + android.hardware.automotive.audiocontrol.FadeState fadeState; + long fadeInDurationMs = DEFAULT_FADE_IN_DURATION_MS /* 1000 */; + long fadeOutDurationMs = DEFAULT_FADE_OUT_DURATION_MS /* 2000 */; + long fadeInDelayedForOffendersMs = DEFAULT_DELAY_FADE_IN_OFFENDERS_MS /* 2000 */; + android.media.audio.common.AudioUsage[] fadeableUsages; + @nullable android.media.audio.common.AudioContentType[] unfadeableContentTypes; + List unfadableAudioAttributes; + List fadeOutConfigurations; + List fadeInConfigurations; + const long DEFAULT_FADE_IN_DURATION_MS = 1000; + const long DEFAULT_FADE_OUT_DURATION_MS = 2000; + const long DEFAULT_DELAY_FADE_IN_OFFENDERS_MS = 2000; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl index 58a36673cd..8eab521ce4 100644 --- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl @@ -39,7 +39,7 @@ enum AudioFocusChange { GAIN_TRANSIENT = 2, GAIN_TRANSIENT_MAY_DUCK = 3, GAIN_TRANSIENT_EXCLUSIVE = 4, - LOSS = -1, - LOSS_TRANSIENT = -2, - LOSS_TRANSIENT_CAN_DUCK = -3, + LOSS = ((-1) * GAIN) /* -1 */, + LOSS_TRANSIENT = ((-1) * GAIN_TRANSIENT) /* -2 */, + LOSS_TRANSIENT_CAN_DUCK = ((-1) * GAIN_TRANSIENT_MAY_DUCK) /* -3 */, } diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZone.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZone.aidl new file mode 100644 index 0000000000..2cb176078e --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZone.aidl @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AudioZone { + String name; + int id; + int occupantZoneId = UNASSIGNED_OCCUPANT /* -1 */; + android.hardware.automotive.audiocontrol.AudioZoneContext audioZoneContext; + List audioZoneConfigs; + List inputAudioDevices; + const int PRIMARY_AUDIO_ZONE = 0; + const int UNASSIGNED_OCCUPANT = (-1) /* -1 */; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneConfig.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneConfig.aidl new file mode 100644 index 0000000000..3fd37bc1cf --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneConfig.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AudioZoneConfig { + String name; + boolean isDefault; + List volumeGroups; + @nullable android.hardware.automotive.audiocontrol.AudioZoneFadeConfiguration fadeConfiguration; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneContext.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneContext.aidl new file mode 100644 index 0000000000..0f8b946e30 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneContext.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AudioZoneContext { + List audioContextInfos; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneContextInfo.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneContextInfo.aidl new file mode 100644 index 0000000000..01ab1be643 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneContextInfo.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AudioZoneContextInfo { + String name; + int id = UNASSIGNED_CONTEXT_ID /* -1 */; + List audioAttributes; + const int UNASSIGNED_CONTEXT_ID = (-1) /* -1 */; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneFadeConfiguration.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneFadeConfiguration.aidl new file mode 100644 index 0000000000..f3f32bf6f3 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioZoneFadeConfiguration.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable AudioZoneFadeConfiguration { + android.hardware.automotive.audiocontrol.AudioFadeConfiguration defaultConfiguration; + List transientConfiguration; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DeviceToContextEntry.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DeviceToContextEntry.aidl new file mode 100644 index 0000000000..923b0bdc48 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DeviceToContextEntry.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable DeviceToContextEntry { + List contextNames; + android.media.audio.common.AudioPort device; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/FadeConfiguration.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/FadeConfiguration.aidl new file mode 100644 index 0000000000..2c978e75ad --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/FadeConfiguration.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable FadeConfiguration { + long fadeDurationMillis; + android.hardware.automotive.audiocontrol.FadeConfiguration.AudioAttributesOrUsage audioAttributesOrUsage; + @JavaDerive(equals=true, toString=true) @VintfStability + union AudioAttributesOrUsage { + android.media.audio.common.AudioAttributes fadeAttribute; + android.media.audio.common.AudioUsage usage; + } +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/FadeState.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/FadeState.aidl new file mode 100644 index 0000000000..9b25dfbdec --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/FadeState.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@Backing(type="int") @JavaDerive(toString=true) @VintfStability +enum FadeState { + FADE_STATE_DISABLED, + FADE_STATE_ENABLED_DEFAULT, +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl index ffd575dfa4..fe39f92cc0 100644 --- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl @@ -12,6 +12,34 @@ * 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. + *//** + * Important note on Metadata: + * Metadata qualifies a playback track for an output stream. + * This is highly closed to {@link android.media.AudioAttributes}. + * It allows to identify the audio stream rendered / requesting / abandonning the focus. + * + * AudioControl 1.0 was limited to identification through {@code AttributeUsage} listed as + * {@code audioUsage} in audio_policy_configuration.xsd. + * + * Any new OEM needs would not be possible without extension. + * + * Relying on {@link android.hardware.automotive.audiocontrol.PlaybackTrackMetadata} allows + * to use a combination of {@code AttributeUsage}, {@code AttributeContentType} and + * {@code AttributeTags} to identify the use case / routing thanks to + * {@link android.media.audiopolicy.AudioProductStrategy}. + * The belonging to a strategy is deduced by an AOSP logic (in sync at native and java layer). + * + * IMPORTANT NOTE ON TAGS: + * To limit the possibilies and prevent from confusion, we expect the String to follow + * a given formalism that will be enforced. + * + * 1 / By convention, tags shall be a "key=value" pair. + * Vendor must namespace their tag's key (for example com.google.strategy=VR) to avoid conflicts. + * vendor specific applications and must be prefixed by "VX_". Vendor must + * + * 2 / Tags reported here shall be the same as the tags used to define a given + * {@link android.media.audiopolicy.AudioProductStrategy} and so in + * audio_policy_engine_configuration.xml file. */ /////////////////////////////////////////////////////////////////////////////// // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // @@ -48,4 +76,7 @@ interface IAudioControl { oneway void registerGainCallback(in android.hardware.automotive.audiocontrol.IAudioGainCallback callback); void setModuleChangeCallback(in android.hardware.automotive.audiocontrol.IModuleChangeCallback callback); void clearModuleChangeCallback(); + android.hardware.automotive.audiocontrol.AudioDeviceConfiguration getAudioDeviceConfiguration(); + List getOutputMirroringDevices(); + List getCarAudioZones(); } diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/Reasons.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/Reasons.aidl index c1e22d44a7..8d669850a5 100644 --- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/Reasons.aidl +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/Reasons.aidl @@ -34,14 +34,14 @@ package android.hardware.automotive.audiocontrol; @Backing(type="int") @VintfStability enum Reasons { - FORCED_MASTER_MUTE = 1, - REMOTE_MUTE = 2, - TCU_MUTE = 4, - ADAS_DUCKING = 8, - NAV_DUCKING = 16, - PROJECTION_DUCKING = 32, - THERMAL_LIMITATION = 64, - SUSPEND_EXIT_VOL_LIMITATION = 128, - EXTERNAL_AMP_VOL_FEEDBACK = 256, - OTHER = -2147483648, + FORCED_MASTER_MUTE = 0x1, + REMOTE_MUTE = 0x2, + TCU_MUTE = 0x4, + ADAS_DUCKING = 0x8, + NAV_DUCKING = 0x10, + PROJECTION_DUCKING = 0x20, + THERMAL_LIMITATION = 0x40, + SUSPEND_EXIT_VOL_LIMITATION = 0x80, + EXTERNAL_AMP_VOL_FEEDBACK = 0x100, + OTHER = 0x80000000, } diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/RoutingDeviceConfiguration.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/RoutingDeviceConfiguration.aidl new file mode 100644 index 0000000000..901078c696 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/RoutingDeviceConfiguration.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +enum RoutingDeviceConfiguration { + DEFAULT_AUDIO_ROUTING, + DYNAMIC_AUDIO_ROUTING, + CONFIGURABLE_AUDIO_ENGINE_ROUTING, +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/TransientFadeConfigurationEntry.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/TransientFadeConfigurationEntry.aidl new file mode 100644 index 0000000000..72b247bb8e --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/TransientFadeConfigurationEntry.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable TransientFadeConfigurationEntry { + android.media.audio.common.AudioUsage[] transientUsages; + android.hardware.automotive.audiocontrol.AudioFadeConfiguration transientFadeConfiguration; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeActivationConfiguration.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeActivationConfiguration.aidl new file mode 100644 index 0000000000..50b76a163e --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeActivationConfiguration.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable VolumeActivationConfiguration { + @nullable String name; + List volumeActivationEntries; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeActivationConfigurationEntry.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeActivationConfigurationEntry.aidl new file mode 100644 index 0000000000..d457e57db7 --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeActivationConfigurationEntry.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable VolumeActivationConfigurationEntry { + android.hardware.automotive.audiocontrol.VolumeInvocationType type = android.hardware.automotive.audiocontrol.VolumeInvocationType.ON_PLAYBACK_CHANGED; + int maxActivationVolumePercentage = DEFAULT_MAX_ACTIVATION_VALUE /* 100 */; + int minActivationVolumePercentage = DEFAULT_MIN_ACTIVATION_VALUE /* 0 */; + const int DEFAULT_MAX_ACTIVATION_VALUE = 100; + const int DEFAULT_MIN_ACTIVATION_VALUE = 0; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeGroupConfig.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeGroupConfig.aidl new file mode 100644 index 0000000000..cc90bbe77f --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeGroupConfig.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@JavaDerive(equals=true, toString=true) @VintfStability +parcelable VolumeGroupConfig { + String name; + int id = UNASSIGNED_ID /* -1 */; + List carAudioRoutes; + @nullable android.hardware.automotive.audiocontrol.VolumeActivationConfiguration activationConfiguration; + const int UNASSIGNED_ID = (-1) /* -1 */; +} diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeInvocationType.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeInvocationType.aidl new file mode 100644 index 0000000000..8ce84913ca --- /dev/null +++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/VolumeInvocationType.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.audiocontrol; +@Backing(type="int") @JavaDerive(toString=true) @VintfStability +enum VolumeInvocationType { + ON_PLAYBACK_CHANGED, + ON_SOURCE_CHANGED, + ON_BOOT, +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioDeviceConfiguration.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioDeviceConfiguration.aidl new file mode 100644 index 0000000000..9b5e72422f --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioDeviceConfiguration.aidl @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.RoutingDeviceConfiguration; + +/** + * Use to configure audio configurations at boot up time. + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable AudioDeviceConfiguration { + /** + * Use to configure audio device routing mechanism + */ + RoutingDeviceConfiguration routingConfig; + + /** + * Use to configure core audio volume usage in car audio service + */ + boolean useCoreAudioVolume; + + /** + * Use to determine if HAL ducking signal should be sent to audio control HAL from car audio + * service + */ + boolean useHalDuckingSignals; + + /** + * Use to determine if HAL volume signal should be sent to audio control HAL from car audio + * service + */ + boolean useCarVolumeGroupMuting; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioFadeConfiguration.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioFadeConfiguration.aidl new file mode 100644 index 0000000000..d3181da732 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioFadeConfiguration.aidl @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.FadeConfiguration; +import android.hardware.automotive.audiocontrol.FadeState; +import android.media.audio.common.AudioAttributes; +import android.media.audio.common.AudioContentType; +import android.media.audio.common.AudioUsage; + +/** + * Encapsulates the audio fade configuration info + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable AudioFadeConfiguration { + /** + * Default fade in duration + */ + const long DEFAULT_FADE_IN_DURATION_MS = 1000; + + /** + * Default fade out duration + */ + const long DEFAULT_FADE_OUT_DURATION_MS = 2000; + + /** + * Default delay for fade in offenders + */ + const long DEFAULT_DELAY_FADE_IN_OFFENDERS_MS = 2000; + + /** + * Audio configuration name, use for debugging purposes + */ + String name; + + /** + * Audio configuration state + */ + FadeState fadeState; + + /** + * Fade in duration in milliseconds + * + *

Use to construct the default fade in configuration. This can be overwritten for different + * attributes/usages by passing a list of fade-in configuration, + * see {@code #fadeInConfigurations} + */ + long fadeInDurationMs = DEFAULT_FADE_IN_DURATION_MS; + + /** + * Fade out duration in milliseconds + * + *

Use to construct the default fade out configuration. This can be overwritten for different + * attributes/usages by passing a list of fade-out configuration, + * see {@code #fadeOutConfigurations} + */ + long fadeOutDurationMs = DEFAULT_FADE_OUT_DURATION_MS; + + /** + * Fade in delayed duration for audio focus offender in milliseconds + */ + long fadeInDelayedForOffendersMs = DEFAULT_DELAY_FADE_IN_OFFENDERS_MS; + + /** + * List of audio attribute usage that should be faded using the parameters in + * this configuration. + * + *

If the list is empty car audio service will overwrite the list for the confgiruation with + * default usages, e.g. {AudioUsage#MEDIA, AudioUsage#GAME} + */ + AudioUsage[] fadeableUsages; + + /** + * Optional list of audio attribute content types that should not be faded. + * + **

The list can be empty in cases where there are no unfadeable content types. + * + *

If the list is not set car audio service will overwrite the list for the confgiruation + * with default content type, e.g. {AudioContentType#SPEECH}. + */ + @nullable AudioContentType[] unfadeableContentTypes; + + /** + * List of audio attribute that should not be faded. + * + *

The list can be empty in cases where there are no unfadeable attributes + */ + List unfadableAudioAttributes; + + /** + * List of fade out configutions which should apply to this audio fade configurations + * + *

The list can be empty in cases where there are no fade out configurations. + */ + List fadeOutConfigurations; + + /** + * List of fade in configutions which should apply to this audio fade configurations + * + *

The list can be empty in cases where there are no fade out configurations + */ + List fadeInConfigurations; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZone.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZone.aidl new file mode 100644 index 0000000000..c90bcfd9dc --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZone.aidl @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.AudioZoneConfig; +import android.hardware.automotive.audiocontrol.AudioZoneContext; +import android.media.audio.common.AudioPort; + +/** + * Encapsulates the audio configurations for each audio zone + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable AudioZone { + /** + * Value indicating the primary audio zone + */ + const int PRIMARY_AUDIO_ZONE = 0; + + /** + * Value indicating the occupant zone is not assigned. + */ + const int UNASSIGNED_OCCUPANT = -1; + + /** + * Audio zone name, only use for debug purposes. + * + *

If present it must be non-empty otherwise car audio service will construct a name + * based on audio zone id. + */ + String name; + + /** + * Audio zone id use to distiguish between the different audio zones for + * volume management, fade, and min/max activation management. + */ + int id; + + /** + * Occupant zone id that should be mapped to this audio zone. + * + *

For audio zones not mapped to an occupant zone use UNASSIGNED_OCCUPANT + */ + int occupantZoneId = UNASSIGNED_OCCUPANT; + + /** + * Car audio context which can be used in the audio zone + */ + AudioZoneContext audioZoneContext; + + /** + * List of car audio configurations + */ + List audioZoneConfigs; + + /** + * List of input audio devices used for this zone + */ + List inputAudioDevices; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneConfig.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneConfig.aidl new file mode 100644 index 0000000000..6822da580a --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneConfig.aidl @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.AudioZoneFadeConfiguration; +import android.hardware.automotive.audiocontrol.VolumeGroupConfig; + +/** + * Encapsulates the audio zone config information + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable AudioZoneConfig { + /** + * Audio zone config name + * + *

Must be non-empty and unique among the configurations within a zone. + */ + String name; + + /** + * Determines if the audio configuration is the default configuration. + * + *

There can only be a single default configuration per zone. + */ + boolean isDefault; + + /** + * List car volume group that should be managed within this configuration + */ + List volumeGroups; + + /** + * Car audio zone fade configuration + */ + @nullable AudioZoneFadeConfiguration fadeConfiguration; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneContext.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneContext.aidl new file mode 100644 index 0000000000..390cb09160 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneContext.aidl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.AudioZoneContextInfo; + +/** + * Encapsulates the list of car audio context info definitions + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable AudioZoneContext { + /** + * List of car audio context info. + * + *

The list must include all audio attributes usages currently supported so that all audio + * attribute usages can be routed for each car audio configuration. + */ + List audioContextInfos; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneContextInfo.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneContextInfo.aidl new file mode 100644 index 0000000000..0ca425c044 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneContextInfo.aidl @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +import android.media.audio.common.AudioAttributes; + +/** + * Encapsulates groups of audio attributes which should be managed together. + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable AudioZoneContextInfo { + /** + * Value indicating the context info id is not assigned. + */ + const int UNASSIGNED_CONTEXT_ID = -1; + + /** + * Context name which can be used to map the info to an audio route + * management as described in each audio configuration. + * + *

Name must be non-empty and unique among all audio context info within the same + * {@link android.hardware.automotive.audiocontrol.AudioZoneContext} container. + */ + String name; + + /** + * Used in car audio service to manage the info + * + *

Must be non-negative integer if assigned, or UNASSIGNED_CONTEXT_ID otherwise. If using + * configurable audio policy engine audio routing with multi-zone configurations the value must + * be assigned. + */ + int id = UNASSIGNED_CONTEXT_ID; + + /** + * List of audio attributes that belong to the context + */ + List audioAttributes; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneFadeConfiguration.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneFadeConfiguration.aidl new file mode 100644 index 0000000000..a604214713 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioZoneFadeConfiguration.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.AudioFadeConfiguration; +import android.hardware.automotive.audiocontrol.TransientFadeConfigurationEntry; + +/** + * Encapsulates the audio zone fade configuration + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable AudioZoneFadeConfiguration { + /** + * Defines the default fade configuration + */ + AudioFadeConfiguration defaultConfiguration; + + /** + * List of transient fade configurations. + * + *

The list can be empty if the fade configuration for the zone does not have transient fade + * configurations. + */ + List transientConfiguration; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DeviceToContextEntry.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DeviceToContextEntry.aidl new file mode 100644 index 0000000000..bcb5ee7c7c --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DeviceToContextEntry.aidl @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +import android.media.audio.common.AudioPort; + +/** + * Encapsulates the audio context that should be route to particular device + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable DeviceToContextEntry { + /** + * List of audio context names that should be routed to the audio device. + * + *

The names must match a {@link AudioZoneContextInfo#name} in the corresponding + * {@link AudioZone#audioZoneContext). + * + *

Within a {@link AudioZoneConfig} a context name must not repeat among the different + * {@link VolumeGroupConfig}. The value can repeat among different {@link AudioZoneConfig} + * within a {@link AudioZone}. + */ + List contextNames; + + /** + * Audio port where contexts should be routed. + * + *

For dynamic devices (OUT_HEADSET, OUT_HEADPHONE, etc.) , the audio device address can be + * omitted since the information will be obtained at run time when the device is + * connected/enabled. + */ + AudioPort device; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/FadeConfiguration.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/FadeConfiguration.aidl new file mode 100644 index 0000000000..e700d6c184 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/FadeConfiguration.aidl @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +import android.media.audio.common.AudioAttributes; +import android.media.audio.common.AudioUsage; + +/** + * Encapsulates the in/out fade configuration + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable FadeConfiguration { + /** + * Fade duration in milliseconds + */ + long fadeDurationMillis; + + @JavaDerive(equals=true, toString=true) + @VintfStability + union AudioAttributesOrUsage { + AudioAttributes fadeAttribute; + AudioUsage usage; + } + + /** + * Audio attribute or usage that should be impacted by the fade out duration + * {@code #fadeDurationMillis} + */ + AudioAttributesOrUsage audioAttributesOrUsage; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/FadeState.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/FadeState.aidl new file mode 100644 index 0000000000..346caae57c --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/FadeState.aidl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +/** + * Encapsulates the audio fade configuration state + */ +@VintfStability +@Backing(type="int") +@JavaDerive(toString=true) +enum FadeState { + /** + * Fade configuration should be disabled + */ + FADE_STATE_DISABLED, + /** + * Fade configuration should be enabled by default + */ + FADE_STATE_ENABLED_DEFAULT, +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl index 9564efc859..1202b4cd01 100644 --- a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl @@ -46,14 +46,17 @@ package android.hardware.automotive.audiocontrol; * audio_policy_engine_configuration.xml file. */ import android.hardware.audio.common.PlaybackTrackMetadata; +import android.hardware.automotive.audiocontrol.AudioDeviceConfiguration; import android.hardware.automotive.audiocontrol.AudioFocusChange; import android.hardware.automotive.audiocontrol.AudioGainConfigInfo; +import android.hardware.automotive.audiocontrol.AudioZone; import android.hardware.automotive.audiocontrol.DuckingInfo; import android.hardware.automotive.audiocontrol.IAudioGainCallback; import android.hardware.automotive.audiocontrol.IFocusListener; import android.hardware.automotive.audiocontrol.IModuleChangeCallback; import android.hardware.automotive.audiocontrol.MutingInfo; import android.hardware.automotive.audiocontrol.Reasons; +import android.media.audio.common.AudioPort; /** * Interacts with the car's audio subsystem to manage audio sources and volumes @@ -206,4 +209,41 @@ interface IAudioControl { * @throws EX_UNSUPPORTED_OPERATION if dynamic audio configs are not supported. */ void clearModuleChangeCallback(); + + /** + * Returns the audio device configurations that should be used to configure + * the car audio service audio management. + * + *

If this method is not supported, car audio service will attempt to configure the car audio + * service properties based on previously supported mechanisms. + * + *

If the returned value contains the + * {@link RoutingDeviceConfiguration#DEFAULT_AUDIO_ROUTING} value, the car audio service will + * attempt to configure audio routing based on the mechanism previously supported by car audio + * service (e.g. car audio configuration file). Otherwise, the {@link #getCarAudioZones()} + * API must return valid audio zone(s) configuration(s) for the device. + * + */ + AudioDeviceConfiguration getAudioDeviceConfiguration(); + + /** + * Returns the list of audio devices that can be used for mirroring between different audio + * zones. + * + * @throws EX_UNSUPPORTED_OPERATION if mirroring devices are not supported. + */ + List getOutputMirroringDevices(); + + /** + * List of audio zones used to configure car audio service at bootup. + * + *

If the returned value from {@link #getAudioDeviceConfiguration()} contains + * {@link RoutingDeviceConfiguration#DEFAULT_AUDIO_ROUTING} value, the car audio service will + * attempt to configure the audio routing based on the mechanism previously supported by + * car audio service (e.g. car audio configuration file). Otherwise, this method must return + * valid audio zone(s) configuration(s) for the device. + * + * @throws EX_UNSUPPORTED_OPERATION if audio zone configuration are not supported. + */ + List getCarAudioZones(); } diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/RoutingDeviceConfiguration.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/RoutingDeviceConfiguration.aidl new file mode 100644 index 0000000000..2d175401c5 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/RoutingDeviceConfiguration.aidl @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +/** + * Use to configure audio device routing mechanism + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +enum RoutingDeviceConfiguration { + /** + * Use to indicate that audio should be managed based on previously supportec mechamisms in + * car audio service. + * + *

If this used then the API to setup the audio zones can just throw + * {@code EX_UNSUPPORTED_OPERATION} if called. + */ + DEFAULT_AUDIO_ROUTING, + /** + * Use to indicate that audio should be managed using the dynamic audio + * policy as setup by car audio service using the setup configuration from + * the {@Link android.hardware.automotive.audiocontrol.AudioZone}'s info from audio control HAL. + * + *

If this used then the APIs to setup the audio zones must return a valid audio zone + * configuration for the device. + */ + DYNAMIC_AUDIO_ROUTING, + /** + * Use to indicate that audio should be managed using the core audio + * routing as setup by car audio service using the setup configuration from + * the {@Link android.hardware.automotive.audiocontrol.AudioZone}'s info from audio control HAL + * and the information contained within the configurable audio policy engine. + * + *

If this used then the APIs to setup the audio zone(s) must return valid audio zone + * configuration(s) for the device. + */ + CONFIGURABLE_AUDIO_ENGINE_ROUTING, +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/TransientFadeConfigurationEntry.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/TransientFadeConfigurationEntry.aidl new file mode 100644 index 0000000000..198423657f --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/TransientFadeConfigurationEntry.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.AudioFadeConfiguration; +import android.media.audio.common.AudioUsage; + +/** + * Encapsulates the transient audio fade configuration entry. + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable TransientFadeConfigurationEntry { + /** + * List of audio usages gainers that should be used for this configuration entry. + */ + AudioUsage[] transientUsages; + + /** + * Defines the transient fade configuration that should be used for the focus interaction with + * the usages defined in {@link #transientUsages} + */ + AudioFadeConfiguration transientFadeConfiguration; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeActivationConfiguration.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeActivationConfiguration.aidl new file mode 100644 index 0000000000..edc5f6010e --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeActivationConfiguration.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.VolumeActivationConfigurationEntry; + +/** + * Use to configure audio activiations, only used at boot up time. + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable VolumeActivationConfiguration { + /** + * Configuration name used for debugging purposes to identify config used. + * + *

Is present, it must be non-empty and unique for all volume acvitations, otherwise + * car audio service will construct one based on audio zone, configuration and volume group + * info. + */ + @nullable String name; + + /** + * List of activation configurations. + * + *

Car audio service currently only uses the first activation config on the list. + */ + List volumeActivationEntries; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeActivationConfigurationEntry.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeActivationConfigurationEntry.aidl new file mode 100644 index 0000000000..7072a2c84c --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeActivationConfigurationEntry.aidl @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.VolumeInvocationType; + +/** + * Audio activiation volume configuration entry. + * + *

The entry can defined both the minimum and maximum activation values or only one. The latter + * allows activations to occur only on the minimum value or maximum value as configured. + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable VolumeActivationConfigurationEntry { + /** + * Default maximum activation value. + */ + const int DEFAULT_MAX_ACTIVATION_VALUE = 100; + + /** + * Default minimum activation value. + */ + const int DEFAULT_MIN_ACTIVATION_VALUE = 0; + + /** + * Activation type, should be one of: + * ON_PLAYBACK_CHANGED, ON_SOURCE_CHANGED, ON_BOOT + */ + VolumeInvocationType type = VolumeInvocationType.ON_PLAYBACK_CHANGED; + + /** + * Max activation percentage between {@code DEFAULT_MIN_ACTIVATION_VALUE} to + * {@code DEFAULT_MAX_ACTIVATION_VALUE} percen. + * + *

The value should be {@code DEFAULT_MAX_ACTIVATION_VALUE} if max activation should not + * apply. + */ + int maxActivationVolumePercentage = DEFAULT_MAX_ACTIVATION_VALUE; + + /** + * Min activation percentage between {@code DEFAULT_MIN_ACTIVATION_VALUE} to + * {@code DEFAULT_MAX_ACTIVATION_VALUE} percent. + * + *

The value should be {@code DEFAULT_MIN_ACTIVATION_VALUE} if min activation should not + * apply. + */ + int minActivationVolumePercentage = DEFAULT_MIN_ACTIVATION_VALUE; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeGroupConfig.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeGroupConfig.aidl new file mode 100644 index 0000000000..7e3bc60da5 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeGroupConfig.aidl @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +import android.hardware.automotive.audiocontrol.DeviceToContextEntry; +import android.hardware.automotive.audiocontrol.VolumeActivationConfiguration; + +/** + * Encapsulates the audio volume grouping for audio zone config. + */ +@JavaDerive(equals=true, toString=true) +@VintfStability +parcelable VolumeGroupConfig { + /** + * Value indicating the volume group is not assigned an ID. + */ + const int UNASSIGNED_ID = -1; + + /** + * Audio zone group name. + * + *

Must be non-empty if using configurable audio policy engine volume management, see + * {@code AudioDeviceConfiguration#useCoreAudioVolume} for details. + */ + String name; + + /** + * Audio zone group id. + * + *

Must be set if using configurable audio policy engine volume management, can be + * {@code #UNASSIGNED_ID} otherwise. See {@code AudioDeviceConfiguration#useCoreAudioVolume} + * for details. + */ + int id = UNASSIGNED_ID; + + /** + * Entries of audio device to audio context that are managed similarly for this volume group. + */ + List carAudioRoutes; + + /** + * Optional volume activation configuration that should be used for this volume group. + */ + @nullable VolumeActivationConfiguration activationConfiguration; +} diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeInvocationType.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeInvocationType.aidl new file mode 100644 index 0000000000..0323505048 --- /dev/null +++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/VolumeInvocationType.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024 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.hardware.automotive.audiocontrol; + +/** + * Audio activiation type which can be used to activate the min/max + * volume changes. + */ +@VintfStability +@Backing(type="int") +@JavaDerive(toString=true) +enum VolumeInvocationType { + /** + * Invocation of volume group activation performed at every playback change. + */ + ON_PLAYBACK_CHANGED, + /** + * Invocation of volume group activation performed only once at playback after first playback + * for a client (app/service UID). + */ + ON_SOURCE_CHANGED, + /** + * Invocation of volume group activation in perform only at playback once after boot up. + */ + ON_BOOT, +} diff --git a/automotive/audiocontrol/aidl/default/Android.bp b/automotive/audiocontrol/aidl/default/Android.bp index fd7e167545..1c11c989b7 100644 --- a/automotive/audiocontrol/aidl/default/Android.bp +++ b/automotive/audiocontrol/aidl/default/Android.bp @@ -31,13 +31,19 @@ cc_binary { "latest_android_hardware_audio_common_ndk_shared", "latest_android_hardware_automotive_audiocontrol_ndk_shared", "powerpolicyclient_defaults", + "car.audio.configuration.xsd.default", + "car.fade.configuration.xsd.default", ], shared_libs: [ "android.hardware.audio.common@7.0-enums", - "libbase", "libbinder_ndk", "libcutils", "liblog", + "libbase", + "libxml2", + "libutils", + "android.hardware.audiocontrol.internal", + "libaudio_aidl_conversion_common_ndk", ], srcs: [ "AudioControl.cpp", diff --git a/automotive/audiocontrol/aidl/default/AudioControl.cpp b/automotive/audiocontrol/aidl/default/AudioControl.cpp index 7e7e145d37..9ae422b1cf 100644 --- a/automotive/audiocontrol/aidl/default/AudioControl.cpp +++ b/automotive/audiocontrol/aidl/default/AudioControl.cpp @@ -19,6 +19,7 @@ #include "AudioControl.h" +#include #include #include #include @@ -27,8 +28,8 @@ #include #include #include - #include + #include #include @@ -41,16 +42,18 @@ using ::android::base::EqualsIgnoreCase; using ::android::base::ParseBool; using ::android::base::ParseBoolResult; using ::android::base::ParseInt; +using ::android::hardware::audiocontrol::internal::CarAudioConfigurationXmlConverter; using ::std::shared_ptr; using ::std::string; -namespace xsd { -using namespace ::android::audio::policy::configuration::V7_0; +namespace converter { +using namespace ::android::hardware::audiocontrol::internal; } +namespace api = aidl::android::hardware::automotive::audiocontrol; +namespace xsd = ::android::audio::policy::configuration::V7_0; + namespace { -const float kLowerBound = -1.0f; -const float kUpperBound = 1.0f; bool checkCallerHasWritePermissions(int fd) { // Double check that's only called by root - it should be be blocked at debug() level, // but it doesn't hurt to make sure... @@ -62,7 +65,7 @@ bool checkCallerHasWritePermissions(int fd) { } bool isValidValue(float value) { - return (value >= kLowerBound) && (value <= kUpperBound); + return (value >= -1.0f) && (value <= 1.0f); } bool safelyParseInt(string s, int* out) { @@ -71,6 +74,53 @@ bool safelyParseInt(string s, int* out) { } return true; } + +std::string formatDump(const std::string& input) { + const char kSpacer = ' '; + std::string output; + int indentLevel = 0; + bool newLine = false; + + for (char c : input) { + switch (c) { + case '{': + if (!newLine) { + output += '\n'; + } + newLine = true; + indentLevel++; + for (int i = 0; i < indentLevel; ++i) { + output += kSpacer; + } + break; + case '}': + if (!newLine) { + output += '\n'; + } + newLine = true; + indentLevel--; + for (int i = 0; i < indentLevel; ++i) { + output += kSpacer; + } + break; + case ',': + if (!newLine) { + output += '\n'; + } + newLine = true; + for (int i = 0; i < indentLevel; ++i) { + output += kSpacer; + } + break; + default: + newLine = false; + output += c; + } + } + + return output; +} + } // namespace namespace { @@ -90,6 +140,9 @@ using ::aidl::android::media::audio::common::AudioPortMixExt; using ::aidl::android::media::audio::common::AudioProfile; using ::aidl::android::media::audio::common::PcmType; +const static std::string kAudioConfigFile = "/vendor/etc/car_audio_configuration.xml"; +const static std::string kFadeConfigFile = "/vendor/etc/car_audio_fade_configuration.xml"; + // reuse common code artifacts void fillProfile(const std::vector& channelLayouts, const std::vector& sampleRates, AudioProfile* profile) { @@ -162,6 +215,12 @@ AudioGain createGain(int32_t mode, AudioChannelLayout channelMask, int32_t minVa } } // namespace +AudioControl::AudioControl() : AudioControl(kAudioConfigFile, kFadeConfigFile) {} + +AudioControl::AudioControl(const std::string& carAudioConfig, const std::string& audioFadeConfig) + : mCarAudioConfigurationConverter(std::make_shared( + carAudioConfig, audioFadeConfig)) {} + ndk::ScopedAStatus AudioControl::registerFocusListener( const shared_ptr& in_listener) { LOG(DEBUG) << "registering focus listener"; @@ -245,14 +304,23 @@ template static inline std::string toString(const std::vector& in_values) { return std::accumulate(std::begin(in_values), std::end(in_values), std::string{}, [](const std::string& ls, const aidl_type& rs) { - return ls + (ls.empty() ? "" : ",") + rs.toString(); + return ls + (ls.empty() ? "" : ", ") + rs.toString(); }); } template static inline std::string toEnumString(const std::vector& in_values) { return std::accumulate(std::begin(in_values), std::end(in_values), std::string{}, [](const std::string& ls, const aidl_enum_type& rs) { - return ls + (ls.empty() ? "" : ",") + toString(rs); + return ls + (ls.empty() ? "" : ", ") + toString(rs); + }); +} + +template +static inline std::string toString(const std::vector>& in_values) { + return std::accumulate(std::begin(in_values), std::end(in_values), std::string{}, + [](const std::string& ls, const std::optional& rs) { + return ls + (ls.empty() ? "" : ", ") + + (rs.has_value() ? rs.value().toString() : "empty"); }); } @@ -309,6 +377,50 @@ ndk::ScopedAStatus AudioControl::clearModuleChangeCallback() { return ndk::ScopedAStatus::ok(); } +ndk::ScopedAStatus AudioControl::getAudioDeviceConfiguration( + AudioDeviceConfiguration* audioDeviceConfig) { + if (!audioDeviceConfig) { + LOG(ERROR) << __func__ << "Audio device configuration must not be null"; + return ndk::ScopedAStatus::fromStatus(STATUS_UNEXPECTED_NULL); + } + if (!mCarAudioConfigurationConverter) { + return ndk::ScopedAStatus::ok(); + } + const auto& innerDeviceConfig = mCarAudioConfigurationConverter->getAudioDeviceConfiguration(); + audioDeviceConfig->routingConfig = innerDeviceConfig.routingConfig; + audioDeviceConfig->useCoreAudioVolume = innerDeviceConfig.useCoreAudioVolume; + audioDeviceConfig->useCarVolumeGroupMuting = innerDeviceConfig.useCarVolumeGroupMuting; + audioDeviceConfig->useHalDuckingSignals = innerDeviceConfig.useHalDuckingSignals; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus AudioControl::getOutputMirroringDevices( + std::vector* mirroringDevices) { + if (!mirroringDevices) { + LOG(ERROR) << __func__ << "Mirroring devices must not be null"; + return ndk::ScopedAStatus::fromStatus(STATUS_UNEXPECTED_NULL); + } + if (!mCarAudioConfigurationConverter || !mCarAudioConfigurationConverter->getErrors().empty()) { + return ndk::ScopedAStatus::ok(); + } + const auto& innerDevice = mCarAudioConfigurationConverter->getOutputMirroringDevices(); + mirroringDevices->insert(mirroringDevices->end(), innerDevice.begin(), innerDevice.end()); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus AudioControl::getCarAudioZones(std::vector* audioZones) { + if (!audioZones) { + LOG(ERROR) << __func__ << "Audio zones must not be null"; + return ndk::ScopedAStatus::fromStatus(STATUS_UNEXPECTED_NULL); + } + if (!mCarAudioConfigurationConverter || !mCarAudioConfigurationConverter->getErrors().empty()) { + return ndk::ScopedAStatus::ok(); + } + const auto& innerZones = mCarAudioConfigurationConverter->getAudioZones(); + audioZones->insert(audioZones->end(), innerZones.begin(), innerZones.end()); + return ndk::ScopedAStatus::ok(); +} + binder_status_t AudioControl::dump(int fd, const char** args, uint32_t numArgs) { if (numArgs == 0) { return dumpsys(fd); @@ -342,6 +454,25 @@ binder_status_t AudioControl::dumpsys(int fd) { dprintf(fd, "Focus listener registered\n"); } dprintf(fd, "AudioGainCallback %sregistered\n", (mAudioGainCallback == nullptr ? "NOT " : "")); + + AudioDeviceConfiguration configuration; + if (getAudioDeviceConfiguration(&configuration).isOk()) { + dprintf(fd, "AudioDeviceConfiguration: %s\n", configuration.toString().c_str()); + } + std::vector audioZones; + if (getCarAudioZones(&audioZones).isOk()) { + dprintf(fd, "Audio zones count: %zu\n", audioZones.size()); + for (const auto& zone : audioZones) { + dprintf(fd, "AudioZone: %s\n", formatDump(zone.toString()).c_str()); + } + } + std::vector mirroringDevices; + if (getOutputMirroringDevices(&mirroringDevices).isOk()) { + dprintf(fd, "Mirroring devices count: %zu\n", mirroringDevices.size()); + for (const auto& device : mirroringDevices) { + dprintf(fd, "Mirroring device: %s\n", formatDump(device.toString()).c_str()); + } + } return STATUS_OK; } diff --git a/automotive/audiocontrol/aidl/default/AudioControl.h b/automotive/audiocontrol/aidl/default/AudioControl.h index 7eca446f12..0425570e2b 100644 --- a/automotive/audiocontrol/aidl/default/AudioControl.h +++ b/automotive/audiocontrol/aidl/default/AudioControl.h @@ -35,13 +35,17 @@ #include #include +#include "converter/include/CarAudioConfigurationXmlConverter.h" + namespace aidl::android::hardware::automotive::audiocontrol { -namespace audiohalcommon = ::aidl::android::hardware::audio::common; namespace audiomediacommon = ::aidl::android::media::audio::common; +namespace audiohalcommon = ::aidl::android::hardware::audio::common; class AudioControl : public BnAudioControl { public: + AudioControl(); + AudioControl(const std::string& carAudioConfig, const std::string& audioFadeConfig); ndk::ScopedAStatus onAudioFocusChange(const std::string& in_usage, int32_t in_zoneId, AudioFocusChange in_focusChange) override; ndk::ScopedAStatus onDevicesToDuckChange( @@ -63,6 +67,11 @@ class AudioControl : public BnAudioControl { ndk::ScopedAStatus setModuleChangeCallback( const std::shared_ptr& in_callback) override; ndk::ScopedAStatus clearModuleChangeCallback() override; + ndk::ScopedAStatus getAudioDeviceConfiguration( + AudioDeviceConfiguration* audioDeviceConfig) override; + ndk::ScopedAStatus getOutputMirroringDevices( + std::vector<::aidl::android::media::audio::common::AudioPort>* mirrorDevices) override; + ndk::ScopedAStatus getCarAudioZones(std::vector* audioZones) override; binder_status_t dump(int fd, const char** args, uint32_t numArgs) override; @@ -81,6 +90,9 @@ class AudioControl : public BnAudioControl { std::shared_ptr mModuleChangeCallback = nullptr; + std::shared_ptr<::android::hardware::audiocontrol::internal::CarAudioConfigurationXmlConverter> + mCarAudioConfigurationConverter = nullptr; + binder_status_t cmdHelp(int fd) const; binder_status_t cmdRequestFocus(int fd, const char** args, uint32_t numArgs); binder_status_t cmdAbandonFocus(int fd, const char** args, uint32_t numArgs); diff --git a/automotive/audiocontrol/aidl/default/audiocontrol-default.xml b/automotive/audiocontrol/aidl/default/audiocontrol-default.xml index bcb5669f38..ffef7fc6dd 100644 --- a/automotive/audiocontrol/aidl/default/audiocontrol-default.xml +++ b/automotive/audiocontrol/aidl/default/audiocontrol-default.xml @@ -1,7 +1,7 @@ android.hardware.automotive.audiocontrol - 4 + 5 IAudioControl/default diff --git a/automotive/audiocontrol/aidl/default/converter/Android.bp b/automotive/audiocontrol/aidl/default/converter/Android.bp new file mode 100644 index 0000000000..c00afa2dbf --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/Android.bp @@ -0,0 +1,56 @@ +// Copyright (C) 2024 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library { + name: "android.hardware.audiocontrol.internal", + vendor: true, + srcs: [ + "src/CarAudioConfigurationXmlConverter.cpp", + "src/CarAudioConfigurationUtils.cpp", + ], + export_include_dirs: [ + "include", + ], + defaults: [ + "latest_android_hardware_audio_common_ndk_static", + "latest_android_hardware_automotive_audiocontrol_ndk_shared", + "car.audio.configuration.xsd.default", + "car.fade.configuration.xsd.default", + "aidlaudioservice_defaults", + "latest_android_media_audio_common_types_ndk_static", + ], + shared_libs: [ + "libbase", + "libutils", + "libmedia_helper", + "car.audio.configuration.xsd.default", + "car.fade.configuration.xsd.default", + "liblog", + ], + static_libs: [ + "libaudio_aidl_conversion_common_ndk_cpp", + ], + header_libs: [ + "libaudio_system_headers", + ], +} diff --git a/automotive/audiocontrol/aidl/default/converter/include/CarAudioConfigurationUtils.h b/automotive/audiocontrol/aidl/default/converter/include/CarAudioConfigurationUtils.h new file mode 100644 index 0000000000..29fec0b1f1 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/include/CarAudioConfigurationUtils.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 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. + */ + +#ifndef ANDROID_HARDWARE_AUDIOCONTROL_INTERNAL_CONFIGURATION_UTILS_H +#define ANDROID_HARDWARE_AUDIOCONTROL_INTERNAL_CONFIGURATION_UTILS_H + +#include + +#include +#include + +namespace android { +namespace hardware { +namespace audiocontrol { +namespace internal { + +::aidl::android::hardware::automotive::audiocontrol::AudioZoneContext getDefaultCarAudioContext(); + +} // namespace internal +} // namespace audiocontrol +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_AUDIOCONTROL_INTERNAL_CONFIGURATION_UTILS_H diff --git a/automotive/audiocontrol/aidl/default/converter/include/CarAudioConfigurationXmlConverter.h b/automotive/audiocontrol/aidl/default/converter/include/CarAudioConfigurationXmlConverter.h new file mode 100644 index 0000000000..ed29172cf5 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/include/CarAudioConfigurationXmlConverter.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2024 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. + */ + +#ifndef MAIN8_CARAUDIOCONFIGURATIONXMLCONVERTER_H +#define MAIN8_CARAUDIOCONFIGURATIONXMLCONVERTER_H + +#include + +#include "../include/CarAudioConfigurationUtils.h" + +#include +#include +#include + +namespace android::hardware::automotive::audiocontrol { +class CarAudioConfigurationType; +} + +namespace android { +namespace hardware { +namespace audiocontrol { +namespace internal { + +class CarAudioConfigurationXmlConverter { + public: + explicit CarAudioConfigurationXmlConverter(const std::string& audioConfigFile, + const std::string& fadeConfigFile) + : mAudioConfigFile(audioConfigFile), mFadeConfigFile(fadeConfigFile) { + init(); + } + + ::aidl::android::hardware::automotive::audiocontrol::AudioDeviceConfiguration + getAudioDeviceConfiguration() const; + + std::vector<::aidl::android::hardware::automotive::audiocontrol::AudioZone> getAudioZones() + const; + std::vector<::aidl::android::media::audio::common::AudioPort> getOutputMirroringDevices() const; + + const std::string getErrors() const { return mParseErrors; } + + private: + void init(); + void initNonDynamicRouting(); + void initFadeConfigurations(); + void initAudioDeviceConfiguration( + const ::android::hardware::automotive::audiocontrol::CarAudioConfigurationType& + carAudioConfigurationType); + void initCarAudioConfigurations( + const ::android::hardware::automotive::audiocontrol::CarAudioConfigurationType& + carAudioConfigurationType); + void parseAudioDeviceConfigurations( + const ::android::hardware::automotive::audiocontrol::CarAudioConfigurationType& + carAudioConfigurationType); + + const std::string mAudioConfigFile; + const std::string mFadeConfigFile; + ::aidl::android::hardware::automotive::audiocontrol::AudioDeviceConfiguration + mAudioDeviceConfiguration; + std::optional<::aidl::android::hardware::automotive::audiocontrol::AudioZoneContext> + mAudioZoneContext; + std::vector<::aidl::android::hardware::automotive::audiocontrol::AudioZone> mAudioZones; + std::vector<::aidl::android::media::audio::common::AudioPort> mOutputMirroringDevices; + std::string mParseErrors; + std::unordered_map + mFadeConfigurations; +}; + +} // namespace internal +} // namespace audiocontrol +} // namespace hardware +} // namespace android + +#endif // MAIN8_CARAUDIOCONFIGURATIONXMLCONVERTER_H diff --git a/automotive/audiocontrol/aidl/default/converter/src/CarAudioConfigurationUtils.cpp b/automotive/audiocontrol/aidl/default/converter/src/CarAudioConfigurationUtils.cpp new file mode 100644 index 0000000000..e2f81915c4 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/src/CarAudioConfigurationUtils.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2024 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. + */ + +#include + +#include "../include/CarAudioConfigurationUtils.h" + +#include +#include + +#include +#include + +using ::aidl::android::hardware::automotive::audiocontrol::AudioZoneContext; +using ::aidl::android::hardware::automotive::audiocontrol::AudioZoneContextInfo; + +using aidl::android::media::audio::common::AudioAttributes; +using aidl::android::media::audio::common::AudioUsage; +using aidl::android::media::audio::common::AudioUsage::ALARM; +using aidl::android::media::audio::common::AudioUsage::ANNOUNCEMENT; +using aidl::android::media::audio::common::AudioUsage::ASSISTANCE_ACCESSIBILITY; +using aidl::android::media::audio::common::AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE; +using aidl::android::media::audio::common::AudioUsage::ASSISTANCE_SONIFICATION; +using aidl::android::media::audio::common::AudioUsage::ASSISTANT; +using aidl::android::media::audio::common::AudioUsage::CALL_ASSISTANT; +using aidl::android::media::audio::common::AudioUsage::EMERGENCY; +using aidl::android::media::audio::common::AudioUsage::GAME; +using aidl::android::media::audio::common::AudioUsage::MEDIA; +using aidl::android::media::audio::common::AudioUsage::NOTIFICATION; +using aidl::android::media::audio::common::AudioUsage::NOTIFICATION_EVENT; +using aidl::android::media::audio::common::AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE; +using aidl::android::media::audio::common::AudioUsage::SAFETY; +using aidl::android::media::audio::common::AudioUsage::UNKNOWN; +using aidl::android::media::audio::common::AudioUsage::VEHICLE_STATUS; +using aidl::android::media::audio::common::AudioUsage::VOICE_COMMUNICATION; +using aidl::android::media::audio::common::AudioUsage::VOICE_COMMUNICATION_SIGNALLING; + +namespace android { +namespace hardware { +namespace audiocontrol { +namespace internal { + +std::vector createAudioAttributes(const std::vector& usages) { + std::vector audioAttributes; + for (const auto& usage : usages) { + AudioAttributes attributes; + attributes.usage = usage; + audioAttributes.push_back(attributes); + } + return audioAttributes; +} + +AudioZoneContextInfo createAudioZoneContextInfo(const std::string& name, int id, + const std::vector& usages) { + AudioZoneContextInfo info; + info.name = name; + info.id = id; + info.audioAttributes = createAudioAttributes(usages); + return info; +} + +AudioZoneContext createAudioZoneContextInfo(const std::vector& info) { + AudioZoneContext context; + context.audioContextInfos.insert(context.audioContextInfos.begin(), info.begin(), info.end()); + return context; +} + +AudioZoneContext getDefaultCarAudioContext() { + // For legacy reasons, context names are lower case here. + static const AudioZoneContext kDefaultContext = createAudioZoneContextInfo( + {createAudioZoneContextInfo("music", 1, {UNKNOWN, MEDIA, GAME}), + createAudioZoneContextInfo("navigation", 2, {ASSISTANCE_NAVIGATION_GUIDANCE}), + createAudioZoneContextInfo("voice_command", 3, {ASSISTANCE_ACCESSIBILITY, ASSISTANT}), + createAudioZoneContextInfo("call_ring", 4, {NOTIFICATION_TELEPHONY_RINGTONE}), + createAudioZoneContextInfo( + "call", 5, + {VOICE_COMMUNICATION, CALL_ASSISTANT, VOICE_COMMUNICATION_SIGNALLING}), + createAudioZoneContextInfo("alarm", 6, {ALARM}), + createAudioZoneContextInfo("notification", 7, {NOTIFICATION, NOTIFICATION_EVENT}), + createAudioZoneContextInfo("system_sound", 8, {ASSISTANCE_SONIFICATION}), + createAudioZoneContextInfo("emergency", 9, {EMERGENCY}), + createAudioZoneContextInfo("safety", 10, {SAFETY}), + createAudioZoneContextInfo("vehicle_status", 11, {VEHICLE_STATUS}), + createAudioZoneContextInfo("announcement", 12, {ANNOUNCEMENT})}); + return kDefaultContext; +} + +} // namespace internal +} // namespace audiocontrol +} // namespace hardware +} // namespace android diff --git a/automotive/audiocontrol/aidl/default/converter/src/CarAudioConfigurationXmlConverter.cpp b/automotive/audiocontrol/aidl/default/converter/src/CarAudioConfigurationXmlConverter.cpp new file mode 100644 index 0000000000..d43b595cb9 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/src/CarAudioConfigurationXmlConverter.cpp @@ -0,0 +1,1134 @@ +/* + * Copyright (C) 2024 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. + */ + +#define LOG_TAG "AudioControl::XSD_Converter" + +#define LOG_NDEBUG 0 +#include + +#include "../include/CarAudioConfigurationXmlConverter.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace audiocontrol { +namespace internal { +namespace xsd = ::android::hardware::automotive::audiocontrol; +namespace fade = android::hardware::automotive::audiocontrol::fade; +namespace api = ::aidl::android::hardware::automotive::audiocontrol; + +using aidl::android::media::audio::common::AudioAttributes; +using aidl::android::media::audio::common::AudioContentType; +using aidl::android::media::audio::common::AudioDevice; +using aidl::android::media::audio::common::AudioDeviceAddress; +using aidl::android::media::audio::common::AudioDeviceDescription; +using aidl::android::media::audio::common::AudioDeviceType; +using aidl::android::media::audio::common::AudioPort; +using aidl::android::media::audio::common::AudioPortDeviceExt; +using aidl::android::media::audio::common::AudioPortExt; +using aidl::android::media::audio::common::AudioUsage; + +using namespace ::android::base; + +namespace { + +static const std::string kUseCoreRouting{"useCoreAudioRouting"}; +static const std::string kUseCoreVolume{"useCoreAudioVolume"}; +static const std::string kUseHalDuckingSignals{"useHalDuckingSignals"}; +static const std::string kUseCarVolumeGroupMuting{"useCarVolumeGroupMuting"}; + +static constexpr char kOutBusType[] = "AUDIO_DEVICE_OUT_BUS"; +static constexpr char kInBusType[] = "AUDIO_DEVICE_IN_BUS"; + +using ActivationMap = std::unordered_map; +using FadeConfigurationMap = std::unordered_map< + std::string, ::aidl::android::hardware::automotive::audiocontrol::AudioFadeConfiguration>; + +inline bool isReadableConfigurationFile(const std::string& filePath) { + return !filePath.empty() && filePath.ends_with(".xml") && (access(filePath.c_str(), R_OK) == 0); +} + +inline bool parseBoolOrDefaultIfFailed(const std::string& value, bool defaultValue) { + ParseBoolResult results = ParseBool(value); + return results == ParseBoolResult::kError ? defaultValue : results == ParseBoolResult::kTrue; +} + +void parseCoreRoutingInfo(const std::string& value, api::AudioDeviceConfiguration& config) { + if (!parseBoolOrDefaultIfFailed(value, /* defaultValue= */ false)) { + return; + } + config.routingConfig = api::RoutingDeviceConfiguration::CONFIGURABLE_AUDIO_ENGINE_ROUTING; +} + +void parseCoreVolumeInfo(const std::string& value, api::AudioDeviceConfiguration& config) { + config.useCoreAudioVolume = parseBoolOrDefaultIfFailed(value, config.useCoreAudioVolume); +} + +void parseHalDuckingInfo(const std::string& value, api::AudioDeviceConfiguration& config) { + config.useHalDuckingSignals = parseBoolOrDefaultIfFailed(value, config.useHalDuckingSignals); +} + +void parseHalMutingInfo(const std::string& value, api::AudioDeviceConfiguration& config) { + config.useCarVolumeGroupMuting = + parseBoolOrDefaultIfFailed(value, config.useCarVolumeGroupMuting); +} + +bool parseAudioAttributeUsageString(const std::string& usageString, AudioUsage& usage) { + audio_usage_t legacyUsage; + if (!::android::UsageTypeConverter::fromString(usageString, legacyUsage)) { + LOG(ERROR) << __func__ << " could not parse usage from string " << usageString; + return false; + } + ConversionResult result = + ::aidl::android::legacy2aidl_audio_usage_t_AudioUsage(legacyUsage); + if (!result.ok()) { + LOG(ERROR) << __func__ << " could not parse usage legacy type " << legacyUsage; + return false; + } + usage = result.value(); + return true; +} + +bool parseAudioAttributeUsage(const xsd::UsageType& usageType, AudioAttributes& attributes) { + if (!usageType.hasValue()) { + LOG(ERROR) << __func__ << " usage does not have value"; + return false; + } + if (!parseAudioAttributeUsageString(xsd::toString(usageType.getValue()), attributes.usage)) { + return false; + } + return true; +} + +bool parseAudioAttributesUsages(const std::vector& usages, + std::vector& audioAttributes) { + for (const auto& xsdUsage : usages) { + AudioAttributes attributes; + if (!parseAudioAttributeUsage(xsdUsage, attributes)) { + return false; + } + audioAttributes.push_back(attributes); + } + return true; +} + +bool parseContentTypeString(const std::string& typeString, AudioContentType& type) { + audio_content_type_t legacyContentType; + if (!::android::AudioContentTypeConverter::fromString(typeString, legacyContentType)) { + LOG(ERROR) << __func__ << " could not parse content type from string " << typeString; + return false; + } + ConversionResult result = + ::aidl::android::legacy2aidl_audio_content_type_t_AudioContentType(legacyContentType); + if (!result.ok()) { + LOG(ERROR) << __func__ << " could not convert legacy content type " << legacyContentType; + return false; + } + type = result.value(); + return true; +} + +bool parseAudioAttribute(const xsd::AttributesType& attributesType, AudioAttributes& attributes) { + if (attributesType.hasUsage()) { + if (!parseAudioAttributeUsageString(xsd::toString(attributesType.getUsage()), + attributes.usage)) { + LOG(ERROR) << __func__ << " could not parse audio usage: " + << xsd::toString(attributesType.getUsage()); + return false; + } + } + + if (attributesType.hasContentType()) { + if (!parseContentTypeString(xsd::toString(attributesType.getContentType()), + attributes.contentType)) { + return false; + } + } + + if (attributesType.hasTags()) { + attributes.tags.push_back(attributesType.getTags()); + } + return true; +} + +bool parseAudioAttributes(const std::vector& xsdAttributes, + std::vector& audioAttributes) { + for (const auto& xsdAttribute : xsdAttributes) { + AudioAttributes attribute; + if (!parseAudioAttribute(xsdAttribute, attribute)) { + return false; + } + audioAttributes.push_back(attribute); + } + return true; +} + +bool parseAudioAttributes(const xsd::AudioAttributesUsagesType& xsdAttributeOrUsages, + std::vector& audioAttributes) { + if (xsdAttributeOrUsages.hasUsage_optional()) { + if (!parseAudioAttributesUsages(xsdAttributeOrUsages.getUsage_optional(), + audioAttributes)) { + LOG(ERROR) << __func__ << " could not parse audio usages"; + return false; + } + } + + if (xsdAttributeOrUsages.hasAudioAttribute_optional()) { + if (!parseAudioAttributes(xsdAttributeOrUsages.getAudioAttribute_optional(), + audioAttributes)) { + LOG(ERROR) << __func__ << " could not parse audio attributes"; + return false; + } + } + return true; +} + +bool parseAudioContext(const xsd::OemContextType& xsdContextInfo, + api::AudioZoneContextInfo& contextInfo) { + if (!xsdContextInfo.hasName()) { + LOG(ERROR) << __func__ << " Audio context info missing name"; + return false; + } + + contextInfo.name = xsdContextInfo.getName(); + + if (xsdContextInfo.hasId()) { + ParseInt(xsdContextInfo.getId().c_str(), &contextInfo.id); + } + + if (xsdContextInfo.hasAudioAttributes()) { + if (!parseAudioAttributes(*xsdContextInfo.getFirstAudioAttributes(), + contextInfo.audioAttributes)) { + return false; + } + } + + return true; +} + +bool parseAudioContexts(const xsd::OemContextsType* xsdContexts, api::AudioZoneContext& context) { + if (!xsdContexts->hasOemContext()) { + return false; + } + const auto xsdContextInfos = xsdContexts->getOemContext(); + for (const auto& xsdContextInfo : xsdContextInfos) { + api::AudioZoneContextInfo info; + if (!parseAudioContext(xsdContextInfo, info)) { + continue; + } + context.audioContextInfos.push_back(info); + } + return true; +} + +bool createAudioDevice(const std::string& address, const std::string& type, AudioPort& port) { + audio_devices_t legacyDeviceType = AUDIO_DEVICE_NONE; + ::android::DeviceConverter::fromString(type, legacyDeviceType); + std::string tempString; + ::android::DeviceConverter::toString(legacyDeviceType, tempString); + ConversionResult result = + ::aidl::android::legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyDeviceType); + if (legacyDeviceType == AUDIO_DEVICE_NONE || !result.ok()) { + LOG(ERROR) << __func__ << " could not parse legacy device type"; + return false; + } + AudioDevice device; + if (!address.empty()) { + device.address = AudioDeviceAddress::make(address); + } + device.type = result.value(); + + port.ext = AudioPortExt::make(device); + + return true; +} + +std::string outTypeToOutAudioDevice(const std::string& device) { + const static std::unordered_map typeToOutDevice{ + {"TYPE_BUILTIN_SPEAKER", "AUDIO_DEVICE_OUT_SPEAKER"}, + {"TYPE_WIRED_HEADSET", "AUDIO_DEVICE_OUT_WIRED_HEADSET"}, + {"TYPE_WIRED_HEADPHONES", "AUDIO_DEVICE_OUT_WIRED_HEADPHONE,"}, + {"TYPE_BLUETOOTH_A2DP", "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP"}, + {"TYPE_HDMI", "AUDIO_DEVICE_OUT_HDMI"}, + {"TYPE_USB_ACCESSORY", "AUDIO_DEVICE_OUT_USB_ACCESSORY"}, + {"TYPE_USB_DEVICE", "AUDIO_DEVICE_OUT_USB_DEVICE,"}, + {"TYPE_USB_HEADSET", "AUDIO_DEVICE_OUT_USB_HEADSET"}, + {"TYPE_AUX_LINE", "AUDIO_DEVICE_OUT_AUX_LINE"}, + {"TYPE_BUS", "AUDIO_DEVICE_OUT_BUS"}, + {"TYPE_BLE_HEADSET", "AUDIO_DEVICE_OUT_BLE_HEADSET"}, + {"TYPE_BLE_SPEAKER", "AUDIO_DEVICE_OUT_BLE_SPEAKER"}, + {"TYPE_BLE_BROADCAST", "AUDIO_DEVICE_OUT_BLE_BROADCAST"}, + }; + + if (!device.starts_with("TYPE_")) { + return device; + } + + const auto it = typeToOutDevice.find(device); + return it != typeToOutDevice.end() ? it->second : device; +} + +bool parseAudioDeviceToContexts(const xsd::DeviceRoutesType& deviceRoutesType, + api::DeviceToContextEntry& route) { + std::string address = deviceRoutesType.hasAddress() ? deviceRoutesType.getAddress() : ""; + // Default type is bus for schema + std::string type = outTypeToOutAudioDevice(deviceRoutesType.hasType() + ? xsd::toString(deviceRoutesType.getType()) + : std::string(kOutBusType)); + // Address must be present for audio device bus + if (address.empty() && type == std::string(kOutBusType)) { + LOG(ERROR) << __func__ << " empty device address for bus device type"; + return false; + } + if (!createAudioDevice(address, type, route.device)) { + return false; + } + + if (!deviceRoutesType.hasContext()) { + LOG(ERROR) << __func__ << " empty device context mapping"; + return false; + } + + for (const auto& xsdContext : deviceRoutesType.getContext()) { + if (!xsdContext.hasContext()) { + LOG(ERROR) << __func__ << " audio device route missing context info"; + return false; + } + route.contextNames.push_back(xsdContext.getContext()); + } + + return true; +} + +bool parseAudioDeviceRoutes(const std::vector deviceRoutesTypes, + std::vector& routes) { + for (const auto& deviceRouteType : deviceRoutesTypes) { + api::DeviceToContextEntry entry; + if (!parseAudioDeviceToContexts(deviceRouteType, entry)) { + return false; + } + routes.push_back(entry); + } + return true; +} + +void parseVolumeGroupActivation(const std::string& activationConfigName, + const ActivationMap& activations, + api::VolumeGroupConfig& volumeGroup) { + if (activationConfigName.empty()) { + LOG(ERROR) << __func__ << " Volume group " << volumeGroup.name + << " has empty volume group activation name"; + return; + } + const auto& it = activations.find(activationConfigName); + if (it == activations.end()) { + LOG(ERROR) << __func__ << " Volume group " << volumeGroup.name + << " has non-existing volume group activation name " << activationConfigName; + return; + } + volumeGroup.activationConfiguration = it->second; +} + +bool parseVolumeGroup(const xsd::VolumeGroupType& volumeGroupType, const ActivationMap& activations, + api::VolumeGroupConfig& volumeGroup) { + if (!volumeGroupType.hasDevice()) { + LOG(ERROR) << __func__ << " no device found"; + return false; + } + + if (volumeGroupType.hasName()) { + volumeGroup.name = volumeGroupType.getName(); + } + + if (!parseAudioDeviceRoutes(volumeGroupType.getDevice(), volumeGroup.carAudioRoutes)) { + return false; + } + + if (volumeGroupType.hasActivationConfig()) { + parseVolumeGroupActivation(volumeGroupType.getActivationConfig(), activations, volumeGroup); + } + + return true; +} + +bool parseVolumeGroups(const xsd::VolumeGroupsType* volumeGroupsType, + const ActivationMap& activations, + std::vector& volumeGroups) { + if (!volumeGroupsType->hasGroup()) { + LOG(ERROR) << __func__ << " no volume groups found"; + return false; + } + for (const auto& volumeGroupType : volumeGroupsType->getGroup()) { + api::VolumeGroupConfig volumeGroup; + if (!parseVolumeGroup(volumeGroupType, activations, volumeGroup)) { + return false; + } + volumeGroups.push_back(volumeGroup); + } + return true; +} + +void parseFadeConfigurationUsages(const xsd::ApplyFadeConfigType& fadeConfigType, + std::vector& usages) { + if (!fadeConfigType.hasAudioAttributes()) { + return; + } + const xsd::AudioAttributeUsagesType* attributesOrUsagesType = + fadeConfigType.getFirstAudioAttributes(); + if (!attributesOrUsagesType->hasUsage()) { + return; + } + for (const auto& usageType : attributesOrUsagesType->getUsage()) { + AudioUsage usage; + if (!usageType.hasValue() || + !parseAudioAttributeUsageString(xsd::toString(usageType.getValue()), usage)) { + continue; + } + usages.push_back(usage); + } +} + +void parseZoneFadeConfiguration(const xsd::ApplyFadeConfigType& fadeConfigType, + const FadeConfigurationMap& fadeConfigurations, + api::AudioZoneFadeConfiguration& zoneFadeConfiguration) { + if (!fadeConfigType.hasName()) { + LOG(ERROR) << __func__ << " Found a fade config without a name, skipping assignment"; + return; + } + + const auto it = fadeConfigurations.find(fadeConfigType.getName()); + if (it == fadeConfigurations.end()) { + LOG(ERROR) << __func__ << " Config name " << fadeConfigType.getName() + << " not found, skipping assignment"; + return; + } + // Return for default since default configurations do not have any audio attributes mapping + if (fadeConfigType.hasIsDefault()) { + zoneFadeConfiguration.defaultConfiguration = it->second; + return; + } + + api::TransientFadeConfigurationEntry entry; + entry.transientFadeConfiguration = it->second; + parseFadeConfigurationUsages(fadeConfigType, entry.transientUsages); + zoneFadeConfiguration.transientConfiguration.push_back(entry); +} + +void parseZoneFadeConfigurations(const xsd::ZoneConfigType& zoneConfigType, + const FadeConfigurationMap& fadeConfigurations, + std::optional& zoneFadeConfig) { + if (!zoneConfigType.hasApplyFadeConfigs()) { + return; + } + const xsd::ApplyFadeConfigsType* applyFadeConfigs = zoneConfigType.getFirstApplyFadeConfigs(); + if (!applyFadeConfigs->hasFadeConfig()) { + return; + } + api::AudioZoneFadeConfiguration zoneFadeConfiguration; + for (const auto& fadeConfigType : applyFadeConfigs->getFadeConfig()) { + parseZoneFadeConfiguration(fadeConfigType, fadeConfigurations, zoneFadeConfiguration); + } + zoneFadeConfig = zoneFadeConfiguration; +} + +bool parseAudioZoneConfig(const xsd::ZoneConfigType& zoneConfigType, + const ActivationMap& activations, + const FadeConfigurationMap& fadeConfigurations, + api::AudioZoneConfig& config) { + if (!zoneConfigType.hasVolumeGroups()) { + LOG(ERROR) << __func__ << " no volume groups found"; + return false; + } + + if (zoneConfigType.hasName()) { + config.name = zoneConfigType.getName(); + } + if (!parseVolumeGroups(zoneConfigType.getFirstVolumeGroups(), activations, + config.volumeGroups)) { + return false; + } + + parseZoneFadeConfigurations(zoneConfigType, fadeConfigurations, config.fadeConfiguration); + + config.isDefault = zoneConfigType.hasIsDefault() && zoneConfigType.getIsDefault(); + + return true; +} + +bool parseAudioZoneConfigs(const xsd::ZoneConfigsType* zoneConfigsType, + const ActivationMap& activations, + const FadeConfigurationMap& fadeConfigurations, + std::vector& configs) { + if (!zoneConfigsType->hasZoneConfig()) { + LOG(ERROR) << __func__ << " No zone configs found"; + return false; + } + + if (zoneConfigsType->getZoneConfig().empty()) { + LOG(ERROR) << __func__ << " Empty list of audio configurations"; + return false; + } + + for (const auto& zoneConfigType : zoneConfigsType->getZoneConfig()) { + api::AudioZoneConfig config; + if (!parseAudioZoneConfig(zoneConfigType, activations, fadeConfigurations, config)) { + return false; + } + configs.push_back(config); + } + + return true; +} + +bool parseInputDevice(const xsd::InputDeviceType& xsdInputDevice, AudioPort& inputDevice) { + // Input device must have a non-empty address + if (!xsdInputDevice.hasAddress() || xsdInputDevice.getAddress().empty()) { + LOG(ERROR) << __func__ << " missing device address"; + return false; + } + // By default a device is bus type, unless specified + std::string inputDeviceType = + xsdInputDevice.hasType() ? xsd::toString(xsdInputDevice.getType()) : kInBusType; + if (!createAudioDevice(xsdInputDevice.getAddress(), inputDeviceType, inputDevice)) { + return false; + } + return true; +} + +void parseInputDevices(const xsd::InputDevicesType* xsdInputDevices, + std::vector& inputDevices) { + if (!xsdInputDevices->hasInputDevice()) { + return; + } + for (const auto& xsdInputDevice : xsdInputDevices->getInputDevice()) { + AudioPort inputDevice; + if (!parseInputDevice(xsdInputDevice, inputDevice)) { + continue; + } + inputDevices.push_back(inputDevice); + } +} + +bool parseAudioZone(const xsd::ZoneType& zone, const ActivationMap& activations, + const FadeConfigurationMap& fadeConfigurations, api::AudioZone& audioZone) { + if (zone.hasName()) { + audioZone.name = zone.getName(); + } + + if (zone.hasOccupantZoneId()) { + ParseInt(zone.getOccupantZoneId().c_str(), &audioZone.occupantZoneId); + } + + if (zone.hasInputDevices()) { + parseInputDevices(zone.getFirstInputDevices(), audioZone.inputAudioDevices); + } + + // Audio zone id is required + if (!zone.hasAudioZoneId()) { + LOG(ERROR) << __func__ << " Audio zone id required for each zone"; + return false; + } + + bool isPrimary = zone.hasIsPrimary() && zone.getIsPrimary(); + + if (isPrimary) { + audioZone.id = api::AudioZone::PRIMARY_AUDIO_ZONE; + } + + // ID not required in XML for primary zone + if (!ParseInt(zone.getAudioZoneId().c_str(), &audioZone.id) && !isPrimary) { + LOG(ERROR) << __func__ + << " Could not parse audio zone id, must be a non-negative integer or isPrimary " + "must be specify as true for primary zone"; + return false; + } + + if (isPrimary && audioZone.id != api::AudioZone::PRIMARY_AUDIO_ZONE) { + LOG(ERROR) << __func__ << " Audio zone is primary but has zone id " + << std::to_string(audioZone.id) << " instead of primary zone id " + << std::to_string(api::AudioZone::PRIMARY_AUDIO_ZONE); + return false; + } + + if (!zone.hasZoneConfigs()) { + LOG(ERROR) << __func__ << " Missing audio zone configs for audio zone id " << audioZone.id; + return false; + } + if (!parseAudioZoneConfigs(zone.getFirstZoneConfigs(), activations, fadeConfigurations, + audioZone.audioZoneConfigs)) { + LOG(ERROR) << __func__ << " Could not parse zone configs for audio zone id " << audioZone.id + << ", name " << audioZone.name; + return false; + } + + return true; +} + +std::string parseAudioZones(const xsd::ZonesType* zones, const api::AudioZoneContext& context, + const ActivationMap& activations, + const FadeConfigurationMap& fadeConfigurations, + std::vector& audioZones) { + if (!zones->hasZone()) { + return "audio zones are missing"; + } + const auto& xsdZones = zones->getZone(); + for (const auto& xsdZone : xsdZones) { + api::AudioZone audioZone; + audioZone.audioZoneContext = context; + if (!parseAudioZone(xsdZone, activations, fadeConfigurations, audioZone)) { + continue; + } + audioZones.push_back(audioZone); + } + return ""; +} + +std::unordered_map> +getConfigsParsers() { + static const std::unordered_map< + std::string, std::function> + parsers{ + {kUseCoreRouting, parseCoreRoutingInfo}, + {kUseCoreVolume, parseCoreVolumeInfo}, + {kUseHalDuckingSignals, parseHalDuckingInfo}, + {kUseCarVolumeGroupMuting, parseHalMutingInfo}, + }; + + return parsers; +} + +bool parseVolumeActivationType(const xsd::ActivationType& xsdType, + api::VolumeInvocationType& activationType) { + switch (xsdType) { + case xsd::ActivationType::onBoot: + activationType = api::VolumeInvocationType::ON_BOOT; + break; + case xsd::ActivationType::onSourceChanged: + activationType = api::VolumeInvocationType::ON_SOURCE_CHANGED; + break; + case xsd::ActivationType::onPlaybackChanged: + activationType = api::VolumeInvocationType::ON_PLAYBACK_CHANGED; + break; + default: + return false; + } + return true; +} + +bool parseVolumeGroupActivationEntry(const xsd::ActivationVolumeConfigEntryType& xsdEntry, + api::VolumeActivationConfigurationEntry& entry) { + if (!xsdEntry.hasInvocationType()) { + LOG(ERROR) << __func__ << " Activation config entry missing invocation type"; + return false; + } + + if (!parseVolumeActivationType(xsdEntry.getInvocationType(), entry.type)) { + LOG(ERROR) << __func__ << " Could not parse configuration entry type"; + return false; + } + + if (xsdEntry.hasMaxActivationVolumePercentage()) { + // Parse int ranges are not inclusive + ParseInt(xsdEntry.getMaxActivationVolumePercentage().c_str(), + &entry.maxActivationVolumePercentage, + api::VolumeActivationConfigurationEntry::DEFAULT_MIN_ACTIVATION_VALUE - 1, + api::VolumeActivationConfigurationEntry::DEFAULT_MAX_ACTIVATION_VALUE + 1); + } + + if (xsdEntry.hasMinActivationVolumePercentage()) { + // Parse int ranges are not inclusive + ParseInt(xsdEntry.getMinActivationVolumePercentage().c_str(), + &entry.minActivationVolumePercentage, + api::VolumeActivationConfigurationEntry::DEFAULT_MIN_ACTIVATION_VALUE - 1, + api::VolumeActivationConfigurationEntry::DEFAULT_MAX_ACTIVATION_VALUE + 1); + } + + return true; +} + +bool parseVolumeGroupActivationEntries( + const std::vector& xsdEntries, + std::vector& entries) { + for (const auto& xsdEntry : xsdEntries) { + api::VolumeActivationConfigurationEntry entry; + if (!parseVolumeGroupActivationEntry(xsdEntry, entry)) { + LOG(ERROR) << __func__ << " Could not parse volume group activation entries"; + return false; + } + entries.push_back(entry); + } + return true; +} + +bool parseVolumeGroupActivation(const xsd::ActivationVolumeConfigType& xsdActivationConfig, + api::VolumeActivationConfiguration& activation) { + if (!xsdActivationConfig.hasName()) { + LOG(ERROR) << __func__ << " Activation config missing volume activation name"; + return false; + } + if (!xsdActivationConfig.hasActivationVolumeConfigEntry()) { + LOG(ERROR) << __func__ << " Activation config missing volume activation entries"; + return false; + } + if (!parseVolumeGroupActivationEntries(xsdActivationConfig.getActivationVolumeConfigEntry(), + activation.volumeActivationEntries)) { + LOG(ERROR) << __func__ << " Could not parse volume activation name"; + return false; + } + activation.name = xsdActivationConfig.getName(); + return true; +} + +void parseVolumeGroupActivations(const xsd::ActivationVolumeConfigsType* xsdActivationConfigs, + ActivationMap& activations) { + if (!xsdActivationConfigs->hasActivationVolumeConfig()) { + LOG(ERROR) << __func__ << " No volume group activations found"; + return; + } + for (const auto& xsdActivationConfig : xsdActivationConfigs->getActivationVolumeConfig()) { + api::VolumeActivationConfiguration activationConfiguration; + if (!parseVolumeGroupActivation(xsdActivationConfig, activationConfiguration)) { + continue; + } + std::string name = xsdActivationConfig.getName(); + activations.emplace(name, activationConfiguration); + } +} + +void parseOutputMirroringDevices(const xsd::MirroringDevicesType* mirroringDevicesType, + std::vector& mirroringDevices) { + if (!mirroringDevicesType->hasMirroringDevice()) { + LOG(ERROR) << __func__ << " Missing audio mirroring devices"; + return; + } + for (const auto& xsdMirrorDevice : mirroringDevicesType->getMirroringDevice()) { + AudioPort mirrorDevicePort; + if (!xsdMirrorDevice.hasAddress()) { + LOG(ERROR) << __func__ << " Missing audio mirroring device address"; + continue; + } + if (!createAudioDevice(xsdMirrorDevice.getAddress(), kOutBusType, mirrorDevicePort)) { + LOG(ERROR) << __func__ << " Could not create mirror device with address " + << xsdMirrorDevice.getAddress(); + continue; + } + mirroringDevices.push_back(mirrorDevicePort); + } +} + +api::FadeState getFadeState(const fade::FadeStateType& xsdFadeState) { + // Return default value if missing + if (!xsdFadeState.hasValue()) { + return api::FadeState::FADE_STATE_ENABLED_DEFAULT; + } + // For legacy files, "0" and "1 " need to be supported. + switch (xsdFadeState.getValue()) { + case fade::FadeStateEnumType::_0: + // Fallthrough + case fade::FadeStateEnumType::FADE_STATE_DISABLED: + return api::FadeState::FADE_STATE_DISABLED; + case fade::FadeStateEnumType::_1: + // Fallthrough + case fade::FadeStateEnumType::FADE_STATE_ENABLED_DEFAULT: + // Fallthrough + default: + return api::FadeState::FADE_STATE_ENABLED_DEFAULT; + } +} + +void parseFadeableUsages(const fade::FadeableUsagesType& fadeUsages, + std::vector& usages) { + if (!fadeUsages.hasUsage()) { + return; + } + for (const auto& fadeUsage : fadeUsages.getUsage()) { + AudioUsage audioUsage; + if (!fadeUsage.hasValue() || + !parseAudioAttributeUsageString(fade::toString(fadeUsage.getValue()), audioUsage)) { + continue; + } + usages.push_back(audioUsage); + } +} + +void parseFadeAudioAttribute(const fade::AttributesType& fadeAttributes, + AudioAttributes& attributes) { + if (fadeAttributes.hasUsage()) { + parseAudioAttributeUsageString(fade::toString(fadeAttributes.getUsage()), attributes.usage); + } + if (fadeAttributes.hasContentType()) { + parseContentTypeString(fade::toString(fadeAttributes.getContentType()), + attributes.contentType); + } + if (fadeAttributes.hasTags()) { + attributes.tags.push_back(fadeAttributes.getTags()); + } +} + +bool parseFadeAudioAttribute(const fade::AudioAttributesUsagesType& fadeAttributes, + std::vector& audioAttributes) { + if (fadeAttributes.hasUsage_optional()) { + for (const auto& usage : fadeAttributes.getUsage_optional()) { + AudioAttributes attributes; + if (!usage.hasValue() || !parseAudioAttributeUsageString( + fade::toString(usage.getValue()), attributes.usage)) { + continue; + } + audioAttributes.push_back(attributes); + } + } + if (fadeAttributes.hasAudioAttribute_optional()) { + for (const auto& fadeAttribute : fadeAttributes.getAudioAttribute_optional()) { + AudioAttributes attribute; + parseFadeAudioAttribute(fadeAttribute, attribute); + audioAttributes.push_back(attribute); + } + } + return true; +} + +void parseUnfadeableAudioAttributes(const fade::UnfadeableAudioAttributesType& fadeAttributes, + std::vector& audioAttributes) { + if (!fadeAttributes.hasAudioAttributes()) { + return; + } + parseFadeAudioAttribute(*fadeAttributes.getFirstAudioAttributes(), audioAttributes); +} + +void parseUnfadeableContentType(const fade::UnfadeableContentTypesType& fadeTypes, + std::optional>& contentTypes) { + if (!fadeTypes.hasContentType()) { + return; + } + std::vector contents; + for (const auto& fadeContentType : fadeTypes.getContentType()) { + AudioContentType contentType; + if (!fadeContentType.hasValue() || + !parseContentTypeString(fade::toString(fadeContentType.getValue()), contentType)) { + continue; + } + contents.push_back(contentType); + } + contentTypes = contents; +} + +void parseFadeConfigAudioAttributes(const fade::AudioAttributesUsagesType& fadeAudioAttributesType, + const int64_t fadeDurationMillins, + std::vector& fadeInConfigurations) { + if (fadeAudioAttributesType.hasAudioAttribute_optional()) { + for (const auto& fadeAudioAttribute : + fadeAudioAttributesType.getAudioAttribute_optional()) { + api::FadeConfiguration fadeConfiguration; + AudioAttributes attributes; + parseFadeAudioAttribute(fadeAudioAttribute, attributes); + fadeConfiguration.fadeDurationMillis = fadeDurationMillins; + fadeConfiguration.audioAttributesOrUsage + .set(attributes); + fadeInConfigurations.push_back(fadeConfiguration); + } + } + + if (fadeAudioAttributesType.hasUsage_optional()) { + for (const auto& fadeAudioUsage : fadeAudioAttributesType.getUsage_optional()) { + api::FadeConfiguration fadeConfiguration; + AudioUsage usage; + if (!fadeAudioUsage.hasValue() || + !parseAudioAttributeUsageString(fade::toString(fadeAudioUsage.getValue()), usage)) { + continue; + } + fadeConfiguration.fadeDurationMillis = fadeDurationMillins; + fadeConfiguration.audioAttributesOrUsage + .set(usage); + fadeInConfigurations.push_back(fadeConfiguration); + } + } +} +void parseFadeConfiguration(const fade::FadeConfigurationType& fadeConfigurationType, + std::vector& fadeConfigurations) { + if (!fadeConfigurationType.hasFadeDurationMillis() || + !fadeConfigurationType.hasAudioAttributes() || + fadeConfigurationType.getAudioAttributes().empty()) { + return; + } + + int64_t fadeDurationMillis = 0L; + + if (!ParseInt(fadeConfigurationType.getFadeDurationMillis().c_str(), &fadeDurationMillis, + static_cast(0))) { + return; + } + parseFadeConfigAudioAttributes(*fadeConfigurationType.getFirstAudioAttributes(), + fadeDurationMillis, fadeConfigurations); +} + +void parseFadeInConfigurations(const fade::FadeInConfigurationsType& fadeInConfigurationsType, + std::vector& fadeInConfigurations) { + if (!fadeInConfigurationsType.hasFadeConfiguration()) { + return; + } + for (const auto& fadeConfigurationType : fadeInConfigurationsType.getFadeConfiguration()) { + parseFadeConfiguration(fadeConfigurationType, fadeInConfigurations); + } +} + +void parseFadeOutConfigurations(const fade::FadeOutConfigurationsType& fadeOutConfigurationsType, + std::vector& fadeOutConfigurations) { + if (!fadeOutConfigurationsType.hasFadeConfiguration()) { + return; + } + for (const auto& fadeConfigurationType : fadeOutConfigurationsType.getFadeConfiguration()) { + parseFadeConfiguration(fadeConfigurationType, fadeOutConfigurations); + } +} + +bool parseFadeConfig(const fade::FadeConfigurationConfig& fadeConfig, + api::AudioFadeConfiguration& configuration) { + // Fade configuration must have a name for zone association. Fade state is also needed to + // determine accurate usage. + if (!fadeConfig.hasName()) { + LOG(ERROR) << __func__ << " Fade configuration missing name"; + return false; + } + if (!fadeConfig.hasFadeState()) { + LOG(ERROR) << __func__ << " Fade configuration missing fade state"; + return false; + } + configuration.name = fadeConfig.getName(); + configuration.fadeState = getFadeState(*fadeConfig.getFirstFadeState()); + if (fadeConfig.hasDefaultFadeOutDurationInMillis()) { + ParseInt(fadeConfig.getDefaultFadeOutDurationInMillis().c_str(), + &configuration.fadeOutDurationMs, static_cast(0)); + } + if (fadeConfig.hasDefaultFadeInDurationInMillis()) { + ParseInt(fadeConfig.getDefaultFadeInDurationInMillis().c_str(), + &configuration.fadeInDurationMs, static_cast(0)); + } + if (fadeConfig.hasDefaultFadeInDelayForOffenders()) { + ParseInt(fadeConfig.getDefaultFadeInDelayForOffenders().c_str(), + &configuration.fadeInDelayedForOffendersMs, static_cast(0)); + } + + if (fadeConfig.hasFadeableUsages()) { + parseFadeableUsages(*fadeConfig.getFirstFadeableUsages(), configuration.fadeableUsages); + } + + if (fadeConfig.hasUnfadeableContentTypes()) { + parseUnfadeableContentType(*fadeConfig.getFirstUnfadeableContentTypes(), + configuration.unfadeableContentTypes); + } + + if (fadeConfig.hasUnfadeableAudioAttributes()) { + parseUnfadeableAudioAttributes(*fadeConfig.getFirstUnfadeableAudioAttributes(), + configuration.unfadableAudioAttributes); + } + if (fadeConfig.hasFadeInConfigurations()) { + parseFadeInConfigurations(*fadeConfig.getFirstFadeInConfigurations(), + configuration.fadeInConfigurations); + } + if (fadeConfig.hasFadeOutConfigurations()) { + parseFadeOutConfigurations(*fadeConfig.getFirstFadeOutConfigurations(), + configuration.fadeOutConfigurations); + } + + return true; +} + +void parseFadeConfigs(const std::vector& fadeConfigTypes, + std::vector& fadeConfigs) { + for (const auto& fadeConfig : fadeConfigTypes) { + api::AudioFadeConfiguration configuration; + if (!parseFadeConfig(fadeConfig, configuration)) { + continue; + } + fadeConfigs.push_back(configuration); + } +} + +void parseFadeConfigs(const fade::FadeConfigurationConfigs& fadeConfigsType, + std::vector& fadeConfigs) { + if (!fadeConfigsType.hasConfig()) { + LOG(ERROR) << __func__ << " Fade config file does not contains any fade configs"; + return; + } + parseFadeConfigs(fadeConfigsType.getConfig(), fadeConfigs); +} +} // namespace + +void CarAudioConfigurationXmlConverter::init() { + if (!isReadableConfigurationFile(mAudioConfigFile)) { + mParseErrors = "Configuration file " + mAudioConfigFile + " is not readable"; + initNonDynamicRouting(); + return; + } + + // Supports loading legacy fade configurations from a different file + if (isReadableConfigurationFile(mFadeConfigFile)) { + initFadeConfigurations(); + } + + const auto& configOptional = xsd::read(mAudioConfigFile.c_str()); + + if (!configOptional.has_value()) { + mParseErrors = + "Configuration file " + mAudioConfigFile + " , does not have any configurations"; + initNonDynamicRouting(); + return; + } + + const auto& configurations = configOptional.value(); + initAudioDeviceConfiguration(configurations); + initCarAudioConfigurations(configurations); +} + +void CarAudioConfigurationXmlConverter::initFadeConfigurations() { + const auto& fadeConfigOptional = fade::read(mFadeConfigFile.c_str()); + if (!fadeConfigOptional.has_value() || !fadeConfigOptional.value().hasConfigs()) { + LOG(ERROR) << __func__ << " Fade config file " << mFadeConfigFile.c_str() + << " does not contains fade configuration"; + return; + } + + const auto& fadeConfigs = fadeConfigOptional.value().getConfigs(); + + if (fadeConfigs.empty()) { + LOG(ERROR) << __func__ << " Fade config file " << mFadeConfigFile.c_str() + << " does not contains fade configs"; + } + std::vector fadeConfigurations; + parseFadeConfigs(fadeConfigs.front(), fadeConfigurations); + for (const auto& fadeConfiguration : fadeConfigurations) { + mFadeConfigurations.emplace(fadeConfiguration.name, fadeConfiguration); + } +} + +void CarAudioConfigurationXmlConverter::initNonDynamicRouting() { + mAudioDeviceConfiguration.routingConfig = + api::RoutingDeviceConfiguration::DEFAULT_AUDIO_ROUTING; +} + +void CarAudioConfigurationXmlConverter::initAudioDeviceConfiguration( + const xsd::CarAudioConfigurationType& carAudioConfigurationType) { + parseAudioDeviceConfigurations(carAudioConfigurationType); +} + +void CarAudioConfigurationXmlConverter::parseAudioDeviceConfigurations( + const xsd::CarAudioConfigurationType& carAudioConfigurationType) { + if (!carAudioConfigurationType.hasDeviceConfigurations()) { + return; + } + + mAudioDeviceConfiguration.routingConfig = + api::RoutingDeviceConfiguration::DYNAMIC_AUDIO_ROUTING; + + const auto deviceConfigs = carAudioConfigurationType.getFirstDeviceConfigurations(); + if (!deviceConfigs->hasDeviceConfiguration()) { + return; + } + + std::vector<::android::hardware::automotive::audiocontrol::DeviceConfigurationType> configs = + deviceConfigs->getDeviceConfiguration(); + const auto& parsers = getConfigsParsers(); + for (const auto& deviceConfig : configs) { + if (!deviceConfig.hasName() || !deviceConfig.hasValue()) { + continue; + } + const auto& parser = parsers.find(deviceConfig.getName()); + if (parser == parsers.end()) { + continue; + } + const auto& method = parser->second; + method(deviceConfig.getValue(), mAudioDeviceConfiguration); + } +} + +void CarAudioConfigurationXmlConverter::initCarAudioConfigurations( + const automotive::audiocontrol::CarAudioConfigurationType& carAudioConfigurationType) { + if (!carAudioConfigurationType.hasZones()) { + mParseErrors = "Audio zones not found in file " + mAudioConfigFile; + initNonDynamicRouting(); + return; + } + + api::AudioZoneContext context; + if (!carAudioConfigurationType.hasOemContexts() || + !parseAudioContexts(carAudioConfigurationType.getFirstOemContexts(), context)) { + context = getDefaultCarAudioContext(); + } + + ActivationMap activations; + if (carAudioConfigurationType.hasActivationVolumeConfigs()) { + parseVolumeGroupActivations(carAudioConfigurationType.getFirstActivationVolumeConfigs(), + activations); + } + + if (carAudioConfigurationType.hasMirroringDevices()) { + parseOutputMirroringDevices(carAudioConfigurationType.getFirstMirroringDevices(), + mOutputMirroringDevices); + } + + const auto audioZones = carAudioConfigurationType.getFirstZones(); + + std::string message = + parseAudioZones(audioZones, context, activations, mFadeConfigurations, mAudioZones); + + // Assign dynamic configuration if not assigned + if (!mAudioZones.empty() && mAudioDeviceConfiguration.routingConfig == + api::RoutingDeviceConfiguration::DEFAULT_AUDIO_ROUTING) { + mAudioDeviceConfiguration.routingConfig = + api::RoutingDeviceConfiguration::DYNAMIC_AUDIO_ROUTING; + } + + if (message.empty()) { + return; + } + mParseErrors = + "Error parsing audio zone(s) in file " + mAudioConfigFile + ", message: " + message; + LOG(ERROR) << __func__ << " Error parsing zones: " << message; + initNonDynamicRouting(); +} + +api::AudioDeviceConfiguration CarAudioConfigurationXmlConverter::getAudioDeviceConfiguration() + const { + return mAudioDeviceConfiguration; +} + +std::vector CarAudioConfigurationXmlConverter::getAudioZones() const { + return mAudioZones; +} + +std::vector<::aidl::android::media::audio::common::AudioPort> +CarAudioConfigurationXmlConverter::getOutputMirroringDevices() const { + return mOutputMirroringDevices; +} + +} // namespace internal +} // namespace audiocontrol +} // namespace hardware +} // namespace android \ No newline at end of file diff --git a/automotive/audiocontrol/aidl/default/converter/test/Android.bp b/automotive/audiocontrol/aidl/default/converter/test/Android.bp new file mode 100644 index 0000000000..70d4a20456 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/Android.bp @@ -0,0 +1,63 @@ +// Copyright (C) 2024 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 { + default_team: "trendy_team_aaos_framework", + default_applicable_licenses: ["Android-Apache-2.0"], +} + +filegroup { + name: "simple_car_audio_configuration_xml", + srcs: [ + "simple_car_audio_configuration.xml", + "simple_car_audio_configuration_with_device_type.xml", + "multi_zone_car_audio_configuration.xml", + "car_audio_configuration_without_configuration.xml", + "car_audio_configuration_with_default_context.xml", + "car_audio_configuration_with_missing_zones.xml", + "car_audio_configuration_without_audio_zone.xml", + "car_audio_fade_configuration.xml", + ], +} + +cc_test { + name: "AudioControlConverterUnitTest", + vendor: true, + require_root: true, + srcs: ["*.cpp"], + stl: "libc++_static", + static_libs: [ + "libbase", + "android.hardware.audiocontrol.internal", + "libgtest", + "libgmock", + "libutils", + "libaudio_aidl_conversion_common_ndk", + ], + shared_libs: ["liblog"], + defaults: [ + "latest_android_hardware_audio_common_ndk_static", + "car.audio.configuration.xsd.default", + "car.fade.configuration.xsd.default", + "latest_android_hardware_automotive_audiocontrol_ndk_static", + "latest_android_media_audio_common_types_ndk_static", + ], + data: [ + ":simple_car_audio_configuration_xml", + ], + test_suites: ["device-tests"], + exclude_shared_libs: [ + "android.hardware.automotive.audiocontrol-V5-ndk", + ], +} diff --git a/automotive/audiocontrol/aidl/default/converter/test/AudioControlConverterUnitTest.cpp b/automotive/audiocontrol/aidl/default/converter/test/AudioControlConverterUnitTest.cpp new file mode 100644 index 0000000000..b6bebe5f39 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/AudioControlConverterUnitTest.cpp @@ -0,0 +1,834 @@ +/* + * Copyright (C) 2024 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. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace converter = ::android::hardware::audiocontrol::internal; +namespace api = ::aidl::android::hardware::automotive::audiocontrol; + +using ::testing::ContainsRegex; +using ::testing::UnorderedElementsAreArray; + +namespace { + +using ::aidl::android::media::audio::common::AudioAttributes; +using ::aidl::android::media::audio::common::AudioContentType; +using ::aidl::android::media::audio::common::AudioDevice; +using ::aidl::android::media::audio::common::AudioDeviceAddress; +using ::aidl::android::media::audio::common::AudioDeviceDescription; +using ::aidl::android::media::audio::common::AudioDeviceType; +using ::aidl::android::media::audio::common::AudioPort; +using ::aidl::android::media::audio::common::AudioPortDeviceExt; +using ::aidl::android::media::audio::common::AudioPortExt; +using ::aidl::android::media::audio::common::AudioUsage; + +std::string getTestFilePath(const std::string& filename) { + static std::string baseDir = android::base::GetExecutableDirectory(); + return baseDir + "/" + filename; +} + +AudioAttributes createAudioAttributes(const AudioUsage& usage, + const AudioContentType& type = AudioContentType::UNKNOWN, + const std::string tags = "") { + AudioAttributes attributes; + attributes.usage = usage; + attributes.contentType = type; + if (!tags.empty()) { + attributes.tags.push_back(tags); + } + return attributes; +} + +api::AudioZoneContextInfo createContextInfo(const std::string& name, + const std::vector& attributes, + const int id = -1) { + api::AudioZoneContextInfo info; + info.name = name; + if (id != -1) { + info.id = id; + } + for (const auto& attribute : attributes) { + info.audioAttributes.push_back(attribute); + } + return info; +} + +api::AudioZoneContextInfo createContextInfo(const std::string& name, + const std::vector& usages, + const int id = -1) { + std::vector attributes; + attributes.reserve(usages.size()); + for (const auto& usage : usages) { + attributes.push_back(createAudioAttributes(usage)); + } + return createContextInfo(name, attributes, id); +} + +AudioPort createAudioPort(const std::string& address, const AudioDeviceType& type, + const std::string& connection = "") { + AudioPort port; + AudioDevice device; + device.address = AudioDeviceAddress::make(address); + + AudioDeviceDescription description; + description.type = type; + description.connection = connection; + device.type = description; + + port.ext = AudioPortExt::make(device); + + return port; +} + +api::DeviceToContextEntry createRoutes(const AudioPort& port, + const std::vector& contexts) { + api::DeviceToContextEntry entry; + entry.device = port; + entry.contextNames = contexts; + return entry; +} + +api::VolumeGroupConfig createVolumeGroup(const std::string& name, + const api::VolumeActivationConfiguration& activation, + const std::vector& routes) { + api::VolumeGroupConfig config; + config.name = name; + config.activationConfiguration = activation; + config.carAudioRoutes = routes; + return config; +} + +api::AudioZoneConfig createAudioZoneConfig(const std::string& name, + const api::AudioZoneFadeConfiguration& fadeConfiguration, + const std::vector& groups, + bool isDefault = false) { + api::AudioZoneConfig config; + config.name = name; + config.isDefault = isDefault; + config.volumeGroups = groups; + config.fadeConfiguration = fadeConfiguration; + return config; +} + +api::VolumeActivationConfiguration createVolumeActivation(const std::string& name, + const api::VolumeInvocationType& type, + int minVolume, int maxVolume) { + api::VolumeActivationConfiguration activation; + activation.name = name; + api::VolumeActivationConfigurationEntry entry; + entry.maxActivationVolumePercentage = maxVolume; + entry.minActivationVolumePercentage = minVolume; + entry.type = type; + activation.volumeActivationEntries.push_back(entry); + + return activation; +} + +api::FadeConfiguration createFadeConfiguration(const long& fadeDurationsMillis, + const AudioAttributes& audioAttributes) { + api::FadeConfiguration configuration; + configuration.fadeDurationMillis = fadeDurationsMillis; + configuration.audioAttributesOrUsage + .set( + audioAttributes); + return configuration; +} + +api::FadeConfiguration createFadeConfiguration(const long& fadeDurationsMillis, + const AudioUsage& audioUsage) { + api::FadeConfiguration configuration; + configuration.fadeDurationMillis = fadeDurationsMillis; + configuration.audioAttributesOrUsage + .set(audioUsage); + return configuration; +} + +api::AudioFadeConfiguration createAudioFadeConfiguration( + const std::string& name, const api::FadeState& state, + const std::vector& fadeableUsages = std::vector(), + const std::optional>& unfadeableContentTypes = std::nullopt, + const std::vector unfadeableAudioAttributes = + std::vector(), + const std::vector fadeOutConfigurations = + std::vector(), + const std::vector fadeInConfigurations = + std::vector(), + const long& fadeOutDurationMs = api::AudioFadeConfiguration::DEFAULT_FADE_OUT_DURATION_MS, + const long& fadeInDurationMs = api::AudioFadeConfiguration::DEFAULT_FADE_IN_DURATION_MS, + const long& fadeInDelayedForOffendersMs = + api::AudioFadeConfiguration::DEFAULT_DELAY_FADE_IN_OFFENDERS_MS) { + api::AudioFadeConfiguration audioZoneFadeConfiguration; + audioZoneFadeConfiguration.name = name; + audioZoneFadeConfiguration.fadeInDurationMs = fadeInDurationMs; + audioZoneFadeConfiguration.fadeOutDurationMs = fadeOutDurationMs; + audioZoneFadeConfiguration.fadeInDelayedForOffendersMs = fadeInDelayedForOffendersMs; + audioZoneFadeConfiguration.fadeState = state; + audioZoneFadeConfiguration.fadeableUsages = fadeableUsages; + audioZoneFadeConfiguration.unfadeableContentTypes = unfadeableContentTypes; + audioZoneFadeConfiguration.unfadableAudioAttributes = unfadeableAudioAttributes; + audioZoneFadeConfiguration.fadeOutConfigurations = fadeOutConfigurations; + audioZoneFadeConfiguration.fadeInConfigurations = fadeInConfigurations; + + return audioZoneFadeConfiguration; +} + +api::TransientFadeConfigurationEntry createTransientFadeConfiguration( + const api::AudioFadeConfiguration& fadeConfig, const std::vector& usages) { + api::TransientFadeConfigurationEntry entry; + entry.transientFadeConfiguration = fadeConfig; + entry.transientUsages = usages; + return entry; +} + +api::AudioZoneFadeConfiguration createAudioZoneFadeConfiguration( + const api::AudioFadeConfiguration& defaultConfig, + const std::vector& transientConfigs) { + api::AudioZoneFadeConfiguration zoneFadeConfiguration; + zoneFadeConfiguration.defaultConfiguration = defaultConfig; + zoneFadeConfiguration.transientConfiguration = transientConfigs; + return zoneFadeConfiguration; +} + +api::AudioZone createAudioZone(const std::string& name, const int zoneId, + const std::vector& contexts, + const std::vector& configs) { + api::AudioZone zone; + zone.name = name; + zone.id = zoneId; + zone.occupantZoneId = zoneId; + zone.audioZoneContext.audioContextInfos = contexts; + zone.audioZoneConfigs = configs; + return zone; +} + +const std::vector kFadeableUsages = {AudioUsage::MEDIA, + AudioUsage::GAME, + AudioUsage::ASSISTANCE_SONIFICATION, + AudioUsage::ASSISTANCE_ACCESSIBILITY, + AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE, + AudioUsage::ASSISTANT, + AudioUsage::NOTIFICATION, + AudioUsage::ANNOUNCEMENT}; + +const std::vector kUnfadeableAudioAttributes = { + createAudioAttributes(AudioUsage::MEDIA, AudioContentType::UNKNOWN, "oem_specific_tag1")}; + +const std::vector kFadeOutConfigurations = { + createFadeConfiguration( + 500, createAudioAttributes(AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, + "oem_specific_tag2")), + createFadeConfiguration(500, AudioUsage::MEDIA), + createFadeConfiguration(500, AudioUsage::GAME), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_SONIFICATION), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_ACCESSIBILITY), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE), + createFadeConfiguration(800, AudioUsage::ASSISTANT), + createFadeConfiguration(800, AudioUsage::ANNOUNCEMENT), +}; + +const std::vector kFadeInConfigurations = { + createFadeConfiguration( + 1000, createAudioAttributes(AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, + "oem_specific_tag2")), + createFadeConfiguration(1000, AudioUsage::MEDIA), + createFadeConfiguration(1000, AudioUsage::GAME), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_SONIFICATION), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_ACCESSIBILITY), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE), + createFadeConfiguration(800, AudioUsage::ASSISTANT), + createFadeConfiguration(800, AudioUsage::ANNOUNCEMENT), +}; + +const api::AudioFadeConfiguration kRelaxedFading = createAudioFadeConfiguration( + "relaxed fading", api::FadeState::FADE_STATE_ENABLED_DEFAULT, kFadeableUsages, + std::optional>( + {AudioContentType::SPEECH, AudioContentType::SONIFICATION}), + kUnfadeableAudioAttributes, kFadeOutConfigurations, kFadeInConfigurations, 800, 500, 10000); + +const std::vector kAggressiveUnfadeableAudioAttributes = { + createAudioAttributes(AudioUsage::MEDIA, AudioContentType::UNKNOWN, "oem_specific_tag1"), + createAudioAttributes(AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, + "oem_projection_service"), +}; + +const std::vector kAggressiveFadeOutConfigurations = { + createFadeConfiguration(150, AudioUsage::MEDIA), + createFadeConfiguration(150, AudioUsage::GAME), + createFadeConfiguration(400, AudioUsage::ASSISTANCE_SONIFICATION), + createFadeConfiguration(400, AudioUsage::ASSISTANCE_ACCESSIBILITY), + createFadeConfiguration(400, AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE), + createFadeConfiguration(400, AudioUsage::ASSISTANT), + createFadeConfiguration(400, AudioUsage::ANNOUNCEMENT), +}; + +const std::vector kAggressiveFadeInConfigurations = { + createFadeConfiguration(300, AudioUsage::MEDIA), + createFadeConfiguration(300, AudioUsage::GAME), + createFadeConfiguration(550, AudioUsage::ASSISTANCE_SONIFICATION), + createFadeConfiguration(550, AudioUsage::ASSISTANCE_ACCESSIBILITY), + createFadeConfiguration(550, AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE), + createFadeConfiguration(550, AudioUsage::ASSISTANT), + createFadeConfiguration(550, AudioUsage::ANNOUNCEMENT), +}; + +const api::AudioFadeConfiguration kAggressiveFading = createAudioFadeConfiguration( + "aggressive fading", api::FadeState::FADE_STATE_ENABLED_DEFAULT, kFadeableUsages, + std::optional>( + {AudioContentType::SPEECH, AudioContentType::MUSIC}), + kAggressiveUnfadeableAudioAttributes, kAggressiveFadeOutConfigurations, + kAggressiveFadeInConfigurations); + +const api::AudioFadeConfiguration kDisabledFading = + createAudioFadeConfiguration("disabled fading", api::FadeState::FADE_STATE_DISABLED); + +const std::vector kDynamicFadeOutConfigurations = { + createFadeConfiguration( + 500, createAudioAttributes(AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, + "oem_specific_tag2")), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_SONIFICATION), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_ACCESSIBILITY), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE), + createFadeConfiguration(800, AudioUsage::ASSISTANT), + createFadeConfiguration(800, AudioUsage::ANNOUNCEMENT), +}; + +const std::vector kDynamicFadeInConfigurations = { + createFadeConfiguration( + 1000, createAudioAttributes(AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, + "oem_specific_tag2")), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_SONIFICATION), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_ACCESSIBILITY), + createFadeConfiguration(800, AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE), + createFadeConfiguration(800, AudioUsage::ASSISTANT), + createFadeConfiguration(800, AudioUsage::ANNOUNCEMENT), +}; + +const api::AudioFadeConfiguration kDynamicFading = createAudioFadeConfiguration( + "dynamic fading", api::FadeState::FADE_STATE_ENABLED_DEFAULT, kFadeableUsages, + std::optional>( + {AudioContentType::SPEECH, AudioContentType::MOVIE}), + kUnfadeableAudioAttributes, kDynamicFadeOutConfigurations, kDynamicFadeInConfigurations, + 800, 500); + +const api::AudioZoneFadeConfiguration kDefaultAudioConfigFading = createAudioZoneFadeConfiguration( + kRelaxedFading, + {createTransientFadeConfiguration( + kAggressiveFading, {AudioUsage::VOICE_COMMUNICATION, AudioUsage::ANNOUNCEMENT, + AudioUsage::VEHICLE_STATUS, AudioUsage::SAFETY}), + createTransientFadeConfiguration(kDisabledFading, {AudioUsage::EMERGENCY})}); + +const api::AudioZoneFadeConfiguration kDynamicDeviceAudioConfigFading = + createAudioZoneFadeConfiguration( + kDynamicFading, + {createTransientFadeConfiguration( + kAggressiveFading, + {AudioUsage::VOICE_COMMUNICATION, AudioUsage::ANNOUNCEMENT, + AudioUsage::VEHICLE_STATUS, AudioUsage::SAFETY}), + createTransientFadeConfiguration(kDisabledFading, {AudioUsage::EMERGENCY})}); + +const api::AudioZoneContextInfo kMusicContextInfo = + createContextInfo("oem_music", {AudioUsage::MEDIA, AudioUsage::GAME, AudioUsage::UNKNOWN}); +const api::AudioZoneContextInfo kNotificationContextInfo = createContextInfo( + "oem_notification", {AudioUsage::NOTIFICATION, AudioUsage::NOTIFICATION_EVENT}); +const api::AudioZoneContextInfo kVoiceContextInfo = createContextInfo( + "oem_voice_command", {AudioUsage::ASSISTANT, AudioUsage::ASSISTANCE_ACCESSIBILITY, + AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE}); +const api::AudioZoneContextInfo kCallContextInfo = + createContextInfo("oem_call", {AudioUsage::VOICE_COMMUNICATION, AudioUsage::CALL_ASSISTANT, + AudioUsage::VOICE_COMMUNICATION_SIGNALLING}); +const api::AudioZoneContextInfo kRingContextInfo = + createContextInfo("oem_call_ring", {AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE}); +const api::AudioZoneContextInfo kAlarmContextInfo = + createContextInfo("oem_alarm", {AudioUsage::ALARM}); +const api::AudioZoneContextInfo kSystemContextInfo = createContextInfo( + "oem_system_sound", + {AudioUsage::ASSISTANCE_SONIFICATION, AudioUsage::EMERGENCY, AudioUsage::SAFETY, + AudioUsage::VEHICLE_STATUS, AudioUsage::ANNOUNCEMENT}); +const api::AudioZoneContextInfo kOemContextInfo = createContextInfo( + "oem_context", {createAudioAttributes(AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE, + AudioContentType::SPEECH, "oem=extension_8675309")}); + +const std::vector kSimpleCarAudioConfigurationContext = { + kOemContextInfo, kMusicContextInfo, kNotificationContextInfo, kVoiceContextInfo, + kCallContextInfo, kRingContextInfo, kAlarmContextInfo, kSystemContextInfo}; + +const api::AudioZoneContextInfo kDefaultMusicContextInfo = + createContextInfo("music", {AudioUsage::UNKNOWN, AudioUsage::MEDIA, AudioUsage::GAME}, 1); +const api::AudioZoneContextInfo kDefaultNavContextInfo = + createContextInfo("navigation", {AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE}, 2); +const api::AudioZoneContextInfo kDefaultVoiceContextInfo = createContextInfo( + "voice_command", {AudioUsage::ASSISTANCE_ACCESSIBILITY, AudioUsage::ASSISTANT}, 3); +const api::AudioZoneContextInfo kDefaultRingContextInfo = + createContextInfo("call_ring", {AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE}, 4); +const api::AudioZoneContextInfo kDefaultCallContextInfo = + createContextInfo("call", + {AudioUsage::VOICE_COMMUNICATION, AudioUsage::CALL_ASSISTANT, + AudioUsage::VOICE_COMMUNICATION_SIGNALLING}, + 5); +const api::AudioZoneContextInfo kDefaultAlarmContextInfo = + createContextInfo("alarm", {AudioUsage::ALARM}, 6); +const api::AudioZoneContextInfo kDefaultNotificationContextInfo = createContextInfo( + "notification", {AudioUsage::NOTIFICATION, AudioUsage::NOTIFICATION_EVENT}, 7); +const api::AudioZoneContextInfo kDefaultSystemContextInfo = + createContextInfo("system_sound", {AudioUsage::ASSISTANCE_SONIFICATION}, 8); +const api::AudioZoneContextInfo kDefaultEmergencyContextInfo = + createContextInfo("emergency", {AudioUsage::EMERGENCY}, 9); +const api::AudioZoneContextInfo kDefaultSafetyContextInfo = + createContextInfo("safety", {AudioUsage::SAFETY}, 10); +const api::AudioZoneContextInfo kDefaultVehicleStatusContextInfo = + createContextInfo("vehicle_status", {AudioUsage::VEHICLE_STATUS}, 11); +const api::AudioZoneContextInfo kDefaultAnnouncementContextInfo = + createContextInfo("announcement", {AudioUsage::ANNOUNCEMENT}, 12); + +const std::vector kDefaultCarAudioConfigurationContext = { + kDefaultMusicContextInfo, kDefaultNavContextInfo, + kDefaultVoiceContextInfo, kDefaultRingContextInfo, + kDefaultCallContextInfo, kDefaultAlarmContextInfo, + kDefaultNotificationContextInfo, kDefaultSystemContextInfo, + kDefaultEmergencyContextInfo, kDefaultSafetyContextInfo, + kDefaultVehicleStatusContextInfo, kDefaultAnnouncementContextInfo}; + +const api::VolumeActivationConfiguration kOnBootVolumeActivation = + createVolumeActivation("on_boot_config", api::VolumeInvocationType::ON_BOOT, 0, 80); +const api::VolumeActivationConfiguration kOnSourceVolumeActivation = createVolumeActivation( + "on_source_changed_config", api::VolumeInvocationType::ON_SOURCE_CHANGED, 20, 80); +const api::VolumeActivationConfiguration kOnPlayVolumeActivation = createVolumeActivation( + "on_playback_changed_config", api::VolumeInvocationType::ON_PLAYBACK_CHANGED, 10, 90); + +const AudioPort kBusMediaDevice = createAudioPort("BUS00_MEDIA", AudioDeviceType::OUT_BUS); +const AudioPort kBTMediaDevice = createAudioPort("temp", AudioDeviceType::OUT_DEVICE, "bt-a2dp"); +const AudioPort kUSBMediaDevice = createAudioPort("", AudioDeviceType::OUT_HEADSET, "usb"); + +const AudioPort kBusNavDevice = createAudioPort("BUS02_NAV_GUIDANCE", AudioDeviceType::OUT_BUS); +const AudioPort kBusPhoneDevice = createAudioPort("BUS03_PHONE", AudioDeviceType::OUT_BUS); +const AudioPort kBusSysDevice = createAudioPort("BUS01_SYS_NOTIFICATION", AudioDeviceType::OUT_BUS); + +const AudioPort kMirrorDevice1 = createAudioPort("mirror_bus_device_1", AudioDeviceType::OUT_BUS); +const AudioPort kMirrorDevice2 = createAudioPort("mirror_bus_device_2", AudioDeviceType::OUT_BUS); +const std::vector kMirroringDevices = {kMirrorDevice1, kMirrorDevice2}; + +const AudioPort kMirrorDeviceThree = + createAudioPort("mirror_bus_device_three", AudioDeviceType::OUT_BUS); +const AudioPort kMirrorDeviceFour = + createAudioPort("mirror_bus_device_four", AudioDeviceType::OUT_BUS); +const std::vector kMultiZoneMirroringDevices = {kMirrorDeviceThree, kMirrorDeviceFour}; + +const AudioPort kInFMTunerDevice = createAudioPort("fm_tuner", AudioDeviceType::IN_FM_TUNER); +const AudioPort kInMicDevice = createAudioPort("built_in_mic", AudioDeviceType::IN_MICROPHONE); +const AudioPort kInBusDevice = createAudioPort("in_bus_device", AudioDeviceType::IN_BUS); +const std::vector kInputDevices{kInFMTunerDevice, kInMicDevice, kInBusDevice}; + +const api::VolumeGroupConfig kBusMediaVolumeGroup = createVolumeGroup( + "entertainment", kOnBootVolumeActivation, {createRoutes(kBusMediaDevice, {"oem_music"})}); +const api::VolumeGroupConfig kUSBMediaVolumeGroup = createVolumeGroup( + "entertainment", kOnBootVolumeActivation, {createRoutes(kUSBMediaDevice, {"oem_music"})}); +const api::VolumeGroupConfig kBTMediaVolumeGroup = createVolumeGroup( + "entertainment", kOnBootVolumeActivation, {createRoutes(kBTMediaDevice, {"oem_music"})}); +const api::VolumeGroupConfig kBusNavVolumeGroup = + createVolumeGroup("navvoicecommand", kOnSourceVolumeActivation, + {createRoutes(kBusNavDevice, {"oem_voice_command"})}); +const api::VolumeGroupConfig kBusCallVolumeGroup = + createVolumeGroup("telringvol", kOnPlayVolumeActivation, + {createRoutes(kBusPhoneDevice, {"oem_call", "oem_call_ring"})}); +const api::VolumeGroupConfig kBusSysVolumeGroup = createVolumeGroup( + "systemalarm", kOnSourceVolumeActivation, + {createRoutes(kBusSysDevice, {"oem_alarm", "oem_system_sound", "oem_notification"})}); + +const api::AudioZoneConfig kAllBusZoneConfig = createAudioZoneConfig( + "primary zone config 0", kDefaultAudioConfigFading, + {kBusMediaVolumeGroup, kBusNavVolumeGroup, kBusCallVolumeGroup, kBusSysVolumeGroup}, true); +const api::AudioZoneConfig kBTMediaZoneConfig = createAudioZoneConfig( + "primary zone BT media", kDynamicDeviceAudioConfigFading, + {kBTMediaVolumeGroup, kBusNavVolumeGroup, kBusCallVolumeGroup, kBusSysVolumeGroup}); +const api::AudioZoneConfig kUsBMediaZoneConfig = createAudioZoneConfig( + "primary zone USB media", kDynamicDeviceAudioConfigFading, + {kUSBMediaVolumeGroup, kBusNavVolumeGroup, kBusCallVolumeGroup, kBusSysVolumeGroup}); + +const std::unordered_map kConfigNameToZoneConfig = { + {kAllBusZoneConfig.name, kAllBusZoneConfig}, + {kBTMediaZoneConfig.name, kBTMediaZoneConfig}, + {kUsBMediaZoneConfig.name, kUsBMediaZoneConfig}, +}; + +const api::AudioZoneConfig kDriverZoneConfig = createAudioZoneConfig( + "driver zone config 0", kDefaultAudioConfigFading, + {kBusMediaVolumeGroup, kBusNavVolumeGroup, kBusCallVolumeGroup, kBusSysVolumeGroup}, true); + +const api::AudioZone kDriverZone = + createAudioZone("driver zone", api::AudioZone::PRIMARY_AUDIO_ZONE, + kSimpleCarAudioConfigurationContext, {kDriverZoneConfig}); + +const api::AudioZoneFadeConfiguration kZoneAudioConfigFading = createAudioZoneFadeConfiguration( + kRelaxedFading, + {createTransientFadeConfiguration(kDisabledFading, {AudioUsage::EMERGENCY})}); + +const AudioPort kBusFrontDevice = createAudioPort("BUS_FRONT", AudioDeviceType::OUT_BUS); +const api::VolumeGroupConfig kFrontVolumeGroup = createVolumeGroup( + "entertainment", kOnBootVolumeActivation, + {createRoutes(kBusFrontDevice, + {"oem_music", "oem_voice_command", "oem_call", "oem_call_ring", "oem_alarm", + "oem_system_sound", "oem_notification"})}); +const api::AudioZoneConfig kFrontZoneConfig = createAudioZoneConfig( + "front passenger config 0", kZoneAudioConfigFading, {kFrontVolumeGroup}, true); +const api::AudioZone kFrontZone = + createAudioZone("front passenger zone", api::AudioZone::PRIMARY_AUDIO_ZONE + 1, + kSimpleCarAudioConfigurationContext, {kFrontZoneConfig}); + +const AudioPort kBusRearDevice = createAudioPort("BUS_REAR", AudioDeviceType::OUT_BUS); +const api::VolumeGroupConfig kRearVolumeGroup = + createVolumeGroup("entertainment", kOnBootVolumeActivation, + {createRoutes(kBusRearDevice, {"oem_music", "oem_voice_command", + "oem_call", "oem_call_ring", "oem_alarm", + "oem_system_sound", "oem_notification"})}); +const api::AudioZoneConfig kRearZoneConfig = createAudioZoneConfig( + "rear seat config 0", kZoneAudioConfigFading, {kRearVolumeGroup}, true); +const api::AudioZone kRearZone = + createAudioZone("rear seat zone", api::AudioZone::PRIMARY_AUDIO_ZONE + 2, + kSimpleCarAudioConfigurationContext, {kRearZoneConfig}); + +std::vector kMultiZones = {kDriverZone, kFrontZone, kRearZone}; + +void expectSameFadeConfiguration(const api::AudioFadeConfiguration& actual, + const api::AudioFadeConfiguration& expected, + const std::string& configName) { + EXPECT_EQ(actual.name, expected.name) << "Audio fade configuration for config " << configName; + const std::string fadeConfigInfo = + "fade config " + actual.name + " in config name " + configName; + EXPECT_EQ(actual.fadeState, expected.fadeState) + << "Audio fade config state for " << fadeConfigInfo; + EXPECT_EQ(actual.fadeInDurationMs, expected.fadeInDurationMs) + << "Audio fade in duration for " << fadeConfigInfo; + EXPECT_EQ(actual.fadeOutDurationMs, expected.fadeOutDurationMs) + << "Audio fade out duration for " << fadeConfigInfo; + EXPECT_EQ(actual.fadeInDelayedForOffendersMs, expected.fadeInDelayedForOffendersMs) + << "Audio fade in delayed for offenders duration for " << fadeConfigInfo; + EXPECT_THAT(actual.fadeableUsages, UnorderedElementsAreArray(expected.fadeableUsages)) + << "Fadeable usages for " << fadeConfigInfo; + EXPECT_TRUE(actual.unfadeableContentTypes.has_value() == + expected.unfadeableContentTypes.has_value()) + << "Optional unfadeable for " << fadeConfigInfo; + if (actual.unfadeableContentTypes.has_value() && expected.unfadeableContentTypes.has_value()) { + EXPECT_THAT(actual.unfadeableContentTypes.value(), + UnorderedElementsAreArray(expected.unfadeableContentTypes.value())) + << "Unfadeable content type for " << fadeConfigInfo; + } + EXPECT_THAT(actual.unfadableAudioAttributes, + UnorderedElementsAreArray(expected.unfadableAudioAttributes)) + << "Unfadeable audio attributes type for " << fadeConfigInfo; + EXPECT_THAT(actual.fadeOutConfigurations, + UnorderedElementsAreArray(expected.fadeOutConfigurations)) + << "Fade-out configurations for " << fadeConfigInfo; + EXPECT_THAT(actual.fadeInConfigurations, + UnorderedElementsAreArray(expected.fadeInConfigurations)) + << "Fade-in configurations for " << fadeConfigInfo; +} + +void expectSameAudioZoneFadeConfiguration( + const std::optional& actual, + const std::optional& expected, + const std::string& configName) { + if (!actual.has_value() || !expected.has_value()) { + EXPECT_EQ(actual.has_value(), expected.has_value()) + << "Audio zone config " << configName << " fade configuration missing"; + return; + } + const api::AudioZoneFadeConfiguration& actualConfig = actual.value(); + const api::AudioZoneFadeConfiguration& expectedConfig = expected.value(); + expectSameFadeConfiguration(actualConfig.defaultConfiguration, + expectedConfig.defaultConfiguration, configName); + EXPECT_THAT(actualConfig.transientConfiguration, + UnorderedElementsAreArray(expectedConfig.transientConfiguration)) + << "Transient fade configuration for config " << configName; +} + +void expectSameAudioZoneConfiguration(const api::AudioZoneConfig& actual, + const api::AudioZoneConfig& expected) { + EXPECT_EQ(actual.isDefault, expected.isDefault) + << "Zone default's status do not match for config " << actual.name; + EXPECT_THAT(actual.volumeGroups, UnorderedElementsAreArray(expected.volumeGroups)) + << "Volume groups for config " << actual.name; + expectSameAudioZoneFadeConfiguration(actual.fadeConfiguration, expected.fadeConfiguration, + actual.name); +} + +class CarAudioConfigurationTest : public testing::Test { + protected: + void SetUp() override; + void TearDown() override; + + std::unique_ptr converter; + + protected: + virtual std::string getCarAudioConfiguration() = 0; + virtual std::string getCarFadeConfiguration() = 0; +}; + +void CarAudioConfigurationTest::SetUp() { + converter = std::make_unique( + getTestFilePath(getCarAudioConfiguration()), + getTestFilePath(getCarFadeConfiguration())); +} + +void CarAudioConfigurationTest::TearDown() { + converter.reset(); +} + +class SimpleCarAudioConfigurationTest : public CarAudioConfigurationTest { + virtual std::string getCarAudioConfiguration() { return "simple_car_audio_configuration.xml"; } + + virtual std::string getCarFadeConfiguration() { return "car_audio_fade_configuration.xml"; } +}; + +TEST_F(SimpleCarAudioConfigurationTest, TestLoadSimpleConfiguration) { + EXPECT_EQ(converter->getErrors(), ""); + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::DYNAMIC_AUDIO_ROUTING); + EXPECT_FALSE(audioDeviceConfigs.useCoreAudioVolume); + EXPECT_TRUE(audioDeviceConfigs.useHalDuckingSignals); + EXPECT_TRUE(audioDeviceConfigs.useCarVolumeGroupMuting); + + const auto& mirroringDevices = converter->getOutputMirroringDevices(); + + EXPECT_EQ(mirroringDevices.size(), 2) << "Mirroring device size"; + for (const auto& mirroringDevice : mirroringDevices) { + const auto& it = + std::find(kMirroringDevices.begin(), kMirroringDevices.end(), mirroringDevice); + EXPECT_TRUE(it != kMirroringDevices.end()) + << "Mirroring device not found " << mirroringDevice.toString(); + } + + const auto zones = converter->getAudioZones(); + EXPECT_EQ(zones.size(), 1); + + const auto& zone = zones.front(); + EXPECT_EQ(zone.id, api::AudioZone::PRIMARY_AUDIO_ZONE); + EXPECT_EQ(zone.occupantZoneId, 0); + EXPECT_EQ(zone.name, "primary zone"); + + EXPECT_EQ(zone.audioZoneContext.audioContextInfos.size(), + kSimpleCarAudioConfigurationContext.size()); + for (const auto& info : zone.audioZoneContext.audioContextInfos) { + const auto iterator = std::find(kSimpleCarAudioConfigurationContext.begin(), + kSimpleCarAudioConfigurationContext.end(), info); + EXPECT_TRUE(iterator != kSimpleCarAudioConfigurationContext.end()) + << "Context name " << info.toString() << kMusicContextInfo.toString(); + } + + for (const auto& config : zone.audioZoneConfigs) { + const auto& iterator = kConfigNameToZoneConfig.find(config.name); + EXPECT_TRUE(iterator != kConfigNameToZoneConfig.end()) + << "Zone config not found " << config.name; + expectSameAudioZoneConfiguration(config, iterator->second); + } + + const auto& inputDevices = zone.inputAudioDevices; + EXPECT_EQ(inputDevices.size(), 3) << "Input devices"; + for (const auto& inputDevice : inputDevices) { + const auto& it = std::find(kInputDevices.begin(), kInputDevices.end(), inputDevice); + EXPECT_TRUE(it != kInputDevices.end()) + << "Input device " << inputDevice.toString() << " not found"; + } +} + +class TypeDeviceCarAudioConfigurationTest : public CarAudioConfigurationTest { + virtual std::string getCarAudioConfiguration() { + return "simple_car_audio_configuration_with_device_type.xml"; + } + + virtual std::string getCarFadeConfiguration() { return "car_audio_fade_configuration.xml"; } +}; + +TEST_F(TypeDeviceCarAudioConfigurationTest, TestLoadConfigurationWithDeviceType) { + EXPECT_EQ(converter->getErrors(), ""); + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::DYNAMIC_AUDIO_ROUTING); + EXPECT_FALSE(audioDeviceConfigs.useCoreAudioVolume); + EXPECT_TRUE(audioDeviceConfigs.useHalDuckingSignals); + EXPECT_TRUE(audioDeviceConfigs.useCarVolumeGroupMuting); + + const auto& mirroringDevices = converter->getOutputMirroringDevices(); + + EXPECT_EQ(mirroringDevices.size(), 2) << "Mirroring device size"; + for (const auto& mirroringDevice : mirroringDevices) { + const auto& it = + std::find(kMirroringDevices.begin(), kMirroringDevices.end(), mirroringDevice); + EXPECT_TRUE(it != kMirroringDevices.end()) + << "Mirroring device not found " << mirroringDevice.toString(); + } + + const auto zones = converter->getAudioZones(); + EXPECT_EQ(zones.size(), 1); + + const auto& zone = zones.front(); + EXPECT_EQ(zone.id, api::AudioZone::PRIMARY_AUDIO_ZONE); + EXPECT_EQ(zone.occupantZoneId, 0); + EXPECT_EQ(zone.name, "primary zone"); + + EXPECT_EQ(zone.audioZoneContext.audioContextInfos.size(), + kSimpleCarAudioConfigurationContext.size()); + for (const auto& info : zone.audioZoneContext.audioContextInfos) { + const auto iterator = std::find(kSimpleCarAudioConfigurationContext.begin(), + kSimpleCarAudioConfigurationContext.end(), info); + EXPECT_TRUE(iterator != kSimpleCarAudioConfigurationContext.end()) + << "Context name " << info.toString() << kMusicContextInfo.toString(); + } + + for (const auto& config : zone.audioZoneConfigs) { + const auto& iterator = kConfigNameToZoneConfig.find(config.name); + EXPECT_TRUE(iterator != kConfigNameToZoneConfig.end()) + << "Zone config not found " << config.name; + expectSameAudioZoneConfiguration(config, iterator->second); + } + + const auto& inputDevices = zone.inputAudioDevices; + EXPECT_EQ(inputDevices.size(), 3) << "Input devices"; + for (const auto& inputDevice : inputDevices) { + const auto& it = std::find(kInputDevices.begin(), kInputDevices.end(), inputDevice); + EXPECT_TRUE(it != kInputDevices.end()) + << "Input device " << inputDevice.toString() << " not found"; + } +} + +class CarAudioConfigurationWithDefaultContextTest : public CarAudioConfigurationTest { + virtual std::string getCarAudioConfiguration() { + return "car_audio_configuration_with_default_context.xml"; + } + + virtual std::string getCarFadeConfiguration() { return ""; } +}; + +TEST_F(CarAudioConfigurationWithDefaultContextTest, TestLoadConfiguration) { + EXPECT_EQ(converter->getErrors(), ""); + const auto& zones = converter->getAudioZones(); + EXPECT_EQ(zones.size(), 1) << "Default audio context zones"; + const auto& zone = zones.front(); + const auto& context = zone.audioZoneContext; + EXPECT_THAT(context.audioContextInfos, + UnorderedElementsAreArray(kDefaultCarAudioConfigurationContext)) + << "Default audio contexts"; +} + +class MultiZoneCarAudioConfigurationTest : public CarAudioConfigurationTest { + std::string getCarAudioConfiguration() override { + return "multi_zone_car_audio_configuration.xml"; + } + + std::string getCarFadeConfiguration() override { return "car_audio_fade_configuration.xml"; } +}; + +TEST_F(MultiZoneCarAudioConfigurationTest, TestLoadMultiZoneConfiguration) { + EXPECT_EQ(converter->getErrors(), ""); + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::CONFIGURABLE_AUDIO_ENGINE_ROUTING); + EXPECT_TRUE(audioDeviceConfigs.useCoreAudioVolume); + EXPECT_FALSE(audioDeviceConfigs.useHalDuckingSignals); + EXPECT_FALSE(audioDeviceConfigs.useCarVolumeGroupMuting); + + const auto& mirroringDevices = converter->getOutputMirroringDevices(); + + EXPECT_THAT(mirroringDevices, UnorderedElementsAreArray(kMultiZoneMirroringDevices)); + + const auto zones = converter->getAudioZones(); + EXPECT_THAT(zones, UnorderedElementsAreArray(kMultiZones)); +} + +class MalformedCarAudioConfigurationTest : public testing::Test { + protected: + void TearDown() override; + + std::unique_ptr converter; +}; + +void MalformedCarAudioConfigurationTest::TearDown() { + converter.reset(); +} + +TEST_F(MalformedCarAudioConfigurationTest, TestLoadEmptyConfiguration) { + converter = + std::make_unique(getTestFilePath(""), ""); + EXPECT_THAT(converter->getErrors(), ContainsRegex("Configuration file .+ is not readable")) + << "Empty configuration file"; + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::DEFAULT_AUDIO_ROUTING) + << "Default configuration for empty file"; +} + +TEST_F(MalformedCarAudioConfigurationTest, TestLoadNonExistingConfiguration) { + converter = std::make_unique( + getTestFilePath("non_existing_file.xml"), ""); + EXPECT_THAT(converter->getErrors(), ContainsRegex("Configuration file .+ is not readable")) + << "Empty configuration file"; + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::DEFAULT_AUDIO_ROUTING) + << "Default configuration for empty file"; +} + +TEST_F(MalformedCarAudioConfigurationTest, TestLoadMalforedConfiguration) { + converter = std::make_unique( + getTestFilePath("car_audio_configuration_without_configuration.xml"), ""); + EXPECT_THAT(converter->getErrors(), + ContainsRegex("Configuration file .+ does not have any configurations")) + << "Configuration file without configurations"; + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::DEFAULT_AUDIO_ROUTING) + << "Default configuration for malformed file"; +} + +TEST_F(MalformedCarAudioConfigurationTest, TestLoadConfigurationWithoutZones) { + converter = std::make_unique( + getTestFilePath("car_audio_configuration_without_audio_zone.xml"), ""); + EXPECT_THAT(converter->getErrors(), ContainsRegex("Audio zones not found in file")) + << "Configuration file without zones"; + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::DEFAULT_AUDIO_ROUTING) + << "Default configuration for file without zones"; +} + +TEST_F(MalformedCarAudioConfigurationTest, TestLoadConfigurationWithMissingZones) { + converter = std::make_unique( + getTestFilePath("car_audio_configuration_with_missing_zones.xml"), ""); + EXPECT_THAT(converter->getErrors(), ContainsRegex("Error parsing audio zone")) + << "Configuration file with missing zones"; + + const auto audioDeviceConfigs = converter->getAudioDeviceConfiguration(); + EXPECT_EQ(audioDeviceConfigs.routingConfig, + api::RoutingDeviceConfiguration::DEFAULT_AUDIO_ROUTING) + << "Default configuration for file with missing zones"; +} + +} // namespace diff --git a/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_with_default_context.xml b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_with_default_context.xml new file mode 100644 index 0000000000..80cb5cdfc1 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_with_default_context.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_with_missing_zones.xml b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_with_missing_zones.xml new file mode 100644 index 0000000000..a5880b33f4 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_with_missing_zones.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_without_audio_zone.xml b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_without_audio_zone.xml new file mode 100644 index 0000000000..1e50e6e2d2 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_without_audio_zone.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_without_configuration.xml b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_without_configuration.xml new file mode 100644 index 0000000000..4f50ca260c --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/car_audio_configuration_without_configuration.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/automotive/audiocontrol/aidl/default/converter/test/car_audio_fade_configuration.xml b/automotive/audiocontrol/aidl/default/converter/test/car_audio_fade_configuration.xml new file mode 100644 index 0000000000..249f915815 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/car_audio_fade_configuration.xml @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/converter/test/multi_zone_car_audio_configuration.xml b/automotive/audiocontrol/aidl/default/converter/test/multi_zone_car_audio_configuration.xml new file mode 100644 index 0000000000..f0c9081f59 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/multi_zone_car_audio_configuration.xml @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/converter/test/simple_car_audio_configuration.xml b/automotive/audiocontrol/aidl/default/converter/test/simple_car_audio_configuration.xml new file mode 100644 index 0000000000..a6f5317a41 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/simple_car_audio_configuration.xml @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/converter/test/simple_car_audio_configuration_with_device_type.xml b/automotive/audiocontrol/aidl/default/converter/test/simple_car_audio_configuration_with_device_type.xml new file mode 100644 index 0000000000..eec9db9c71 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/converter/test/simple_car_audio_configuration_with_device_type.xml @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/loaders/config/Android.bp b/automotive/audiocontrol/aidl/default/loaders/config/Android.bp new file mode 100644 index 0000000000..0d5eb8139c --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/config/Android.bp @@ -0,0 +1,45 @@ +// Copyright (C) 2024 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +xsd_config { + name: "car_audio_configuration_xsd", + srcs: ["car_audio_configuration.xsd"], + package_name: "android.hardware.automotive.audiocontrol", + nullability: true, +} + +cc_defaults { + name: "car.audio.configuration.xsd.default", + static_libs: [ + "libxml2", + ], + generated_sources: [ + "car_audio_configuration_xsd", + ], + generated_headers: [ + "car_audio_configuration_xsd", + ], + header_libs: [ + "libxsdc-utils", + ], +} diff --git a/automotive/audiocontrol/aidl/default/loaders/config/api/current.txt b/automotive/audiocontrol/aidl/default/loaders/config/api/current.txt new file mode 100644 index 0000000000..c87b8c6adb --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/config/api/current.txt @@ -0,0 +1,331 @@ +// Signature format: 2.0 +package android.hardware.automotive.audiocontrol { + + public enum ActivationType { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.ActivationType onBoot; + enum_constant public static final android.hardware.automotive.audiocontrol.ActivationType onPlaybackChanged; + enum_constant public static final android.hardware.automotive.audiocontrol.ActivationType onSourceChanged; + } + + public class ActivationVolumeConfigEntryType { + ctor public ActivationVolumeConfigEntryType(); + method @Nullable public android.hardware.automotive.audiocontrol.ActivationType getInvocationType(); + method @Nullable public String getMaxActivationVolumePercentage(); + method @Nullable public String getMinActivationVolumePercentage(); + method public void setInvocationType(@Nullable android.hardware.automotive.audiocontrol.ActivationType); + method public void setMaxActivationVolumePercentage(@Nullable String); + method public void setMinActivationVolumePercentage(@Nullable String); + } + + public class ActivationVolumeConfigType { + ctor public ActivationVolumeConfigType(); + method @Nullable public java.util.List getActivationVolumeConfigEntry(); + method @Nullable public String getName(); + method public void setName(@Nullable String); + } + + public class ActivationVolumeConfigsType { + ctor public ActivationVolumeConfigsType(); + method @Nullable public java.util.List getActivationVolumeConfig(); + } + + public class ApplyFadeConfigType { + ctor public ApplyFadeConfigType(); + method @Nullable public java.util.List getAudioAttributes(); + method @Nullable public boolean getIsDefault(); + method @Nullable public String getName(); + method public void setIsDefault(@Nullable boolean); + method public void setName(@Nullable String); + } + + public class ApplyFadeConfigsType { + ctor public ApplyFadeConfigsType(); + method @Nullable public java.util.List getFadeConfig(); + } + + public class AttributesType { + ctor public AttributesType(); + method @Nullable public android.hardware.automotive.audiocontrol.ContentTypeEnum getContentType(); + method @Nullable public String getTags(); + method @Nullable public android.hardware.automotive.audiocontrol.UsageEnumType getUsage(); + method public void setContentType(@Nullable android.hardware.automotive.audiocontrol.ContentTypeEnum); + method public void setTags(@Nullable String); + method public void setUsage(@Nullable android.hardware.automotive.audiocontrol.UsageEnumType); + } + + public class AudioAttributeUsagesType { + ctor public AudioAttributeUsagesType(); + method @Nullable public java.util.List getUsage(); + } + + public class AudioAttributesUsagesType { + ctor public AudioAttributesUsagesType(); + method @Nullable public java.util.List getAudioAttribute_optional(); + method @Nullable public java.util.List getUsage_optional(); + } + + public class CarAudioConfigurationType { + ctor public CarAudioConfigurationType(); + method @Nullable public android.hardware.automotive.audiocontrol.ActivationVolumeConfigsType getActivationVolumeConfigs(); + method @Nullable public android.hardware.automotive.audiocontrol.DeviceConfigurationsType getDeviceConfigurations(); + method @Nullable public android.hardware.automotive.audiocontrol.MirroringDevicesType getMirroringDevices(); + method @Nullable public android.hardware.automotive.audiocontrol.OemContextsType getOemContexts(); + method @Nullable public String getVersion(); + method @Nullable public android.hardware.automotive.audiocontrol.ZonesType getZones(); + method public void setActivationVolumeConfigs(@Nullable android.hardware.automotive.audiocontrol.ActivationVolumeConfigsType); + method public void setDeviceConfigurations(@Nullable android.hardware.automotive.audiocontrol.DeviceConfigurationsType); + method public void setMirroringDevices(@Nullable android.hardware.automotive.audiocontrol.MirroringDevicesType); + method public void setOemContexts(@Nullable android.hardware.automotive.audiocontrol.OemContextsType); + method public void setVersion(@Nullable String); + method public void setZones(@Nullable android.hardware.automotive.audiocontrol.ZonesType); + } + + public class ContentType { + ctor public ContentType(); + method @Nullable public android.hardware.automotive.audiocontrol.ContentTypeEnum getValue(); + method public void setValue(@Nullable android.hardware.automotive.audiocontrol.ContentTypeEnum); + } + + public enum ContentTypeEnum { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.ContentTypeEnum AUDIO_CONTENT_TYPE_MOVIE; + enum_constant public static final android.hardware.automotive.audiocontrol.ContentTypeEnum AUDIO_CONTENT_TYPE_MUSIC; + enum_constant public static final android.hardware.automotive.audiocontrol.ContentTypeEnum AUDIO_CONTENT_TYPE_SONIFICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.ContentTypeEnum AUDIO_CONTENT_TYPE_SPEECH; + enum_constant public static final android.hardware.automotive.audiocontrol.ContentTypeEnum AUDIO_CONTENT_TYPE_UNKNOWN; + } + + public class ContextNameType { + ctor public ContextNameType(); + method @Nullable public String getContext(); + method public void setContext(@Nullable String); + } + + public class DeviceConfigurationType { + ctor public DeviceConfigurationType(); + method @Nullable public String getName(); + method @Nullable public String getValue(); + method public void setName(@Nullable String); + method public void setValue(@Nullable String); + } + + public class DeviceConfigurationsType { + ctor public DeviceConfigurationsType(); + method @Nullable public java.util.List getDeviceConfiguration(); + } + + public class DeviceRoutesType { + ctor public DeviceRoutesType(); + method @Nullable public String getAddress(); + method @Nullable public java.util.List getContext(); + method @Nullable public android.hardware.automotive.audiocontrol.OutDeviceType getType(); + method public void setAddress(@Nullable String); + method public void setType(@Nullable android.hardware.automotive.audiocontrol.OutDeviceType); + } + + public enum InDeviceType { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_AMBIENT; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_AUX_DIGITAL; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_BACK_MIC; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_BLUETOOTH_A2DP; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_BLUETOOTH_BLE; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_BUILTIN_MIC; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_BUS; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_COMMUNICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_DEFAULT; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_ECHO_REFERENCE; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_FM_TUNER; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_HDMI; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_HDMI_ARC; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_IP; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_LINE; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_LOOPBACK; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_PROXY; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_REMOTE_SUBMIX; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_SPDIF; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_STUB; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_TELEPHONY_RX; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_TV_TUNER; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_USB_ACCESSORY; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_USB_DEVICE; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_USB_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_VOICE_CALL; + enum_constant public static final android.hardware.automotive.audiocontrol.InDeviceType AUDIO_DEVICE_IN_WIRED_HEADSET; + } + + public class InputDeviceType { + ctor public InputDeviceType(); + method @Nullable public String getAddress(); + method @Nullable public android.hardware.automotive.audiocontrol.InDeviceType getType(); + method public void setAddress(@Nullable String); + method public void setType(@Nullable android.hardware.automotive.audiocontrol.InDeviceType); + } + + public class InputDevicesType { + ctor public InputDevicesType(); + method @Nullable public java.util.List getInputDevice(); + } + + public class MirroringDevice { + ctor public MirroringDevice(); + method @Nullable public String getAddress(); + method public void setAddress(@Nullable String); + } + + public class MirroringDevicesType { + ctor public MirroringDevicesType(); + method @Nullable public java.util.List getMirroringDevice(); + } + + public class OemContextType { + ctor public OemContextType(); + method @Nullable public android.hardware.automotive.audiocontrol.AudioAttributesUsagesType getAudioAttributes(); + method @Nullable public String getId(); + method @Nullable public String getName(); + method public void setAudioAttributes(@Nullable android.hardware.automotive.audiocontrol.AudioAttributesUsagesType); + method public void setId(@Nullable String); + method public void setName(@Nullable String); + } + + public class OemContextsType { + ctor public OemContextsType(); + method @Nullable public java.util.List getOemContext(); + } + + public enum OutDeviceType { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_AUX_DIGITAL; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_AUX_LINE; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_BLE_BROADCAST; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_BLE_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_BLE_SPEAKER; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_BUS; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_DEFAULT; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_HDMI; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_HDMI_ARC; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_HDMI_EARC; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_LINE; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_SPEAKER; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_SPEAKER_SAFE; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_USB_ACCESSORY; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_USB_DEVICE; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_USB_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_WIRED_HEADPHONE; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType AUDIO_DEVICE_OUT_WIRED_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_AUX_LINE; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_BLE_BROADCAST; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_BLE_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_BLE_SPEAKER; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_BLUETOOTH_A2DP; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_BUILTIN_SPEAKER; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_BUS; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_HDMI; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_USB_ACCESSORY; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_USB_DEVICE; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_USB_HEADSET; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_WIRED_HEADPHONES; + enum_constant public static final android.hardware.automotive.audiocontrol.OutDeviceType TYPE_WIRED_HEADSET; + } + + public enum UsageEnumType { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_ALARM; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_ANNOUNCEMENT; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_ASSISTANCE_SONIFICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_ASSISTANT; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_CALL_ASSISTANT; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_EMERGENCY; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_GAME; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_MEDIA; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_NOTIFICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_NOTIFICATION_EVENT; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_SAFETY; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_UNKNOWN; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_VEHICLE_STATUS; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_VIRTUAL_SOURCE; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_VOICE_COMMUNICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.UsageEnumType AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING; + } + + public class UsageType { + ctor public UsageType(); + method @Nullable public android.hardware.automotive.audiocontrol.UsageEnumType getValue(); + method public void setValue(@Nullable android.hardware.automotive.audiocontrol.UsageEnumType); + } + + public class VolumeGroupType { + ctor public VolumeGroupType(); + method @Nullable public String getActivationConfig(); + method @Nullable public java.util.List getDevice(); + method @Nullable public String getName(); + method public void setActivationConfig(@Nullable String); + method public void setName(@Nullable String); + } + + public class VolumeGroupsType { + ctor public VolumeGroupsType(); + method @Nullable public java.util.List getGroup(); + } + + public class XmlParser { + ctor public XmlParser(); + method @Nullable public static android.hardware.automotive.audiocontrol.CarAudioConfigurationType read(@NonNull java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method @Nullable public static String readText(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public static void skip(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + } + + public class ZoneConfigType { + ctor public ZoneConfigType(); + method @Nullable public android.hardware.automotive.audiocontrol.ApplyFadeConfigsType getApplyFadeConfigs(); + method @Nullable public boolean getIsDefault(); + method @Nullable public String getName(); + method @Nullable public android.hardware.automotive.audiocontrol.VolumeGroupsType getVolumeGroups(); + method public void setApplyFadeConfigs(@Nullable android.hardware.automotive.audiocontrol.ApplyFadeConfigsType); + method public void setIsDefault(@Nullable boolean); + method public void setName(@Nullable String); + method public void setVolumeGroups(@Nullable android.hardware.automotive.audiocontrol.VolumeGroupsType); + } + + public class ZoneConfigsType { + ctor public ZoneConfigsType(); + method @Nullable public android.hardware.automotive.audiocontrol.ZoneConfigType getZoneConfig(); + method public void setZoneConfig(@Nullable android.hardware.automotive.audiocontrol.ZoneConfigType); + } + + public class ZoneType { + ctor public ZoneType(); + method @Nullable public String getAudioZoneId(); + method @Nullable public android.hardware.automotive.audiocontrol.InputDevicesType getInputDevices(); + method @Nullable public boolean getIsPrimary(); + method @Nullable public String getName(); + method @Nullable public String getOccupantZoneId(); + method @Nullable public android.hardware.automotive.audiocontrol.ZoneConfigsType getZoneConfigs(); + method public void setAudioZoneId(@Nullable String); + method public void setInputDevices(@Nullable android.hardware.automotive.audiocontrol.InputDevicesType); + method public void setIsPrimary(@Nullable boolean); + method public void setName(@Nullable String); + method public void setOccupantZoneId(@Nullable String); + method public void setZoneConfigs(@Nullable android.hardware.automotive.audiocontrol.ZoneConfigsType); + } + + public class ZonesType { + ctor public ZonesType(); + method @Nullable public java.util.List getZone(); + } + +} + diff --git a/automotive/audiocontrol/aidl/default/loaders/config/api/last_current.txt b/automotive/audiocontrol/aidl/default/loaders/config/api/last_current.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/automotive/audiocontrol/aidl/default/loaders/config/api/last_removed.txt b/automotive/audiocontrol/aidl/default/loaders/config/api/last_removed.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/automotive/audiocontrol/aidl/default/loaders/config/api/removed.txt b/automotive/audiocontrol/aidl/default/loaders/config/api/removed.txt new file mode 100644 index 0000000000..d802177e24 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/config/api/removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/automotive/audiocontrol/aidl/default/loaders/config/car_audio_configuration.xsd b/automotive/audiocontrol/aidl/default/loaders/config/car_audio_configuration.xsd new file mode 100644 index 0000000000..634aedab66 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/config/car_audio_configuration.xsd @@ -0,0 +1,248 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/default/loaders/fade/Android.bp b/automotive/audiocontrol/aidl/default/loaders/fade/Android.bp new file mode 100644 index 0000000000..3dbc2f1ce0 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/fade/Android.bp @@ -0,0 +1,45 @@ +// Copyright (C) 2024 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +xsd_config { + name: "car_fade_audio_configuration_xsd", + srcs: ["car_fade_audio_configuration.xsd"], + package_name: "android.hardware.automotive.audiocontrol.fade", + nullability: true, +} + +cc_defaults { + name: "car.fade.configuration.xsd.default", + static_libs: [ + "libxml2", + ], + generated_sources: [ + "car_fade_audio_configuration_xsd", + ], + generated_headers: [ + "car_fade_audio_configuration_xsd", + ], + header_libs: [ + "libxsdc-utils", + ], +} diff --git a/automotive/audiocontrol/aidl/default/loaders/fade/api/current.txt b/automotive/audiocontrol/aidl/default/loaders/fade/api/current.txt new file mode 100644 index 0000000000..f40f1bef4f --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/fade/api/current.txt @@ -0,0 +1,160 @@ +// Signature format: 2.0 +package android.hardware.automotive.audiocontrol.fade { + + public class AttributesType { + ctor public AttributesType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.ContentTypeEnum getContentType(); + method @Nullable public String getTags(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.UsageEnumType getUsage(); + method public void setContentType(@Nullable android.hardware.automotive.audiocontrol.fade.ContentTypeEnum); + method public void setTags(@Nullable String); + method public void setUsage(@Nullable android.hardware.automotive.audiocontrol.fade.UsageEnumType); + } + + public class AudioAttributesUsagesType { + ctor public AudioAttributesUsagesType(); + method @Nullable public java.util.List getAudioAttribute_optional(); + method @Nullable public java.util.List getUsage_optional(); + } + + public class CarAudioFadeConfigurationType { + ctor public CarAudioFadeConfigurationType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeConfigurationConfigs getConfigs(); + method public void setConfigs(@Nullable android.hardware.automotive.audiocontrol.fade.FadeConfigurationConfigs); + } + + public class ContentType { + ctor public ContentType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.ContentTypeEnum getValue(); + method public void setValue(@Nullable android.hardware.automotive.audiocontrol.fade.ContentTypeEnum); + } + + public enum ContentTypeEnum { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.fade.ContentTypeEnum AUDIO_CONTENT_TYPE_MOVIE; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.ContentTypeEnum AUDIO_CONTENT_TYPE_MUSIC; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.ContentTypeEnum AUDIO_CONTENT_TYPE_SONIFICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.ContentTypeEnum AUDIO_CONTENT_TYPE_SPEECH; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.ContentTypeEnum AUDIO_CONTENT_TYPE_UNKNOWN; + } + + public class FadeConfigurationConfig { + ctor public FadeConfigurationConfig(); + method @Nullable public String getDefaultFadeInDelayForOffenders(); + method @Nullable public String getDefaultFadeInDurationInMillis(); + method @Nullable public String getDefaultFadeOutDurationInMillis(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeInConfigurationsType getFadeInConfigurations(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeOutConfigurationsType getFadeOutConfigurations(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeStateType getFadeState(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeableUsagesType getFadeableUsages(); + method @Nullable public String getName(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.UnfadeableAudioAttributesType getUnfadeableAudioAttributes(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.UnfadeableContentTypesType getUnfadeableContentTypes(); + method public void setDefaultFadeInDelayForOffenders(@Nullable String); + method public void setDefaultFadeInDurationInMillis(@Nullable String); + method public void setDefaultFadeOutDurationInMillis(@Nullable String); + method public void setFadeInConfigurations(@Nullable android.hardware.automotive.audiocontrol.fade.FadeInConfigurationsType); + method public void setFadeOutConfigurations(@Nullable android.hardware.automotive.audiocontrol.fade.FadeOutConfigurationsType); + method public void setFadeState(@Nullable android.hardware.automotive.audiocontrol.fade.FadeStateType); + method public void setFadeableUsages(@Nullable android.hardware.automotive.audiocontrol.fade.FadeableUsagesType); + method public void setName(@Nullable String); + method public void setUnfadeableAudioAttributes(@Nullable android.hardware.automotive.audiocontrol.fade.UnfadeableAudioAttributesType); + method public void setUnfadeableContentTypes(@Nullable android.hardware.automotive.audiocontrol.fade.UnfadeableContentTypesType); + } + + public class FadeConfigurationConfigs { + ctor public FadeConfigurationConfigs(); + method @Nullable public java.util.List getConfig(); + } + + public class FadeConfigurationType { + ctor public FadeConfigurationType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.AudioAttributesUsagesType getAudioAttributes(); + method @Nullable public String getFadeDurationMillis(); + method public void setAudioAttributes(@Nullable android.hardware.automotive.audiocontrol.fade.AudioAttributesUsagesType); + method public void setFadeDurationMillis(@Nullable String); + } + + public class FadeInConfigurationsType { + ctor public FadeInConfigurationsType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeConfigurationType getFadeConfiguration(); + method public void setFadeConfiguration(@Nullable android.hardware.automotive.audiocontrol.fade.FadeConfigurationType); + } + + public class FadeOutConfigurationsType { + ctor public FadeOutConfigurationsType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeConfigurationType getFadeConfiguration(); + method public void setFadeConfiguration(@Nullable android.hardware.automotive.audiocontrol.fade.FadeConfigurationType); + } + + public enum FadeStateEnumType { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.fade.FadeStateEnumType FADE_STATE_DISABLED; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.FadeStateEnumType FADE_STATE_ENABLED_DEFAULT; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.FadeStateEnumType _0; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.FadeStateEnumType _1; + } + + public class FadeStateType { + ctor public FadeStateType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.FadeStateEnumType getValue(); + method public void setValue(@Nullable android.hardware.automotive.audiocontrol.fade.FadeStateEnumType); + } + + public class FadeableUsagesType { + ctor public FadeableUsagesType(); + method @Nullable public java.util.List getUsage(); + } + + public class UnfadeableAudioAttributesType { + ctor public UnfadeableAudioAttributesType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.AudioAttributesUsagesType getAudioAttributes(); + method public void setAudioAttributes(@Nullable android.hardware.automotive.audiocontrol.fade.AudioAttributesUsagesType); + } + + public class UnfadeableContentTypesType { + ctor public UnfadeableContentTypesType(); + method @Nullable public java.util.List getContentType(); + } + + public enum UsageEnumType { + method @NonNull public String getRawName(); + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_ALARM; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_ANNOUNCEMENT; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_ASSISTANCE_SONIFICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_ASSISTANT; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_CALL_ASSISTANT; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_EMERGENCY; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_GAME; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_MEDIA; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_NOTIFICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_NOTIFICATION_EVENT; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_SAFETY; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_UNKNOWN; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_VEHICLE_STATUS; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_VIRTUAL_SOURCE; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_VOICE_COMMUNICATION; + enum_constant public static final android.hardware.automotive.audiocontrol.fade.UsageEnumType AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING; + } + + public class UsageType { + ctor public UsageType(); + method @Nullable public android.hardware.automotive.audiocontrol.fade.UsageEnumType getValue(); + method public void setValue(@Nullable android.hardware.automotive.audiocontrol.fade.UsageEnumType); + } + + public class XmlParser { + ctor public XmlParser(); + method @Nullable public static android.hardware.automotive.audiocontrol.fade.CarAudioFadeConfigurationType read(@NonNull java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method @Nullable public static String readText(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public static void skip(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + } + +} + diff --git a/automotive/audiocontrol/aidl/default/loaders/fade/api/last_current.txt b/automotive/audiocontrol/aidl/default/loaders/fade/api/last_current.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/automotive/audiocontrol/aidl/default/loaders/fade/api/last_removed.txt b/automotive/audiocontrol/aidl/default/loaders/fade/api/last_removed.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/automotive/audiocontrol/aidl/default/loaders/fade/api/removed.txt b/automotive/audiocontrol/aidl/default/loaders/fade/api/removed.txt new file mode 100644 index 0000000000..d802177e24 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/fade/api/removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/automotive/audiocontrol/aidl/default/loaders/fade/car_fade_audio_configuration.xsd b/automotive/audiocontrol/aidl/default/loaders/fade/car_fade_audio_configuration.xsd new file mode 100644 index 0000000000..051be7e286 --- /dev/null +++ b/automotive/audiocontrol/aidl/default/loaders/fade/car_fade_audio_configuration.xsd @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/audiocontrol/aidl/rust_impl/Android.bp b/automotive/audiocontrol/aidl/rust_impl/Android.bp index 062d989bab..f9d07b22ce 100644 --- a/automotive/audiocontrol/aidl/rust_impl/Android.bp +++ b/automotive/audiocontrol/aidl/rust_impl/Android.bp @@ -15,7 +15,7 @@ */ rust_binary { - name: "android.hardware.automotive.audiocontrol-V4-rust-service", + name: "android.hardware.automotive.audiocontrol-rust-service", relative_install_path: "hw", vendor: true, srcs: ["src/*.rs"], @@ -23,6 +23,7 @@ rust_binary { defaults: [ "latest_android_hardware_automotive_audiocontrol_rust", "latest_android_hardware_audio_common_rust", + "latest_android_media_audio_common_types_rust", ], vintf_fragments: ["audiocontrol-rust-service.xml"], init_rc: ["audiocontrol-rust-service.rc"], diff --git a/automotive/audiocontrol/aidl/rust_impl/README.md b/automotive/audiocontrol/aidl/rust_impl/README.md index ed22356920..b68daf3f87 100644 --- a/automotive/audiocontrol/aidl/rust_impl/README.md +++ b/automotive/audiocontrol/aidl/rust_impl/README.md @@ -6,7 +6,7 @@ not contain any actual implementation. This folder contains a skeleton audio control HAL implementation in Rust to demonstrate how vendor may implement a Rust audio control HAL. To run this audio control HAL, include -`android.hardware.automotive.audiocontrol-V4-rust-service` in your image. +`android.hardware.automotive.audiocontrol-rust-service` in your image. This implementation returns `StatusCode::UNKNOWN_ERROR` for all operations and does not pass VTS/CTS. Vendor must replace the logic in diff --git a/automotive/audiocontrol/aidl/rust_impl/src/default_audio_control_hal.rs b/automotive/audiocontrol/aidl/rust_impl/src/default_audio_control_hal.rs index ba0ca238f4..8184c436fc 100644 --- a/automotive/audiocontrol/aidl/rust_impl/src/default_audio_control_hal.rs +++ b/automotive/audiocontrol/aidl/rust_impl/src/default_audio_control_hal.rs @@ -23,8 +23,15 @@ use android_hardware_automotive_audiocontrol::aidl::android::hardware::automotiv IModuleChangeCallback::IModuleChangeCallback, MutingInfo::MutingInfo, Reasons::Reasons, + AudioDeviceConfiguration::AudioDeviceConfiguration, + AudioZone::AudioZone +}; +use android_hardware_audio_common::aidl::android::hardware::audio::common::{ + PlaybackTrackMetadata::PlaybackTrackMetadata, +}; +use android_media_audio_common_types::aidl::android::media::audio::common::{ + AudioPort::AudioPort, }; -use android_hardware_audio_common::aidl::android::hardware::audio::common::PlaybackTrackMetadata::PlaybackTrackMetadata; use binder::{Interface, Result as BinderResult, StatusCode, Strong}; /// This struct is defined to implement IAudioControl AIDL interface. @@ -81,4 +88,16 @@ impl IAudioControl for DefaultAudioControlHal { fn clearModuleChangeCallback(&self) -> BinderResult<()> { Err(StatusCode::UNKNOWN_ERROR.into()) } + + fn getAudioDeviceConfiguration(&self) -> std::result::Result { + Err(binder::StatusCode::UNKNOWN_ERROR.into()) + } + + fn getOutputMirroringDevices(&self) -> std::result::Result, binder::Status> { + Err(binder::StatusCode::UNKNOWN_ERROR.into()) + } + + fn getCarAudioZones(&self) -> std::result::Result, binder::Status> { + Err(binder::StatusCode::UNKNOWN_ERROR.into()) + } } diff --git a/automotive/audiocontrol/aidl/vts/Android.bp b/automotive/audiocontrol/aidl/vts/Android.bp index d94ad556dc..57c6ae47ff 100644 --- a/automotive/audiocontrol/aidl/vts/Android.bp +++ b/automotive/audiocontrol/aidl/vts/Android.bp @@ -22,6 +22,25 @@ package { default_applicable_licenses: ["hardware_interfaces_license"], } +cc_library { + name: "AudioControlHalTestUtils", + srcs: [ + "src/AudioControlTestUtils.cpp", + ], + export_include_dirs: [ + "include", + ], + defaults: [ + "latest_android_hardware_audio_common_cpp_static", + "latest_android_hardware_automotive_audiocontrol_cpp_static", + "latest_android_media_audio_common_types_cpp_static", + ], + shared_libs: [ + "libbase", + "libutils", + ], +} + cc_test { name: "VtsAidlHalAudioControlTest", defaults: [ @@ -39,9 +58,11 @@ cc_test { "libbinder", "libbase", "libxml2", + "libutils", ], static_libs: [ "libgmock", + "AudioControlHalTestUtils", ], test_suites: [ "general-tests", diff --git a/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp b/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp index 4e7e963981..6e646a6ddd 100644 --- a/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp +++ b/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include @@ -26,24 +28,49 @@ #include #include #include +#include using android::ProcessState; using android::sp; using android::String16; using android::binder::Status; +using android::hardware::automotive::audiocontrol::AudioDeviceConfiguration; +using android::hardware::automotive::audiocontrol::AudioFadeConfiguration; using android::hardware::automotive::audiocontrol::AudioFocusChange; using android::hardware::automotive::audiocontrol::AudioGainConfigInfo; +using android::hardware::automotive::audiocontrol::AudioZone; +using android::hardware::automotive::audiocontrol::AudioZoneConfig; +using android::hardware::automotive::audiocontrol::AudioZoneContextInfo; +using android::hardware::automotive::audiocontrol::AudioZoneFadeConfiguration; using android::hardware::automotive::audiocontrol::BnAudioGainCallback; using android::hardware::automotive::audiocontrol::BnFocusListener; using android::hardware::automotive::audiocontrol::BnModuleChangeCallback; +using android::hardware::automotive::audiocontrol::DeviceToContextEntry; using android::hardware::automotive::audiocontrol::DuckingInfo; +using android::hardware::automotive::audiocontrol::FadeConfiguration; using android::hardware::automotive::audiocontrol::IAudioControl; using android::hardware::automotive::audiocontrol::IModuleChangeCallback; using android::hardware::automotive::audiocontrol::MutingInfo; using android::hardware::automotive::audiocontrol::Reasons; +using android::hardware::automotive::audiocontrol::VolumeActivationConfiguration; +using android::hardware::automotive::audiocontrol::VolumeActivationConfigurationEntry; +using android::hardware::automotive::audiocontrol::VolumeGroupConfig; +using android::hardware::automotive::audiocontrol::RoutingDeviceConfiguration:: + CONFIGURABLE_AUDIO_ENGINE_ROUTING; +using android::hardware::automotive::audiocontrol::RoutingDeviceConfiguration:: + DEFAULT_AUDIO_ROUTING; +using android::hardware::automotive::audiocontrol::VolumeActivationConfigurationEntry:: + DEFAULT_MAX_ACTIVATION_VALUE; +using android::hardware::automotive::audiocontrol::VolumeActivationConfigurationEntry:: + DEFAULT_MIN_ACTIVATION_VALUE; using ::testing::AnyOf; using ::testing::Eq; +using ::testing::Not; +using ::testing::UnorderedElementsAreArray; + +using android::internal::ToString; + #include "android_audio_policy_configuration_V7_0.h" namespace xsd { @@ -52,11 +79,218 @@ using namespace android::audio::policy::configuration::V7_0; namespace audiohalcommon = android::hardware::audio::common; namespace audiomediacommon = android::media::audio::common; +namespace testutils = android::hardware::audiocontrol::testutils; namespace { constexpr int32_t kAidlVersionThree = 3; +constexpr int32_t kAidlVersionFive = 5; + +bool hasValidVolumeGroupActivation(const VolumeActivationConfiguration& activation, + std::string& message) { + if (activation.volumeActivationEntries.empty()) { + message = "Volume group activation must have at least one volume activation entry"; + return false; + } + for (const auto& entry : activation.volumeActivationEntries) { + int32_t max = entry.maxActivationVolumePercentage; + int32_t min = entry.minActivationVolumePercentage; + if (min > DEFAULT_MAX_ACTIVATION_VALUE || min < DEFAULT_MIN_ACTIVATION_VALUE) { + message = "Invalid minActivationVolumePercentage, must be between " + + std::to_string(DEFAULT_MIN_ACTIVATION_VALUE) + " and " + + std::to_string(DEFAULT_MAX_ACTIVATION_VALUE); + return false; + } + if (max > DEFAULT_MAX_ACTIVATION_VALUE || max < DEFAULT_MIN_ACTIVATION_VALUE) { + message = "Invalid maxActivationVolumePercentage, must be between " + + std::to_string(DEFAULT_MIN_ACTIVATION_VALUE) + " and " + + std::to_string(DEFAULT_MAX_ACTIVATION_VALUE); + return false; + } + if (min >= max) { + message = + "Invalid maxActivationVolumePercentage and minActivationVolumePercentage " + "combination, minActivationVolumePercentage must be less than " + "maxActivationVolumePercentage"; + return false; + } + } + return true; } +bool hasValidAudioRoute(const DeviceToContextEntry& entry, std::string& message, + std::set& groupDevices) { + if (entry.contextNames.empty()) { + message = " Contexts can not be empty for DeviceToContextEntry"; + return false; + } + std::set contextInRoute; + for (const auto& context : entry.contextNames) { + if (!contextInRoute.contains(ToString(context))) { + continue; + } + message = " Context can not repeat for the same DeviceToContextEntry"; + return false; + } + audiomediacommon::AudioDeviceDescription description; + if (!testutils::getAudioPortDeviceDescriptor(entry.device, description)) { + message = " DeviceToContextEntry must have a valid device port"; + return false; + } + // BUS type also has empty connection + // Note: OUT_BUS is also mapped to OUT_DEVICE + if (description.type != audiomediacommon::AudioDeviceType::OUT_BUS && + !description.connection.empty()) { + return true; + } + std::string address; + if (!testutils::getAddressForAudioPort(entry.device, address) || address.empty()) { + message = " Address can not be empty for BUS devices"; + return false; + } + if (groupDevices.contains(address)) { + message = " Audio device address can not repeat in the same volume group"; + return false; + } + groupDevices.insert(address); + return true; +} + +inline bool hasValidTimeout(int64_t timeout) { + return timeout > 0; +} +bool hasValidFadeConfiguration(const FadeConfiguration& fadeConfiguration, + const std::string& prefix, std::string& message) { + if (!hasValidTimeout(fadeConfiguration.fadeDurationMillis)) { + message = prefix + " duration must be greater than 0"; + return false; + } + return true; +} +bool hadValidAudioFadeConfiguration(const AudioFadeConfiguration& fadeConfiguration, + std::string& message) { + if (!hasValidTimeout(fadeConfiguration.fadeInDurationMs)) { + message = "Fade-in duration must be greater than 0"; + return false; + } + if (!hasValidTimeout(fadeConfiguration.fadeOutDurationMs)) { + message = "Fade-out duration must be greater than 0"; + return false; + } + if (!hasValidTimeout(fadeConfiguration.fadeInDelayedForOffendersMs)) { + message = "Fade-in delayed for offenders duration must be greater than 0"; + return false; + } + for (const auto& fadeOutConfig : fadeConfiguration.fadeOutConfigurations) { + if (!hasValidFadeConfiguration(fadeOutConfig, "Fade-out", message)) { + return false; + } + } + for (const auto& fadeOutConfig : fadeConfiguration.fadeInConfigurations) { + if (!hasValidFadeConfiguration(fadeOutConfig, "Fade-in", message)) { + return false; + } + } + return true; +} + +void validateVolumeGroupInfo(const AudioZoneConfig& audioZoneConfig, + const VolumeGroupConfig& volumeGroupConfig, + const AudioDeviceConfiguration& deviceConfig) { + std::string zoneConfigName = testutils::toAlphaNumeric(ToString(audioZoneConfig.name)); + std::string volumeGroupName = testutils::toAlphaNumeric(ToString(volumeGroupConfig.name)); + std::string volumeGroupInfo = + "Audio zone config " + zoneConfigName + " volume group " + volumeGroupName; + ALOGI("%s test", volumeGroupInfo.c_str()); + + EXPECT_FALSE(volumeGroupConfig.carAudioRoutes.empty()) + << volumeGroupInfo << " must have at least one audio route"; + if (deviceConfig.routingConfig == CONFIGURABLE_AUDIO_ENGINE_ROUTING) { + EXPECT_FALSE(volumeGroupConfig.name.empty()) + << volumeGroupInfo << " must have a non-empty volume name"; + } + std::set groupDevices; + for (const auto& audioRoute : volumeGroupConfig.carAudioRoutes) { + std::string routeMessage; + EXPECT_TRUE(hasValidAudioRoute(audioRoute, routeMessage, groupDevices)) + << volumeGroupInfo << " Volume route message: " << routeMessage; + } + if (volumeGroupConfig.activationConfiguration.has_value()) { + std::string activationMessage; + EXPECT_TRUE(hasValidVolumeGroupActivation(volumeGroupConfig.activationConfiguration.value(), + activationMessage)) + << volumeGroupInfo << " Activation message: " << activationMessage; + } +} + +void validateAudioZoneFadeConfiguration(const AudioZoneFadeConfiguration& fadeConfiguration) { + ALOGI("Fade configuration test"); + std::set usages; + std::string defaultValidationMessage; + EXPECT_TRUE(hadValidAudioFadeConfiguration(fadeConfiguration.defaultConfiguration, + defaultValidationMessage)) + << "Default configuration validation failed: " << defaultValidationMessage; + for (const auto& entry : fadeConfiguration.transientConfiguration) { + ALOGI("Transient fade configuration test"); + std::string transientFadeConfigurationMessage; + EXPECT_TRUE(hadValidAudioFadeConfiguration(entry.transientFadeConfiguration, + transientFadeConfigurationMessage)) + << "Transient fade configuration validation failed: " + << transientFadeConfigurationMessage; + EXPECT_FALSE(entry.transientUsages.empty()) + << "Transient fade configuration must have at least one audio usage"; + for (const auto& usage : entry.transientUsages) { + EXPECT_FALSE(usages.contains(usage)) << "Audio usages " << ToString(usage) + << " repeat in transient fade configuration"; + } + } +} + +void validateAudioZoneConfiguration(const AudioZone& carAudioZone, + const AudioZoneConfig& audioZoneConfig, + const AudioDeviceConfiguration& deviceConfig) { + std::string zoneConfigName = testutils::toAlphaNumeric(ToString(audioZoneConfig.name)); + ALOGI("Zone config name %s test", zoneConfigName.c_str()); + std::set contextInfoNames; + EXPECT_FALSE(audioZoneConfig.volumeGroups.empty()) + << "Volume groups for zone config " << zoneConfigName.c_str(); + for (const auto& volumeGroup : audioZoneConfig.volumeGroups) { + ALOGI("Zone config name %s volume group test %s", zoneConfigName.c_str(), + ToString(volumeGroup.name).c_str()); + std::vector groupContexts = + testutils::getContextInfoNamesForVolumeGroup(volumeGroup); + for (const auto& context : groupContexts) { + EXPECT_FALSE(contextInfoNames.contains(context)) + << "Context " << context << " repeats in zone config " << zoneConfigName; + contextInfoNames.insert(context); + } + validateVolumeGroupInfo(audioZoneConfig, volumeGroup, deviceConfig); + } + const auto& audioZoneContexts = carAudioZone.audioZoneContext.audioContextInfos; + std::map infoNameToInfo; + std::transform(audioZoneContexts.begin(), audioZoneContexts.end(), + std::inserter(infoNameToInfo, infoNameToInfo.end()), + [&](const AudioZoneContextInfo& context) { + return std::make_pair(ToString(context.name), context); + }); + std::vector configContextInfos; + for (const auto& contextName : contextInfoNames) { + const auto& pair = infoNameToInfo.find(contextName); + if (pair == infoNameToInfo.end()) { + continue; + } + configContextInfos.push_back(pair->second); + } + std::string message; + EXPECT_TRUE(testutils::contextInfosContainAllAudioAttributeUsages(configContextInfos, message)) + << "Config " << zoneConfigName << " message: " << message; + + if (audioZoneConfig.fadeConfiguration.has_value()) { + validateAudioZoneFadeConfiguration(audioZoneConfig.fadeConfiguration.value()); + } +} + +} // namespace + class AudioControlAidl : public testing::TestWithParam { public: virtual void SetUp() override { @@ -292,12 +526,193 @@ TEST_P(AudioControlAidl, RegisterModuleChangeNullCallbackThrowsException) { AnyOf(Eq(Status::EX_ILLEGAL_ARGUMENT), Eq(Status::EX_UNSUPPORTED_OPERATION))); } +class AudioControlVersionFiveAndAbove : public AudioControlAidl { + public: + virtual void SetUp() override { + AudioControlAidl::SetUp(); + if (isAidlVersionAtleast(kAidlVersionFive)) { + return; + } + GTEST_SKIP() << " Version is lower than " << std::to_string(kAidlVersionFive); + } +}; + +class AudioControlWithAudioConfiguration : public AudioControlVersionFiveAndAbove { + public: + virtual void SetUp() override { + AudioControlVersionFiveAndAbove::SetUp(); + + if (IsSkipped()) { + return; + } + + const auto& configStatus = + audioControl->getAudioDeviceConfiguration(&audioDeviceConfiguration); + + EXPECT_THAT(configStatus.exceptionCode(), + AnyOf(Eq(Status::EX_NONE), Eq(Status::EX_UNSUPPORTED_OPERATION))); + if (!configStatus.isOk()) { + GTEST_SKIP() << "Device does not support audio configurations APIs"; + } + ALOGD("Audio device info: %s", audioDeviceConfiguration.toString().c_str()); + } + + AudioDeviceConfiguration audioDeviceConfiguration; +}; + +TEST_P(AudioControlWithAudioConfiguration, DefaultAudioRoutingConfiguration) { + if (audioDeviceConfiguration.routingConfig != DEFAULT_AUDIO_ROUTING) { + GTEST_SKIP() << "Default audio routing not supported"; + } + std::vector zones; + + const auto& zoneStatus = audioControl->getCarAudioZones(&zones); + + EXPECT_THAT(zoneStatus.exceptionCode(), + AnyOf(Eq(Status::EX_NONE), Eq(Status::EX_UNSUPPORTED_OPERATION))) + << "Default routing can be implemented or unsupported"; + if (!zoneStatus.isOk()) return; + EXPECT_TRUE(zones.empty()) << "Zones must be empty for default routing"; +} + +class AudioControlWithDynamicConfiguration : public AudioControlWithAudioConfiguration { + public: + virtual void SetUp() override { + AudioControlWithAudioConfiguration::SetUp(); + if (IsSkipped()) { + return; + } + if (audioDeviceConfiguration.routingConfig == DEFAULT_AUDIO_ROUTING) { + GTEST_SKIP() << "Dynamic/core audio routing not supported"; + } + const auto& zoneStatus = audioControl->getCarAudioZones(&audioZones); + EXPECT_EQ(zoneStatus.exceptionCode(), Status::EX_NONE) + << "Zones API must be supported for core/dynamic routing"; + } + + std::vector audioZones; +}; + +TEST_P(AudioControlWithDynamicConfiguration, DynamicAudioRoutingConfiguration) { + EXPECT_FALSE(audioZones.empty()) << "Zones must not be empty for core/dynamic routing"; +} + +class AudioControlWithAudioZoneInfo : public AudioControlWithDynamicConfiguration { + public: + virtual void SetUp() override { + AudioControlWithDynamicConfiguration::SetUp(); + if (IsSkipped()) { + return; + } + EXPECT_TRUE(!audioZones.empty()) << "Zones must exist for core/dynamic routing"; + } +}; + +TEST_P(AudioControlWithAudioZoneInfo, AudioZonesRequirements) { + bool primaryZoneFound = false; + std::set zoneIds; + std::set occupantIds; + std::set zoneNames; + std::set deviceAddresses; + for (const auto& zone : audioZones) { + if (zone.id == AudioZone::PRIMARY_AUDIO_ZONE) { + EXPECT_FALSE(primaryZoneFound) << "There can only be one primary zone"; + primaryZoneFound = true; + } + EXPECT_FALSE(zoneIds.contains(zone.id)) << "Zone " << std::to_string(zone.id) << " repeats"; + zoneIds.insert(zone.id); + if (!zone.name.empty()) { + EXPECT_FALSE(zoneNames.contains(zone.name)) << "Zone " << zone.name << " repeats"; + zoneNames.insert(zone.name); + } + if (zone.occupantZoneId != AudioZone::UNASSIGNED_OCCUPANT) { + EXPECT_FALSE(occupantIds.contains(zone.occupantZoneId)) + << "Occupant zone id " << zone.occupantZoneId << " repeats"; + occupantIds.insert(zone.occupantZoneId); + } + const auto& zoneAddresses = testutils::getDeviceAddressesForZone(zone); + for (const auto& address : zoneAddresses) { + EXPECT_FALSE(deviceAddresses.contains(address)) + << "Device address " << address << " in zone " << zone.name << " repeats"; + } + // Add after zone comparison is done since devices may repeat within a zone for different + // configurations + deviceAddresses.insert(zoneAddresses.begin(), zoneAddresses.end()); + } + EXPECT_TRUE(primaryZoneFound) << "Primary zone must exist"; +} + +TEST_P(AudioControlWithAudioZoneInfo, AudioZoneInfoRequirements) { + for (const auto& carAudioZone : audioZones) { + ALOGI("Zone id %d test", carAudioZone.id); + std::string missingContextMessage; + EXPECT_TRUE(testutils::contextContainsAllAudioAttributeUsages(carAudioZone.audioZoneContext, + missingContextMessage)) + << "Audio zone context for zone id " << std::to_string(carAudioZone.id) + << missingContextMessage; + EXPECT_FALSE(carAudioZone.audioZoneConfigs.empty()) + << "Audio zone zone id " << std::to_string(carAudioZone.id) + << " missing zone configs"; + std::set configNames; + bool defaultConfigFound = false; + for (const auto& config : carAudioZone.audioZoneConfigs) { + ALOGI("Zone id %d config name %s test", carAudioZone.id, ToString(config.name).c_str()); + if (config.isDefault) { + EXPECT_FALSE(defaultConfigFound) + << "Config name " << config.name + << " repeats default config value in zone id " << carAudioZone.id; + defaultConfigFound = true; + } + EXPECT_FALSE(configNames.contains(config.name)) + << "Config name " << config.name << " repeats in " << carAudioZone.id; + } + EXPECT_TRUE(defaultConfigFound) + << "Audio zone " << carAudioZone.id << " must contain default config"; + std::set inputPorts; + ALOGI("Zone id %d input devices test", carAudioZone.id); + for (const auto& audioPort : carAudioZone.inputAudioDevices) { + std::string address; + const auto hasAddress = testutils::getAddressForAudioPort(audioPort, address); + EXPECT_FALSE(inputPorts.contains(audioPort)) + << "Repeating input device for " << carAudioZone.id << ", device address " + << (hasAddress ? address : "empty address"); + inputPorts.insert(audioPort); + } + } +} + +TEST_P(AudioControlWithAudioZoneInfo, AudioZoneConfigInfoRequirements) { + for (const auto& carAudioZone : audioZones) { + for (const auto& audioZoneConfig : carAudioZone.audioZoneConfigs) { + validateAudioZoneConfiguration(carAudioZone, audioZoneConfig, audioDeviceConfiguration); + } + } +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioControlAidl); INSTANTIATE_TEST_SUITE_P( Audiocontrol, AudioControlAidl, testing::ValuesIn(android::getAidlHalInstanceNames(IAudioControl::descriptor)), android::PrintInstanceNameToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioControlWithAudioConfiguration); +INSTANTIATE_TEST_SUITE_P( + Audiocontrol, AudioControlWithAudioConfiguration, + testing::ValuesIn(android::getAidlHalInstanceNames(IAudioControl::descriptor)), + android::PrintInstanceNameToString); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioControlWithDynamicConfiguration); +INSTANTIATE_TEST_SUITE_P( + Audiocontrol, AudioControlWithDynamicConfiguration, + testing::ValuesIn(android::getAidlHalInstanceNames(IAudioControl::descriptor)), + android::PrintInstanceNameToString); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioControlWithAudioZoneInfo); +INSTANTIATE_TEST_SUITE_P( + Audiocontrol, AudioControlWithAudioZoneInfo, + testing::ValuesIn(android::getAidlHalInstanceNames(IAudioControl::descriptor)), + android::PrintInstanceNameToString); + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); ProcessState::self()->setThreadPoolMaxThreadCount(1); diff --git a/automotive/audiocontrol/aidl/vts/include/AudioControlTestUtils.h b/automotive/audiocontrol/aidl/vts/include/AudioControlTestUtils.h new file mode 100644 index 0000000000..46fdce2111 --- /dev/null +++ b/automotive/audiocontrol/aidl/vts/include/AudioControlTestUtils.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2024 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. + */ + +#ifndef MAIN8_AUDIOCONTROLTESTUTILS_H +#define MAIN8_AUDIOCONTROLTESTUTILS_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace audiocontrol { +namespace testutils { + +std::string toAlphaNumeric(const std::string& info); + +bool getAudioPortDeviceDescriptor( + const android::media::audio::common::AudioPort& audioPort, + android::media::audio::common::AudioDeviceDescription& description); + +bool getAddressForAudioPort(const android::media::audio::common::AudioPort& audioPort, + std::string& address); + +bool getAddressForAudioDevice( + const android::hardware::automotive::audiocontrol::DeviceToContextEntry& device, + std::string& address); + +std::vector getDeviceAddressesForVolumeGroup( + const android::hardware::automotive::audiocontrol::VolumeGroupConfig& config); + +std::vector getDeviceAddressesForZoneConfig( + const android::hardware::automotive::audiocontrol::AudioZoneConfig& config); + +std::vector getDeviceAddressesForZone( + const android::hardware::automotive::audiocontrol::AudioZone& config); + +bool contextInfosContainAllAudioAttributeUsages( + const std::vector& infos, + std::string& message); + +bool contextContainsAllAudioAttributeUsages( + const android::hardware::automotive::audiocontrol::AudioZoneContext& context, + std::string& message); + +std::vector getContextInfoNamesForVolumeGroup( + const android::hardware::automotive::audiocontrol::VolumeGroupConfig& group); + +} // namespace testutils +} // namespace audiocontrol +} // namespace hardware +} // namespace android + +#endif // MAIN8_AUDIOCONTROLTESTUTILS_H diff --git a/automotive/audiocontrol/aidl/vts/src/AudioControlTestUtils.cpp b/automotive/audiocontrol/aidl/vts/src/AudioControlTestUtils.cpp new file mode 100644 index 0000000000..7b7c896fc6 --- /dev/null +++ b/automotive/audiocontrol/aidl/vts/src/AudioControlTestUtils.cpp @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2024 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. + */ + +#include "../include/AudioControlTestUtils.h" + +#include + +using android::hardware::automotive::audiocontrol::AudioZone; +using android::hardware::automotive::audiocontrol::AudioZoneConfig; +using android::hardware::automotive::audiocontrol::AudioZoneContext; +using android::hardware::automotive::audiocontrol::AudioZoneContextInfo; +using android::hardware::automotive::audiocontrol::DeviceToContextEntry; +using android::hardware::automotive::audiocontrol::VolumeGroupConfig; + +namespace audiomediacommon = android::media::audio::common; + +namespace android { +namespace hardware { +namespace audiocontrol { +namespace testutils { + +std::string toAlphaNumeric(const std::string& info) { + std::string name = info; + for (size_t i = 0; i < name.size(); i++) { + // gtest test names must only contain alphanumeric characters + if (!std::isalnum(name[i])) name[i] = '_'; + } + + return name; +} + +bool getAudioPortDeviceDescriptor(const audiomediacommon::AudioPort& audioPort, + audiomediacommon::AudioDeviceDescription& description) { + if (audioPort.ext.getTag() != audiomediacommon::AudioPortExt::Tag::device) { + return false; + } + const auto& audioDevice = + audioPort.ext.get().device; + description = audioDevice.type; + return true; +} + +bool getAddressForAudioPort(const android::media::audio::common::AudioPort& audioPort, + std::string& address) { + if (audioPort.ext.getTag() != audiomediacommon::AudioPortExt::Tag::device) { + return false; + } + const auto& audioDevice = + audioPort.ext.get().device; + + switch (audioDevice.address.getTag()) { + case audiomediacommon::AudioDeviceAddress::Tag::id: + address = audioDevice.address.get(); + return true; + case audiomediacommon::AudioDeviceAddress::Tag::alsa: + address = android::internal::ToString( + audioDevice.address.get()); + return true; + case audiomediacommon::AudioDeviceAddress::Tag::mac: + address = android::internal::ToString( + audioDevice.address.get()); + return true; + case audiomediacommon::AudioDeviceAddress::Tag::ipv4: + address = android::internal::ToString( + audioDevice.address.get()); + return true; + case audiomediacommon::AudioDeviceAddress::Tag::ipv6: + address = android::internal::ToString( + audioDevice.address.get()); + return true; + default: + address = audioDevice.address.toString(); + return true; + } +} + +bool getAddressForAudioDevice(const DeviceToContextEntry& device, std::string& address) { + if (device.device.flags.getTag() == audiomediacommon::AudioIoFlags::input || + device.device.ext.getTag() != audiomediacommon::AudioPortExt::Tag::device) { + return false; + } + return getAddressForAudioPort(device.device, address); +} + +std::vector getDeviceAddressesForVolumeGroup(const VolumeGroupConfig& config) { + std::vector addresses; + for (const auto& route : config.carAudioRoutes) { + std::string address; + if (!getAddressForAudioDevice(route, address)) { + continue; + } + addresses.push_back(address); + } + return addresses; +} + +std::vector getDeviceAddressesForZoneConfig(const AudioZoneConfig& config) { + std::vector addresses; + for (const auto& volumeGroup : config.volumeGroups) { + const auto groupAddresses = getDeviceAddressesForVolumeGroup(volumeGroup); + addresses.insert(addresses.begin(), groupAddresses.begin(), groupAddresses.end()); + } + return addresses; +} + +std::vector getDeviceAddressesForZone(const AudioZone& config) { + std::vector addresses; + for (const auto& zoneConfig : config.audioZoneConfigs) { + const auto groupAddresses = getDeviceAddressesForZoneConfig(zoneConfig); + addresses.insert(addresses.begin(), groupAddresses.begin(), groupAddresses.end()); + } + return addresses; +} + +static void addContextUsages(const AudioZoneContextInfo& info, + std::set& contextUsages) { + for (const auto& audioAttribute : info.audioAttributes) { + contextUsages.insert(audioAttribute.usage); + } +} + +bool contextInfosContainAllAudioAttributeUsages(const std::vector& infos, + std::string& message) { + static const std::vector audioUsages{ + audiomediacommon::AudioUsage::UNKNOWN, + audiomediacommon::AudioUsage::MEDIA, + audiomediacommon::AudioUsage::VOICE_COMMUNICATION, + audiomediacommon::AudioUsage::VOICE_COMMUNICATION_SIGNALLING, + audiomediacommon::AudioUsage::ALARM, + audiomediacommon::AudioUsage::NOTIFICATION, + audiomediacommon::AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE, + audiomediacommon::AudioUsage::NOTIFICATION_EVENT, + audiomediacommon::AudioUsage::ASSISTANCE_ACCESSIBILITY, + audiomediacommon::AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE, + audiomediacommon::AudioUsage::ASSISTANCE_SONIFICATION, + audiomediacommon::AudioUsage::GAME, + audiomediacommon::AudioUsage::ASSISTANT, + audiomediacommon::AudioUsage::CALL_ASSISTANT, + audiomediacommon::AudioUsage::EMERGENCY, + audiomediacommon::AudioUsage::SAFETY, + audiomediacommon::AudioUsage::VEHICLE_STATUS, + audiomediacommon::AudioUsage::ANNOUNCEMENT, + }; + + std::set contextUsages; + for (const auto& contextInfo : infos) { + addContextUsages(contextInfo, contextUsages); + } + + bool allUsagesPresent = true; + for (const auto& usage : audioUsages) { + if (contextUsages.contains(usage)) { + continue; + } + if (message.empty()) { + message = " Missing usage(s): "; + } + message += audiomediacommon::toString(usage) + ", "; + allUsagesPresent = false; + } + return allUsagesPresent; +} + +bool contextContainsAllAudioAttributeUsages(const AudioZoneContext& context, std::string& message) { + return contextInfosContainAllAudioAttributeUsages(context.audioContextInfos, message); +} + +std::vector getContextInfoNamesForAudioRoute(const DeviceToContextEntry& route) { + std::vector contextInfoNames; + contextInfoNames.reserve(route.contextNames.size()); + for (const auto& contextName : route.contextNames) { + contextInfoNames.push_back(android::internal::ToString(contextName)); + } + return contextInfoNames; +} + +std::vector getContextInfoNamesForVolumeGroup(const VolumeGroupConfig& group) { + std::vector contextInfoNames; + for (const auto& route : group.carAudioRoutes) { + std::vector routeContexts = getContextInfoNamesForAudioRoute(route); + contextInfoNames.insert(contextInfoNames.begin(), routeContexts.begin(), + routeContexts.end()); + } + return contextInfoNames; +} + +} // namespace testutils +} // namespace audiocontrol +} // namespace hardware +} // namespace android \ No newline at end of file