Merge "meminfo: Use getprogname(3) in all tools."
diff --git a/adb/adb.cpp b/adb/adb.cpp
index fdf720c..06e4c50 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -359,6 +359,11 @@
         if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
             std::string_view address(p->payload.begin(), p->payload.size());
 
+            // Historically, we received service names as a char*, and stopped at the first NUL
+            // byte. The client sent strings with null termination, which post-string_view, start
+            // being interpreted as part of the string, unless we explicitly strip them.
+            address = StripTrailingNulls(address);
+
             asocket* s = create_local_service_socket(address, t);
             if (s == nullptr) {
                 send_close(0, p->msg.arg0, t);
diff --git a/adb/daemon/services.cpp b/adb/daemon/services.cpp
index 84a7655..3693997 100644
--- a/adb/daemon/services.cpp
+++ b/adb/daemon/services.cpp
@@ -328,13 +328,6 @@
 }
 
 unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) {
-    // Historically, we received service names as a char*, and stopped at the first NUL byte.
-    // The client unintentionally sent strings with embedded NULs, which post-string_view, start
-    // being interpreted as part of the string, unless we explicitly strip them.
-    // Notably, shell checks that the part after "shell:" is empty to determine whether the session
-    // is interactive, and {'\0'} is non-empty.
-    name = StripTrailingNulls(name);
-
     if (name.starts_with("dev:")) {
         name.remove_prefix(strlen("dev:"));
         return unique_fd{unix_open(name, O_RDWR | O_CLOEXEC)};
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index c4b57c7..d9786ad 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -203,7 +203,8 @@
         }
         next += vers->next;
         data_size -= vers->next;
-        vers = reinterpret_cast<struct dm_target_versions*>(static_cast<char*>(buffer.get()) + next);
+        vers = reinterpret_cast<struct dm_target_versions*>(static_cast<char*>(buffer.get()) +
+                                                            next);
     }
 
     return true;
@@ -288,12 +289,23 @@
 }
 
 bool DeviceMapper::GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) {
+    return GetTable(name, 0, table);
+}
+
+bool DeviceMapper::GetTableInfo(const std::string& name, std::vector<TargetInfo>* table) {
+    return GetTable(name, DM_STATUS_TABLE_FLAG, table);
+}
+
+// private methods of DeviceMapper
+bool DeviceMapper::GetTable(const std::string& name, uint32_t flags,
+                            std::vector<TargetInfo>* table) {
     char buffer[4096];
     struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(buffer);
 
     InitIo(io, name);
     io->data_size = sizeof(buffer);
     io->data_start = sizeof(*io);
+    io->flags = flags;
     if (ioctl(fd_, DM_TABLE_STATUS, io) < 0) {
         PLOG(ERROR) << "DM_TABLE_STATUS failed for " << name;
         return false;
@@ -327,7 +339,6 @@
     return true;
 }
 
-// private methods of DeviceMapper
 void DeviceMapper::InitIo(struct dm_ioctl* io, const std::string& name) const {
     CHECK(io != nullptr) << "nullptr passed to dm_ioctl initialization";
     memset(io, 0, sizeof(*io));
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index 91f8bb4..28e6e01 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -128,6 +128,10 @@
     };
     bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table);
 
+    // Identical to GetTableStatus, except also retrives the active table for the device
+    // mapper device from the kernel.
+    bool GetTableInfo(const std::string& name, std::vector<TargetInfo>* table);
+
   private:
     // Maximum possible device mapper targets registered in the kernel.
     // This is only used to read the list of targets from kernel so we allocate
@@ -140,6 +144,8 @@
     // limit we are imposing here of 256.
     static constexpr uint32_t kMaxPossibleDmDevices = 256;
 
+    bool GetTable(const std::string& name, uint32_t flags, std::vector<TargetInfo>* table);
+
     void InitIo(struct dm_ioctl* io, const std::string& name = std::string()) const;
 
     DeviceMapper();
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index f78093b..3b6ff9b 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -36,6 +36,8 @@
 #include <string>
 #include <vector>
 
+using namespace std::literals::string_literals;
+
 using DeviceMapper = ::android::dm::DeviceMapper;
 using DmTable = ::android::dm::DmTable;
 using DmTarget = ::android::dm::DmTarget;
@@ -51,7 +53,7 @@
     std::cerr << "commands:" << std::endl;
     std::cerr << "  create <dm-name> [-ro] <targets...>" << std::endl;
     std::cerr << "  delete <dm-name>" << std::endl;
-    std::cerr << "  list <devices | targets>" << std::endl;
+    std::cerr << "  list <devices | targets> [-v]" << std::endl;
     std::cerr << "  getpath <dm-name>" << std::endl;
     std::cerr << "  table <dm-name>" << std::endl;
     std::cerr << "  help" << std::endl;
@@ -197,7 +199,8 @@
     return 0;
 }
 
