Merge changes from topic "set_assistants_uid"

* changes:
  Added audio service API to set active assistants.
  Added mechanism for setting multiple UIDs as assistants.
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 40efb38..32c77c7 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1911,20 +1911,22 @@
             aps->setSurroundFormatEnabled(audioFormatAidl, enabled));
 }
 
-status_t AudioSystem::setAssistantUid(uid_t uid) {
+status_t AudioSystem::setAssistantServicesUids(const std::vector<uid_t>& uids) {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    int32_t uidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(uid));
-    return statusTFromBinderStatus(aps->setAssistantUid(uidAidl));
+    std::vector<int32_t> uidsAidl = VALUE_OR_RETURN_STATUS(
+                convertContainer<std::vector<int32_t>>(uids, legacy2aidl_uid_t_int32_t));
+    return statusTFromBinderStatus(aps->setAssistantServicesUids(uidsAidl));
 }
 
-status_t AudioSystem::setHotwordDetectionServiceUid(uid_t uid) {
+status_t AudioSystem::setActiveAssistantServicesUids(const std::vector<uid_t>& activeUids) {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    int32_t uidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(uid));
-    return statusTFromBinderStatus(aps->setHotwordDetectionServiceUid(uidAidl));
+    std::vector<int32_t> activeUidsAidl = VALUE_OR_RETURN_STATUS(
+                convertContainer<std::vector<int32_t>>(activeUids, legacy2aidl_uid_t_int32_t));
+    return statusTFromBinderStatus(aps->setActiveAssistantServicesUids(activeUidsAidl));
 }
 
 status_t AudioSystem::setA11yServicesUids(const std::vector<uid_t>& uids) {
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index 69328a7..de0f75b 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -302,9 +302,9 @@
 
     void setSurroundFormatEnabled(in AudioFormatDescription audioFormat, boolean enabled);
 
-    void setAssistantUid(int /* uid_t */ uid);
+    void setAssistantServicesUids(in int[] /* uid_t[] */ uids);
 
-    void setHotwordDetectionServiceUid(int /* uid_t */ uid);
+    void setActiveAssistantServicesUids(in int[] /* uid_t[] */ activeUids);
 
     void setA11yServicesUids(in int[] /* uid_t[] */ uids);
 
diff --git a/media/libaudioclient/include/media/AidlConversionUtil.h b/media/libaudioclient/include/media/AidlConversionUtil.h
index 4d16792..820b7cb 100644
--- a/media/libaudioclient/include/media/AidlConversionUtil.h
+++ b/media/libaudioclient/include/media/AidlConversionUtil.h
@@ -77,6 +77,26 @@
 }
 
 /**
+ * A generic template that helps convert containers of convertible types, using iterators.
+ * Uses a limit as maximum conversion items.
+ */
+template<typename InputIterator, typename OutputIterator, typename Func>
+status_t convertRangeWithLimit(InputIterator start,
+                      InputIterator end,
+                      OutputIterator out,
+                      const Func& itemConversion,
+                      const size_t limit) {
+    InputIterator last = end;
+    if (end - start > limit) {
+        last = start + limit;
+    }
+    for (InputIterator iter = start; (iter != last); ++iter, ++out) {
+        *out = VALUE_OR_RETURN_STATUS(itemConversion(*iter));
+    }
+    return OK;
+}
+
+/**
  * A generic template that helps convert containers of convertible types.
  */
 template<typename OutputContainer, typename InputContainer, typename Func>
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index e0cb47e..baefee3 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -438,8 +438,9 @@
                                                audio_format_t *surroundFormats);
     static status_t setSurroundFormatEnabled(audio_format_t audioFormat, bool enabled);
 
-    static status_t setAssistantUid(uid_t uid);
-    static status_t setHotwordDetectionServiceUid(uid_t uid);
+    static status_t setAssistantServicesUids(const std::vector<uid_t>& uids);
+    static status_t setActiveAssistantServicesUids(const std::vector<uid_t>& activeUids);
+
     static status_t setA11yServicesUids(const std::vector<uid_t>& uids);
     static status_t setCurrentImeUid(uid_t uid);
 
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 582c048..4da4ea0 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -2002,34 +2002,43 @@
             mAudioPolicyManager->setSurroundFormatEnabled(audioFormat, enabled));
 }
 
