Merge "libutils: Improve performance of utf8_to_utf16/utf16_to_utf8" into main
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 2941216..61c7204 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -2213,6 +2213,7 @@
                                       {"disable-verification", no_argument, 0, 0},
                                       {"disable-verity", no_argument, 0, 0},
                                       {"disable-super-optimization", no_argument, 0, 0},
+                                      {"disable-fastboot-info", no_argument, 0, 0},
                                       {"force", no_argument, 0, 0},
                                       {"fs-options", required_argument, 0, 0},
                                       {"header-version", required_argument, 0, 0},
@@ -2253,6 +2254,8 @@
                 g_disable_verity = true;
             } else if (name == "disable-super-optimization") {
                 fp->should_optimize_flash_super = false;
+            } else if (name == "disable-fastboot-info") {
+                fp->should_use_fastboot_info = false;
             } else if (name == "force") {
                 fp->force_flash = true;
             } else if (name == "fs-options") {
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index 50db25d..f6ffb64 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -97,7 +97,7 @@
     bool skip_secondary = false;
     bool force_flash = false;
     bool should_optimize_flash_super = true;
-    bool should_use_fastboot_info = false;
+    bool should_use_fastboot_info = true;
     uint64_t sparse_limit = 0;
 
     std::string slot_override;
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 01827d6..82a8b8b 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -75,8 +75,8 @@
     return access(path.c_str(), F_OK) == 0;
 }
 
-const auto kLowerdirOption = "lowerdir="s;
-const auto kUpperdirOption = "upperdir="s;
+const auto kLowerdirOption = "lowerdir=";
+const auto kUpperdirOption = "upperdir=";
 
 bool fs_mgr_in_recovery() {
     // Check the existence of recovery binary instead of using the compile time
@@ -99,8 +99,8 @@
 }
 
 // list of acceptable overlayfs backing storage
-const auto kScratchMountPoint = "/mnt/scratch"s;
-const auto kCacheMountPoint = "/cache"s;
+const auto kScratchMountPoint = "/mnt/scratch";
+const auto kCacheMountPoint = "/cache";
 
 bool IsABDevice() {
     return !android::base::GetProperty("ro.boot.slot_suffix", "").empty();
@@ -158,7 +158,7 @@
            (static_cast<uint64_t>(vst.f_bfree) * vst.f_frsize) >= kSizeThreshold;
 }
 
-const auto kPhysicalDevice = "/dev/block/by-name/"s;
+const auto kPhysicalDevice = "/dev/block/by-name/";
 constexpr char kScratchImageMetadata[] = "/metadata/gsi/remount/lp_metadata";
 
 // Note: this is meant only for recovery/first-stage init.
@@ -182,7 +182,7 @@
     }
 
     // special case for system-as-root (taimen and others)
