Merge "Register pullers in separate thread"
diff --git a/libstats/pull/stats_pull_atom_callback.cpp b/libstats/pull/stats_pull_atom_callback.cpp
index 99233c3..e8fc2ea 100644
--- a/libstats/pull/stats_pull_atom_callback.cpp
+++ b/libstats/pull/stats_pull_atom_callback.cpp
@@ -25,7 +25,8 @@
 #include <android/os/IStatsd.h>
 #include <android/util/StatsEventParcel.h>
 #include <binder/IServiceManager.h>
-#include "include/stats_pull_atom_callback.h"
+
+#include <thread>
 
 struct pulled_stats_event_list {
     std::vector<stats_event*> data;
@@ -94,7 +95,7 @@
 static android::sp<android::os::IStatsd> sStatsd = nullptr;
 
 static std::map<int32_t, android::sp<StatsPullAtomCallbackInternal>> mPullers;
-static android::sp<android::os::IStatsd> getStatsServiceLocked();
+static android::sp<android::os::IStatsd> getStatsService();
 
 class StatsDeathRecipient : public android::IBinder::DeathRecipient {
   public:
@@ -103,15 +104,21 @@
 
     // android::IBinder::DeathRecipient override:
     void binderDied(const android::wp<android::IBinder>& /* who */) override {
-        std::lock_guard<std::mutex> lock(pullAtomMutex);
-        if (sStatsd) {
+        {
+            std::lock_guard<std::mutex> lock(pullAtomMutex);
             sStatsd = nullptr;
         }
-        android::sp<android::os::IStatsd> statsService = getStatsServiceLocked();
+        android::sp<android::os::IStatsd> statsService = getStatsService();
         if (statsService == nullptr) {
             return;
         }
-        for (auto it : mPullers) {
+
+        std::map<int32_t, android::sp<StatsPullAtomCallbackInternal>> pullersCopy;
+        {
+            std::lock_guard<std::mutex> lock(pullAtomMutex);
+            pullersCopy = mPullers;
+        }
+        for (auto it : pullersCopy) {
             statsService->registerNativePullAtomCallback(it.first, it.second->getCoolDownNs(),
                                                          it.second->getTimeoutNs(),
                                                          it.second->getAdditiveFields(), it.second);
@@ -121,11 +128,12 @@
 
 static android::sp<StatsDeathRecipient> statsDeathRecipient = new StatsDeathRecipient();
 
-static android::sp<android::os::IStatsd> getStatsServiceLocked() {
+static android::sp<android::os::IStatsd> getStatsService() {
+    std::lock_guard<std::mutex> lock(pullAtomMutex);
     if (!sStatsd) {
         // Fetch statsd.
         const android::sp<android::IBinder> binder =
-                android::defaultServiceManager()->checkService(android::String16("stats"));
+                android::defaultServiceManager()->getService(android::String16("stats"));
         if (!binder) {
             return nullptr;
         }
@@ -135,6 +143,28 @@
     return sStatsd;
 }
 
+void registerStatsPullAtomCallbackBlocking(int32_t atomTag,
+                                           android::sp<StatsPullAtomCallbackInternal> cb) {
+    const android::sp<android::os::IStatsd> statsService = getStatsService();
+    if (statsService == nullptr) {
+        // Statsd not available
+        return;
+    }
+
+    statsService->registerNativePullAtomCallback(atomTag, cb->getCoolDownNs(), cb->getTimeoutNs(),
+                                                 cb->getAdditiveFields(), cb);
+}
+
+void unregisterStatsPullAtomCallbackBlocking(int32_t atomTag) {
+    const android::sp<android::os::IStatsd> statsService = getStatsService();
+    if (statsService == nullptr) {
+        // Statsd not available
+        return;
+    }
+
+    statsService->unregisterNativePullAtomCallback(atomTag);
+}
+
 void register_stats_pull_atom_callback(int32_t atom_tag, stats_pull_atom_callback_t callback,
                                        pull_atom_metadata* metadata, void* cookie) {
     int64_t coolDownNs = metadata == nullptr ? DEFAULT_COOL_DOWN_NS : metadata->cool_down_ns;
@@ -146,32 +176,26 @@
                               metadata->additive_fields + metadata->additive_fields_size);
     }
 
-    std::lock_guard<std::mutex> lg(pullAtomMutex);
-
-    // Always add to the map. If statsd is dead, we will add them when it comes back.
     android::sp<StatsPullAtomCallbackInternal> callbackBinder = new StatsPullAtomCallbackInternal(
             callback, cookie, coolDownNs, timeoutNs, additiveFields);
-    mPullers[atom_tag] = callbackBinder;
 
-    const android::sp<android::os::IStatsd> statsService = getStatsServiceLocked();
-    if (statsService == nullptr) {
-        // Statsd not available
-        return;
+    {
+        std::lock_guard<std::mutex> lg(pullAtomMutex);
+        // Always add to the map. If statsd is dead, we will add them when it comes back.
+        mPullers[atom_tag] = callbackBinder;
     }
 
-    statsService->registerNativePullAtomCallback(atom_tag, coolDownNs, timeoutNs, additiveFields,
-                                                 callbackBinder);
+    std::thread registerThread(registerStatsPullAtomCallbackBlocking, atom_tag, callbackBinder);
+    registerThread.detach();
 }
 
 void unregister_stats_pull_atom_callback(int32_t atom_tag) {
-    std::lock_guard<std::mutex> lg(pullAtomMutex);
-    // Always remove the puller from our map.
-    // If statsd is down, we will not register it when it comes back.
-    mPullers.erase(atom_tag);
-    const android::sp<android::os::IStatsd> statsService = getStatsServiceLocked();
-    if (statsService == nullptr) {
-        // Statsd not available
-        return;
+    {
+        std::lock_guard<std::mutex> lg(pullAtomMutex);
+        // Always remove the puller from our map.
+        // If statsd is down, we will not register it when it comes back.
+        mPullers.erase(atom_tag);
     }
-    statsService->unregisterNativePullAtomCallback(atom_tag);
+    std::thread unregisterThread(unregisterStatsPullAtomCallbackBlocking, atom_tag);
+    unregisterThread.detach();
 }