APIs for registering config activation broadcasts

Creates a StatsManager API to register a pending intent that is invoked
whenever the active status of any of any config sent by that uid
changes.

ag/6112554 and further cls are needed to properly send back the pending
intent.

Bug: 123372077
Test: build success on blueline-eng. More thorough testing should be
done once ag/6112554 is submitted.

Change-Id: I36985c9820d4e7ac178064924190af88ea822254
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 9c320d3..b26c713 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -989,6 +989,25 @@
     return Status::ok();
 }
 
+Status StatsService::setActiveConfigsChangedOperation(const sp<android::IBinder>& intentSender,
+                                                      const String16& packageName,
+                                                      vector<int64_t>* output) {
+    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+
+    IPCThreadState* ipc = IPCThreadState::self();
+    mConfigManager->SetActiveConfigsChangedReceiver(ipc->getCallingUid(), intentSender);
+    //TODO: Return the list of configs that are already active
+    return Status::ok();
+}
+
+Status StatsService::removeActiveConfigsChangedOperation(const String16& packageName) {
+    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+
+    IPCThreadState* ipc = IPCThreadState::self();
+    mConfigManager->RemoveActiveConfigsChangedReceiver(ipc->getCallingUid());
+    return Status::ok();
+}
+
 Status StatsService::removeConfiguration(int64_t key, const String16& packageName) {
     ENFORCE_DUMP_AND_USAGE_STATS(packageName);
 
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index fe0504f..cdff50f 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -132,6 +132,17 @@
                                             const String16& packageName) override;
 
     /**
+     * Binder call to let clients register the active configs changed operation.
+     */
+    virtual Status setActiveConfigsChangedOperation(const sp<android::IBinder>& intentSender,
+                                                    const String16& packageName,
+                                                    vector<int64_t>* output) override;
+
+    /**
+     * Binder call to remove the active configs changed operation for the specified package..
+     */
+    virtual Status removeActiveConfigsChangedOperation(const String16& packageName) override;
+    /**
      * Binder call to allow clients to remove the specified configuration.
      */
     virtual Status removeConfiguration(int64_t key,
diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp
index 5fea90b..aa22333 100644
--- a/cmds/statsd/src/config/ConfigManager.cpp
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -128,6 +128,17 @@
     mConfigReceivers.erase(key);
 }
 
+void ConfigManager::SetActiveConfigsChangedReceiver(const int uid,
+                                                    const sp<IBinder>& intentSender) {
+    lock_guard<mutex> lock(mMutex);
+    mActiveConfigsChangedReceivers[uid] = intentSender;
+}
+
+void ConfigManager::RemoveActiveConfigsChangedReceiver(const int uid) {
+    lock_guard<mutex> lock(mMutex);
+    mActiveConfigsChangedReceivers.erase(uid);
+}
+
 void ConfigManager::RemoveConfig(const ConfigKey& key) {
     vector<sp<ConfigListener>> broadcastList;
     {
@@ -181,6 +192,11 @@
                 mConfigReceivers.erase(*it);
         }
 
+        auto itActiveConfigsChangedReceiver = mActiveConfigsChangedReceivers.find(uid);
+        if (itActiveConfigsChangedReceiver != mActiveConfigsChangedReceivers.end()) {
+            mActiveConfigsChangedReceivers.erase(itActiveConfigsChangedReceiver);
+        }
+
         mConfigs.erase(uidIt);
 
         for (const sp<ConfigListener>& listener : mListeners) {
@@ -213,6 +229,7 @@
         }
 
         mConfigReceivers.clear();
+        mActiveConfigsChangedReceivers.clear();
         for (const sp<ConfigListener>& listener : mListeners) {
             broadcastList.push_back(listener);
         }
@@ -250,6 +267,17 @@
     }
 }
 
+const sp<android::IBinder> ConfigManager::GetActiveConfigsChangedReceiver(const int uid) const {
+    lock_guard<mutex> lock(mMutex);
+
+    auto it = mActiveConfigsChangedReceivers.find(uid);
+    if (it == mActiveConfigsChangedReceivers.end()) {
+        return nullptr;
+    } else {
+        return it->second;
+    }
+}
+
 void ConfigManager::Dump(FILE* out) {
     lock_guard<mutex> lock(mMutex);
 
diff --git a/cmds/statsd/src/config/ConfigManager.h b/cmds/statsd/src/config/ConfigManager.h
index 122e669..c064a51 100644
--- a/cmds/statsd/src/config/ConfigManager.h
+++ b/cmds/statsd/src/config/ConfigManager.h
@@ -82,6 +82,23 @@
     void RemoveConfigReceiver(const ConfigKey& key);
 
     /**
+     * Sets the broadcast receiver that is notified whenever the list of active configs
+     * changes for this uid.
+     */
+    void SetActiveConfigsChangedReceiver(const int uid, const sp<IBinder>& intentSender);
+
+    /**
+     * Returns the broadcast receiver for active configs changed for this uid.
+     */
+
+    const sp<IBinder> GetActiveConfigsChangedReceiver(const int uid) const;
+
+    /**
+     * Erase any active configs changed broadcast receiver associated with this uid.
+     */
+    void RemoveActiveConfigsChangedReceiver(const int uid);
+
+    /**
      * A configuration was removed.
      *
      * Reports this to listeners.
@@ -130,6 +147,12 @@
     std::map<ConfigKey, sp<android::IBinder>> mConfigReceivers;
 
     /**
+     * Each uid can be subscribed by up to one receiver to notify that the list of active configs
+     * for this uid has changed. The receiver is specified as IBinder from PendingIntent.
+     */
+     std::map<int, sp<android::IBinder>> mActiveConfigsChangedReceivers;
+
+    /**
      * The ConfigListeners that will be told about changes.
      */
     std::vector<sp<ConfigListener>> mListeners;