logd: logcat: Add persist.logd.size group of properties

- logd Add persist.logd.size (global), persist.logd.size.<logid>
- logcat report a more flexible multiplier in -g command.

Bug: 14563261
Bug: 14469172
Change-Id: Ie389caa14ad3ae3d4a3a3cc463425bb9dbc5e483
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index ea46345..db4fddd 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -281,6 +281,30 @@
     return 0;
 }
 
+static const char multipliers[][2] = {
+    { "" },
+    { "K" },
+    { "M" },
+    { "G" }
+};
+
+static unsigned long value_of_size(unsigned long value)
+{
+    for (unsigned i = 0;
+            (i < sizeof(multipliers)/sizeof(multipliers[0])) && (value >= 1024);
+            value /= 1024, ++i) ;
+    return value;
+}
+
+static const char *multiplier_of_size(unsigned long value)
+{
+    unsigned i;
+    for (i = 0;
+            (i < sizeof(multipliers)/sizeof(multipliers[0])) && (value >= 1024);
+            value /= 1024, ++i) ;
+    return multipliers[i];
+}
+
 int main(int argc, char **argv)
 {
     int err;
@@ -715,9 +739,10 @@
                 exit(EXIT_FAILURE);
             }
 
-            printf("%s: ring buffer is %ldKb (%ldKb consumed), "
+            printf("%s: ring buffer is %ld%sb (%ld%sb consumed), "
                    "max entry is %db, max payload is %db\n", dev->device,
-                   size / 1024, readable / 1024,
+                   value_of_size(size), multiplier_of_size(size),
+                   value_of_size(readable), multiplier_of_size(readable),
                    (int) LOGGER_ENTRY_MAX_LEN, (int) LOGGER_ENTRY_MAX_PAYLOAD);
         }
 
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 38a237c..dc9d47e 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -14,29 +14,68 @@
  * limitations under the License.
  */
 
+#include <ctype.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
 
+#include <cutils/properties.h>
 #include <log/logger.h>
 
 #include "LogBuffer.h"
+#include "LogReader.h"
 #include "LogStatistics.h"
 #include "LogWhiteBlackList.h"
-#include "LogReader.h"
 
 // Default
 #define LOG_BUFFER_SIZE (256 * 1024) // Tuned on a per-platform basis here?
 #define log_buffer_size(id) mMaxSize[id]
 
+static unsigned long property_get_size(const char *key) {
+    char property[PROPERTY_VALUE_MAX];
+    property_get(key, property, "");
+
+    char *cp;
+    unsigned long value = strtoul(property, &cp, 10);
+
+    switch(*cp) {
+    case 'm':
+    case 'M':
+        value *= 1024;
+    /* FALLTHRU */
+    case 'k':
+    case 'K':
+        value *= 1024;
+    /* FALLTHRU */
+    case '\0':
+        break;
+
+    default:
+        value = 0;
+    }
+
+    return value;
+}
+
 LogBuffer::LogBuffer(LastLogTimes *times)
         : mTimes(*times) {
     pthread_mutex_init(&mLogElementsLock, NULL);
     dgram_qlen_statistics = false;
 
+    static const char global_default[] = "persist.logd.size";
+    unsigned long default_size = property_get_size(global_default);
+
     log_id_for_each(i) {
-        mMaxSize[i] = LOG_BUFFER_SIZE;
+        setSize(i, LOG_BUFFER_SIZE);
+        setSize(i, default_size);
+
+        char key[PROP_NAME_MAX];
+        snprintf(key, sizeof(key), "%s.%s",
+                 global_default, android_log_id_to_name(i));
+
+        setSize(i, property_get_size(key));
     }
 }
 
diff --git a/logd/README.property b/logd/README.property
index 5d92d09..f4b3c3c 100644
--- a/logd/README.property
+++ b/logd/README.property
@@ -10,3 +10,16 @@
                                          minimum domain socket network FIFO
                                          size (see source for details) based
                                          on typical load (logcat -S to view)
+persist.logd.size          number 256K   default size of the buffer for all
+                                         log ids at initial startup, at runtime
+                                         use: logcat -b all -G <value>
+persist.logd.size.main     number 256K   Size of the buffer for the main log
+persist.logd.size.system   number 256K   Size of the buffer for the system log
+persist.logd.size.radio    number 256K   Size of the buffer for the radio log
+persist.logd.size.event    number 256K   Size of the buffer for the event log
+persist.logd.size.crash    number 256K   Size of the buffer for the crash log
+
+NB:
+- number support multipliers (K or M) for convenience. Range is limited
+  to between 64K and 256M for log buffer sizes. Individual logs override the
+  global default.