Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 18d7585e authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

audio HAL: Support for external device connections

Add methods 'IModule.connect/disconnectExternalDevice' which inform
audio HAL about connection / disconnection of an external
non-attached device. Add method 'getAudioRoutesForPort' to
retrieve only routes that include the specified port.

Update the behavior of 'getAudioPorts' and 'getAudioRoutes'
indicating that the result may change due to instantiation
of new device ports for connected external devices.

Clarify behavior of 'IModule.setAudioPortConfig' that it can not
work with device ports with no profiles.

Add debug flags structure 'ModuleDebug' and method
'IModule.setModuleDebug' to control the debugging aspects. VTS
tests use these flags to test HAL behavior which would otherwise
require human intervention.

Update the default implementation and VTS for the AIDL changes.

Bug: 205884982
Test: atest VtsHalAudioCoreTargetTest
Change-Id: Iad5f7009e283729206f88b6278c8992f7f8a92a2
parent 82c115a8
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ aidl_interface {
        "android/hardware/audio/core/IModule.aidl",
        "android/hardware/audio/core/IStreamIn.aidl",
        "android/hardware/audio/core/IStreamOut.aidl",
        "android/hardware/audio/core/ModuleDebug.aidl",
    ],
    imports: [
        "android.hardware.audio.common-V1",
@@ -94,6 +95,4 @@ aidl_interface {
            },
        },
    },
    versions: [
    ],
}
+4 −0
Original line number Diff line number Diff line
@@ -34,11 +34,15 @@
package android.hardware.audio.core;
@VintfStability
interface IModule {
  void setModuleDebug(in android.hardware.audio.core.ModuleDebug debug);
  android.media.audio.common.AudioPort connectExternalDevice(in android.media.audio.common.AudioPort templateIdAndAdditionalData);
  void disconnectExternalDevice(int portId);
  android.hardware.audio.core.AudioPatch[] getAudioPatches();
  android.media.audio.common.AudioPort getAudioPort(int portId);
  android.media.audio.common.AudioPortConfig[] getAudioPortConfigs();
  android.media.audio.common.AudioPort[] getAudioPorts();
  android.hardware.audio.core.AudioRoute[] getAudioRoutes();
  android.hardware.audio.core.AudioRoute[] getAudioRoutesForAudioPort(int portId);
  android.hardware.audio.core.IStreamIn openInputStream(int portConfigId, in android.hardware.audio.common.SinkMetadata sinkMetadata);
  android.hardware.audio.core.IStreamOut openOutputStream(int portConfigId, in android.hardware.audio.common.SourceMetadata sourceMetadata, in @nullable android.media.audio.common.AudioOffloadInfo offloadInfo);
  android.hardware.audio.core.AudioPatch setAudioPatch(in android.hardware.audio.core.AudioPatch requested);
+38 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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 <name>-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.audio.core;
@JavaDerive(equals=true, toString=true) @VintfStability
parcelable ModuleDebug {
  boolean simulateDeviceConnections;
}
+146 −21
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.hardware.audio.core.AudioPatch;
import android.hardware.audio.core.AudioRoute;
import android.hardware.audio.core.IStreamIn;
import android.hardware.audio.core.IStreamOut;
import android.hardware.audio.core.ModuleDebug;
import android.media.audio.common.AudioOffloadInfo;
import android.media.audio.common.AudioPort;
import android.media.audio.common.AudioPortConfig;
@@ -43,6 +44,116 @@ import android.media.audio.common.AudioPortConfig;
 */
@VintfStability
interface IModule {
    /**
     * Sets debugging configuration for the HAL module. This method is only
     * called during xTS testing and is intended for validating the aspects of
     * the HAL module behavior that would otherwise require human intervention.
     *
     * The HAL module must throw an error if there is an attempt to change
     * the debug behavior for the aspect which is currently in use.
     *
     * @param debug The debug options.
     * @throws EX_ILLEGAL_STATE If the flag(s) being changed affect functionality
     *                          which is currently in use.
     */
    void setModuleDebug(in ModuleDebug debug);

