Merge "Avoid two SELinux related error messages at boot time" into main
diff --git a/fs_mgr/libfiemap/binder.cpp b/fs_mgr/libfiemap/binder.cpp
index 41e534a..439aac9 100644
--- a/fs_mgr/libfiemap/binder.cpp
+++ b/fs_mgr/libfiemap/binder.cpp
@@ -77,7 +77,7 @@
 
 static FiemapStatus ToFiemapStatus(const char* func, const binder::Status& status) {
     if (!status.isOk()) {
-        LOG(ERROR) << func << " binder returned: " << status.toString8().string();
+        LOG(ERROR) << func << " binder returned: " << status.toString8().c_str();
         if (status.serviceSpecificErrorCode() != 0) {
             return FiemapStatus::FromErrorCode(status.serviceSpecificErrorCode());
         } else {
@@ -106,7 +106,7 @@
     auto status = manager_->deleteBackingImage(name);
     if (!status.isOk()) {
         LOG(ERROR) << __PRETTY_FUNCTION__
-                   << " binder returned: " << status.exceptionMessage().string();
+                   << " binder returned: " << status.exceptionMessage().c_str();
         return false;
     }
     return true;
@@ -122,7 +122,7 @@
     auto status = manager_->mapImageDevice(name, timeout_ms_count, &map);
     if (!status.isOk()) {
         LOG(ERROR) << __PRETTY_FUNCTION__
-                   << " binder returned: " << status.exceptionMessage().string();
+                   << " binder returned: " << status.exceptionMessage().c_str();
         return false;
     }
     *path = map.path;
@@ -133,7 +133,7 @@
     auto status = manager_->unmapImageDevice(name);
     if (!status.isOk()) {
         LOG(ERROR) << __PRETTY_FUNCTION__
-                   << " binder returned: " << status.exceptionMessage().string();
+                   << " binder returned: " << status.exceptionMessage().c_str();
         return false;
     }
     return true;
@@ -144,7 +144,7 @@
     auto status = manager_->backingImageExists(name, &retval);
     if (!status.isOk()) {
         LOG(ERROR) << __PRETTY_FUNCTION__
-                   << " binder returned: " << status.exceptionMessage().string();
+                   << " binder returned: " << status.exceptionMessage().c_str();
         return false;
     }
     return retval;
@@ -155,7 +155,7 @@
     auto status = manager_->isImageMapped(name, &retval);
     if (!status.isOk()) {
         LOG(ERROR) << __PRETTY_FUNCTION__
-                   << " binder returned: " << status.exceptionMessage().string();
+                   << " binder returned: " << status.exceptionMessage().c_str();
         return false;
     }
     return retval;
@@ -175,7 +175,7 @@
     auto status = manager_->getAllBackingImages(&retval);
     if (!status.isOk()) {
         LOG(ERROR) << __PRETTY_FUNCTION__
-                   << " binder returned: " << status.exceptionMessage().string();
+                   << " binder returned: " << status.exceptionMessage().c_str();
     }
     return retval;
 }
@@ -189,7 +189,7 @@
     auto status = manager_->removeAllImages();
     if (!status.isOk()) {
         LOG(ERROR) << __PRETTY_FUNCTION__
-                   << " binder returned: " << status.exceptionMessage().string();
+                   << " binder returned: " << status.exceptionMessage().c_str();
         return false;
     }
     return true;
@@ -199,7 +199,7 @@
     auto status = manager_->disableImage(name);
     if (!status.isOk()) {
         LOG(ERROR) << __PRETTY_FUNCTION__
-                   << " binder returned: " << status.exceptionMessage().string();
+                   << " binder returned: " << status.exceptionMessage().c_str();
         return false;
     }
     return true;
@@ -209,7 +209,7 @@
     auto status = manager_->removeDisabledImages();
     if (!status.isOk()) {
         LOG(ERROR) << __PRETTY_FUNCTION__
-                   << " binder returned: " << status.exceptionMessage().string();
+                   << " binder returned: " << status.exceptionMessage().c_str();
         return false;
     }
     return true;
@@ -219,7 +219,7 @@
     auto status = manager_->getMappedImageDevice(name, device);
     if (!status.isOk()) {
         LOG(ERROR) << __PRETTY_FUNCTION__
-                   << " binder returned: " << status.exceptionMessage().string();
+                   << " binder returned: " << status.exceptionMessage().c_str();
         return false;
     }
     return !device->empty();
@@ -230,7 +230,7 @@
     auto status = manager_->isImageDisabled(name, &retval);
     if (!status.isOk()) {
         LOG(ERROR) << __PRETTY_FUNCTION__
-                   << " binder returned: " << status.exceptionMessage().string();
+                   << " binder returned: " << status.exceptionMessage().c_str();
         return false;
     }
     return retval;
@@ -249,7 +249,7 @@
 
     auto status = service->openImageService(dir, &manager);
     if (!status.isOk() || !manager) {
-        LOG(ERROR) << "Could not acquire IImageManager: " << status.exceptionMessage().string();
+        LOG(ERROR) << "Could not acquire IImageManager: " << status.exceptionMessage().c_str();
         return nullptr;
     }
     return std::make_unique<ImageManagerBinder>(std::move(service), std::move(manager));
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index bd7955a..15c30be 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -444,12 +444,10 @@
 
     for (size_t i = 0; i < mChargerNames.size(); i++) {
         String8 path;
-        path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
-                          mChargerNames[i].string());
+        path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, mChargerNames[i].c_str());
         if (getIntField(path)) {
             path.clear();
-            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
-                              mChargerNames[i].string());
+            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, mChargerNames[i].c_str());
             switch(readPowerSupplyType(path)) {
             case ANDROID_POWER_SUPPLY_TYPE_AC:
                 mHealthInfo->chargerAcOnline = true;
@@ -466,26 +464,24 @@
             default:
                 path.clear();
                 path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH,
-                                  mChargerNames[i].string());
-                if (access(path.string(), R_OK) == 0)
+                                  mChargerNames[i].c_str());
+                if (access(path.c_str(), R_OK) == 0)
                     mHealthInfo->chargerDockOnline = true;
                 else
                     KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
