Merge "Create android-base/format.h that includes fmtlib headers"
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index ac739c4..1abae87 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -169,12 +169,12 @@
 };
 
 struct UsbFfsConnection : public Connection {
-    UsbFfsConnection(unique_fd* control, unique_fd read, unique_fd write,
+    UsbFfsConnection(unique_fd control, unique_fd read, unique_fd write,
                      std::promise<void> destruction_notifier)
         : worker_started_(false),
           stopped_(false),
           destruction_notifier_(std::move(destruction_notifier)),
-          control_fd_(control),
+          control_fd_(std::move(control)),
           read_fd_(std::move(read)),
           write_fd_(std::move(write)) {
         LOG(INFO) << "UsbFfsConnection constructed";
@@ -183,6 +183,11 @@
             PLOG(FATAL) << "failed to create eventfd";
         }
 
+        monitor_event_fd_.reset(eventfd(0, EFD_CLOEXEC));
+        if (monitor_event_fd_ == -1) {
+            PLOG(FATAL) << "failed to create eventfd";
+        }
+
         aio_context_ = ScopedAioContext::Create(kUsbReadQueueDepth + kUsbWriteQueueDepth);
     }
 
@@ -194,6 +199,7 @@
         // We need to explicitly close our file descriptors before we notify our destruction,
         // because the thread listening on the future will immediately try to reopen the endpoint.
         aio_context_.reset();
+        control_fd_.reset();
         read_fd_.reset();
         write_fd_.reset();
 
@@ -240,6 +246,13 @@
             PLOG(FATAL) << "failed to notify worker eventfd to stop UsbFfsConnection";
         }
         CHECK_EQ(static_cast<size_t>(rc), sizeof(notify));
+
+        rc = adb_write(monitor_event_fd_.get(), &notify, sizeof(notify));
+        if (rc < 0) {
+            PLOG(FATAL) << "failed to notify monitor eventfd to stop UsbFfsConnection";
+        }
+
+        CHECK_EQ(static_cast<size_t>(rc), sizeof(notify));
     }
 
   private:
@@ -258,24 +271,33 @@
         monitor_thread_ = std::thread([this]() {
             adb_thread_setname("UsbFfs-monitor");
 
+            bool bound = false;
             bool enabled = false;
             bool running = true;
             while (running) {
                 adb_pollfd pfd[2] = {
-                        {.fd = control_fd_->get(), .events = POLLIN, .revents = 0},
+                  { .fd = control_fd_.get(), .events = POLLIN, .revents = 0 },
+                  { .fd = monitor_event_fd_.get(), .events = POLLIN, .revents = 0 },
                 };
 
-                int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, -1));
+                // If we don't see our first bind within a second, try again.
+                int timeout_ms = bound ? -1 : 1000;
+
+                int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, timeout_ms));
                 if (rc == -1) {
                     PLOG(FATAL) << "poll on USB control fd failed";
+                } else if (rc == 0) {
+                    LOG(WARNING) << "timed out while waiting for FUNCTIONFS_BIND, trying again";
+                    break;
                 }
 
                 if (pfd[1].revents) {
-                    // We were told to die, continue reading until FUNCTIONFS_UNBIND.
+                    // We were told to die.
+                    break;
                 }
 
                 struct usb_functionfs_event event;
