Throttler for incidentd based on size putting into dropbox.

The incidentd will accumulate the total size put into dropbox and once
it exceeds a threshold (currently 20MB) daily, it will stop further
requests. It allows collection again 24 hours later.

Bug: 64219725
Test: atest incidentd_test and manually flashed incidentd and test.
Change-Id: Iea21fbae40d5d01108797b190231d73e74eff213
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index 9ae6240..28fb38a 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define DEBUG false
 #include "Log.h"
 
 #include "IncidentService.h"
@@ -38,9 +39,11 @@
 
 enum { WHAT_RUN_REPORT = 1, WHAT_SEND_BACKLOG_TO_DROPBOX = 2 };
 
-//#define DEFAULT_BACKLOG_DELAY_NS (1000000000LL * 60 * 5)
 #define DEFAULT_BACKLOG_DELAY_NS (1000000000LL)
 
+#define DEFAULT_BYTES_SIZE_LIMIT (20 * 1024 * 1024)        // 20MB
+#define DEFAULT_REFACTORY_PERIOD_MS (24 * 60 * 60 * 1000)  // 1 Day
+
 // ================================================================================
 String16 const DUMP_PERMISSION("android.permission.DUMP");
 String16 const USAGE_STATS_PERMISSION("android.permission.PACKAGE_USAGE_STATS");
@@ -113,8 +116,12 @@
 }
 
 // ================================================================================
-ReportHandler::ReportHandler(const sp<Looper>& handlerLooper, const sp<ReportRequestQueue>& queue)
-    : mBacklogDelay(DEFAULT_BACKLOG_DELAY_NS), mHandlerLooper(handlerLooper), mQueue(queue) {}
+ReportHandler::ReportHandler(const sp<Looper>& handlerLooper, const sp<ReportRequestQueue>& queue,
+                             const sp<Throttler>& throttler)
+    : mBacklogDelay(DEFAULT_BACKLOG_DELAY_NS),
+      mHandlerLooper(handlerLooper),
+      mQueue(queue),
+      mThrottler(throttler) {}
 
 ReportHandler::~ReportHandler() {}
 
@@ -159,10 +166,17 @@
         reporter->batch.add(request);
     }
 
+    if (mThrottler->shouldThrottle()) {
+        ALOGW("RunReport got throttled.");
+        return;
+    }
+
     // Take the report, which might take a while. More requests might queue
     // up while we're doing this, and we'll handle them in their next batch.
     // TODO: We should further rate-limit the reports to no more than N per time-period.
-    Reporter::run_report_status_t reportStatus = reporter->runReport();
+    size_t reportByteSize = 0;
+    Reporter::run_report_status_t reportStatus = reporter->runReport(&reportByteSize);
+    mThrottler->addReportSize(reportByteSize);
     if (reportStatus == Reporter::REPORT_NEEDS_DROPBOX) {
         unique_lock<mutex> lock(mLock);
         schedule_send_backlog_to_dropbox_locked();
@@ -184,8 +198,9 @@
 
 // ================================================================================
 IncidentService::IncidentService(const sp<Looper>& handlerLooper)
-    : mQueue(new ReportRequestQueue()) {
-    mHandler = new ReportHandler(handlerLooper, mQueue);
+    : mQueue(new ReportRequestQueue()),
+      mThrottler(new Throttler(DEFAULT_BYTES_SIZE_LIMIT, DEFAULT_REFACTORY_PERIOD_MS)) {
+    mHandler = new ReportHandler(handlerLooper, mQueue, mThrottler);
 }
 
 IncidentService::~IncidentService() {}
@@ -294,6 +309,10 @@
         if (!args[0].compare(String8("privacy"))) {
             return cmd_privacy(in, out, err, args);
         }
+        if (!args[0].compare(String8("throttler"))) {
+            mThrottler->dump(out);
+            return NO_ERROR;
+        }
     }
     return cmd_help(out);
 }
@@ -302,6 +321,9 @@
     fprintf(out, "usage: adb shell cmd incident privacy print <section_id>\n");
     fprintf(out, "usage: adb shell cmd incident privacy parse <section_id> < proto.txt\n");
     fprintf(out, "    Prints/parses for the section id.\n");
+    fprintf(out, "\n");
+    fprintf(out, "usage: adb shell cmd incident throttler\n");
+    fprintf(out, "    Prints the current throttler state\n");
     return NO_ERROR;
 }