Add sound trigger control by audio policy

Audio policy:
- Added active capture indication to sound trigger service:
recognition stops if concurrent capture is not supported.
- Added generation of reserved I/O handle and session ID for
utterance capture.

Sound trigger service
- Added sound model update callback handling.
- Added service state callback
- Simplified callback shared memory allocation.

Bug: 12378680.

Change-Id: Ib0292c2733e6df90fdae480633dd9953d0016ef1
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index f3be42d..6512c38 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -30,7 +30,7 @@
     libbinder \
     libmedia \
     libhardware \
-    libhardware_legacy \
+    libhardware_legacy
 
 ifneq ($(USE_LEGACY_AUDIO_POLICY), 1)
 LOCAL_SHARED_LIBRARIES += \
@@ -58,7 +58,8 @@
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
     libutils \
-    liblog
+    liblog \
+    libsoundtrigger
 
 LOCAL_STATIC_LIBRARIES := \
     libmedia_helper
diff --git a/services/audiopolicy/AudioPolicyClientImpl.cpp b/services/audiopolicy/AudioPolicyClientImpl.cpp
index c0019d1..3e090e9 100644
--- a/services/audiopolicy/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/AudioPolicyClientImpl.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "AudioPolicyClientImpl"
 //#define LOG_NDEBUG 0
 
+#include <soundtrigger/SoundTrigger.h>
 #include <utils/Log.h>
 #include "AudioPolicyService.h"
 
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 50ee803..5524463 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -190,6 +190,11 @@
     virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
     virtual void clearAudioPatches(uid_t uid) = 0;
 
+    virtual status_t acquireSoundTriggerSession(audio_session_t *session,
+                                           audio_io_handle_t *ioHandle,
+                                           audio_devices_t *device) = 0;
+
+    virtual status_t releaseSoundTriggerSession(audio_session_t session) = 0;
 };
 
 
diff --git a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
index 75745b3..2c51e25 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
@@ -531,4 +531,24 @@
     return mAudioPolicyManager->setAudioPortConfig(config);
 }
 
+status_t AudioPolicyService::acquireSoundTriggerSession(audio_session_t *session,
+                                       audio_io_handle_t *ioHandle,
+                                       audio_devices_t *device)
+{
+    if (mAudioPolicyManager == NULL) {
+        return NO_INIT;
+    }
+
+    return mAudioPolicyManager->acquireSoundTriggerSession(session, ioHandle, device);
+}
+
+status_t AudioPolicyService::releaseSoundTriggerSession(audio_session_t session)
+{
+    if (mAudioPolicyManager == NULL) {
+        return NO_INIT;
+    }
+
+    return mAudioPolicyManager->releaseSoundTriggerSession(session);
+}
+
 }; // namespace android
diff --git a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
index aa46ace..f20c070 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
@@ -496,10 +496,21 @@
                                     audio_output_flags_t flags,
                                     const audio_offload_info_t *offloadInfo)
 {
-    //FIXME: temporary to fix build with USE_LEGACY_AUDIO_POLICY
-    audio_stream_type_t stream = AUDIO_STREAM_MUSIC;
+    audio_stream_type_t stream = audio_attributes_to_stream_type(attr);
+
     return getOutput(stream, samplingRate, format, channelMask, flags, offloadInfo);
 }
 
+status_t AudioPolicyService::acquireSoundTriggerSession(audio_session_t *session,
+                                       audio_io_handle_t *ioHandle,
+                                       audio_devices_t *device)
+{
+    return INVALID_OPERATION;
+}
+
+status_t AudioPolicyService::releaseSoundTriggerSession(audio_session_t session)
+{
+    return INVALID_OPERATION;
+}
 
 }; // namespace android
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index 440f5d0..f716358 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -43,6 +43,7 @@
 #include <hardware/audio.h>
 #include <hardware/audio_effect.h>
 #include <media/AudioParameter.h>
+#include <soundtrigger/SoundTrigger.h>
 #include "AudioPolicyManager.h"
 #include "audio_policy_conf.h"
 
