logd: liblog: logcat: Add LogWhiteBlackList

- liblog android_logger_get_log_size and android_logger_get_readable_size
  adjusted to return long instead of int because of -G flag extending range

NB: ifdef'd only for userdebug and eng builds

- liblog Add android_logger_[sg]et_prune_list and android_logger_set_log_size
- logcat Add -P, -p and -G flags
- logd Add LogWhiteBlackList and configurable log size

(cherry picked from commit 62a5b9dda2f06b88e7f249e7fa0b5052c89aacfb)

Change-Id: I1572338c1b34bd968ad7867857ef708156ec3b6a
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index cf172d1..197b7e8 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -23,13 +23,25 @@
 
 #include "LogBuffer.h"
 #include "LogStatistics.h"
+#include "LogWhiteBlackList.h"
 #include "LogReader.h"
 
+// Default
 #define LOG_BUFFER_SIZE (256 * 1024) // Tuned on a per-platform basis here?
+#ifdef USERDEBUG_BUILD
+#define log_buffer_size(id) mMaxSize[id]
+#else
+#define log_buffer_size(id) LOG_BUFFER_SIZE
+#endif
 
 LogBuffer::LogBuffer(LastLogTimes *times)
         : mTimes(*times) {
     pthread_mutex_init(&mLogElementsLock, NULL);
+#ifdef USERDEBUG_BUILD
+    log_id_for_each(i) {
+        mMaxSize[i] = LOG_BUFFER_SIZE;
+    }
+#endif
 }
 
 void LogBuffer::log(log_id_t log_id, log_time realtime,
@@ -100,8 +112,8 @@
 // mLogElementsLock must be held when this function is called.
 void LogBuffer::maybePrune(log_id_t id) {
     size_t sizes = stats.sizes(id);
-    if (sizes > LOG_BUFFER_SIZE) {
-        size_t sizeOver90Percent = sizes - ((LOG_BUFFER_SIZE * 9) / 10);
+    if (sizes > log_buffer_size(id)) {
+        size_t sizeOver90Percent = sizes - ((log_buffer_size(id) * 9) / 10);
         size_t elements = stats.elements(id);
         unsigned long pruneRows = elements * sizeOver90Percent / sizes;
         elements /= 10;
@@ -140,18 +152,23 @@
         size_t worst_sizes = 0;
         size_t second_worst_sizes = 0;
 
-        LidStatistics &l = stats.id(id);
-        UidStatisticsCollection::iterator iu;
-        for (iu = l.begin(); iu != l.end(); ++iu) {
-            UidStatistics *u = (*iu);
-            size_t sizes = u->sizes();
-            if (worst_sizes < sizes) {
-                second_worst_sizes = worst_sizes;
-                worst_sizes = sizes;
-                worst = u->getUid();
-            }
-            if ((second_worst_sizes < sizes) && (sizes < worst_sizes)) {
-                second_worst_sizes = sizes;
+#ifdef USERDEBUG_BUILD
+        if (mPrune.worstUidEnabled())
+#endif
+        {
+            LidStatistics &l = stats.id(id);
+            UidStatisticsCollection::iterator iu;
+            for (iu = l.begin(); iu != l.end(); ++iu) {
+                UidStatistics *u = (*iu);
+                size_t sizes = u->sizes();
+                if (worst_sizes < sizes) {
+                    second_worst_sizes = worst_sizes;
+                    worst_sizes = sizes;
+                    worst = u->getUid();
+                }
+                if ((second_worst_sizes < sizes) && (sizes < worst_sizes)) {
+                    second_worst_sizes = sizes;
+                }
             }
         }
 
@@ -163,7 +180,14 @@
                 break;
             }
 
-            if ((e->getLogId() == id) && (e->getUid() == worst)) {
+            if (e->getLogId() != id) {
+                ++it;
+                continue;
+            }
+
+            uid_t uid = e->getUid();
+
+            if (uid == worst) {
                 it = mLogElements.erase(it);
                 unsigned short len = e->getMsgLen();
                 stats.subtract(len, id, worst, e->getPid());
@@ -174,29 +198,60 @@
                     break;
                 }
                 worst_sizes -= len;
-            } else {
+            }
+#ifdef USERDEBUG_BUILD
+            else if (mPrune.naughty(e)) { // BlackListed
+                it = mLogElements.erase(it);
+                stats.subtract(e->getMsgLen(), id, uid, e->getPid());
+                delete e;
+                pruneRows--;
+                if (pruneRows == 0) {
+                    break;
+                }
+            }
+#endif
+            else {
                 ++it;
             }
         }
 
-        if (!kick) {
+        if (!kick
+#ifdef USERDEBUG_BUILD
+                || !mPrune.worstUidEnabled()
+#endif
+        ) {
             break; // the following loop will ask bad clients to skip/drop
         }
     }
 
+#ifdef USERDEBUG_BUILD
+    bool whitelist = false;
+#endif
     it = mLogElements.begin();
     while((pruneRows > 0) && (it != mLogElements.end())) {
         LogBufferElement *e = *it;
         if (e->getLogId() == id) {
             if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
-                if (stats.sizes(id) > (2 * LOG_BUFFER_SIZE)) {
-                    // kick a misbehaving log reader client off the island
-                    oldest->release_Locked();
-                } else {
-                    oldest->triggerSkip_Locked(pruneRows);
+#ifdef USERDEBUG_BUILD
+                if (!whitelist)
+#endif
+                {
+                    if (stats.sizes(id) > (2 * log_buffer_size(id))) {
+                        // kick a misbehaving log reader client off the island
+                        oldest->release_Locked();
+                    } else {
+                        oldest->triggerSkip_Locked(pruneRows);
+                    }
                 }
                 break;
             }
+#ifdef USERDEBUG_BUILD
+            if (mPrune.nice(e)) { // WhiteListed
+                whitelist = true;
+                it++;
+                continue;
+            }
+#endif
             it = mLogElements.erase(it);
             stats.subtract(e->getMsgLen(), id, e->getUid(), e->getPid());
             delete e;
@@ -206,6 +261,32 @@
         }
     }
 
+#ifdef USERDEBUG_BUILD
+    if (whitelist && (pruneRows > 0)) {
+        it = mLogElements.begin();
+        while((it != mLogElements.end()) && (pruneRows > 0)) {
+            LogBufferElement *e = *it;
+            if (e->getLogId() == id) {
+                if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
+                    if (stats.sizes(id) > (2 * log_buffer_size(id))) {
+                        // kick a misbehaving log reader client off the island
+                        oldest->release_Locked();
+                    } else {
+                        oldest->triggerSkip_Locked(pruneRows);
+                    }
+                    break;
+                }
+                it = mLogElements.erase(it);
+                stats.subtract(e->getMsgLen(), id, e->getUid(), e->getPid());
+                delete e;
+                pruneRows--;
+            } else {
+                it++;
+            }
+        }
+    }
+#endif
+
     LogTimeEntry::unlock();
 }
 
@@ -224,11 +305,37 @@
     return retval;
 }
 
+#ifdef USERDEBUG_BUILD
+
+// set the total space allocated to "id"
+int LogBuffer::setSize(log_id_t id, unsigned long size) {
+    // Reasonable limits ...
+    if ((size < (64 * 1024)) || ((256 * 1024 * 1024) < size)) {
+        return -1;
+    }
+    pthread_mutex_lock(&mLogElementsLock);
+    log_buffer_size(id) = size;
+    pthread_mutex_unlock(&mLogElementsLock);
+    return 0;
+}
+
+// get the total space allocated to "id"
+unsigned long LogBuffer::getSize(log_id_t id) {
+    pthread_mutex_lock(&mLogElementsLock);
+    size_t retval = log_buffer_size(id);
+    pthread_mutex_unlock(&mLogElementsLock);
+    return retval;
+}
+
+#else // ! USERDEBUG_BUILD
+
 // get the total space allocated to "id"
 unsigned long LogBuffer::getSize(log_id_t /*id*/) {
-    return LOG_BUFFER_SIZE;
+    return log_buffer_size(id);
 }
 
+#endif
+
 log_time LogBuffer::flushTo(
         SocketClient *reader, const log_time start, bool privileged,
         bool (*filter)(const LogBufferElement *element, void *arg), void *arg) {
@@ -269,7 +376,7 @@
     return max;
 }
 
-size_t LogBuffer::formatStatistics(char **strp, uid_t uid, unsigned int logMask) {
+void LogBuffer::formatStatistics(char **strp, uid_t uid, unsigned int logMask) {
     log_time oldest(CLOCK_MONOTONIC);
 
     pthread_mutex_lock(&mLogElementsLock);
@@ -285,9 +392,7 @@
         }
     }
 
-    size_t ret = stats.format(strp, uid, logMask, oldest);
+    stats.format(strp, uid, logMask, oldest);
 
     pthread_mutex_unlock(&mLogElementsLock);
-
-    return ret;
 }