-                                 mChargerNames[i].string());
+                                 mChargerNames[i].c_str());
             }
             path.clear();
             path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
-                              mChargerNames[i].string());
-            int ChargingCurrent =
-                    (access(path.string(), R_OK) == 0) ? getIntField(path) : 0;
+                              mChargerNames[i].c_str());
+            int ChargingCurrent = (access(path.c_str(), R_OK) == 0) ? getIntField(path) : 0;
 
             path.clear();
             path.appendFormat("%s/%s/voltage_max", POWER_SUPPLY_SYSFS_PATH,
-                              mChargerNames[i].string());
+                              mChargerNames[i].c_str());
 
             int ChargingVoltage =
-                (access(path.string(), R_OK) == 0) ? getIntField(path) :
-                DEFAULT_VBUS_VOLTAGE;
+                    (access(path.c_str(), R_OK) == 0) ? getIntField(path) : DEFAULT_VBUS_VOLTAGE;
 
             double power = ((double)ChargingCurrent / MILLION) *
                            ((double)ChargingVoltage / MILLION);
@@ -775,8 +771,7 @@
             case ANDROID_POWER_SUPPLY_TYPE_DOCK:
                 path.clear();
                 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
-                if (access(path.string(), R_OK) == 0)
-                    mChargerNames.add(String8(name));
+                if (access(path.c_str(), R_OK) == 0) mChargerNames.add(String8(name));
                 break;
 
             case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
@@ -958,12 +953,10 @@
             // Look for "is_dock" file
             path.clear();
             path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH, name);
-            if (access(path.string(), R_OK) == 0) {
+            if (access(path.c_str(), R_OK) == 0) {
                 path.clear();
                 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
-                if (access(path.string(), R_OK) == 0)
-                    mChargerNames.add(String8(name));
-
+                if (access(path.c_str(), R_OK) == 0) mChargerNames.add(String8(name));
             }
         }
     }