-                rc = TEMP_FAILURE_RETRY(adb_read(control_fd_->get(), &event, sizeof(event)));
+                rc = TEMP_FAILURE_RETRY(adb_read(control_fd_.get(), &event, sizeof(event)));
                 if (rc == -1) {
                     PLOG(FATAL) << "failed to read functionfs event";
                 } else if (rc == 0) {
@@ -291,10 +313,28 @@
 
                 switch (event.type) {
                     case FUNCTIONFS_BIND:
-                        LOG(FATAL) << "received FUNCTIONFS_BIND after already opened?";
+                        if (bound) {
+                            LOG(WARNING) << "received FUNCTIONFS_BIND while already bound?";
+                            running = false;
+                            break;
+                        }
+
+                        if (enabled) {
+                            LOG(WARNING) << "received FUNCTIONFS_BIND while already enabled?";
+                            running = false;
+                            break;
+                        }
+
+                        bound = true;
                         break;
 
                     case FUNCTIONFS_ENABLE:
+                        if (!bound) {
+                            LOG(WARNING) << "received FUNCTIONFS_ENABLE while not bound?";
+                            running = false;
+                            break;
+                        }
+
                         if (enabled) {
                             LOG(WARNING) << "received FUNCTIONFS_ENABLE while already enabled?";
                             running = false;
@@ -306,6 +346,10 @@
                         break;
 
                     case FUNCTIONFS_DISABLE:
+                        if (!bound) {
+                            LOG(WARNING) << "received FUNCTIONFS_DISABLE while not bound?";
+                        }
+
                         if (!enabled) {
                             LOG(WARNING) << "received FUNCTIONFS_DISABLE while not enabled?";
                         }
@@ -319,6 +363,11 @@
                             LOG(WARNING) << "received FUNCTIONFS_UNBIND while still enabled?";
                         }
 
+                        if (!bound) {
+                            LOG(WARNING) << "received FUNCTIONFS_UNBIND when not bound?";
+                        }
+
+                        bound = false;
                         running = false;
                         break;
 
@@ -332,7 +381,7 @@
 
                         if ((event.u.setup.bRequestType & USB_DIR_IN)) {
                             LOG(INFO) << "acking device-to-host control transfer";
-                            ssize_t rc = adb_write(control_fd_->get(), "", 0);
+                            ssize_t rc = adb_write(control_fd_.get(), "", 0);
                             if (rc != 0) {
                                 PLOG(ERROR) << "failed to write empty packet to host";
                                 break;
@@ -341,7 +390,7 @@
                             std::string buf;
                             buf.resize(event.u.setup.wLength + 1);
 
-                            ssize_t rc = adb_read(control_fd_->get(), buf.data(), buf.size());
+                            ssize_t rc = adb_read(control_fd_.get(), buf.data(), buf.size());
                             if (rc != event.u.setup.wLength) {
                                 LOG(ERROR)
                                         << "read " << rc
@@ -377,12 +426,6 @@
                 uint64_t dummy;
                 ssize_t rc = adb_read(worker_event_fd_.get(), &dummy, sizeof(dummy));
                 if (rc == -1) {
-                    if (errno == EINTR) {
-                        // We were interrupted either to stop, or because of a backtrace.
-                        // Check stopped_ again to see if we need to exit.
-                        continue;
-                    }
-
                     PLOG(FATAL) << "failed to read from eventfd";
                 } else if (rc == 0) {
                     LOG(FATAL) << "hit EOF on eventfd";
@@ -419,7 +462,6 @@
         }
 
         worker_thread_.join();
-        worker_started_ = false;
     }
 
     void PrepareReadBlock(IoBlock* block, uint64_t id) {
@@ -637,13 +679,10 @@
     std::once_flag error_flag_;
 
     unique_fd worker_event_fd_;
+    unique_fd monitor_event_fd_;
 
     ScopedAioContext aio_context_;
-
-    // We keep a pointer to the control fd, so that we can reuse it to avoid USB reconfiguration,
-    // and still be able to reset it to force a reopen after FUNCTIONFS_UNBIND or running into an
-    // unexpected situation.
-    unique_fd* control_fd_;
+    unique_fd control_fd_;
     unique_fd read_fd_;
     unique_fd write_fd_;
 
@@ -672,16 +711,15 @@
 static void usb_ffs_open_thread() {
     adb_thread_setname("usb ffs open");
 
-    unique_fd control;
-    unique_fd bulk_out;
-    unique_fd bulk_in;
-
     while (true) {
         if (gFfsAioSupported.has_value() && !gFfsAioSupported.value()) {
             LOG(INFO) << "failed to use nonblocking ffs, falling back to legacy";
             return usb_init_legacy();
         }
 
+        unique_fd control;
+        unique_fd bulk_out;
+        unique_fd bulk_in;
         if (!open_functionfs(&control, &bulk_out, &bulk_in)) {
             std::this_thread::sleep_for(1s);
             continue;
@@ -692,7 +730,7 @@
         std::promise<void> destruction_notifier;
         std::future<void> future = destruction_notifier.get_future();
         transport->SetConnection(std::make_unique<UsbFfsConnection>(
-                &control, std::move(bulk_out), std::move(bulk_in),
+                std::move(control), std::move(bulk_out), std::move(bulk_in),
                 std::move(destruction_notifier)));
         register_transport(transport);
         future.wait();
diff --git a/adb/daemon/usb_ffs.cpp b/adb/daemon/usb_ffs.cpp
index 1b54022..a64ce40 100644
--- a/adb/daemon/usb_ffs.cpp
+++ b/adb/daemon/usb_ffs.cpp
@@ -297,32 +297,8 @@
             PLOG(ERROR) << "failed to write USB strings";
             return false;
         }
-
-        // Signal init after we've wwritten our descriptors.
+        // Signal only when writing the descriptors to ffs
         android::base::SetProperty("sys.usb.ffs.ready", "1");
-
-        // Read until we get FUNCTIONFS_BIND from the control endpoint.
-        while (true) {
-            struct usb_functionfs_event event;
-            ssize_t rc = TEMP_FAILURE_RETRY(adb_read(control.get(), &event, sizeof(event)));
-
-            if (rc == -1) {
-                PLOG(FATAL) << "failed to read from FFS control fd";
-            } else if (rc == 0) {
-                LOG(WARNING) << "hit EOF on functionfs control fd during initialization";
-            } else if (rc != sizeof(event)) {
-                LOG(FATAL) << "read functionfs event of unexpected size, expected " << sizeof(event)
-                           << ", got " << rc;
-            }
-
-            if (event.type != FUNCTIONFS_BIND) {
-                LOG(FATAL) << "first read on functionfs control fd returned non-bind: "
-                           << event.type;
-            } else {
-                break;
-            }
-        }
-
         *out_control = std::move(control);
     }
 
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 403f9be..31790b1 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -171,6 +171,18 @@
                 fs_options.append(",");  // appends a comma if not the first
             }
             fs_options.append(flag);
+
+            if (entry->fs_type == "f2fs" && StartsWith(flag, "reserve_root=")) {
+                std::string arg;
+                if (auto equal_sign = flag.find('='); equal_sign != std::string::npos) {
+                    arg = flag.substr(equal_sign + 1);
+                }
+                if (!ParseInt(arg, &entry->reserved_size)) {
+                    LWARNING << "Warning: reserve_root= flag malformed: " << arg;
+                } else {
+                    entry->reserved_size <<= 12;
+                }
+            }
         }
     }
     entry->fs_options = std::move(fs_options);
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index 7039994..b504161 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -14,6 +14,16 @@
 // limitations under the License.
 //
 
+liblp_lib_deps = [
+    "libbase",
+    "liblog",
+    "libcrypto",
+    "libcrypto_utils",
+    "libsparse",
+    "libext4_utils",
+    "libz",
+]
+
 cc_library {
     name: "liblp",
     host_supported: true,
@@ -30,15 +40,7 @@
         "utility.cpp",
         "writer.cpp",
     ],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcrypto",
-        "libcrypto_utils",
-        "libsparse",
-        "libext4_utils",
-        "libz",
-    ],
+    shared_libs: liblp_lib_deps,
     target: {
         windows: {
             enabled: true,
@@ -53,24 +55,28 @@
 }
 
 cc_test {
-    name: "liblp_test",
+    name: "liblp_test_static",
     defaults: ["fs_mgr_defaults"],
     cppflags: [
         "-Wno-unused-parameter",
     ],
     static_libs: [
         "libgmock",
-    ],
-    shared_libs: [
-        "liblp",
-        "libbase",
         "libfs_mgr",
-        "libsparse",
-    ],
+        "liblp",
+    ] + liblp_lib_deps,
+    stl: "libc++_static",
     srcs: [
         "builder_test.cpp",
         "io_test.cpp",
         "test_partition_opener.cpp",
         "utility_test.cpp",
     ],
+    target: {
+        android: {
+            static_libs: [
+                "libcutils",
+            ],
+        },
+    },
 }
diff --git a/fs_mgr/liblp/AndroidTest.xml b/fs_mgr/liblp/AndroidTest.xml
index 007a302..fe1002c 100644
--- a/fs_mgr/liblp/AndroidTest.xml
+++ b/fs_mgr/liblp/AndroidTest.xml
@@ -21,8 +21,8 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
       <option name="test-module-name" value="VtsKernelLiblpTest"/>
-        <option name="binary-test-source" value="_32bit::DATA/nativetest/liblp_test/liblp_test" />
-        <option name="binary-test-source" value="_64bit::DATA/nativetest64/liblp_test/liblp_test" />
+        <option name="binary-test-source" value="_32bit::DATA/nativetest/liblp_test_static/liblp_test_static" />
+        <option name="binary-test-source" value="_64bit::DATA/nativetest64/liblp_test_static/liblp_test_static" />
         <option name="binary-test-type" value="gtest"/>
         <option name="test-timeout" value="1m"/>
         <option name="precondition-first-api-level" value="29" />
diff --git a/init/keychords_test.cpp b/init/keychords_test.cpp
index a3baeb1..33373d4 100644
--- a/init/keychords_test.cpp
+++ b/init/keychords_test.cpp
@@ -29,7 +29,6 @@
 #include <vector>
 
 #include <android-base/properties.h>
-#include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <gtest/gtest.h>
 
diff --git a/init/keyword_map.h b/init/keyword_map.h
index c95fc73..7837bb3 100644
--- a/init/keyword_map.h
+++ b/init/keyword_map.h
@@ -14,14 +14,11 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_KEYWORD_MAP_H_
-#define _INIT_KEYWORD_MAP_H_
+#pragma once
 
 #include <map>
 #include <string>
 
-#include <android-base/stringprintf.h>
-
 #include "result.h"
 
 namespace android {
@@ -37,8 +34,6 @@
     }
 
     const Result<Function> FindFunction(const std::vector<std::string>& args) const {
-        using android::base::StringPrintf;
-
         if (args.empty()) return Error() << "Keyword needed, but not provided";
 
         auto& keyword = args[0];
@@ -46,7 +41,7 @@
 
         auto function_info_it = map().find(keyword);
         if (function_info_it == map().end()) {
-            return Error() << StringPrintf("Invalid keyword '%s'", keyword.c_str());
+            return Errorf("Invalid keyword '{}'", keyword);
         }
 
         auto function_info = function_info_it->second;
@@ -54,17 +49,17 @@
         auto min_args = std::get<0>(function_info);
         auto max_args = std::get<1>(function_info);
         if (min_args == max_args && num_args != min_args) {
-            return Error() << StringPrintf("%s requires %zu argument%s", keyword.c_str(), min_args,
-                                           (min_args > 1 || min_args == 0) ? "s" : "");
+            return Errorf("{} requires {} argument{}", keyword, min_args,
+                          (min_args > 1 || min_args == 0) ? "s" : "");
         }
 
         if (num_args < min_args || num_args > max_args) {
             if (max_args == std::numeric_limits<decltype(max_args)>::max()) {
-                return Error() << StringPrintf("%s requires at least %zu argument%s",
-                                               keyword.c_str(), min_args, min_args > 1 ? "s" : "");
+                return Errorf("{} requires at least {} argument{}", keyword, min_args,
+                              min_args > 1 ? "s" : "");
             } else {
-                return Error() << StringPrintf("%s requires between %zu and %zu arguments",
-                                               keyword.c_str(), min_args, max_args);
+                return Errorf("{} requires between {} and {} arguments", keyword, min_args,
+                              max_args);
             }
         }
 
@@ -79,5 +74,3 @@
 
 }  // namespace init
 }  // namespace android
-
-#endif
diff --git a/init/reboot.cpp b/init/reboot.cpp
index fbc03c2..eaba3cc 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -41,7 +41,6 @@
 #include <android-base/logging.h>
 #include <android-base/macros.h>
 #include <android-base/properties.h>
-#include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <bootloader_message/bootloader_message.h>
@@ -62,7 +61,6 @@
 
 using android::base::GetBoolProperty;
 using android::base::Split;
-using android::base::StringPrintf;
 using android::base::Timer;
 using android::base::unique_fd;
 using android::base::WriteStringToFile;
diff --git a/init/result.h b/init/result.h
index 8c1f91e..b70dd1b 100644
--- a/init/result.h
+++ b/init/result.h
@@ -22,6 +22,8 @@
 #include <android-base/result.h>
 
 using android::base::ErrnoError;
+using android::base::ErrnoErrorf;
 using android::base::Error;
+using android::base::Errorf;
 using android::base::Result;
 using android::base::ResultError;
diff --git a/init/service.cpp b/init/service.cpp
index b6a7c33..4fe374c 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -332,12 +332,11 @@
         const std::string& arg = args[i];
         int res = LookupCap(arg);
         if (res < 0) {
-            return Error() << StringPrintf("invalid capability '%s'", arg.c_str());
+            return Errorf("invalid capability '{}'", arg);
         }
         unsigned int cap = static_cast<unsigned int>(res);  // |res| is >= 0.
         if (cap > last_valid_cap) {
-            return Error() << StringPrintf("capability '%s' not supported by the kernel",
-                                           arg.c_str());
+            return Errorf("capability '{}' not supported by the kernel", arg);
         }
         (*capabilities_)[cap] = true;
     }
@@ -402,8 +401,8 @@
     if (!ParseInt(args[1], &proc_attr_.priority,
                   static_cast<int>(ANDROID_PRIORITY_HIGHEST),  // highest is negative
                   static_cast<int>(ANDROID_PRIORITY_LOWEST))) {
-        return Error() << StringPrintf("process priority value must be range %d - %d",
-                                       ANDROID_PRIORITY_HIGHEST, ANDROID_PRIORITY_LOWEST);
+        return Errorf("process priority value must be range {} - {}", ANDROID_PRIORITY_HIGHEST,
+                      ANDROID_PRIORITY_LOWEST);
     }
     return {};
 }