-    auto blk_device = kPhysicalDevice + "system";
+    auto blk_device = std::string(kPhysicalDevice) + "system";
     if (!fs_mgr_access(blk_device)) {
         blk_device += fs_mgr_get_slot_suffix();
         if (!fs_mgr_access(blk_device)) {
@@ -301,9 +301,9 @@
     return ret;
 }
 
-const auto kUpperName = "upper"s;
-const auto kWorkName = "work"s;
-const auto kOverlayTopDir = "/overlay"s;
+const auto kUpperName = "upper";
+const auto kWorkName = "work";
+const auto kOverlayTopDir = "/overlay";
 
 std::string fs_mgr_get_overlayfs_candidate(const std::string& mount_point) {
     if (!fs_mgr_is_dir(mount_point)) return "";
@@ -472,10 +472,10 @@
 // Returns true if immediate unmount succeeded and the scratch mount point was
 // removed.
 bool fs_mgr_overlayfs_umount_scratch() {
-    if (umount(kScratchMountPoint.c_str()) != 0) {
+    if (umount(kScratchMountPoint) != 0) {
         return false;
     }
-    if (rmdir(kScratchMountPoint.c_str()) != 0 && errno != ENOENT) {
+    if (rmdir(kScratchMountPoint) != 0 && errno != ENOENT) {
         PLOG(ERROR) << "rmdir " << kScratchMountPoint;
     }
     return true;
@@ -573,7 +573,7 @@
     auto cleanup_all = mount_point.empty();
     const auto partition_name = android::base::Basename(mount_point);
     const auto oldpath = top + (cleanup_all ? "" : ("/" + partition_name));
-    const auto newpath = cleanup_all ? overlay + "/." + kOverlayTopDir.substr(1) + ".teardown"
+    const auto newpath = cleanup_all ? overlay + "/." + (kOverlayTopDir + 1) + ".teardown"
                                      : top + "/." + partition_name + ".teardown";
     auto ret = fs_mgr_rm_all(newpath);
     if (!rename(oldpath.c_str(), newpath.c_str())) {
@@ -853,7 +853,7 @@
     if (!createcon.Ok()) {
         return false;
     }
-    if (mkdir(kScratchMountPoint.c_str(), 0755) && (errno != EEXIST)) {
+    if (mkdir(kScratchMountPoint, 0755) && (errno != EEXIST)) {
         PERROR << "create " << kScratchMountPoint;
         return false;
     }
@@ -884,7 +884,7 @@
         return false;
     }
     if (!mounted) {
-        rmdir(kScratchMountPoint.c_str());
+        rmdir(kScratchMountPoint);
         return false;
     }
     return true;
@@ -1192,7 +1192,7 @@
     // If the partition exists, assume first that it can be mounted.
     if (partition_exists) {
         if (MountScratch(scratch_device)) {
-            if (fs_mgr_access(kScratchMountPoint + kOverlayTopDir) ||
+            if (fs_mgr_access(std::string(kScratchMountPoint) + kOverlayTopDir) ||
                 fs_mgr_filesystem_has_space(kScratchMountPoint)) {
                 return true;
             }
@@ -1331,7 +1331,7 @@
     if (!MountScratch(scratch_device, true /* readonly */)) {
         return;
     }
-    auto has_overlayfs_dir = fs_mgr_access(kScratchMountPoint + kOverlayTopDir);
+    auto has_overlayfs_dir = fs_mgr_access(std::string(kScratchMountPoint) + kOverlayTopDir);
     fs_mgr_overlayfs_umount_scratch();
     if (has_overlayfs_dir) {
         MountScratch(scratch_device);
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
index 7cffc1c..c984a61 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
@@ -119,7 +119,6 @@
     }
 
     // Functions interacting with dm-user
-    bool ReadDmUserHeader();
     bool WriteDmUserPayload(size_t size);
     bool DmuserReadRequest();
 
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp
index 0eb2a14..1b17698 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp
@@ -290,21 +290,6 @@
     return true;
 }
 
-// Read Header from dm-user misc device. This gives
-// us the sector number for which IO is issued by dm-snapshot device
-bool Worker::ReadDmUserHeader() {
-    if (!android::base::ReadFully(ctrl_fd_, bufsink_.GetBufPtr(), sizeof(struct dm_user_header))) {
-        if (errno != ENOTBLK) {
-            SNAP_PLOG(ERROR) << "Control-read failed";
-        }
-
-        SNAP_PLOG(DEBUG) << "ReadDmUserHeader failed....";
-        return false;
-    }
-
-    return true;
-}
-
 // Send the payload/data back to dm-user misc device.
 bool Worker::WriteDmUserPayload(size_t size) {
     size_t payload_size = size;
@@ -345,19 +330,15 @@
 }
 
 bool Worker::ReadAlignedSector(sector_t sector, size_t sz) {
-    struct dm_user_header* header = bufsink_.GetHeaderPtr();
     size_t remaining_size = sz;
     std::vector<std::pair<sector_t, const CowOperation*>>& chunk_vec = snapuserd_->GetChunkVec();
-    bool io_error = false;
     int ret = 0;
 
     do {
         // Process 1MB payload at a time
         size_t read_size = std::min(PAYLOAD_BUFFER_SZ, remaining_size);
 
-        header->type = DM_USER_RESP_SUCCESS;
         size_t total_bytes_read = 0;
-        io_error = false;
         bufsink_.ResetBufferOffset();
 
         while (read_size) {
@@ -375,7 +356,7 @@
                 // device.
                 if (!ReadDataFromBaseDevice(sector, size)) {
                     SNAP_LOG(ERROR) << "ReadDataFromBaseDevice failed";
-                    header->type = DM_USER_RESP_ERROR;
+                    return false;
                 }
 
                 ret = size;
@@ -384,35 +365,26 @@
                 // process it.
                 if (!ProcessCowOp(it->second)) {
                     SNAP_LOG(ERROR) << "ProcessCowOp failed";
-                    header->type = DM_USER_RESP_ERROR;
+                    return false;
                 }
 
                 ret = BLOCK_SZ;
             }
 
-            // Just return the header if it is an error
-            if (header->type == DM_USER_RESP_ERROR) {
-                RespondIOError();
-                io_error = true;
-                break;
-            }
-
             read_size -= ret;
             total_bytes_read += ret;
             sector += (ret >> SECTOR_SHIFT);
             bufsink_.UpdateBufferOffset(ret);
         }
 
-        if (!io_error) {
-            if (!WriteDmUserPayload(total_bytes_read)) {
-                return false;
-            }
-
-            SNAP_LOG(DEBUG) << "WriteDmUserPayload success total_bytes_read: " << total_bytes_read
-                            << " remaining_size: " << remaining_size;
-            remaining_size -= total_bytes_read;
+        if (!WriteDmUserPayload(total_bytes_read)) {
+            return false;
         }
-    } while (remaining_size > 0 && !io_error);
+
+        SNAP_LOG(DEBUG) << "WriteDmUserPayload success total_bytes_read: " << total_bytes_read
+                        << " remaining_size: " << remaining_size;
+        remaining_size -= total_bytes_read;
+    } while (remaining_size > 0);
 
     return true;
 }
@@ -453,8 +425,6 @@
 }
 
 bool Worker::ReadUnalignedSector(sector_t sector, size_t size) {
-    struct dm_user_header* header = bufsink_.GetHeaderPtr();
-    header->type = DM_USER_RESP_SUCCESS;
     bufsink_.ResetBufferOffset();
     std::vector<std::pair<sector_t, const CowOperation*>>& chunk_vec = snapuserd_->GetChunkVec();
 
@@ -622,9 +592,15 @@
 }
 
 bool Worker::ProcessIORequest() {
+    // Read Header from dm-user misc device. This gives
+    // us the sector number for which IO is issued by dm-snapshot device
     struct dm_user_header* header = bufsink_.GetHeaderPtr();
+    if (!android::base::ReadFully(ctrl_fd_, header, sizeof(*header))) {
+        if (errno != ENOTBLK) {
+            SNAP_PLOG(ERROR) << "Control-read failed";
+        }
 
-    if (!ReadDmUserHeader()) {
+        SNAP_PLOG(DEBUG) << "ReadDmUserHeader failed....";
         return false;
     }
 
@@ -634,26 +610,34 @@
     SNAP_LOG(DEBUG) << "Daemon: msg->type: " << std::dec << header->type;
     SNAP_LOG(DEBUG) << "Daemon: msg->flags: " << std::dec << header->flags;
 
+    // Use the same header buffer as the response header.
+    int request_type = header->type;
+    header->type = DM_USER_RESP_SUCCESS;
     header_response_ = true;
 
-    switch (header->type) {
-        case DM_USER_REQ_MAP_READ: {
-            if (!DmuserReadRequest()) {
-                return false;
-            }
+    bool ok;
+    switch (request_type) {
+        case DM_USER_REQ_MAP_READ:
+            ok = DmuserReadRequest();
             break;
-        }
 
-        case DM_USER_REQ_MAP_WRITE: {
+        case DM_USER_REQ_MAP_WRITE:
             // TODO: We should not get any write request
             // to dm-user as we mount all partitions
             // as read-only. Need to verify how are TRIM commands
             // handled during mount.
-            return false;
-        }
+            ok = false;
+            break;
+
+        default:
+            ok = false;
+            break;
     }
 
-    return true;
+    if (!ok && header->type != DM_USER_RESP_ERROR) {
+        RespondIOError();
+    }
+    return ok;
 }
 
 }  // namespace snapshot
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 1f29040..06d386f 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -223,6 +223,13 @@
         std::this_thread::sleep_for(5ms);
     }
 
+    if (!ret && uid >= AID_ISOLATED_START && uid <= AID_ISOLATED_END) {
+        // Isolated UIDs are unlikely to be reused soon after removal,
+        // so free up the kernel resources for the UID level cgroup.
+        const auto uid_path = ConvertUidToPath(cgroup, uid);
+        ret = rmdir(uid_path.c_str());
+    }
+
     return ret;
 }
 
diff --git a/libstats/push_compat/Android.bp b/libstats/push_compat/Android.bp
index 819066e..c5c1934 100644
--- a/libstats/push_compat/Android.bp
+++ b/libstats/push_compat/Android.bp
@@ -26,7 +26,7 @@
 cc_defaults {
     name: "libstatspush_compat_defaults",
     srcs: [
-        "statsd_writer.c",
+        "statsd_writer.cpp",
         "stats_event_list.c",
         "StatsEventCompat.cpp"
     ],
diff --git a/libstats/push_compat/statsd_writer.c b/libstats/push_compat/statsd_writer.cpp
similarity index 97%
rename from libstats/push_compat/statsd_writer.c
rename to libstats/push_compat/statsd_writer.cpp
index 4818d11..a3600f3 100644
--- a/libstats/push_compat/statsd_writer.c
+++ b/libstats/push_compat/statsd_writer.cpp
@@ -15,9 +15,9 @@
  */
 #include "statsd_writer.h"
 
+#include <android-base/threads.h>
 #include <cutils/fs.h>
 #include <cutils/sockets.h>
-#include <cutils/threads.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
@@ -108,7 +108,7 @@
                     case -ECONNREFUSED:
                     case -ENOENT:
                         i = atomic_exchange(&statsdLoggerWrite.sock, ret);
-                    /* FALLTHRU */
+                        break;
                     default:
                         break;
                 }
@@ -188,7 +188,7 @@
      *  };
      */
 
-    header.tid = gettid();
+    header.tid = android::base::GetThreadId();
     header.realtime.tv_sec = ts->tv_sec;
     header.realtime.tv_nsec = ts->tv_nsec;
 
@@ -272,7 +272,7 @@
             if (ret < 0) {
                 ret = -errno;
             }
-        /* FALLTHRU */
+            break;
         default:
             break;
     }
diff --git a/libstats/push_compat/statsd_writer.h b/libstats/push_compat/statsd_writer.h
index fe2d37c..f030b96 100644
--- a/libstats/push_compat/statsd_writer.h
+++ b/libstats/push_compat/statsd_writer.h
@@ -21,6 +21,8 @@
 #include <stdatomic.h>
 #include <sys/socket.h>
 
+__BEGIN_DECLS
+
 /**
  * Internal lock should not be exposed. This is bad design.
  * TODO: rewrite it in c++ code and encapsulate the functionality in a
@@ -42,4 +44,6 @@
     void (*noteDrop)(int error, int tag);
 };
 
+__END_DECLS
+
 #endif  // ANDROID_STATS_LOG_STATS_WRITER_H