diff --git a/healthd/BatteryMonitor_v1.cpp b/healthd/BatteryMonitor_v1.cpp
index b87c493..b2d6518 100644
--- a/healthd/BatteryMonitor_v1.cpp
+++ b/healthd/BatteryMonitor_v1.cpp
@@ -358,12 +358,10 @@
 
     for (size_t i = 0; i < mChargerNames.size(); i++) {
         String8 path;
-        path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
-                          mChargerNames[i].string());
+        path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, mChargerNames[i].c_str());
         if (getIntField(path)) {
             path.clear();
-            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
-                              mChargerNames[i].string());
+            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, mChargerNames[i].c_str());
             switch(readPowerSupplyType(path)) {
             case ANDROID_POWER_SUPPLY_TYPE_AC:
                 mHealthInfo->chargerAcOnline = true;
@@ -380,26 +378,24 @@
             default:
                 path.clear();
                 path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH,
-                                  mChargerNames[i].string());
-                if (access(path.string(), R_OK) == 0)
+                                  mChargerNames[i].c_str());
+                if (access(path.c_str(), R_OK) == 0)
                     mHealthInfo->chargerDockOnline = true;
                 else
                     KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
-                                 mChargerNames[i].string());
+                                 mChargerNames[i].c_str());
             }
             path.clear();
             path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
-                              mChargerNames[i].string());
-            int ChargingCurrent =
-                    (access(path.string(), R_OK) == 0) ? getIntField(path) : 0;
+                              mChargerNames[i].c_str());
+            int ChargingCurrent = (access(path.c_str(), R_OK) == 0) ? getIntField(path) : 0;
 
             path.clear();
             path.appendFormat("%s/%s/voltage_max", POWER_SUPPLY_SYSFS_PATH,
-                              mChargerNames[i].string());
+                              mChargerNames[i].c_str());
 
             int ChargingVoltage =
-                (access(path.string(), R_OK) == 0) ? getIntField(path) :
-                DEFAULT_VBUS_VOLTAGE;
+                    (access(path.c_str(), R_OK) == 0) ? getIntField(path) : DEFAULT_VBUS_VOLTAGE;
 
             double power = ((double)ChargingCurrent / MILLION) *
                            ((double)ChargingVoltage / MILLION);
@@ -628,8 +624,7 @@
             case ANDROID_POWER_SUPPLY_TYPE_DOCK:
                 path.clear();
                 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
-                if (access(path.string(), R_OK) == 0)
-                    mChargerNames.add(String8(name));
+                if (access(path.c_str(), R_OK) == 0) mChargerNames.add(String8(name));
                 break;
 
             case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
@@ -767,12 +762,10 @@
             // Look for "is_dock" file
             path.clear();
             path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH, name);
-            if (access(path.string(), R_OK) == 0) {
+            if (access(path.c_str(), R_OK) == 0) {
                 path.clear();
                 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
-                if (access(path.string(), R_OK) == 0)
-                    mChargerNames.add(String8(name));
-
+                if (access(path.c_str(), R_OK) == 0) mChargerNames.add(String8(name));
             }
         }
     }
diff --git a/init/apex_init_util.cpp b/init/apex_init_util.cpp
index d88da39..6d17f36 100644
--- a/init/apex_init_util.cpp
+++ b/init/apex_init_util.cpp
@@ -82,7 +82,7 @@
     return configs;
 }
 
