add audioCapabilities to SoundTrigger properties

Bug: 146363190
Test: Assist GTS test suite and manual testing
Change-Id: Ie14844f63e8d87d3baad7e6c50230fe04153f8b4
diff --git a/soundtrigger/2.3/ISoundTriggerHw.hal b/soundtrigger/2.3/ISoundTriggerHw.hal
index 23aa36e..270b00e 100644
--- a/soundtrigger/2.3/ISoundTriggerHw.hal
+++ b/soundtrigger/2.3/ISoundTriggerHw.hal
@@ -17,7 +17,9 @@
 package android.hardware.soundtrigger@2.3;
 
 import @2.0::SoundModelHandle;
+import @2.0::ISoundTriggerHwCallback.CallbackCookie;
 import @2.2::ISoundTriggerHw;
+import @2.1::ISoundTriggerHwCallback;
 
 /**
  * SoundTrigger HAL interface. Used for hardware recognition of hotwords
@@ -38,6 +40,27 @@
     getProperties_2_3() generates (int32_t retval, Properties properties);
 
     /**
+     * Start recognition on a given model. Only one recognition active
+     * at a time per model. Once recognition succeeds or fails, the callback
+     * associated with the model handle is called.
+     *
+     * Must have the exact same semantics as startRecognition from
+     * ISoundTriggerHw@2.1 except that the RecognitionConfig includes audio
+     * capabilities applied when the recognition is active.
+     *
+     * @param modelHandle the handle of the sound model to use for recognition
+     * @param config A RecognitionConfig structure containing attributes of the
+     *     recognition to perform
+     * @return retval Operation completion status: 0 in case of success,
+     *     -EINVAL in case of invalid recognition attributes,
+     *     -ENOSYS in case of invalid model handle,
+     *     -ENOMEM in case of memory allocation failure,
+     *     -ENODEV in case of initialization error.
+     */
+    startRecognition_2_3(SoundModelHandle modelHandle, RecognitionConfig config)
+            generates (int32_t retval);
+
+    /**
      * Set a model specific parameter with the given value. This parameter
      * will keep its value for the duration the model is loaded regardless of starting and stopping
      * recognition. Once the model is unloaded, the value will be lost.
diff --git a/soundtrigger/2.3/default/SoundTriggerHw.cpp b/soundtrigger/2.3/default/SoundTriggerHw.cpp
index 9fd8fe0..d3136b9 100644
--- a/soundtrigger/2.3/default/SoundTriggerHw.cpp
+++ b/soundtrigger/2.3/default/SoundTriggerHw.cpp
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #define LOG_TAG "SoundTriggerHw"
 
 #include "SoundTriggerHw.h"
@@ -357,6 +356,7 @@
                 (const struct sound_trigger_properties_extended_1_3*)header;
         convertPropertiesFromHal(&properties->base, &halProperties->base);
         properties->supportedModelArch = halProperties->supported_model_arch;
+        properties->audioCapabilities = halProperties->audio_capabilities;
     }
 }
 
@@ -460,6 +460,54 @@
     return halConfig;
 }
 
+struct sound_trigger_recognition_config_header* SoundTriggerHw::convertRecognitionConfigToHalHeader(
+        const V2_3::RecognitionConfig* config) {
+    sp<IMemory> memory;
+    const V2_1::ISoundTriggerHw::RecognitionConfig* config_2_1 = &config->base;
+    const V2_0::ISoundTriggerHw::RecognitionConfig* config_2_0 = &config_2_1->header;
+
+    size_t allocSize =
+            sizeof(struct sound_trigger_recognition_config_extended_1_3) + config_2_1->data.size();
+    struct sound_trigger_recognition_config_extended_1_3* halConfigExtended =
+            static_cast<struct sound_trigger_recognition_config_extended_1_3*>(malloc(allocSize));
+    LOG_ALWAYS_FATAL_IF(halConfigExtended == nullptr,
+                        "malloc failed for size %zu in convertRecognitionConfigToHalHeader",
+                        allocSize);
+    halConfigExtended->header.version = SOUND_TRIGGER_DEVICE_API_VERSION_1_3;
+    halConfigExtended->header.size = allocSize;
+
+    struct sound_trigger_recognition_config* halConfigBase = &halConfigExtended->base;
+
+    halConfigBase->capture_handle = (audio_io_handle_t)config_2_0->captureHandle;
+    halConfigBase->capture_device = (audio_devices_t)config_2_0->captureDevice;
+    halConfigBase->capture_requested = config_2_0->captureRequested;
+
+    unsigned int i;
+    for (i = 0; i < config_2_0->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
+        convertPhraseRecognitionExtraToHal(&halConfigBase->phrases[i], &config_2_0->phrases[i]);
+    }
+    halConfigBase->num_phrases = i;
+
+    halConfigBase->data_offset = sizeof(struct sound_trigger_recognition_config_extended_1_3);
+    halConfigBase->data_size = config_2_1->data.size();
+    if (config_2_1->data.size() != 0) {
+        memory = mapMemory(config_2_1->data);
+        LOG_ALWAYS_FATAL_IF(memory == nullptr,
+                            "failed to map config memory in convertRecognitionConfigToHalHeader");
+        memory->read();
+
+        uint8_t* dst = reinterpret_cast<uint8_t*>(halConfigExtended) + halConfigBase->data_offset;
+        const uint8_t* src = static_cast<const uint8_t*>(static_cast<void*>(memory->getPointer()));
+        memcpy(dst, src, config_2_1->data.size());
+
+        memory->commit();
+    }
+
+    halConfigExtended->audio_capabilities = config->audioCapabilities;
+
+    return &halConfigExtended->header;
+}
+
 // static
 void SoundTriggerHw::convertSoundModelEventFromHal(
         V2_0::ISoundTriggerHwCallback::ModelEvent* event,
@@ -741,6 +789,41 @@
     return Void();
 }
 
+Return<int32_t> SoundTriggerHw::startRecognition_2_3(int32_t modelHandle,
+                                                     const V2_3::RecognitionConfig& config) {
+    int32_t ret;
+    sp<SoundTriggerHw::SoundModelClient> client;
+    struct sound_trigger_recognition_config_header* header;
+
+    if (mHwDevice == NULL) {
+        ret = -ENODEV;
+        goto exit;
+    }
+
+    {
+        AutoMutex lock(mLock);
+        client = mClients.valueFor(modelHandle);
+        if (client == 0) {
+            ret = -ENOSYS;
+            goto exit;
+        }
+    }
+
+    header = convertRecognitionConfigToHalHeader(&config);
+
+    if (header == nullptr) {
+        ret = -EINVAL;
+        goto exit;
+    }
+    ret = mHwDevice->start_recognition_extended(mHwDevice, client->getHalHandle(), header,
+                                                recognitionCallback_, client.get());
+
+    free(header);
+
+exit:
+    return ret;
+}
+
 Return<int32_t> SoundTriggerHw::setParameter(V2_0::SoundModelHandle modelHandle,
                                              ModelParameter modelParam, int32_t value) {
     sp<SoundModelClient> client;
diff --git a/soundtrigger/2.3/default/SoundTriggerHw.h b/soundtrigger/2.3/default/SoundTriggerHw.h
index 078debb..ccd468c 100644
--- a/soundtrigger/2.3/default/SoundTriggerHw.h
+++ b/soundtrigger/2.3/default/SoundTriggerHw.h
@@ -86,6 +86,8 @@
 
     // Methods from V2_3::ISoundTriggerHw follow.
     Return<void> getProperties_2_3(getProperties_2_3_cb _hidl_cb) override;
+    Return<int32_t> startRecognition_2_3(int32_t modelHandle,
+                                         const V2_3::RecognitionConfig& config) override;
     Return<int32_t> setParameter(V2_0::SoundModelHandle modelHandle, ModelParameter modelParam,
                                  int32_t value) override;
     Return<void> getParameter(V2_0::SoundModelHandle modelHandle, ModelParameter modelParam,
@@ -170,6 +172,8 @@
     // returned recognition config must be freed by caller
     struct sound_trigger_recognition_config* convertRecognitionConfigToHal(
             const V2_0::ISoundTriggerHw::RecognitionConfig* config);
+    struct sound_trigger_recognition_config_header* convertRecognitionConfigToHalHeader(
+            const V2_3::RecognitionConfig* config);
 
     static void convertPhraseRecognitionExtraFromHal(
             V2_0::PhraseRecognitionExtra* extra,
diff --git a/soundtrigger/2.3/types.hal b/soundtrigger/2.3/types.hal
index 6149126..730f969 100644
--- a/soundtrigger/2.3/types.hal
+++ b/soundtrigger/2.3/types.hal
@@ -18,6 +18,22 @@
 
 import android.hidl.safe_union@1.0::Monostate;
 import @2.0::ISoundTriggerHw.Properties;
+import @2.1::ISoundTriggerHw.RecognitionConfig;
+
+/**
+ * AudioCapabilities supported by the implemented HAL
+ * driver.
+ */
+enum AudioCapabilities : uint32_t {
+    /**
+     * If set the underlying module supports AEC.
+     */
+    ECHO_CANCELLATION = 1 << 0,
+    /**
+     * If set, the underlying module supports noise suppression.
+     */
+    NOISE_SUPPRESSION = 1 << 1,
+};
 
 /**
  * Extended implementation properties providing verbose implementation
@@ -31,6 +47,26 @@
      * (eg. DSP architecture)
      */
     string supportedModelArch;