-static int DmListTargets(DeviceMapper& dm) {
+static int DmListTargets(DeviceMapper& dm, [[maybe_unused]] int argc,
+                         [[maybe_unused]] char** argv) {
     std::vector<DmTargetTypeInfo> targets;
     if (!dm.GetAvailableTargets(&targets)) {
         std::cerr << "Failed to read available device mapper targets" << std::endl;
@@ -218,7 +221,7 @@
     return 0;
 }
 
-static int DmListDevices(DeviceMapper& dm) {
+static int DmListDevices(DeviceMapper& dm, int argc, char** argv) {
     std::vector<DmBlockDevice> devices;
     if (!dm.GetAvailableDevices(&devices)) {
         std::cerr << "Failed to read available device mapper devices" << std::endl;
@@ -230,15 +233,37 @@
         return 0;
     }
 
+    bool verbose = (argc && (argv[0] == "-v"s));
     for (const auto& dev : devices) {
         std::cout << std::left << std::setw(20) << dev.name() << " : " << dev.Major() << ":"
                   << dev.Minor() << std::endl;
+        if (verbose) {
+            std::vector<DeviceMapper::TargetInfo> table;
+            if (!dm.GetTableInfo(dev.name(), &table)) {
+                std::cerr << "Could not query table status for device \"" << dev.name() << "\"."
+                          << std::endl;
+                return -EINVAL;
+            }
+
+            uint32_t target_num = 1;
+            for (const auto& target : table) {
+                std::cout << "  target#" << target_num << ": ";
+                std::cout << target.spec.sector_start << "-"
+                          << (target.spec.sector_start + target.spec.length) << ": "
+                          << target.spec.target_type;
+                if (!target.data.empty()) {
+                    std::cout << ", " << target.data;
+                }
+                std::cout << std::endl;
+                target_num++;
+            }
+        }
     }
 
     return 0;
 }
 
-static const std::map<std::string, std::function<int(DeviceMapper&)>> listmap = {
+static const std::map<std::string, std::function<int(DeviceMapper&, int, char**)>> listmap = {
         {"targets", DmListTargets},
         {"devices", DmListDevices},
 };
@@ -251,7 +276,7 @@
 
     DeviceMapper& dm = DeviceMapper::Instance();
     for (const auto& l : listmap) {
-        if (l.first == argv[0]) return l.second(dm);
+        if (l.first == argv[0]) return l.second(dm, argc - 1, argv + 1);
     }
 
     std::cerr << "Invalid argument to \'dmctl list\': " << argv[0] << std::endl;
diff --git a/init/README.md b/init/README.md
index 5c07ac1..8d47e0a 100644
--- a/init/README.md
+++ b/init/README.md
@@ -813,3 +813,42 @@
 SELinux would permit the operation, or if the UIDs and GIDs resolve.
 2) No checking if a service exists or has a valid SELinux domain defined
 3) No checking if a service has not been previously defined in a different init script.
+
+Early Init Boot Sequence
+------------------------
+The early init boot sequence is broken up into three stages: first stage init, SELinux setup, and
+second stage init.
+
+First stage init is responsible for setting up the bare minimum requirements to load the rest of the
+system. Specifically this includes mounting /dev, /proc, mounting 'early mount' partitions (which
+needs to include all partitions that contain system code, for example system and vendor), and moving
+the system.img mount to / for devices with a ramdisk.
+
+Note that in Android Q, system.img always contains TARGET_ROOT_OUT and always is mounted at / by the
+time first stage init finishes. Android Q will also require dynamic partitions and therefore will
+require using a ramdisk to boot Android. The recovery ramdisk can be used to boot to Android instead
+of a dedicated ramdisk as well.
+
+First stage init has three variations depending on the device configuration:
+1) For system-as-root devices, first stage init is part of /system/bin/init and a symlink at /init
+points to /system/bin/init for backwards compatibility. These devices do not need to do anything to
+mount system.img, since it is by definition already mounted as the rootfs by the kernel.
+
+2) For devices with a ramdisk, first stage init is a static executable located at /init. These
+devices mount system.img as /system then perform a switch root operation to move the mount at
+/system to /. The contents of the ramdisk are freed after mounting has completed.
+
+3) For devices that use recovery as a ramdisk, first stage init it contained within the shared init
+located at /init within the recovery ramdisk. These devices first switch root to
+/first_stage_ramdisk to remove the recovery components from the environment, then proceed the same
+as 2). Note that the decision to boot normally into Android instead of booting
+into recovery mode is made if androidboot.force_normal_boot=1 is present in the
+kernel commandline.
+
+Once first stage init finishes it execs /system/bin/init with the "selinux_setup" argument. This
+phase is where SELinux is optionally compiled and loaded onto the system. selinux.cpp contains more
+information on the specifics of this process.
+
+Lastly once that phase finishes, it execs /system/bin/init again with the "second_stage"
+argument. At this point the main phase of init runs and continues the boot process via the init.rc
+scripts.
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 8f7ceba..49ae960 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -105,6 +105,7 @@
 namespace.default.asan.permitted.paths += /%PRODUCT_SERVICES%/app
 namespace.default.asan.permitted.paths += /%PRODUCT_SERVICES%/priv-app
 namespace.default.asan.permitted.paths += /mnt/expand
+namespace.default.asan.permitted.paths += /apex/com.android.resolv/${LIB}
 
 # Keep in sync with ld.config.txt in the com.android.runtime APEX.
 namespace.default.links = runtime