Revert "Revert "audio policy: concurrent capture""

This reverts commit df628924e691e01da190c1ac5db173304442e54a.

Bug: 120588242
Bug: 111438757
Test: make
Change-Id: If58ff2143fdb744678bb84394598104ced01f5b9
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 78dbf5f..2893872 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -348,11 +348,91 @@
 
 void AudioPolicyService::updateUidStates_l()
 {
-    //TODO: implement real concurrent capture policy: for now just apply each app state directly
+//    Go over all active clients and allow capture (does not force silence) in the
+//    following cases:
+//    - The client is the assistant AND
+//           an accessibility service is on TOP AND the source is VOICE_RECOGNITION or HOTWORD
+//           OR
+//           is on TOP AND uses VOICE_RECOGNITION
+//               OR uses HOTWORD AND there is no privacy sensitive active capture
+//    - The client is an accessibility service AND
+//           is on TOP AND the source is VOICE_RECOGNITION or HOTWORD
+//    - Any other client AND
+//           The assistant is not on TOP AND
+//           is on TOP OR latest started AND
+//              there is no privacy sensitive active capture
+//TODO: mamanage pre processing effects according to use case priority
+
+    sp<AudioRecordClient> topActive;
+    sp<AudioRecordClient> latestActive;
+    nsecs_t latestStartNs = 0;
+    sp<AudioRecordClient> latestSensitiveActive;
+    nsecs_t latestSensitiveStartNs = 0;
+    bool isA11yOnTop = mUidPolicy->isA11yOnTop();
+    bool isAssistantOnTop = false;
+    bool isSensitiveActive = false;
+
     for (size_t i =0; i < mAudioRecordClients.size(); i++) {
         sp<AudioRecordClient> current = mAudioRecordClients[i];
         if (!current->active) continue;
-        setAppState_l(current->uid, apmStatFromAmState(mUidPolicy->getUidState(current->uid)));
+        if (isPrivacySensitive(current->attributes.source)) {
+            if (current->startTimeNs > latestSensitiveStartNs) {
+                latestSensitiveActive = current;
+                latestSensitiveStartNs = current->startTimeNs;
+            }
+            isSensitiveActive = true;
+        }
+        if (mUidPolicy->getUidState(current->uid) == ActivityManager::PROCESS_STATE_TOP) {
+            topActive = current;
+            latestActive = nullptr;
+            if (mUidPolicy->isAssistantUid(current->uid)) {
+                isAssistantOnTop = true;
+            }
+        }
+        if (current->startTimeNs > latestStartNs) {
+            latestActive = current;
+            latestStartNs = current->startTimeNs;
+        }
+    }
+
+    if (topActive == nullptr && latestActive == nullptr) {
+        return;
+    }
+
+    for (size_t i =0; i < mAudioRecordClients.size(); i++) {
+        sp<AudioRecordClient> current = mAudioRecordClients[i];
+        if (!current->active) continue;
+
+        audio_source_t source = current->attributes.source;
+        bool isOnTop = mUidPolicy->getUidState(current->uid) == ActivityManager::PROCESS_STATE_TOP;
+        bool isLatest = current == latestActive;
+        bool isLatestSensitive = current == latestSensitiveActive;
+        bool forceIdle = true;
+        if (mUidPolicy->isAssistantUid(current->uid)) {
+            if (isA11yOnTop) {
+                if (source == AUDIO_SOURCE_HOTWORD || source == AUDIO_SOURCE_VOICE_RECOGNITION) {
+                    forceIdle = false;
+                }
+            } else {
+                if (((isOnTop && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
+                     source == AUDIO_SOURCE_HOTWORD) && !isSensitiveActive) {
+                    forceIdle = false;
+                }
+            }
+        } else if (mUidPolicy->isA11yUid(current->uid)) {
+            if (isOnTop &&
+                (source == AUDIO_SOURCE_VOICE_RECOGNITION || source == AUDIO_SOURCE_HOTWORD)) {
+                forceIdle = false;
+            }
+        } else {
+            if (!isAssistantOnTop && (isOnTop || (topActive == nullptr && isLatest)) &&
+                (!isSensitiveActive || isLatestSensitive)) {
+                forceIdle = false;
+            }
+        }
+        setAppState_l(current->uid,
+                      forceIdle ? APP_STATE_IDLE :
+                                  apmStatFromAmState(mUidPolicy->getUidState(current->uid)));
     }
 }
 
@@ -369,6 +449,22 @@
     return APP_STATE_FOREGROUND;
 }
 
+/* static */
+bool AudioPolicyService::isPrivacySensitive(audio_source_t source)
+{
+    switch (source) {
+        case AUDIO_SOURCE_VOICE_UPLINK:
+        case AUDIO_SOURCE_VOICE_DOWNLINK:
+        case AUDIO_SOURCE_VOICE_CALL:
+        case AUDIO_SOURCE_CAMCORDER:
+        case AUDIO_SOURCE_VOICE_COMMUNICATION:
+            return true;
+        default:
+            break;
+    }
+    return false;
+}
+
 void AudioPolicyService::setAppState_l(uid_t uid, app_state_t state)
 {
     AutoCallerClear acc;
@@ -548,6 +644,7 @@
         mObserverRegistered = true;
     } else {
         ALOGE("UidPolicy::registerSelf linkToDeath failed: %d", res);
+
         am.unregisterUidObserver(this);
     }
 }
@@ -650,6 +747,7 @@
         mCachedUids.insert(std::pair<uid_t,
                            std::pair<bool, int>>(uid, std::pair<bool, int>(active, state)));
     }
+
     return state;
 }
 
@@ -730,6 +828,21 @@
     }
 }
 
+bool AudioPolicyService::UidPolicy::isA11yOnTop() {
+    for (const auto &uid : mCachedUids) {
+        std::vector<uid_t>::iterator it = find(mA11yUids.begin(), mA11yUids.end(), uid.first);
+        if (it == mA11yUids.end()) {
+            continue;
+        }
+        if (uid.second.second == ActivityManager::PROCESS_STATE_TOP ||
+            uid.second.second == ActivityManager::PROCESS_STATE_FOREGROUND_SERVICE ||
+            uid.second.second == ActivityManager::PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
+            return true;
+        }
+    }
+    return false;
+}
+
 bool AudioPolicyService::UidPolicy::isA11yUid(uid_t uid)
 {
     std::vector<uid_t>::iterator it = find(mA11yUids.begin(), mA11yUids.end(), uid);