-Status AudioPolicyService::setAssistantUid(int32_t uidAidl)
-{
-    uid_t uid = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_int32_t_uid_t(uidAidl));
-    Mutex::Autolock _l(mLock);
-    mUidPolicy->setAssistantUid(uid);
+Status convertInt32VectorToUidVectorWithLimit(
+        const std::vector<int32_t>& uidsAidl, std::vector<uid_t>& uids) {
+    RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
+        convertRangeWithLimit(uidsAidl.begin(),
+            uidsAidl.end(),
+            std::back_inserter(uids),
+            aidl2legacy_int32_t_uid_t,
+            MAX_ITEMS_PER_LIST)));
+
     return Status::ok();
 }
 
-Status AudioPolicyService::setHotwordDetectionServiceUid(int32_t uidAidl)
+Status AudioPolicyService::setAssistantServicesUids(const std::vector<int32_t>& uidsAidl)
 {
-    uid_t uid = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_int32_t_uid_t(uidAidl));
+    std::vector<uid_t> uids;
+    RETURN_IF_BINDER_ERROR(convertInt32VectorToUidVectorWithLimit(uidsAidl, uids));
+
     Mutex::Autolock _l(mLock);
-    mUidPolicy->setHotwordDetectionServiceUid(uid);
+    mUidPolicy->setAssistantUids(uids);
+    return Status::ok();
+}
+
+Status AudioPolicyService::setActiveAssistantServicesUids(
+        const std::vector<int32_t>& activeUidsAidl) {
+    std::vector<uid_t> activeUids;
+    RETURN_IF_BINDER_ERROR(convertInt32VectorToUidVectorWithLimit(activeUidsAidl, activeUids));
+
+    Mutex::Autolock _l(mLock);
+    mUidPolicy->setActiveAssistantUids(activeUids);
     return Status::ok();
 }
 
 Status AudioPolicyService::setA11yServicesUids(const std::vector<int32_t>& uidsAidl)
 {
-    size_t size = uidsAidl.size();
-    if (size > MAX_ITEMS_PER_LIST) {
-        size = MAX_ITEMS_PER_LIST;
-    }
     std::vector<uid_t> uids;
-    RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
-            convertRange(uidsAidl.begin(),
-                         uidsAidl.begin() + size,
-                         std::back_inserter(uids),
-                         aidl2legacy_int32_t_uid_t)));
+    RETURN_IF_BINDER_ERROR(convertInt32VectorToUidVectorWithLimit(uidsAidl, uids));
+
     Mutex::Autolock _l(mLock);
     mUidPolicy->setA11yUids(uids);
     return Status::ok();
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 8add137..8263ad1 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -594,6 +594,8 @@
     }
 
     write(fd, result.string(), result.size());
+
+    mUidPolicy->dumpInternals(fd);
     return NO_ERROR;
 }
 
