dumpstate: calculate logcat timeout using readable buffer size

Calculate logcat timeout using readable buffer size instead of the
allotted buffer size for three reasons:

1) With log buffer compression, the readable buffer size may be much
larger than the consumed buffer size, so the timeout should be based
on the former.

2) __android_logger_get_buffer_size() reports the wrong value if
`logcat -G` is used to set the log buffer size, since that directly
informs logd of the new size, without writing to the properties.

3) Given 2), __android_logger_get_buffer_size() is an implementation
detail for logd and should not be generally used.  The
android_logger_get_log_*_size() functions should be used instead.
Future CLs will remove __android_logger_get_buffer_size() from liblog.

Test: bug reports capture logcat correctly
Test: bug reports succeed if `logd` is stopped, after timing out when
      reading from logcat
Change-Id: Iac5dcba4f729c022073a812b48cd028ca2d59e52
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index ec97f1b..78c09f2 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -76,6 +76,7 @@
 #include <hardware_legacy/power.h>
 #include <hidl/ServiceManagement.h>
 #include <log/log.h>
+#include <log/log_read.h>
 #include <openssl/sha.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
@@ -634,14 +635,24 @@
 
 static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
 
-/* timeout in ms to read a list of buffers */
+// Returns the actual readable size of the given buffer or -1 on error.
+static long logcat_buffer_readable_size(const std::string& buffer) {
+    std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
+        android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
+    auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
+
+    return android_logger_get_log_readable_size(logger);
+}
+
+// Returns timeout in ms to read a list of buffers.
 static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
     unsigned long timeout_ms = 0;
     for (const auto& buffer : buffers) {
-        log_id_t id = android_name_to_log_id(buffer.c_str());
-        unsigned long property_size = __android_logger_get_buffer_size(id);
-        /* Engineering margin is ten-fold our guess */
-        timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf;
+        long readable_size = logcat_buffer_readable_size(buffer);
+        if (readable_size > 0) {
+            // Engineering margin is ten-fold our guess.
+            timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
+        }
     }
     return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
 }