Merge "toolbox: drop NetBSD grep for toybox grep."
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 6f6481f..f6ef906 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -82,3 +82,9 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/sbin/charger)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/sbin)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/sbin)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product_services)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product_services.img)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product_services)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/product_services)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/product_services)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/debug_ramdisk/product_services)
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 7211f72..11a3dfd 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -128,7 +128,7 @@
         " pull [-a] REMOTE... LOCAL\n"
         "     copy files/dirs from device\n"
         "     -a: preserve file timestamp and mode\n"
-        " sync [all|data|odm|oem|product_services|product|system|vendor]\n"
+        " sync [all|data|odm|oem|product|system|system_ext|vendor]\n"
         "     sync a local build from $ANDROID_PRODUCT_OUT to the device (default all)\n"
         "     -l: list but don't copy\n"
         "\n"
@@ -775,17 +775,16 @@
         error_exit("abb is not supported by the device");
     }
 
+    optind = 1;  // argv[0] is always "abb", so set `optind` appropriately.
+
     // Defaults.
     constexpr char escape_char = '~';  // -e
     constexpr bool use_shell_protocol = true;
     constexpr auto shell_type_arg = kShellServiceArgRaw;
     constexpr bool empty_command = false;
 
-    std::string service_string("abb:");
-    for (auto i = optind; i < argc; ++i) {
-        service_string.append(argv[i]);
-        service_string.push_back(ABB_ARG_DELIMETER);
-    }
+    std::vector<const char*> args(argv + optind, argv + argc);
+    std::string service_string = "abb:" + android::base::Join(args, ABB_ARG_DELIMETER);
 
     D("abb -e 0x%x [%*.s]\n", escape_char, static_cast<int>(service_string.size()),
       service_string.data());
@@ -1843,8 +1842,8 @@
         }
 
         if (src.empty()) src = "all";