@@ -1119,6 +1120,17 @@
     config.channel_mask = channelMask;
     config.format = format;
     audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
+
+    bool isSoundTrigger = false;
+    if (inputSource == AUDIO_SOURCE_HOTWORD) {
+        ssize_t index = mSoundTriggerSessions.indexOfKey(session);
+        if (index >= 0) {
+            input = mSoundTriggerSessions.valueFor(session);
+            isSoundTrigger = true;
+            ALOGV("SoundTrigger capture on session %d input %d", session, input);
+        }
+    }
+
     status_t status = mpClientInterface->openInput(profile->mModule->mHandle,
                                                    &input,
                                                    &config,
@@ -1149,6 +1161,7 @@
     inputDesc->mChannelMask = channelMask;
     inputDesc->mDevice = device;
     inputDesc->mSessions.add(session);
+    inputDesc->mIsSoundTrigger = isSoundTrigger;
 
     addInput(input, inputDesc);
     mpClientInterface->onAudioPortListUpdate();
@@ -1194,6 +1207,9 @@
     }
 
     if (inputDesc->mRefCount == 0) {
+        if (activeInputsCount() == 0) {
+            SoundTrigger::setCaptureState(true);
+        }
         setInputDevice(input, getNewInputDevice(input), true /* force */);
 
         // Automatically enable the remote submix output when input is started.
@@ -1242,6 +1258,10 @@
         }
 
         resetInputDevice(input);
+
+        if (activeInputsCount() == 0) {
+            SoundTrigger::setCaptureState(false);
+        }
     }
     return NO_ERROR;
 }
@@ -2253,6 +2273,31 @@
     }
 }
 