@@ -607,13 +609,20 @@
 {
 //    Go over all active clients and allow capture (does not force silence) in the
 //    following cases:
-//    The client is the assistant
+//    The client is in the active assistant list
+//         AND is TOP
+//               AND an accessibility service is TOP
+//                  AND source is either VOICE_RECOGNITION OR HOTWORD
+//               OR there is no active privacy sensitive capture or call
+//                          OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+//                  AND source is VOICE_RECOGNITION OR HOTWORD
+//    The client is an assistant AND active assistant is not being used
 //        AND an accessibility service is on TOP or a RTT call is active
 //                AND the source is VOICE_RECOGNITION or HOTWORD
-//            OR uses VOICE_RECOGNITION AND is on TOP
-//                OR uses HOTWORD
-//            AND there is no active privacy sensitive capture or call
+//        OR there is no active privacy sensitive capture or call
 //                OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+//            AND is TOP most recent assistant and uses VOICE_RECOGNITION or HOTWORD
+//                OR there is no top recent assistant and source is HOTWORD
 //    OR The client is an accessibility service
 //        AND Is on TOP
 //                AND the source is VOICE_RECOGNITION or HOTWORD
@@ -641,13 +650,16 @@
     sp<AudioRecordClient> latestActive;
     sp<AudioRecordClient> topSensitiveActive;
     sp<AudioRecordClient> latestSensitiveActiveOrComm;
+    sp<AudioRecordClient> latestActiveAssistant;
 
     nsecs_t topStartNs = 0;
     nsecs_t latestStartNs = 0;
     nsecs_t topSensitiveStartNs = 0;
     nsecs_t latestSensitiveStartNs = 0;
+    nsecs_t latestAssistantStartNs = 0;
     bool isA11yOnTop = mUidPolicy->isA11yOnTop();
     bool isAssistantOnTop = false;
+    bool useActiveAssistantList = false;
     bool isSensitiveActive = false;
     bool isInCall = mPhoneState == AUDIO_MODE_IN_CALL;
     bool isInCommunication = mPhoneState == AUDIO_MODE_IN_COMMUNICATION;
@@ -682,6 +694,7 @@
         // for top or latest active to avoid masking regular clients started before
         if (!isAccessibility && !isVirtualSource(current->attributes.source)) {
             bool isAssistant = mUidPolicy->isAssistantUid(currentUid);
+            bool isActiveAssistant = mUidPolicy->isActiveAssistantUid(currentUid);
             bool isPrivacySensitive =
                     (current->attributes.flags & AUDIO_FLAG_CAPTURE_PRIVATE) != 0;
 
@@ -699,6 +712,14 @@
                 }
                 if (isAssistant) {
                     isAssistantOnTop = true;
+                    if (isActiveAssistant) {
+                        useActiveAssistantList = true;
+                    } else if (!useActiveAssistantList) {
+                        if (current->startTimeNs > latestAssistantStartNs) {
+                            latestActiveAssistant = current;
+                            latestAssistantStartNs = current->startTimeNs;
+                        }
+                    }
                 }
             }
             // Clients capturing for HOTWORD are not considered
@@ -778,6 +799,8 @@
             current->attributionSource.uid == topActive->attributionSource.uid;
         bool isTopOrLatestSensitive = topSensitiveActive == nullptr ? false :
             current->attributionSource.uid == topSensitiveActive->attributionSource.uid;