-        std::vector<std::string> partitions{"data",   "odm",   "oem", "product", "product_services",
-                                            "system", "vendor"};
+        std::vector<std::string> partitions{"data",   "odm",        "oem",   "product",
+                                            "system", "system_ext", "vendor"};
         bool found = false;
         for (const auto& partition : partitions) {
             if (src == "all" || src == partition) {
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index c436be3..8923f40 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -144,14 +144,13 @@
     { "dts",      "dt.img",           "dt.sig",       "dts",      true,  ImageType::BootCritical },
     { "odm",      "odm.img",          "odm.sig",      "odm",      true,  ImageType::Normal },
     { "product",  "product.img",      "product.sig",  "product",  true,  ImageType::Normal },
-    { "product_services",
-                  "product_services.img",
-                                      "product_services.sig",
-                                                      "product_services",
-                                                                  true,  ImageType::Normal },
     { "recovery", "recovery.img",     "recovery.sig", "recovery", true,  ImageType::BootCritical },
     { "super",    "super.img",        "super.sig",    "super",    true,  ImageType::Extra },
     { "system",   "system.img",       "system.sig",   "system",   false, ImageType::Normal },
+    { "system_ext",
+                  "system_ext.img",   "system_ext.sig",
+                                                      "system_ext",
+                                                                  true,  ImageType::Normal },
     { nullptr,    "system_other.img", "system.sig",   "system",   true,  ImageType::Normal },
     { "userdata", "userdata.img",     "userdata.sig", "userdata", true,  ImageType::Extra },
     { "vbmeta",   "vbmeta.img",       "vbmeta.sig",   "vbmeta",   true,  ImageType::BootCritical },
diff --git a/fs_mgr/libfiemap_writer/split_fiemap_writer.cpp b/fs_mgr/libfiemap_writer/split_fiemap_writer.cpp
index a0ccc10..16a82d2 100644
--- a/fs_mgr/libfiemap_writer/split_fiemap_writer.cpp
+++ b/fs_mgr/libfiemap_writer/split_fiemap_writer.cpp
@@ -95,8 +95,9 @@
         // To make sure the alignment doesn't create too much inconsistency, we
         // account the *actual* size, not the requested size.
         total_bytes_written += writer->size();
-        remaining_bytes -= writer->size();
-
+        // writer->size() is block size aligned and could be bigger than remaining_bytes
+        // If remaining_bytes is bigger, set remaining_bytes to 0 to avoid underflow error.
+        remaining_bytes = remaining_bytes > writer->size() ? (remaining_bytes - writer->size()) : 0;
         out->AddFile(std::move(writer));
     }
 
diff --git a/init/Android.bp b/init/Android.bp
index 6bc581d..86dcb4c 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -26,6 +26,7 @@
         "-Wextra",
         "-Wno-unused-parameter",
         "-Werror",
+        "-DALLOW_FIRST_STAGE_CONSOLE=0",
         "-DALLOW_LOCAL_PROP_OVERRIDE=0",
         "-DALLOW_PERMISSIVE_SELINUX=0",
         "-DREBOOT_BOOTLOADER_ON_PANIC=0",
@@ -36,6 +37,8 @@
     product_variables: {
         debuggable: {
             cppflags: [
+                "-UALLOW_FIRST_STAGE_CONSOLE",
+                "-DALLOW_FIRST_STAGE_CONSOLE=1",
                 "-UALLOW_LOCAL_PROP_OVERRIDE",
                 "-DALLOW_LOCAL_PROP_OVERRIDE=1",
                 "-UALLOW_PERMISSIVE_SELINUX",
diff --git a/init/Android.mk b/init/Android.mk
index b24f757..9017772 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -8,6 +8,7 @@
 
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
 init_options += \
+    -DALLOW_FIRST_STAGE_CONSOLE=1 \
     -DALLOW_LOCAL_PROP_OVERRIDE=1 \
     -DALLOW_PERMISSIVE_SELINUX=1 \
     -DREBOOT_BOOTLOADER_ON_PANIC=1 \
@@ -15,6 +16,7 @@
     -DDUMP_ON_UMOUNT_FAILURE=1
 else
 init_options += \
+    -DALLOW_FIRST_STAGE_CONSOLE=0 \
     -DALLOW_LOCAL_PROP_OVERRIDE=0 \
     -DALLOW_PERMISSIVE_SELINUX=0 \
     -DREBOOT_BOOTLOADER_ON_PANIC=0 \
diff --git a/init/builtins.cpp b/init/builtins.cpp
index cc84aa0..55b0248 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -1107,7 +1107,7 @@
         // /apex/<name> paths, so unless we filter them out, we will parse the
         // same file twice.
         std::vector<std::string> paths = android::base::Split(path, "/");
-        if (paths.size() >= 2 && paths[1].find('@') != std::string::npos) {
+        if (paths.size() >= 3 && paths[2].find('@') != std::string::npos) {
             continue;
         }
         configs.push_back(path);
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 17387e2..36eece8 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -24,10 +24,12 @@
 #include <sys/stat.h>
 #include <sys/sysmacros.h>
 #include <sys/types.h>
+#include <sys/wait.h>
 #include <unistd.h>
 
 #include <filesystem>
 #include <string>
+#include <thread>
 #include <vector>
 
 #include <android-base/chrono_utils.h>
@@ -92,9 +94,50 @@
     }
 }
 
-bool ForceNormalBoot() {
-    std::string cmdline;
-    android::base::ReadFileToString("/proc/cmdline", &cmdline);
+void StartConsole() {
+    if (mknod("/dev/console", S_IFCHR | 0600, makedev(5, 1))) {
+        PLOG(ERROR) << "unable to create /dev/console";
+        return;
+    }
+    pid_t pid = fork();
+    if (pid != 0) {
+        int status;
+        waitpid(pid, &status, 0);
+        LOG(ERROR) << "console shell exited with status " << status;
+        return;
+    }
+    int fd = -1;
+    int tries = 10;
+    // The device driver for console may not be ready yet so retry for a while in case of failure.
+    while (tries--) {
+        fd = open("/dev/console", O_RDWR);
+        if (fd != -1) {
+            break;
+        }
+        std::this_thread::sleep_for(100ms);
+    }
+    if (fd == -1) {
+        LOG(ERROR) << "Could not open /dev/console, errno = " << errno;
+        _exit(127);
+    }
+    ioctl(fd, TIOCSCTTY, 0);
+    dup2(fd, 0);
+    dup2(fd, 1);
+    dup2(fd, 2);
+    close(fd);
+
+    const char* path = "/system/bin/sh";
+    const char* args[] = {path, nullptr};
+    int rv = execv(path, const_cast<char**>(args));
+    LOG(ERROR) << "unable to execv, returned " << rv << " errno " << errno;
+    _exit(127);
+}
+
+bool FirstStageConsole(const std::string& cmdline) {
+    return cmdline.find("androidboot.first_stage_console=1") != std::string::npos;
+}
+
+bool ForceNormalBoot(const std::string& cmdline) {
     return cmdline.find("androidboot.force_normal_boot=1") != std::string::npos;
 }
 
@@ -127,6 +170,8 @@
 #undef MAKE_STR
     // Don't expose the raw commandline to unprivileged processes.
     CHECKCALL(chmod("/proc/cmdline", 0440));
+    std::string cmdline;
+    android::base::ReadFileToString("/proc/cmdline", &cmdline);
     gid_t groups[] = {AID_READPROC};
     CHECKCALL(setgroups(arraysize(groups), groups));
     CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL));
@@ -198,7 +243,11 @@
         LOG(FATAL) << "Failed to load kernel modules";
     }
 
-    if (ForceNormalBoot()) {
+    if (ALLOW_FIRST_STAGE_CONSOLE && FirstStageConsole(cmdline)) {
+        StartConsole();
+    }
+
+    if (ForceNormalBoot(cmdline)) {
         mkdir("/first_stage_ramdisk", 0755);
         // SwitchRoot() must be called with a mount point as the target, so we bind mount the
         // target directory to itself here.
diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp
index caf6e86..a8b43c1 100644
--- a/libmeminfo/procmeminfo.cpp
+++ b/libmeminfo/procmeminfo.cpp
@@ -312,12 +312,12 @@
                                     cur_page * sizeof(uint64_t));
             if (bytes != total_bytes) {
                 if (bytes == -1) {
-                    PLOG(ERROR) << "Failed to read page data at offset "
+                    PLOG(ERROR) << "Failed to read page data at offset 0x" << std::hex
                                 << cur_page * sizeof(uint64_t);
                 } else {
-                    LOG(ERROR) << "Failed to read page data at offset "
-                               << cur_page * sizeof(uint64_t) << " read bytes " << sizeof(uint64_t)
-                               << " expected bytes " << bytes;
+                    LOG(ERROR) << "Failed to read page data at offset 0x" << std::hex
+                               << cur_page * sizeof(uint64_t) << std::dec << " read bytes " << bytes
+                               << " expected bytes " << total_bytes;
                 }
                 return false;
             }
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index 0025c56..d13548e 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -468,21 +468,6 @@
     unlockBuffer(len);
 }
 
-size_t String8::getUtf32Length() const
-{
-    return utf8_to_utf32_length(mString, length());
-}
-
-int32_t String8::getUtf32At(size_t index, size_t *next_index) const
-{
-    return utf32_from_utf8_at(mString, length(), index, next_index);
-}
-
-void String8::getUtf32(char32_t* dst) const
-{
-    utf8_to_utf32(mString, length(), dst);
-}
-
 // ---------------------------------------------------------------------------
 // Path functions
 
diff --git a/libutils/include/utils/String8.h b/libutils/include/utils/String8.h
index c8f584e..0ddcbb2 100644
--- a/libutils/include/utils/String8.h
+++ b/libutils/include/utils/String8.h
@@ -95,13 +95,6 @@
                     __attribute__((format (printf, 2, 3)));
             status_t            appendFormatV(const char* fmt, va_list args);
 
-            // Note that this function takes O(N) time to calculate the value.
-            // No cache value is stored.
-            size_t              getUtf32Length() const;
-            int32_t             getUtf32At(size_t index,
-                                           size_t *next_index) const;
-            void                getUtf32(char32_t* dst) const;
-
     inline  String8&            operator=(const String8& other);
     inline  String8&            operator=(const char* other);
 
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 15e07fe..6e38d95 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -483,7 +483,8 @@
                     "                  Additionally, 'kernel' for userdebug and eng builds, and\n"
                     "                  'security' for Device Owner installations.\n"
                     "                  Multiple -b parameters or comma separated list of buffers are\n"
-                    "                  allowed. Buffers interleaved. Default -b main,system,crash.\n"
+                    "                  allowed. Buffers interleaved.\n"
+                    "                  Default -b main,system,crash,kernel.\n"
                     "  -B, --binary    Output the log in binary.\n"
                     "  -S, --statistics                       Output statistics.\n"
                     "  -p, --prune     Print prune white and ~black list. Service is specified as\n"
@@ -1312,6 +1313,10 @@
             dev = dev->next = new log_device_t("crash", false);
             context->devCount++;
         }
+        if (android_name_to_log_id("kernel") == LOG_ID_KERNEL) {
+            dev = dev->next = new log_device_t("kernel", false);
+            context->devCount++;
+        }
     }
 
     if (!!context->logRotateSizeKBytes && !context->outputFileName) {
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index f084cd2..246f9ac 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -113,10 +113,10 @@
 else
   LOCAL_POST_INSTALL_CMD += ; ln -sf /system/product $(TARGET_ROOT_OUT)/product
 endif
-ifdef BOARD_USES_PRODUCT_SERVICESIMAGE
-  LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/product_services
+ifdef BOARD_USES_SYSTEM_EXTIMAGE
+  LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/system_ext
 else
-  LOCAL_POST_INSTALL_CMD += ; ln -sf /system/product_services $(TARGET_ROOT_OUT)/product_services
+  LOCAL_POST_INSTALL_CMD += ; ln -sf /system/system_ext $(TARGET_ROOT_OUT)/system_ext
 endif
 ifdef BOARD_USES_METADATA_PARTITION
   LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/metadata