-static std::set<std::string> GetApexListFrom(const std::string& apex_dir) {
+std::set<std::string> GetApexListFrom(const std::string& apex_dir) {
     std::set<std::string> apex_list;
     auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(apex_dir.c_str()), closedir);
     if (!dirp) {
diff --git a/init/apex_init_util.h b/init/apex_init_util.h
index e55b3c0..75dfee1 100644
--- a/init/apex_init_util.h
+++ b/init/apex_init_util.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <set>
 #include <string>
 #include <vector>
 
@@ -24,6 +25,9 @@
 namespace android {
 namespace init {
 
+// Scans apex_dir (/apex) to get the list of active APEXes.
+std::set<std::string> GetApexListFrom(const std::string& apex_dir);
+
 // Parse all RC scripts for a given apex.
 Result<void> ParseRcScriptsFromApex(const std::string& apex_name);
 
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 2ced66d..a5b762c 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -1269,26 +1269,15 @@
 /*
  * Creates a directory under /data/misc/apexdata/ for each APEX.
  */
-static Result<void> create_apex_data_dirs() {
-    auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/apex"), closedir);
-    if (!dirp) {
-        return ErrnoError() << "Unable to open apex directory";
-    }
-    struct dirent* entry;
-    while ((entry = readdir(dirp.get())) != nullptr) {
-        if (entry->d_type != DT_DIR) continue;
-
-        const char* name = entry->d_name;
-        // skip any starting with "."
-        if (name[0] == '.') continue;
-
-        if (strchr(name, '@') != nullptr) continue;
-
-        auto path = "/data/misc/apexdata/" + std::string(name);
+static void create_apex_data_dirs() {
+    for (const auto& name : GetApexListFrom("/apex")) {
+        auto path = "/data/misc/apexdata/" + name;
         auto options = MkdirOptions{path, 0771, AID_ROOT, AID_SYSTEM, FscryptAction::kNone, "ref"};
-        make_dir_with_options(options);
+        auto result = make_dir_with_options(options);
+        if (!result.ok()) {
+            LOG(ERROR) << result.error();
+        }
     }
-    return {};
 }
 
 static Result<void> do_perform_apex_config(const BuiltinArguments& args) {
@@ -1301,10 +1290,7 @@
     }
 
     if (!bootstrap) {
-        auto create_dirs = create_apex_data_dirs();
-        if (!create_dirs.ok()) {
-            return create_dirs.error();
-        }
+        create_apex_data_dirs();
     }
 
     auto parse_result = ParseRcScriptsFromAllApexes(bootstrap);
diff --git a/libutils/ProcessCallStack.cpp b/libutils/ProcessCallStack.cpp
index f054de9..4b27bdd 100644
--- a/libutils/ProcessCallStack.cpp
+++ b/libutils/ProcessCallStack.cpp
@@ -205,8 +205,7 @@
 }
 
 void ProcessCallStack::printInternal(Printer& printer, Printer& csPrinter) const {
-    dumpProcessHeader(printer, getpid(),
-                      getTimeString(mTimeUpdated).string());
+    dumpProcessHeader(printer, getpid(), getTimeString(mTimeUpdated).c_str());
 
     for (size_t i = 0; i < mThreadMap.size(); ++i) {
         pid_t tid = mThreadMap.keyAt(i);
@@ -214,7 +213,7 @@
         const String8& threadName = threadInfo.threadName;
 
         printer.printLine("");
-        printer.printFormatLine("\"%s\" sysTid=%d", threadName.string(), tid);
+        printer.printFormatLine("\"%s\" sysTid=%d", threadName.c_str(), tid);
 
         threadInfo.callStack.print(csPrinter);
     }
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index ab122c7..e0a2846 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -330,7 +330,7 @@
                      this);
             int rc = open(name, O_RDWR | O_CREAT | O_APPEND, 0644);
             if (rc >= 0) {
-                (void)write(rc, text.string(), text.length());
+                (void)write(rc, text.c_str(), text.length());
                 close(rc);
                 ALOGI("STACK TRACE for %p saved in %s", this, name);
             }
diff --git a/libutils/String16.cpp b/libutils/String16.cpp
index 68642d8..38d483e 100644
--- a/libutils/String16.cpp
+++ b/libutils/String16.cpp
@@ -26,7 +26,7 @@
 
 static const StaticString16 emptyString(u"");
 static inline char16_t* getEmptyString() {
-    return const_cast<char16_t*>(emptyString.string());
+    return const_cast<char16_t*>(emptyString.c_str());
 }
 
 // ---------------------------------------------------------------------------
@@ -112,10 +112,7 @@
 
 String16::String16(const char16_t* o, size_t len) : mString(allocFromUTF16(o, len)) {}
 
-String16::String16(const String8& o)
-    : mString(allocFromUTF8(o.string(), o.size()))
-{
-}
+String16::String16(const String8& o) : mString(allocFromUTF8(o.c_str(), o.size())) {}
 
 String16::String16(const char* o)
     : mString(allocFromUTF8(o, strlen(o)))
@@ -173,7 +170,7 @@
         LOG_ALWAYS_FATAL("Not implemented");
     }
 
-    return setTo(other.string()+begin, len);
+    return setTo(other.c_str() + begin, len);
 }
 
 status_t String16::setTo(const char16_t* other)
@@ -200,7 +197,7 @@
 }
 
 status_t String16::append(const String16& other) {
-    return append(other.string(), other.size());
+    return append(other.c_str(), other.size());
 }
 
 status_t String16::append(const char16_t* chrs, size_t otherLen) {
@@ -286,7 +283,7 @@
 {
     const size_t ps = prefix.size();
     if (ps > size()) return false;
-    return strzcmp16(mString, ps, prefix.string(), ps) == 0;
+    return strzcmp16(mString, ps, prefix.c_str(), ps) == 0;
 }
 
 bool String16::startsWith(const char16_t* prefix) const
diff --git a/libutils/String16_fuzz.cpp b/libutils/String16_fuzz.cpp
index d7e5ec7..a271aee 100644
--- a/libutils/String16_fuzz.cpp
+++ b/libutils/String16_fuzz.cpp
@@ -25,7 +25,7 @@
 
                 // Bytes and size
                 ([](FuzzedDataProvider&, android::String16 str1, android::String16) -> void {
-                    str1.string();
+                    str1.c_str();
                 }),
                 ([](FuzzedDataProvider&, android::String16 str1, android::String16) -> void {
                     str1.isStaticString();
@@ -39,7 +39,7 @@
                     str1.startsWith(str2);
                 }),
                 ([](FuzzedDataProvider&, android::String16 str1, android::String16 str2) -> void {
-                    str1.contains(str2.string());
+                    str1.contains(str2.c_str());
                 }),
                 ([](FuzzedDataProvider&, android::String16 str1, android::String16 str2) -> void {
                     str1.compare(str2);
@@ -52,7 +52,7 @@
                 ([](FuzzedDataProvider& dataProvider, android::String16 str1,
                     android::String16 str2) -> void {
                     int pos = dataProvider.ConsumeIntegralInRange<int>(0, str1.size());
-                    str1.insert(pos, str2.string());
+                    str1.insert(pos, str2.c_str());
                 }),
 
                 // Find and replace operations
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index 8d312b5..79b7edf 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -150,10 +150,7 @@
     }
 }
 
-String8::String8(const String16& o)
-    : mString(allocFromUTF16(o.string(), o.size()))
-{
-}
+String8::String8(const String16& o) : mString(allocFromUTF16(o.c_str(), o.size())) {}
 
 String8::String8(const char16_t* o)
     : mString(allocFromUTF16(o, strlen16(o)))
@@ -267,7 +264,7 @@
         return OK;
     }
 
-    return real_append(other.string(), otherLen);
+    return real_append(other.c_str(), otherLen);
 }
 
 status_t String8::append(const char* other)
diff --git a/libutils/String8_test.cpp b/libutils/String8_test.cpp
index 35fd512..9c12cb1 100644
--- a/libutils/String8_test.cpp
+++ b/libutils/String8_test.cpp
@@ -36,7 +36,7 @@
 TEST_F(String8Test, Cstr) {
     String8 tmp("Hello, world!");
 
-    EXPECT_STREQ(tmp.string(), "Hello, world!");
+    EXPECT_STREQ(tmp.c_str(), "Hello, world!");
 }
 
 TEST_F(String8Test, OperatorPlus) {
@@ -45,16 +45,16 @@
     // Test adding String8 + const char*
     const char* ccsrc2 = "world!";
     String8 dst1 = src1 + ccsrc2;
-    EXPECT_STREQ(dst1.string(), "Hello, world!");
-    EXPECT_STREQ(src1.string(), "Hello, ");
+    EXPECT_STREQ(dst1.c_str(), "Hello, world!");
+    EXPECT_STREQ(src1.c_str(), "Hello, ");
     EXPECT_STREQ(ccsrc2, "world!");
 
     // Test adding String8 + String8
     String8 ssrc2("world!");
     String8 dst2 = src1 + ssrc2;
-    EXPECT_STREQ(dst2.string(), "Hello, world!");
-    EXPECT_STREQ(src1.string(), "Hello, ");
-    EXPECT_STREQ(ssrc2.string(), "world!");
+    EXPECT_STREQ(dst2.c_str(), "Hello, world!");
+    EXPECT_STREQ(src1.c_str(), "Hello, ");
+    EXPECT_STREQ(ssrc2.c_str(), "world!");
 }
 
 TEST_F(String8Test, OperatorPlusEquals) {
@@ -63,14 +63,14 @@
     // Testing String8 += String8
     String8 src2(" is my passport.");
     src1 += src2;
-    EXPECT_STREQ(src1.string(), "My voice is my passport.");
-    EXPECT_STREQ(src2.string(), " is my passport.");
+    EXPECT_STREQ(src1.c_str(), "My voice is my passport.");
+    EXPECT_STREQ(src2.c_str(), " is my passport.");
 
     // Adding const char* to the previous string.
     const char* src3 = " Verify me.";
     src1 += src3;
-    EXPECT_STREQ(src1.string(), "My voice is my passport. Verify me.");
-    EXPECT_STREQ(src2.string(), " is my passport.");
+    EXPECT_STREQ(src1.c_str(), "My voice is my passport. Verify me.");
+    EXPECT_STREQ(src2.c_str(), " is my passport.");
     EXPECT_STREQ(src3, " Verify me.");
 }
 
diff --git a/libutils/Tokenizer.cpp b/libutils/Tokenizer.cpp
index c3ec165..9fc955c 100644
--- a/libutils/Tokenizer.cpp
+++ b/libutils/Tokenizer.cpp
@@ -50,15 +50,15 @@
     *outTokenizer = nullptr;
 
     int result = OK;
-    int fd = ::open(filename.string(), O_RDONLY);
+    int fd = ::open(filename.c_str(), O_RDONLY);
     if (fd < 0) {
         result = -errno;
-        ALOGE("Error opening file '%s': %s", filename.string(), strerror(errno));
+        ALOGE("Error opening file '%s': %s", filename.c_str(), strerror(errno));
     } else {
         struct stat stat;
         if (fstat(fd, &stat)) {
             result = -errno;
-            ALOGE("Error getting size of file '%s': %s", filename.string(), strerror(errno));
+            ALOGE("Error getting size of file '%s': %s", filename.c_str(), strerror(errno));
         } else {
             size_t length = size_t(stat.st_size);
 
@@ -80,7 +80,7 @@
                 ssize_t nrd = read(fd, buffer, length);
                 if (nrd < 0) {
                     result = -errno;
-                    ALOGE("Error reading file '%s': %s", filename.string(), strerror(errno));
+                    ALOGE("Error reading file '%s': %s", filename.c_str(), strerror(errno));
                     delete[] buffer;
                     buffer = nullptr;
                 } else {
@@ -106,7 +106,7 @@
 
 String8 Tokenizer::getLocation() const {
     String8 result;
-    result.appendFormat("%s:%d", mFilename.string(), mLineNumber);
+    result.appendFormat("%s:%d", mFilename.c_str(), mLineNumber);
     return result;
 }
 
diff --git a/libutils/include/utils/String16.h b/libutils/include/utils/String16.h
index 3ef56a3..d719aea 100644
--- a/libutils/include/utils/String16.h
+++ b/libutils/include/utils/String16.h
@@ -53,6 +53,7 @@
 
                                 ~String16();
 
+    inline  const char16_t*     c_str() const;
     inline  const char16_t*     string() const;
 
 private:
@@ -234,6 +235,11 @@
     return compare_type(lhs, rhs) < 0;
 }
 
+inline const char16_t* String16::c_str() const
+{
+    return mString;
+}
+
 inline const char16_t* String16::string() const
 {
     return mString;
@@ -241,7 +247,7 @@
 
 inline std::string String16::std_string(const String16& str)
 {
-    return std::string(String8(str).string());
+    return std::string(String8(str).c_str());
 }
 
 inline String16& String16::operator=(const String16& other)
diff --git a/libutils/include/utils/String8.h b/libutils/include/utils/String8.h
index 8b2dcf9..e58f1a5 100644
--- a/libutils/include/utils/String8.h
+++ b/libutils/include/utils/String8.h
@@ -193,14 +193,14 @@
      * replaces whatever was there before.
      */
     String8& appendPath(const char* leaf);
-    String8& appendPath(const String8& leaf)  { return appendPath(leaf.string()); }
+    String8& appendPath(const String8& leaf) { return appendPath(leaf.c_str()); }
 
     /*
      * Like appendPath(), but does not affect this string.  Returns a new one instead.
      */
     String8 appendPathCopy(const char* leaf) const
                                              { String8 p(*this); p.appendPath(leaf); return p; }
-    String8 appendPathCopy(const String8& leaf) const { return appendPathCopy(leaf.string()); }
+    String8 appendPathCopy(const String8& leaf) const { return appendPathCopy(leaf.c_str()); }
 
     /*
      * Converts all separators in this string to /, the default path separator.
@@ -255,7 +255,7 @@
 
 inline std::string String8::std_string(const String8& str)
 {
-    return std::string(str.string());
+    return std::string(str.c_str());
 }
 
 inline size_t String8::size() const
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 5218753..cc6b64a 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -98,20 +98,31 @@
     ln -sf /data/user_de/0/com.android.shell/files/bugreports $(TARGET_ROOT_OUT)/bugreports; \
     ln -sfn /sys/kernel/debug $(TARGET_ROOT_OUT)/d; \
     ln -sf /storage/self/primary $(TARGET_ROOT_OUT)/sdcard
+
+ALL_ROOTDIR_SYMLINKS := \
+  $(TARGET_ROOT_OUT)/bin \
+  $(TARGET_ROOT_OUT)/etc \
+  $(TARGET_ROOT_OUT)/bugreports \
+  $(TARGET_ROOT_OUT)/d \
+  $(TARGET_ROOT_OUT)/sdcard
+
 ifdef BOARD_USES_VENDORIMAGE
   LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/vendor
 else
   LOCAL_POST_INSTALL_CMD += ; ln -sf /system/vendor $(TARGET_ROOT_OUT)/vendor
+  ALL_ROOTDIR_SYMLINKS += $(TARGET_ROOT_OUT)/vendor
 endif
 ifdef BOARD_USES_PRODUCTIMAGE
   LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/product
 else
   LOCAL_POST_INSTALL_CMD += ; ln -sf /system/product $(TARGET_ROOT_OUT)/product
+  ALL_ROOTDIR_SYMLINKS += $(TARGET_ROOT_OUT)/product
 endif
 ifdef BOARD_USES_SYSTEM_EXTIMAGE
   LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/system_ext
 else
   LOCAL_POST_INSTALL_CMD += ; ln -sf /system/system_ext $(TARGET_ROOT_OUT)/system_ext
+  ALL_ROOTDIR_SYMLINKS += $(TARGET_ROOT_OUT)/system_ext
 endif
 ifdef BOARD_USES_METADATA_PARTITION
   LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/metadata
@@ -134,6 +145,18 @@
 LOCAL_POST_INSTALL_CMD += ; ln -sf /vendor/odm/priv-app $(TARGET_ROOT_OUT)/odm/priv-app
 LOCAL_POST_INSTALL_CMD += ; ln -sf /vendor/odm/usr $(TARGET_ROOT_OUT)/odm/usr
 
+ALL_ROOTDIR_SYMLINKS += \
+  $(TARGET_ROOT_OUT)/odm/app \
+  $(TARGET_ROOT_OUT)/odm/bin \
+  $(TARGET_ROOT_OUT)/odm/etc \
+  $(TARGET_ROOT_OUT)/odm/firmware \
+  $(TARGET_ROOT_OUT)/odm/framework \
+  $(TARGET_ROOT_OUT)/odm/lib \
+  $(TARGET_ROOT_OUT)/odm/lib64 \
+  $(TARGET_ROOT_OUT)/odm/overlay \
+  $(TARGET_ROOT_OUT)/odm/priv-app \
+  $(TARGET_ROOT_OUT)/odm/usr
+
 
 # For /vendor_dlkm partition.
 LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/vendor_dlkm
@@ -144,6 +167,7 @@
 # Note that /vendor_dlkm/lib is omitted because vendor DLKMs should be accessed
 # via /vendor/lib/modules directly.
 LOCAL_POST_INSTALL_CMD += ; ln -sf /vendor/vendor_dlkm/etc $(TARGET_ROOT_OUT)/vendor_dlkm/etc
+ALL_ROOTDIR_SYMLINKS += $(TARGET_ROOT_OUT)/vendor_dlkm/etc
 
 # For /odm_dlkm partition.
 LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/odm_dlkm
@@ -154,6 +178,7 @@
 # Note that /odm_dlkm/lib is omitted because odm DLKMs should be accessed
 # via /odm/lib/modules directly.
 LOCAL_POST_INSTALL_CMD += ; ln -sf /odm/odm_dlkm/etc $(TARGET_ROOT_OUT)/odm_dlkm/etc
+ALL_ROOTDIR_SYMLINKS += $(TARGET_ROOT_OUT)/odm_dlkm/etc
 
 # For /system_dlkm partition
 LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/system_dlkm
@@ -162,6 +187,7 @@
   LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/cache
 else
   LOCAL_POST_INSTALL_CMD += ; ln -sf /data/cache $(TARGET_ROOT_OUT)/cache
+  ALL_ROOTDIR_SYMLINKS += $(TARGET_ROOT_OUT)/cache
 endif
 ifdef BOARD_ROOT_EXTRA_SYMLINKS
 # BOARD_ROOT_EXTRA_SYMLINKS is a list of <target>:<link_name>.
@@ -169,14 +195,19 @@
     $(eval p := $(subst :,$(space),$(s)))\
     ; mkdir -p $(dir $(TARGET_ROOT_OUT)/$(word 2,$(p))) \
     ; ln -sf $(word 1,$(p)) $(TARGET_ROOT_OUT)/$(word 2,$(p)))
+  ALL_ROOTDIR_SYMLINKS += $(foreach s,$(BOARD_ROOT_EXTRA_SYMLINKS),$(TARGET_ROOT_OUT)/$(call word-colon,2,$s))
 endif
 
 # The init symlink must be a post install command of a file that is to TARGET_ROOT_OUT.
 # Since init.environ.rc is required for init and satisfies that requirement, we hijack it to create the symlink.
 LOCAL_POST_INSTALL_CMD += ; ln -sf /system/bin/init $(TARGET_ROOT_OUT)/init
+ALL_ROOTDIR_SYMLINKS += $(TARGET_ROOT_OUT)/init
+
+ALL_DEFAULT_INSTALLED_MODULES += $(ALL_ROOTDIR_SYMLINKS)
 
 include $(BUILD_SYSTEM)/base_rules.mk
 
+$(ALL_ROOTDIR_SYMLINKS): $(LOCAL_BUILT_MODULE)
 $(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/init.environ.rc.in
 	@echo "Generate: $< -> $@"
 	@mkdir -p $(dir $@)