+        bool isTopOrLatestAssistant = latestActiveAssistant == nullptr ? false :
+            current->attributionSource.uid == latestActiveAssistant->attributionSource.uid;
 
         auto canCaptureIfInCallOrCommunication = [&](const auto &recordClient) REQUIRES(mLock) {
             uid_t recordUid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(
@@ -807,23 +830,45 @@
         } else if (isVirtualSource(source)) {
             // Allow capture for virtual (remote submix, call audio TX or RX...) sources
             allowCapture = true;
-        } else if (mUidPolicy->isAssistantUid(currentUid)) {
+        } else if (!useActiveAssistantList && mUidPolicy->isAssistantUid(currentUid)) {
             // For assistant allow capture if:
-            //     An accessibility service is on TOP or a RTT call is active
+            //     Active assistant list is not being used
+            //     AND accessibility service is on TOP or a RTT call is active
             //            AND the source is VOICE_RECOGNITION or HOTWORD
-            //     OR is on TOP AND uses VOICE_RECOGNITION
-            //            OR uses HOTWORD
-            //         AND there is no active privacy sensitive capture or call
-            //             OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+            //     OR there is no active privacy sensitive capture or call
+            //          OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+            //            AND is latest TOP assistant AND
+            //               uses VOICE_RECOGNITION OR uses HOTWORD
+            //            OR there is no TOP assistant and uses HOTWORD
             if (isA11yOnTop || rttCallActive) {
                 if (source == AUDIO_SOURCE_HOTWORD || source == AUDIO_SOURCE_VOICE_RECOGNITION) {
                     allowCapture = true;
                 }
-            } else {
-                if (((isAssistantOnTop && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
-                        source == AUDIO_SOURCE_HOTWORD)
-                        && !(isSensitiveActive && !current->canCaptureOutput)
+            } else if (!(isSensitiveActive && !current->canCaptureOutput)
+                    && canCaptureIfInCallOrCommunication(current)) {
+                if (isTopOrLatestAssistant
+                    && (source == AUDIO_SOURCE_VOICE_RECOGNITION
+                        || source == AUDIO_SOURCE_HOTWORD)) {
+                        allowCapture = true;
+                } else if (!isAssistantOnTop && (source == AUDIO_SOURCE_HOTWORD)) {
+                    allowCapture = true;
+                }
+            }
+        } else if (useActiveAssistantList && mUidPolicy->isActiveAssistantUid(currentUid)) {
+            // For assistant on active list and on top allow capture if:
+            //     An accessibility service is on TOP
+            //         AND the source is VOICE_RECOGNITION or HOTWORD
+            //     OR there is no active privacy sensitive capture or call
+            //             OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+            //         AND uses VOICE_RECOGNITION OR uses HOTWORD
+            if (isA11yOnTop) {
+                if (source == AUDIO_SOURCE_HOTWORD || source == AUDIO_SOURCE_VOICE_RECOGNITION) {
+                    allowCapture = true;
+                }
+            } else if (!(isSensitiveActive && !current->canCaptureOutput)
                         && canCaptureIfInCallOrCommunication(current)) {
+                if ((source == AUDIO_SOURCE_VOICE_RECOGNITION) || (source == AUDIO_SOURCE_HOTWORD))
+                {
                     allowCapture = true;
                 }
             }
@@ -1036,7 +1081,8 @@
         case TRANSACTION_getSurroundFormats:
         case TRANSACTION_getReportedSurroundFormats:
         case TRANSACTION_setSurroundFormatEnabled:
-        case TRANSACTION_setAssistantUid:
+        case TRANSACTION_setAssistantServicesUids:
+        case TRANSACTION_setActiveAssistantServicesUids:
         case TRANSACTION_setA11yServicesUids:
         case TRANSACTION_setUidDeviceAffinities:
         case TRANSACTION_removeUidDeviceAffinities:
@@ -1474,6 +1520,66 @@
     return it != mA11yUids.end();
 }
 
+void AudioPolicyService::UidPolicy::setAssistantUids(const std::vector<uid_t>& uids) {
+    mAssistantUids.clear();
+    mAssistantUids = uids;
+}
+
+bool AudioPolicyService::UidPolicy::isAssistantUid(uid_t uid)
+{
+    std::vector<uid_t>::iterator it = find(mAssistantUids.begin(), mAssistantUids.end(), uid);
+    return it != mAssistantUids.end();
+}
+
+void AudioPolicyService::UidPolicy::setActiveAssistantUids(const std::vector<uid_t>& activeUids) {
+    mActiveAssistantUids = activeUids;
+}
+
+bool AudioPolicyService::UidPolicy::isActiveAssistantUid(uid_t uid)
+{
+    std::vector<uid_t>::iterator it = find(mActiveAssistantUids.begin(),
+            mActiveAssistantUids.end(), uid);
+    return it != mActiveAssistantUids.end();
+}
+
+void AudioPolicyService::UidPolicy::dumpInternals(int fd) {
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    auto appendUidsToResult = [&](const char* title, const std::vector<uid_t> &uids) {
+        snprintf(buffer, SIZE, "\t%s: \n", title);
+        result.append(buffer);
+        int counter = 0;
+        if (uids.empty()) {
+            snprintf(buffer, SIZE, "\t\tNo UIDs present.\n");
+            result.append(buffer);
+            return;
+        }
+        for (const auto &uid : uids) {
+            snprintf(buffer, SIZE, "\t\tUID[%d]=%d\n", counter++, uid);
+            result.append(buffer);
+        }
+    };
+
+    snprintf(buffer, SIZE, "UID Policy:\n");
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tmObserverRegistered=%s\n",(mObserverRegistered ? "True":"False"));
+    result.append(buffer);
+
+    appendUidsToResult("Assistants UIDs", mAssistantUids);
+    appendUidsToResult("Active Assistants UIDs", mActiveAssistantUids);
+
+    appendUidsToResult("Accessibility UIDs", mA11yUids);
+
+    snprintf(buffer, SIZE, "\tInput Method Service UID=%d\n", mCurrentImeUid);
+    result.append(buffer);
+
+    snprintf(buffer, SIZE, "\tIs RTT Enabled: %s\n", (mRttEnabled ? "True":"False"));
+    result.append(buffer);
+
+    write(fd, result.string(), result.size());
+}
+
 // -----------  AudioPolicyService::SensorPrivacyService implementation ----------
 void AudioPolicyService::SensorPrivacyPolicy::registerSelf() {
     SensorPrivacyManager spm;
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 39f2c97..ae65a65 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -218,8 +218,8 @@
             std::vector<AudioFormatDescription>* _aidl_return) override;
     binder::Status setSurroundFormatEnabled(const AudioFormatDescription& audioFormat,
                                             bool enabled) override;
-    binder::Status setAssistantUid(int32_t uid) override;
-    binder::Status setHotwordDetectionServiceUid(int32_t uid) override;
+    binder::Status setAssistantServicesUids(const std::vector<int32_t>& uids) override;
+    binder::Status setActiveAssistantServicesUids(const std::vector<int32_t>& activeUids) override;
     binder::Status setA11yServicesUids(const std::vector<int32_t>& uids) override;
     binder::Status setCurrentImeUid(int32_t uid) override;
     binder::Status isHapticPlaybackSupported(bool* _aidl_return) override;
@@ -420,7 +420,7 @@
     public:
         explicit UidPolicy(wp<AudioPolicyService> service)
                 : mService(service), mObserverRegistered(false),
-                  mAssistantUid(0), mHotwordDetectionServiceUid(0), mCurrentImeUid(0),
+                  mCurrentImeUid(0),
                   mRttEnabled(false) {}
 
         void registerSelf();
@@ -431,13 +431,10 @@
 
         bool isUidActive(uid_t uid);
         int getUidState(uid_t uid);
-        void setAssistantUid(uid_t uid) { mAssistantUid = uid; };
-        void setHotwordDetectionServiceUid(uid_t uid) { mHotwordDetectionServiceUid = uid; }
-        bool isAssistantUid(uid_t uid) const {
-            // The HotwordDetectionService is part of the Assistant package but runs with a separate
-            // (isolated) uid, so we check for either uid here.
-            return uid == mAssistantUid || uid == mHotwordDetectionServiceUid;
-        }
+        void setAssistantUids(const std::vector<uid_t>& uids);
+        bool isAssistantUid(uid_t uid);
+        void setActiveAssistantUids(const std::vector<uid_t>& activeUids);
+        bool isActiveAssistantUid(uid_t uid);
         void setA11yUids(const std::vector<uid_t>& uids) { mA11yUids.clear(); mA11yUids = uids; }
         bool isA11yUid(uid_t uid);
         bool isA11yOnTop();
@@ -459,6 +456,8 @@
         void updateUid(std::unordered_map<uid_t, std::pair<bool, int>> *uids,
                        uid_t uid, bool active, int state, bool insert);
 
+        void dumpInternals(int fd);
+
      private:
         void notifyService();
         void updateOverrideUid(uid_t uid, bool active, bool insert);
@@ -472,8 +471,8 @@
         bool mObserverRegistered = false;
         std::unordered_map<uid_t, std::pair<bool, int>> mOverrideUids;
         std::unordered_map<uid_t, std::pair<bool, int>> mCachedUids;
-        uid_t mAssistantUid = -1;
-        uid_t mHotwordDetectionServiceUid = -1;
+        std::vector<uid_t> mAssistantUids;
+        std::vector<uid_t> mActiveAssistantUids;
         std::vector<uid_t> mA11yUids;
         uid_t mCurrentImeUid = -1;
         bool mRttEnabled = false;