+status_t AudioPolicyManager::acquireSoundTriggerSession(audio_session_t *session,
+                                       audio_io_handle_t *ioHandle,
+                                       audio_devices_t *device)
+{
+    *session = (audio_session_t)mpClientInterface->newAudioUniqueId();
+    *ioHandle = (audio_io_handle_t)mpClientInterface->newAudioUniqueId();
+    *device = getDeviceForInputSource(AUDIO_SOURCE_HOTWORD);
+
+    mSoundTriggerSessions.add(*session, *ioHandle);
+
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManager::releaseSoundTriggerSession(audio_session_t session)
+{
+    ssize_t index = mSoundTriggerSessions.indexOfKey(session);
+    if (index < 0) {
+        ALOGW("acquireSoundTriggerSession() session %d not registered", session);
+        return BAD_VALUE;
+    }
+
+    mSoundTriggerSessions.removeItem(session);
+    return NO_ERROR;
+}
+
 status_t AudioPolicyManager::addAudioPatch(audio_patch_handle_t handle,
                                            const sp<AudioPatch>& patch)
 {
@@ -4013,7 +4058,8 @@
             inputDesc->toAudioPortConfig(&patch.sinks[0]);
             // AUDIO_SOURCE_HOTWORD is for internal use only:
             // handled as AUDIO_SOURCE_VOICE_RECOGNITION by the audio HAL
-            if (patch.sinks[0].ext.mix.usecase.source == AUDIO_SOURCE_HOTWORD) {
+            if (patch.sinks[0].ext.mix.usecase.source == AUDIO_SOURCE_HOTWORD &&
+                    !inputDesc->mIsSoundTrigger) {
                 patch.sinks[0].ext.mix.usecase.source = AUDIO_SOURCE_VOICE_RECOGNITION;
             }
             patch.num_sinks = 1;
@@ -4198,6 +4244,18 @@
     return 0;
 }
 
+uint32_t AudioPolicyManager::activeInputsCount() const
+{
+    uint32_t count = 0;
+    for (size_t i = 0; i < mInputs.size(); i++) {
+        const sp<AudioInputDescriptor>  desc = mInputs.valueAt(i);
+        if (desc->mRefCount > 0) {
+            return count++;
+        }
+    }
+    return count;
+}
+
 
 audio_devices_t AudioPolicyManager::getDeviceForVolume(audio_devices_t device)
 {
@@ -4883,7 +4941,7 @@
 AudioPolicyManager::AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile)
     : mId(0), mIoHandle(0),
       mDevice(AUDIO_DEVICE_NONE), mPatchHandle(0), mRefCount(0),
-      mInputSource(AUDIO_SOURCE_DEFAULT), mProfile(profile)
+      mInputSource(AUDIO_SOURCE_DEFAULT), mProfile(profile), mIsSoundTrigger(false)
 {
     if (profile != NULL) {
         mAudioPort = profile;
diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h
index e28a362..dd0f00f 100644
--- a/services/audiopolicy/AudioPolicyManager.h
+++ b/services/audiopolicy/AudioPolicyManager.h
@@ -172,6 +172,12 @@
         virtual status_t setAudioPortConfig(const struct audio_port_config *config);
         virtual void clearAudioPatches(uid_t uid);
 
+        virtual status_t acquireSoundTriggerSession(audio_session_t *session,
+                                               audio_io_handle_t *ioHandle,
+                                               audio_devices_t *device);
+
+        virtual status_t releaseSoundTriggerSession(audio_session_t session);
+
 protected:
 
         enum routing_strategy {
@@ -477,15 +483,18 @@
 
             status_t    dump(int fd);
 
-            audio_port_handle_t mId;
-            audio_io_handle_t mIoHandle;              // input handle
-            audio_devices_t mDevice;                    // current device this input is routed to
-            audio_patch_handle_t mPatchHandle;
-            uint32_t mRefCount;                         // number of AudioRecord clients using this output
-            uint32_t mOpenRefCount;
-            audio_source_t mInputSource;                // input source selected by application (mediarecorder.h)
-            const sp<IOProfile> mProfile;                  // I/O profile this output derives from
-            SortedVector<audio_session_t> mSessions;  // audio sessions attached to this input
+            audio_port_handle_t           mId;
+            audio_io_handle_t             mIoHandle;       // input handle
+            audio_devices_t               mDevice;         // current device this input is routed to
+            audio_patch_handle_t          mPatchHandle;
+            uint32_t                      mRefCount;       // number of AudioRecord clients using
+                                                           // this input
+            uint32_t                      mOpenRefCount;
+            audio_source_t                mInputSource;    // input source selected by application
+                                                           //(mediarecorder.h)
+            const sp<IOProfile>           mProfile;        // I/O profile this output derives from
+            SortedVector<audio_session_t> mSessions;       // audio sessions attached to this input
+            bool                          mIsSoundTrigger; // used by a soundtrigger capture
 
             virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
                                    const struct audio_port_config *srcConfig = NULL) const;
@@ -569,6 +578,8 @@
         //    ignoreVirtualInputs is true.
         audio_io_handle_t getActiveInput(bool ignoreVirtualInputs = true);
 
+        uint32_t activeInputsCount() const;
+
         // initialize volume curves for each strategy and device category
         void initializeVolumeCurves();
 
@@ -769,6 +780,8 @@
 
         DefaultKeyedVector<audio_patch_handle_t, sp<AudioPatch> > mAudioPatches;
 
+        DefaultKeyedVector<audio_session_t, audio_io_handle_t> mSoundTriggerSessions;
+
 #ifdef AUDIO_POLICY_TEST
         Mutex   mLock;
         Condition mWaitWorkCV;
diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h
index 97236e3..0044e7a 100644
--- a/services/audiopolicy/AudioPolicyService.h
+++ b/services/audiopolicy/AudioPolicyService.h
@@ -168,6 +168,12 @@
 
     virtual void registerClient(const sp<IAudioPolicyServiceClient>& client);
 
+    virtual status_t acquireSoundTriggerSession(audio_session_t *session,
+                                           audio_io_handle_t *ioHandle,
+                                           audio_devices_t *device);
+
+    virtual status_t releaseSoundTriggerSession(audio_session_t session);
+
             status_t doStopOutput(audio_io_handle_t output,
                                   audio_stream_type_t stream,
                                   int session = 0);