    /**
     * Set a device port of an external device into connected state.
     *
     * This method is used to inform the HAL module that an external device has
     * been connected to a device port selected using the 'id' field of the
     * input AudioPort parameter. This device port must have dynamic profiles
     * (an empty list of profiles). This port is further referenced to as "port
     * template" because it acts as a template for creating a new instance of a
     * "connected" device port which gets returned from this method.
     *
     * The input AudioPort parameter may contain any additional data obtained by
     * the system side from other subsystems. The nature of data depends on the
     * type of the connection. For example, for point-to-multipoint external
     * device connections, the input parameter may contain the address of the
     * connected external device. Another example is EDID information for HDMI
     * connections (ExtraAudioDescriptor), which can be provided by the HDMI-CEC
     * HAL module.
     *
     * It is the responsibility of the HAL module to query audio profiles
     * supported by the connected device and return them as part of the returned
     * AudioPort instance. In the case when the HAL is unable to query the
     * external device, an error must be thrown.
     *
     * Thus, the returned audio port instance is the result of combining the
     * following information:
     *  - a unique port ID generated by the HAL module;
     *  - static information from the port template;
     *  - list of audio profiles supported by the connected device;
     *  - additional data from the input AudioPort parameter.
     *
     * The HAL module must also update the list of audio routes to include the
     * ID of the instantiated connected device port. Normally, the connected
     * port allows the same routing as the port template.
     *
     * Also see notes on 'ModuleDebug.simulateDeviceConnections'.
     *
     * The following protocol is used by HAL module client for handling
     * connection of an external device:
     *  1. Obtain the list of device ports and their IDs via 'getAudioPorts'
     *     method. Select the appropriate port template using
     *     AudioDeviceDescription ('ext.device' field of AudioPort).
     *  2. Combine the ID of the port template with any additional data and call
     *     'connectExternalDevice'. The HAL module returns a new instance of
     *     AudioPort created using the rules explained above. Both
     *     'getAudioPort' and 'getAudioPorts' methods will be returning the same
     *     information for this port until disconnection.
     *  3. Configure the connected port with one of supported profiles using
     *     'setAudioPortConfig'.
     *  4. Query the list of AudioRoutes for the new AudioPort using
     *     'getAudioRoutesForAudioPort' or 'getAudioRoutes' methods.
     *
     * External devices are distinguished by the connection type and device
     * address. Calling this method multiple times to inform about connection of
     * the same external device without disconnecting it first is an error.
     *
     * The HAL module must perform validation of the input parameter and throw
     * an error if it is lacking required information, for example, when no
     * device address is specified for a point-to-multipoint external device
     * connection.
     *
     * Handling of a disconnect is done in a reverse order:
     *  1. Reset port configuration using the 'resetAudioPortConfig' method.
     *  2. Release the connected device port by calling the 'disconnectExternalDevice'
     *     method. This also removes the audio routes associated with this
     *     device port.
     *
     * @return New instance of an audio port for the connected external device.
     * @param templateIdAndAdditionalData Specifies port template ID and any
     *                                    additional data.
     * @throws EX_ILLEGAL_ARGUMENT In the following cases:
     *                             - If the template port can not be found by the ID.
     *                             - If the template is not a device port, or
     *                               it does not have dynamic profiles.
     *                             - If the input parameter is lacking required
     *                               information.
     * @throws EX_ILLEGAL_STATE In the following cases:
     *                          - If the HAL module is unable to query audio profiles.
     *                          - If the external device has already been connected.
     */
    AudioPort connectExternalDevice(in AudioPort templateIdAndAdditionalData);

    /**
     * Set a device port of a an external device into disconnected state.
     *
     * This method is used to inform the HAL module that an external device has
     * been disconnected. The 'portId' must be of a connected device port
     * instance previously instantiated using the 'connectExternalDevice'
     * method.
     *
     * @throws EX_ILLEGAL_ARGUMENT In the following cases:
     *                             - If the port can not be found by the ID.
     *                             - If this is not a connected device port.
     * @throws EX_ILLEGAL_STATE If the port has active configurations.
     */
    void disconnectExternalDevice(int portId);

