Merge "storaged: include start time in IO usage dumpsys"
diff --git a/adb/Android.mk b/adb/Android.mk
index b444afa..c51e0b8 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -216,9 +216,9 @@
 LOCAL_SRC_FILES_darwin := $(LIBADB_TEST_darwin_SRCS)
 LOCAL_SRC_FILES_windows := $(LIBADB_TEST_windows_SRCS)
 LOCAL_SANITIZE := $(adb_host_sanitize)
-LOCAL_SHARED_LIBRARIES := libbase
 LOCAL_STATIC_LIBRARIES := \
     libadb \
+    libbase \
     libcrypto_utils \
     libcrypto \
     libcutils \
@@ -232,7 +232,7 @@
 LOCAL_LDFLAGS_windows := -municode
 LOCAL_LDLIBS_linux := -lrt -ldl -lpthread
 LOCAL_LDLIBS_darwin := -framework CoreFoundation -framework IOKit -lobjc
-LOCAL_LDLIBS_windows := -lws2_32 -luserenv
+LOCAL_LDLIBS_windows := -lws2_32 -luserenv -static -lwinpthread
 LOCAL_STATIC_LIBRARIES_windows := AdbWinApi
 
 LOCAL_MULTILIB := first
@@ -249,7 +249,7 @@
 
 # Use wmain instead of main
 LOCAL_LDFLAGS_windows := -municode
-LOCAL_LDLIBS_windows := -lws2_32 -lgdi32
+LOCAL_LDLIBS_windows := -lws2_32 -lgdi32 -static -lwinpthread
 LOCAL_STATIC_LIBRARIES_windows := AdbWinApi
 LOCAL_REQUIRED_MODULES_windows := AdbWinApi AdbWinUsbApi
 
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index ac05d4c..c08b922 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -319,7 +319,7 @@
     D("[ adb: cannot call endpoint alloc: errno=%d ]", errno);
     // Kernel pre-allocation could have failed for recoverable reasons.
     // Continue running with a safe max rw size.
-    h->max_rw *= 2;
+    h->max_rw = USB_FFS_BULK_SIZE;
     return true;
 
 err:
diff --git a/base/include/android-base/properties.h b/base/include/android-base/properties.h
index e275fa2..e2324b7 100644
--- a/base/include/android-base/properties.h
+++ b/base/include/android-base/properties.h
@@ -23,6 +23,7 @@
 #error Only bionic supports system properties.
 #endif
 
+#include <chrono>
 #include <limits>
 #include <string>
 
@@ -58,8 +59,12 @@
 // tell you whether or not your call succeeded. A `false` return value definitely means failure.
 bool SetProperty(const std::string& key, const std::string& value);
 
-// Waits for the system property `key` to have the value `expected_value`, .
-void WaitForProperty(const std::string& key, const std::string& expected_value);
+// Waits for the system property `key` to have the value `expected_value`.
+// Times out after `relative_timeout`.
+// Returns true on success, false on timeout.
+bool WaitForProperty(const std::string& key,
+                     const std::string& expected_value,
+                     std::chrono::milliseconds relative_timeout);
 
 } // namespace base
 } // namespace android
diff --git a/base/properties.cpp b/base/properties.cpp
index 0f0f638..acd6c0f 100644
--- a/base/properties.cpp
+++ b/base/properties.cpp
@@ -21,10 +21,14 @@
 #include <sys/system_properties.h>
 #include <sys/_system_properties.h>
 
+#include <algorithm>
+#include <chrono>
 #include <string>
 
 #include <android-base/parseint.h>
 
+using namespace std::chrono_literals;
+
 namespace android {
 namespace base {
 
@@ -96,14 +100,41 @@
   }
 }
 
