Merge "Create integration test for fastboot CLI" into main
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 18892f9..7ba4d2b 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -158,15 +158,25 @@
     // not checkpointing.
     auto vold = GetVold();
     bool checkpointing = false;
-    if (!vold->isCheckpointing(&checkpointing).isOk()) {
-        LOG(ERROR) << "Could not determine checkpointing status.";
-        return false;
-    }
-    if (checkpointing) {
-        LOG(ERROR) << "Cannot use remount when a checkpoint is in progress.";
-        LOG(ERROR) << "To force end checkpointing, call 'vdc checkpoint commitChanges'";
-        LOG(ERROR) << "Warning: this can lead to data corruption if rolled back.";
-        return false;
+    bool show_help = true;
+
+    while (true) {
+        if (!vold->isCheckpointing(&checkpointing).isOk()) {
+            LOG(ERROR) << "Could not determine checkpointing status.";
+            return false;
+        }
+        if (!checkpointing) {
+            break;
+        }
+        if (show_help) {
+            show_help = false;
+            std::cerr << "WARNING: Userdata checkpoint is in progress. To force end checkpointing, "
+                         "call 'vdc checkpoint commitChanges'. This can lead to data corruption if "
+                         "rolled back."
+                      << std::endl;
+            LOG(INFO) << "Waiting for checkpoint to complete and then continue remount.";
+        }
+        std::this_thread::sleep_for(4s);
     }
     return true;
 }
diff --git a/fs_mgr/liblp/fuzzer/liblp_apis_fuzzer.cpp b/fs_mgr/liblp/fuzzer/liblp_apis_fuzzer.cpp
index b6fbc14..a15bc89 100644
--- a/fs_mgr/liblp/fuzzer/liblp_apis_fuzzer.cpp
+++ b/fs_mgr/liblp/fuzzer/liblp_apis_fuzzer.cpp
@@ -198,13 +198,13 @@
                     [&]() {
                         uint32_t groupVectorSize = metadata->groups.size();
                         uint32_t randomGroupIndex =
-                                mFdp.ConsumeIntegralInRange<uint32_t>(0, groupVectorSize);
+                                mFdp.ConsumeIntegralInRange<uint32_t>(0, groupVectorSize - 1);
                         GetPartitionGroupName(metadata->groups[randomGroupIndex]);
                     },
                     [&]() {
                         uint32_t blockDeviceVectorSize = metadata->block_devices.size();
                         uint32_t randomBlockDeviceIndex =
-                                mFdp.ConsumeIntegralInRange<uint32_t>(0, blockDeviceVectorSize);
+                                mFdp.ConsumeIntegralInRange<uint32_t>(0, blockDeviceVectorSize - 1);
                         GetBlockDevicePartitionName(
                                 metadata->block_devices[randomBlockDeviceIndex]);
                     },
@@ -224,7 +224,7 @@
                     [&]() {
                         uint32_t partitionVectorSize = metadata->partitions.size();
                         uint32_t randomPartitionIndex =
-                                mFdp.ConsumeIntegralInRange<uint32_t>(0, partitionVectorSize);
+                                mFdp.ConsumeIntegralInRange<uint32_t>(0, partitionVectorSize - 1);
                         GetPartitionName(metadata->partitions[randomPartitionIndex]);
                     },
                     [&]() { GetTotalSuperPartitionSize(metadataValue); },
diff --git a/fs_mgr/tests/vts_fs_test.cpp b/fs_mgr/tests/vts_fs_test.cpp
index 32947b5..8f15220 100644
--- a/fs_mgr/tests/vts_fs_test.cpp
+++ b/fs_mgr/tests/vts_fs_test.cpp
@@ -32,6 +32,24 @@
     return android::base::GetIntProperty("ro.vendor.api_level", -1);
 }
 
