puller cache clearing

+ add adb command to manually clear puller cache
+ try to clear puller cache every 10s

Test: manual test
Change-Id: I8005cacd189de1880fcaeb030efbe21e6d3c0244
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index a4066aa..e610fd7 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -146,6 +146,12 @@
         return;
     }
 
+    long curTime = time(nullptr);
+    if (curTime - mLastPullerCacheClearTimeSec > StatsdStats::kPullerCacheClearIntervalSec) {
+        mStatsPullerManager.ClearPullerCacheIfNecessary(curTime);
+        mLastPullerCacheClearTimeSec = curTime;
+    }
+
     if (event->GetTagId() != android::util::ISOLATED_UID_CHANGED) {
         // Map the isolated uid to host uid if necessary.
         mapIsolatedUidToHostUidIfNecessaryLocked(event);
@@ -290,6 +296,10 @@
     StatsdStats::getInstance().noteConfigRemoved(key);
 
     mLastBroadcastTimes.erase(key);
+
+    if (mMetricsManagers.empty()) {
+        mStatsPullerManager.ForceClearPullerCache();
+    }
 }
 
 void StatsLogProcessor::flushIfNecessaryLocked(
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 17741a8..8bbcd75 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -21,6 +21,7 @@
 #include "logd/LogReader.h"
 #include "metrics/MetricsManager.h"
 #include "packages/UidMap.h"
+#include "external/StatsPullerManager.h"
 
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
 
@@ -75,6 +76,8 @@
 
     sp<UidMap> mUidMap;  // Reference to the UidMap to lookup app name and version for each uid.
 
+    StatsPullerManager mStatsPullerManager;
+
     sp<AnomalyMonitor> mAnomalyMonitor;
 
     void onDumpReportLocked(const ConfigKey& key, vector<uint8_t>* outData);
@@ -96,6 +99,8 @@
 
     const long mTimeBaseSec;
 
+    long mLastPullerCacheClearTimeSec = 0;
+
     FRIEND_TEST(StatsLogProcessorTest, TestRateLimitByteSize);
     FRIEND_TEST(StatsLogProcessorTest, TestRateLimitBroadcast);
     FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge);
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 32da94f..3efe9b1 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -240,6 +240,10 @@
         if (!args[0].compare(String8("log-app-hook"))) {
             return cmd_log_app_hook(out, args);
         }
+
+        if (!args[0].compare(String8("clear-puller-cache"))) {
+            return cmd_clear_puller_cache(out);
+        }
     }
 
     print_cmd_help(out);
@@ -320,6 +324,10 @@
     fprintf(out, "\n");
     fprintf(out, "usage: adb shell cmd stats print-stats\n");
     fprintf(out, "  Prints some basic stats.\n");
+    fprintf(out, "\n");
+    fprintf(out, "\n");
+    fprintf(out, "usage: adb shell cmd stats clear-puller-cache\n");
+    fprintf(out, "  Clear cached puller data.\n");
 }
 
 status_t StatsService::cmd_trigger_broadcast(FILE* out, Vector<String8>& args) {
@@ -602,9 +610,15 @@
 }
 
 status_t StatsService::cmd_clear_puller_cache(FILE* out) {
-    mStatsPullerManager.ClearPullerCache();
-    fprintf(out, "Puller cached data removed!\n");
-    return NO_ERROR;
+    IPCThreadState* ipc = IPCThreadState::self();
+    VLOG("StatsService::cmd_clear_puller_cache with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid());
+    if (checkCallingPermission(String16(kPermissionDump))) {
+        int cleared = mStatsPullerManager.ForceClearPullerCache();
+        fprintf(out, "Puller removed %d cached data!\n", cleared);
+        return NO_ERROR;
+    } else {
+        return PERMISSION_DENIED;
+    }
 }
 
 Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp
index da14434..41e4705 100644
--- a/cmds/statsd/src/external/StatsPuller.cpp
+++ b/cmds/statsd/src/external/StatsPuller.cpp
@@ -59,9 +59,24 @@
     return ret;
 }
 
