logd: ratelimit drop messages to 1/sec

Bug: 20334069
Bug: 20370119
Change-Id: I6f850aec46c4df1c99a5b1f28db75d071e134ad5
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 1859461..83a6b1d 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -247,7 +247,7 @@
     uint64_t getKey() { return value; }
 };
 
-struct LogBufferElementEntry {
+class LogBufferElementEntry {
     const uint64_t key;
     LogBufferElement *last;
 
@@ -259,8 +259,9 @@
     LogBufferElement *getLast() { return last; }
 };
 
-struct LogBufferElementLast : public android::BasicHashtable<uint64_t, LogBufferElementEntry> {
+class LogBufferElementLast : public android::BasicHashtable<uint64_t, LogBufferElementEntry> {
 
+public:
     bool merge(LogBufferElement *e, unsigned short dropped) {
         LogBufferElementKey key(e->getUid(), e->getPid(), e->getTid());
         android::hash_t hash = android::hash_type(key.getKey());
@@ -286,6 +287,21 @@
             add(hash, LogBufferElementEntry(key.getKey(), e));
     }
 
+    inline void clear() {
+        android::BasicHashtable<uint64_t, LogBufferElementEntry>::clear();
+    }
+
+    void clear(LogBufferElement *e) {
+        uint64_t current = e->getRealTime().nsec() - NS_PER_SEC;
+        ssize_t index = -1;
+        while((index = next(index)) >= 0) {
+            if (current > editEntryAt(index).getLast()->getRealTime().nsec()) {
+                removeAt(index);
+                index = -1;
+            }
+        }
+    }
+
 };
 
 // prune "pruneRows" of type "id" from the buffer.
@@ -395,7 +411,7 @@
             leading = false;
 
             if (hasBlacklist && mPrune.naughty(e)) {
-                last.clear();
+                last.clear(e);
                 it = erase(it);
                 if (dropped) {
                     continue;
@@ -423,7 +439,7 @@
             }
 
             if (e->getUid() != worst) {
-                last.clear();
+                last.clear(e);
                 ++it;
                 continue;
             }