    /**
     * Return all audio patches of this module.
     *
@@ -57,12 +168,10 @@ interface IModule {
     * Return the current state of the audio port.
     *
     * Using the port ID provided on input, returns the current state of the
     * audio port. For device port representing a connection to some external
     * device, e.g. over HDMI or USB, currently supported audio profiles and
     * extra audio descriptors may change.
     *
     * For all other audio ports it must be the same configuration as returned
     * for this port ID by 'getAudioPorts'.
     * audio port. The values of the AudioPort structure must be the same as
     * currently returned by the 'getAudioPorts' method. The 'getAudioPort'
     * method is provided to reduce overhead in the case when the client needs
     * to check the state of one port only.
     *
     * @return The current state of an audio port.
     * @param portId The ID of the audio port.
@@ -87,32 +196,44 @@ interface IModule {
    AudioPortConfig[] getAudioPortConfigs();

    /**
     * Return all audio ports provided by this module.
     *
     * Returns a list of all mix ports and device ports provided by this
     * module. Each returned port must have a unique ID within this module
     * ('AudioPort.id' field). The returned list must not change during
     * the lifetime of the IModule instance. For audio ports with dynamic
     * profiles (changing depending on external devices being connected
     * to the system) an empty list of profiles must be returned. The list
     * of currently supported audio profiles is obtained from 'getAudioPort'
     * method.
     * Return the current state of all audio ports provided by this module.
     *
     * Returns a list of all mix ports and device ports provided by this HAL
     * module, reflecting their current states. Each returned port must have a
     * unique ID within this module ('AudioPort.id' field). The list also
     * includes "connected" ports created using 'connectExternalDevice' method.
     *
     * @return The list of audio ports.
     */
    AudioPort[] getAudioPorts();

    /**
     * Return all audio routes of this module.
     * Return all current audio routes of this module.
     *
     * Returns a list of audio routes, that is, allowed connections between
     * audio ports. The returned list must not change during the lifetime of the
     * IModule instance.
     * Returns the current list of audio routes, that is, allowed connections
     * between audio ports. The list can change when new device audio ports
     * get created as a result of connecting or disconnecting of external
     * devices.
     *
     * @return The list of audio routes.
     */
    AudioRoute[] getAudioRoutes();

    /**
     * Return audio routes related to the specified audio port.
     *
     * Returns the list of audio routes that include the specified port ID
     * as a source or as a sink. The returned list is a subset of the result
     * returned by the 'getAudioRoutes' method, filtered by the port ID.
     * An empty list can be returned, indicating that the audio port can not
     * be used for creating audio patches.
     *
     * @return The list of audio routes.
     * @param portId The ID of the audio port.
     * @throws EX_ILLEGAL_ARGUMENT If the port can not be found by the ID.
     */
    AudioRoute[] getAudioRoutesForAudioPort(int portId);

    /**
     * Open an input stream using an existing audio mix port configuration.
     *
@@ -230,6 +351,10 @@ interface IModule {
     * parameter. The framework can then set the suggested configuration on a
     * subsequent retry call to this method.
     *
     * Device ports with dynamic audio profiles (an empty list of profiles)
     * can not be used with this method. The list of profiles must be filled in
     * as a result of calling 'connectExternalDevice' method.
     *
     * @return Whether the requested configuration has been applied.
     * @param requested Requested audio port configuration.
     * @param suggested Same as requested configuration, if it was applied.
@@ -241,7 +366,7 @@ interface IModule {
     *                             - If the port can not be found by the port ID.
     *                             - If it is not possible to generate a suggested port
     *                               configuration, for example, if the port only has dynamic
     *                               profiles and they are currently empty.
     *                               profiles.
     */
    boolean setAudioPortConfig(in AudioPortConfig requested, out AudioPortConfig suggested);

+38 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.audio.core;

/**
 * This structure contains flags used for enabling various debugging aspects
 * in a HAL module. By default, all debugging aspects are turned off. They
 * can be enabled during xTS tests for functionality that, for example, would
 * otherwise require human intervention (e.g. connection of external devices).
 */
@JavaDerive(equals=true, toString=true)
@VintfStability
parcelable ModuleDebug {
    /**
     * When set to 'true', HAL module must simulate connection of external
     * devices. An external device becomes 'connected' after a call to
     * IModule.connectExternalDevice, simulation of connection requires:
     *  - provision of at least one non-dynamic device port profile on
     *    connection (as if it was retrieved from a connected device);
     *  - simulating successful application of port configurations for reported
     *    profiles.
     */
    boolean simulateDeviceConnections;
}
Loading