audioflinger: add HOTWORD audio source.

HOTWORD is a special capture audio source that uses
the same audio tuning as VOICE_RECOGNITION but allows an
active capture to be preempted.

Bug: 10640877.

Change-Id: Iea09a11cbcdbacc8d434e5230e7559dcd1b44ac0
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 900b411..4be292f 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -296,9 +296,14 @@
         return 0;
     }
     // already checked by client, but double-check in case the client wrapper is bypassed
-    if (uint32_t(inputSource) >= AUDIO_SOURCE_CNT) {
+    if (inputSource >= AUDIO_SOURCE_CNT && inputSource != AUDIO_SOURCE_HOTWORD) {
         return 0;
     }
+
+    if ((inputSource == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) {
+        return 0;
+    }
+
     Mutex::Autolock _l(mLock);
     // the audio_in_acoustics_t parameter is ignored by get_input()
     audio_io_handle_t input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate,
@@ -308,7 +313,10 @@
         return input;
     }
     // create audio pre processors according to input source
-    ssize_t index = mInputSources.indexOfKey(inputSource);
+    audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
+                                    AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
+
+    ssize_t index = mInputSources.indexOfKey(aliasSource);
     if (index < 0) {
         return input;
     }
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index ffe3e9f..cd8f70c 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -36,6 +36,7 @@
 
             void        destroy();
 
+            void        invalidate();
             // clear the buffer overflow flag
             void        clearOverflow() { mOverflow = false; }
             // set the buffer overflow flag and return previous value
diff --git a/services/audioflinger/ServiceUtilities.cpp b/services/audioflinger/ServiceUtilities.cpp
index 9ee513b..152455d 100644
--- a/services/audioflinger/ServiceUtilities.cpp
+++ b/services/audioflinger/ServiceUtilities.cpp
@@ -43,6 +43,13 @@
     return ok;
 }
 
+bool captureHotwordAllowed() {
+    static const String16 sCaptureHotwordAllowed("android.permission.CAPTURE_AUDIO_HOTWORD");
+    bool ok = checkCallingPermission(sCaptureHotwordAllowed);
+    if (!ok) ALOGE("android.permission.CAPTURE_AUDIO_HOTWORD");
+    return ok;
+}
+
 bool settingsAllowed() {
     if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true;
     static const String16 sAudioSettings("android.permission.MODIFY_AUDIO_SETTINGS");
diff --git a/services/audioflinger/ServiceUtilities.h b/services/audioflinger/ServiceUtilities.h
index 175cd28..531bc56 100644
--- a/services/audioflinger/ServiceUtilities.h
+++ b/services/audioflinger/ServiceUtilities.h
@@ -22,6 +22,7 @@
 
 bool recordingAllowed();
 bool captureAudioOutputAllowed();
+bool captureHotwordAllowed();
 bool settingsAllowed();
 bool dumpAllowed();
 
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index e35f47e..1b5a9a9 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4451,6 +4451,10 @@
 
     {
         Mutex::Autolock _l(mLock);
+        for (size_t i = 0; i < mTracks.size(); i++) {
+            sp<RecordTrack> track = mTracks[i];
+            track->invalidate();
+        }
         mActiveTrack.clear();
         mStartStopCond.broadcast();
     }
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 2042050..9103932 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1760,6 +1760,16 @@
     }
 }
 
+void AudioFlinger::RecordThread::RecordTrack::invalidate()
+{
+    // FIXME should use proxy, and needs work
+    audio_track_cblk_t* cblk = mCblk;
+    android_atomic_or(CBLK_INVALID, &cblk->mFlags);
+    android_atomic_release_store(0x40000000, &cblk->mFutex);
+    // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
+    (void) __futex_syscall3(&cblk->mFutex, FUTEX_WAKE, INT_MAX);
+}
+
 
 /*static*/ void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result)
 {