+// Returns true iff the device has the specified feature.
+bool DeviceSupportsFeature(const char* feature) {
+    bool device_supports_feature = false;
+    FILE* p = popen("pm list features", "re");
+    if (p) {
+        char* line = NULL;
+        size_t len = 0;
+        while (getline(&line, &len, p) > 0) {
+            if (strstr(line, feature)) {
+                device_supports_feature = true;
+                break;
+            }
+        }
+        pclose(p);
+    }
+    return device_supports_feature;
+}
+
 TEST(fs, ErofsSupported) {
     // T-launch GKI kernels and higher must support EROFS.
     if (GetVsrLevel() < __ANDROID_API_T__) {
@@ -82,7 +100,8 @@
     ASSERT_TRUE(android::base::Readlink("/dev/block/by-name/userdata", &userdata_bdev));
 
     std::vector<std::string> must_be_f2fs = {"/data"};
-    if (vsr_level >= __ANDROID_API_U__) {
+    if (vsr_level >= __ANDROID_API_U__ &&
+        !DeviceSupportsFeature("android.hardware.type.automotive")) {
         must_be_f2fs.emplace_back("/metadata");
     }
 
diff --git a/libutils/Android.bp b/libutils/Android.bp
index b3ddda3..4d4294b 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -68,13 +68,6 @@
         "-Wno-exit-time-destructors",
         "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
     ],
-    header_libs: [
-        "libbase_headers",
-        "libutils_headers",
-    ],
-    export_header_lib_headers: [
-        "libutils_headers",
-    ],
 
     shared_libs: [
         "libcutils",
@@ -134,6 +127,14 @@
 
     whole_static_libs: ["libutils_binder"],
 
+    header_libs: [
+        "libbase_headers",
+        "libutils_headers",
+    ],
+    export_header_lib_headers: [
+        "libutils_headers",
+    ],
+
     srcs: [
         "FileMap.cpp",
         "JenkinsHash.cpp",
@@ -221,6 +222,14 @@
         support_system_process: true,
     },
 
+    header_libs: [
+        "libbase_headers",
+        "libutils_headers",
+    ],
+    export_header_lib_headers: [
+        "libutils_headers",
+    ],
+
     srcs: [
         "CallStack.cpp",
     ],
diff --git a/libutils/binder/Android.bp b/libutils/binder/Android.bp
index e2eddb3..a049f3d 100644
--- a/libutils/binder/Android.bp
+++ b/libutils/binder/Android.bp
@@ -10,6 +10,7 @@
     ],
     native_bridge_supported: true,
 
+    export_include_dirs: ["include"],
     srcs: [
         "Errors.cpp",
         "RefBase.cpp",
diff --git a/libutils/binder/RefBase.cpp b/libutils/binder/RefBase.cpp
index c7055fb..4b0cc16 100644
--- a/libutils/binder/RefBase.cpp
+++ b/libutils/binder/RefBase.cpp
@@ -20,8 +20,6 @@
 #include <memory>
 #include <mutex>
 
-#include <android-base/macros.h>
-
 #include <fcntl.h>
 #include <log/log.h>
 
@@ -65,7 +63,7 @@
 #endif
 
 #if CALLSTACK_ENABLED
-#include <utils/CallStack.h>
+#include "../../include/utils/CallStack.h"
 #endif
 
 // ---------------------------------------------------------------------------
@@ -536,7 +534,7 @@
     case INITIAL_STRONG_VALUE:
         refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
                 std::memory_order_relaxed);
-        FALLTHROUGH_INTENDED;
+        [[fallthrough]];
     case 0:
         refs->mBase->onFirstRef();
     }
diff --git a/libutils/binder/String8.cpp b/libutils/binder/String8.cpp
index 6a75484..749bfcb 100644
--- a/libutils/binder/String8.cpp
+++ b/libutils/binder/String8.cpp
@@ -19,7 +19,6 @@
 
 #include <utils/String8.h>
 
-#include <utils/Compat.h>
 #include <log/log.h>
 #include <utils/String16.h>
 
@@ -430,6 +429,13 @@
 // ---------------------------------------------------------------------------
 // Path functions
 
+// TODO: we should remove all the path functions from String8
+#if defined(_WIN32)
+#define OS_PATH_SEPARATOR '\\'
+#else
+#define OS_PATH_SEPARATOR '/'
+#endif
+
 String8 String8::getPathDir(void) const
 {
     const char* cp;
diff --git a/libutils/binder/Unicode.cpp b/libutils/binder/Unicode.cpp
index 364a177..2ed2d4f 100644
--- a/libutils/binder/Unicode.cpp
+++ b/libutils/binder/Unicode.cpp
@@ -16,7 +16,6 @@
 
 #define LOG_TAG "unicode"
 
-#include <android-base/macros.h>
 #include <limits.h>
 #include <utils/Unicode.h>
 
@@ -92,11 +91,11 @@
     switch (bytes)
     {   /* note: everything falls through. */
         case 4: *--dstP = (uint8_t)((srcChar | kByteMark) & kByteMask); srcChar >>= 6;
-            FALLTHROUGH_INTENDED;
+            [[fallthrough]];
         case 3: *--dstP = (uint8_t)((srcChar | kByteMark) & kByteMask); srcChar >>= 6;
-            FALLTHROUGH_INTENDED;
+            [[fallthrough]];
         case 2: *--dstP = (uint8_t)((srcChar | kByteMark) & kByteMask); srcChar >>= 6;
-            FALLTHROUGH_INTENDED;
+            [[fallthrough]];
         case 1: *--dstP = (uint8_t)(srcChar | kFirstByteMark[bytes]);
     }
 }
@@ -304,15 +303,15 @@
 
     while (in < end) {
         char16_t w = *in++;
-        if (LIKELY(w < 0x0080)) {
+        if (w < 0x0080) [[likely]] {
             utf8_len += 1;
             continue;
         }
-        if (LIKELY(w < 0x0800)) {
+        if (w < 0x0800) [[likely]] {
             utf8_len += 2;
             continue;
         }
-        if (LIKELY(!is_any_surrogate(w))) {
+        if (!is_any_surrogate(w)) [[likely]] {
             utf8_len += 3;
             continue;
         }
@@ -345,20 +344,20 @@
 
     while (in < in_end) {
         char16_t w = *in++;
-        if (LIKELY(w < 0x0080)) {
+        if (w < 0x0080) [[likely]] {
             if (out + 1 > out_end)
                 return err_out();
             *out++ = (char)(w & 0xff);
             continue;
         }
-        if (LIKELY(w < 0x0800)) {
+        if (w < 0x0800) [[likely]] {
             if (out + 2 > out_end)
                 return err_out();
             *out++ = (char)(0xc0 | ((w >> 6) & 0x1f));
             *out++ = (char)(0x80 | ((w >> 0) & 0x3f));
             continue;
         }
-        if (LIKELY(!is_any_surrogate(w))) {
+        if (!is_any_surrogate(w)) [[likely]] {
             if (out + 3 > out_end)
                 return err_out();
             *out++ = (char)(0xe0 | ((w >> 12) & 0xf));
@@ -420,25 +419,25 @@
     while (in < in_end) {
         uint8_t c = *in;
         utf16_len++;
-        if (LIKELY((c & 0x80) == 0)) {
+        if ((c & 0x80) == 0) [[likely]] {
             in++;
             continue;
         }
-        if (UNLIKELY(c < 0xc0)) {
+        if (c < 0xc0) [[unlikely]] {
             ALOGW("Invalid UTF-8 leading byte: 0x%02x", c);
             in++;
             continue;
         }
-        if (LIKELY(c < 0xe0)) {
+        if (c < 0xe0) [[likely]] {
             in += 2;
             continue;
         }
-        if (LIKELY(c < 0xf0)) {
+        if (c < 0xf0) [[likely]] {
             in += 3;
             continue;
         } else {
             uint8_t c2, c3, c4;
-            if (UNLIKELY(c >= 0xf8)) {
+            if (c >= 0xf8) [[unlikely]] {
                 ALOGW("Invalid UTF-8 leading byte: 0x%02x", c);
             }
             c2 = in[1]; c3 = in[2]; c4 = in[3];
@@ -487,25 +486,25 @@
 
     while (in < in_end && out < out_end) {
         c = *in++;
-        if (LIKELY((c & 0x80) == 0)) {
+        if ((c & 0x80) == 0) [[likely]] {
             *out++ = (char16_t)(c);
             continue;
         }
-        if (UNLIKELY(c < 0xc0)) {
+        if (c < 0xc0) [[unlikely]] {
             ALOGW("Invalid UTF-8 leading byte: 0x%02x", c);
             *out++ = (char16_t)(c);
             continue;
         }
-        if (LIKELY(c < 0xe0)) {
-            if (UNLIKELY(in + 1 > in_end)) {
+        if (c < 0xe0) [[likely]] {
+            if (in + 1 > in_end) [[unlikely]] {
                 return err_in();
             }
             c2 = *in++;
             *out++ = (char16_t)(((c & 0x1f) << 6) | (c2 & 0x3f));
             continue;
         }
-        if (LIKELY(c < 0xf0)) {
-            if (UNLIKELY(in + 2 > in_end)) {
+        if (c < 0xf0) [[likely]] {
+            if (in + 2 > in_end) [[unlikely]] {
                 return err_in();
             }
             c2 = *in++; c3 = *in++;
@@ -513,19 +512,19 @@
                                 ((c2 & 0x3f) << 6) | (c3 & 0x3f));
             continue;
         } else {
-            if (UNLIKELY(in + 3 > in_end)) {
+            if (in + 3 > in_end) [[unlikely]] {
                 return err_in();
             }
-            if (UNLIKELY(c >= 0xf8)) {
+            if (c >= 0xf8) [[unlikely]] {
                 ALOGW("Invalid UTF-8 leading byte: 0x%02x", c);
             }
             // Multiple UTF16 characters with surrogates
             c2 = *in++; c3 = *in++; c4 = *in++;
             w = utf8_4b_to_utf32(c, c2, c3, c4);
-            if (UNLIKELY(w < 0x10000)) {
+            if (w < 0x10000) [[unlikely]] {
                 *out++ = (char16_t)(w);
             } else {
-                if (UNLIKELY(out + 2 > out_end)) {
+                if (out + 2 > out_end) [[unlikely]] {
                     // Ooops.... not enough room for this surrogate pair.
                     return out;
                 }
diff --git a/libutils/include/utils/LightRefBase.h b/libutils/binder/include/utils/LightRefBase.h
similarity index 100%
rename from libutils/include/utils/LightRefBase.h
rename to libutils/binder/include/utils/LightRefBase.h
diff --git a/libutils/include/utils/TypeHelpers.h b/libutils/binder/include/utils/TypeHelpers.h
similarity index 100%
rename from libutils/include/utils/TypeHelpers.h
rename to libutils/binder/include/utils/TypeHelpers.h
diff --git a/libutils/include/utils/LightRefBase.h b/libutils/include/utils/LightRefBase.h
new file mode 120000
index 0000000..9da2cf0
--- /dev/null
+++ b/libutils/include/utils/LightRefBase.h
@@ -0,0 +1 @@
+../../binder/include/utils/LightRefBase.h
\ No newline at end of file
diff --git a/libutils/include/utils/TypeHelpers.h b/libutils/include/utils/TypeHelpers.h
new file mode 120000
index 0000000..848f6d7
--- /dev/null
+++ b/libutils/include/utils/TypeHelpers.h
@@ -0,0 +1 @@
+../../binder/include/utils/TypeHelpers.h
\ No newline at end of file