-void WaitForProperty(const std::string& key, const std::string& expected_value) {
+// TODO: chrono_utils?
+static void DurationToTimeSpec(timespec& ts, std::chrono::nanoseconds d) {
+  auto s = std::chrono::duration_cast<std::chrono::seconds>(d);
+  auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(d - s);
+  ts.tv_sec = s.count();
+  ts.tv_nsec = ns.count();
+}
+
+static void UpdateTimeSpec(timespec& ts,
+                           const std::chrono::time_point<std::chrono::steady_clock>& timeout) {
+  auto now = std::chrono::steady_clock::now();
+  auto remaining_timeout = std::chrono::duration_cast<std::chrono::nanoseconds>(timeout - now);
+  if (remaining_timeout < 0ns) {
+    ts = { 0, 0 };
+  } else {
+    DurationToTimeSpec(ts, remaining_timeout);
+  }
+}
+
+bool WaitForProperty(const std::string& key,
+                     const std::string& expected_value,
+                     std::chrono::milliseconds relative_timeout) {
+  // TODO: boot_clock?
+  auto now = std::chrono::steady_clock::now();
+  std::chrono::time_point<std::chrono::steady_clock> absolute_timeout = now + relative_timeout;
+  timespec ts;
+
   // Find the property's prop_info*.
   const prop_info* pi;
   unsigned global_serial = 0;
   while ((pi = __system_property_find(key.c_str())) == nullptr) {
     // The property doesn't even exist yet.
     // Wait for a global change and then look again.
-    global_serial = __system_property_wait_any(global_serial);
+    UpdateTimeSpec(ts, absolute_timeout);
+    if (!__system_property_wait(nullptr, global_serial, &global_serial, &ts)) return false;
   }
 
   WaitForPropertyData data;
@@ -112,10 +143,12 @@
   while (true) {
     // Check whether the property has the value we're looking for?
     __system_property_read_callback(pi, WaitForPropertyCallback, &data);
-    if (data.done) return;
+    if (data.done) return true;
 
-    // It didn't so wait for it to change before checking again.
-    __system_property_wait(pi, data.last_read_serial);
+    // It didn't, so wait for the property to change before checking again.
+    UpdateTimeSpec(ts, absolute_timeout);
+    uint32_t unused;
+    if (!__system_property_wait(pi, data.last_read_serial, &unused, &ts)) return false;
   }
 }
 
diff --git a/base/properties_test.cpp b/base/properties_test.cpp
index d8186be..c68c2f8 100644
--- a/base/properties_test.cpp
+++ b/base/properties_test.cpp
@@ -134,8 +134,19 @@
     android::base::SetProperty("debug.libbase.WaitForProperty_test", "b");
   });
 
-  android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "a");
+  ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "a", 1s));
   flag = true;
-  android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b");
+  ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b", 1s));
   thread.join();
 }
+
+TEST(properties, WaitForProperty_timeout) {
+  auto t0 = std::chrono::steady_clock::now();
+  ASSERT_FALSE(android::base::WaitForProperty("debug.libbase.WaitForProperty_timeout_test", "a",
+                                              200ms));
+  auto t1 = std::chrono::steady_clock::now();
+
+  ASSERT_GE(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 200ms);
+  // Upper bounds on timing are inherently flaky, but let's try...
+  ASSERT_LT(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 600ms);
+}
diff --git a/init/README.md b/init/README.md
index c76a33b..d3dd73a 100644
--- a/init/README.md
+++ b/init/README.md
@@ -26,7 +26,7 @@
 Init .rc Files
 --------------
 The init language is used in plain text files that take the .rc file
-extension.  These are typically multiple of these in multiple
+extension.  There are typically multiple of these in multiple
 locations on the system, described below.
 
 /init.rc is the primary .rc file and is loaded by the init executable
diff --git a/liblog/logd_reader.c b/liblog/logd_reader.c
index ccc7da8..a6c3f7a 100644
--- a/liblog/logd_reader.c
+++ b/liblog/logd_reader.c
@@ -91,7 +91,7 @@
 
 static int logdAvailable(log_id_t logId)
 {
-    if (logId > LOG_ID_KERNEL) {
+    if (logId >= LOG_ID_MAX) {
         return -EINVAL;
     }
     if (logId == LOG_ID_SECURITY) {
diff --git a/liblog/logd_writer.c b/liblog/logd_writer.c
index 2bab92e..12b797d 100644
--- a/liblog/logd_writer.c
+++ b/liblog/logd_writer.c
@@ -117,7 +117,7 @@
 
 static int logdAvailable(log_id_t logId)
 {
-    if (logId > LOG_ID_SECURITY) {
+    if (logId >= LOG_ID_MAX || logId == LOG_ID_KERNEL) {
         return -EINVAL;
     }
     if (atomic_load(&logdLoggerWrite.context.sock) < 0) {
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 15cef1a..7f852d4 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -1231,8 +1231,11 @@
                     android::close_error(context);
                     context->stderr_stdout = true;
                     context->output = fp;
-                    context->error = context->output;
-                    if (context->stderr_null) context->error = NULL;
+                    context->output_fd = fileno(fp);
+                    if (context->stderr_null) break;
+                    context->stderr_stdout = true;
+                    context->error = fp;
+                    context->error_fd = fileno(fp);
                 }
                 break;