+
+    /**
+     * Bit field encoding of the AudioCapabilities
+     * supported by the firmware.
+     */
+    bitfield<AudioCapabilities> audioCapabilities;
+};
+
+/**
+ * Configuration for sound trigger capture session passed to
+ * startRecognition_2_1() method.
+ */
+struct RecognitionConfig {
+    @2.1::ISoundTriggerHw.RecognitionConfig base;
+
+    /**
+     * Bit field encoding of the AudioCapabilities
+     * supported by the firmware.
+     */
+    uint32_t audioCapabilities;
 };
 
 /**
diff --git a/soundtrigger/2.3/vts/functional/VtsHalSoundtriggerV2_3TargetTest.cpp b/soundtrigger/2.3/vts/functional/VtsHalSoundtriggerV2_3TargetTest.cpp
index ed38368..2d147e4 100644
--- a/soundtrigger/2.3/vts/functional/VtsHalSoundtriggerV2_3TargetTest.cpp
+++ b/soundtrigger/2.3/vts/functional/VtsHalSoundtriggerV2_3TargetTest.cpp
@@ -27,6 +27,7 @@
 using ::android::sp;
 using ::android::hardware::Return;
 using ::android::hardware::soundtrigger::V2_0::RecognitionMode;
+using ::android::hardware::soundtrigger::V2_3::AudioCapabilities;
 using ::android::hardware::soundtrigger::V2_3::ISoundTriggerHw;
 using ::android::hardware::soundtrigger::V2_3::Properties;
 
@@ -79,6 +80,8 @@
     EXPECT_GT(halProperties.base.maxSoundModels, 0u);
     EXPECT_GT(halProperties.base.maxKeyPhrases, 0u);
     EXPECT_NE(0u, (halProperties.base.recognitionModes & (uint32_t)RecognitionMode::VOICE_TRIGGER));
+    EXPECT_TRUE(halProperties.audioCapabilities <=
+                (AudioCapabilities::ECHO_CANCELLATION | AudioCapabilities::NOISE_SUPPRESSION));
 }
 
 INSTANTIATE_TEST_SUITE_P(