-void StatsPuller::ClearCache() {
+int StatsPuller::ForceClearCache() {
+    return clearCache();
+}
+
+int StatsPuller::clearCache() {
     lock_guard<std::mutex> lock(mLock);
+    int ret = mCachedData.size();
     mCachedData.clear();
+    mLastPullTimeSec = 0;
+    return ret;
+}
+
+int StatsPuller::ClearCacheIfNecessary(long timestampSec) {
+    if (timestampSec - mLastPullTimeSec > mCoolDownSec) {
+        return clearCache();
+    } else {
+        return 0;
+    }
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/external/StatsPuller.h b/cmds/statsd/src/external/StatsPuller.h
index bc7c45f..3446f9b 100644
--- a/cmds/statsd/src/external/StatsPuller.h
+++ b/cmds/statsd/src/external/StatsPuller.h
@@ -38,7 +38,11 @@
 
     bool Pull(std::vector<std::shared_ptr<LogEvent>>* data);
 
-    void ClearCache();
+    // Clear cache immediately
+    int ForceClearCache();
+
+    // Clear cache if elapsed time is more than cooldown time
+    int ClearCacheIfNecessary(long timestampSec);
 
 protected:
     // The atom tag id this puller pulls
@@ -61,6 +65,8 @@
     std::vector<std::shared_ptr<LogEvent>> mCachedData;
 
     long mLastPullTimeSec;
+
+    int clearCache();
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index 4826d96..0dee342 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -54,8 +54,12 @@
         mPullerManager.SetTimeBaseSec(timeBaseSec);
     }
 
-    void ClearPullerCache() {
-        mPullerManager.ClearPullerCache();
+    int ForceClearPullerCache() {
+        return mPullerManager.ForceClearPullerCache();
+    }
+
+    int ClearPullerCacheIfNecessary(long timestampSec) {
+        return mPullerManager.ClearPullerCacheIfNecessary(timestampSec);
     }
 
  private:
diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
index 71b0abe..19b3a86 100644
--- a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
+++ b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
@@ -199,10 +199,20 @@
     }
 }
 
-void StatsPullerManagerImpl::ClearPullerCache() {
+int StatsPullerManagerImpl::ForceClearPullerCache() {
+    int totalCleared = 0;
     for (auto puller : mPullers) {
-        puller.second->ClearCache();
+        totalCleared += puller.second->ForceClearCache();
     }
+    return totalCleared;
+}
+
+int StatsPullerManagerImpl::ClearPullerCacheIfNecessary(long timestampSec) {
+    int totalCleared = 0;
+    for (auto puller : mPullers) {
+        totalCleared += puller.second->ClearCacheIfNecessary(timestampSec);
+    }
+    return totalCleared;
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.h b/cmds/statsd/src/external/StatsPullerManagerImpl.h
index fba3ade..3535fa3 100644
--- a/cmds/statsd/src/external/StatsPullerManagerImpl.h
+++ b/cmds/statsd/src/external/StatsPullerManagerImpl.h
@@ -49,7 +49,9 @@
 
     void SetTimeBaseSec(long timeBaseSec) {mTimeBaseSec = timeBaseSec;};
 
-    void ClearPullerCache();
+    int ForceClearPullerCache();
+
+    int ClearPullerCacheIfNecessary(long timestampSec);
 
 private:
     StatsPullerManagerImpl();
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 1f4bfa6..f254327 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -85,6 +85,9 @@
     // Maximum size of all files that can be written to stats directory on disk.
     static const int kMaxFileSize = 50 * 1024 * 1024;
 
+    // How long to try to clear puller cache from last time
+    static const long kPullerCacheClearIntervalSec = 1;
+
     /**
      * Report a new config has been received and report the static stats about the config.
      *