Merge "Adding public volume mounts for clone user." into main
diff --git a/Android.bp b/Android.bp
index 7e41f22..6d70d4d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -165,7 +165,6 @@
         },
     },
     whole_static_libs: [
-        "libcom.android.sysprop.apex",
         "libc++fs",
     ],
 }
diff --git a/IdleMaint.cpp b/IdleMaint.cpp
index fedfc3d..7d3eaf4 100644
--- a/IdleMaint.cpp
+++ b/IdleMaint.cpp
@@ -436,7 +436,7 @@
     idle_maint_stat = IdleMaintStats::kStopped;
     lk.unlock();
 
-    cv_stop.notify_one();
+    cv_stop.notify_all();
 
     if (listener) {
         android::os::PersistableBundle extras;
@@ -551,9 +551,9 @@
 
     int32_t freeSegments = std::stoi(freeSegmentsStr);
     int32_t dirtySegments = std::stoi(dirtySegmentsStr);
-    int32_t reservedBlocks = std::stoi(ovpSegmentsStr) + std::stoi(reservedBlocksStr);
+    int32_t reservedSegments = std::stoi(ovpSegmentsStr) + std::stoi(reservedBlocksStr) / 512;
 
-    freeSegments = freeSegments > reservedBlocks ? freeSegments - reservedBlocks : 0;
+    freeSegments = freeSegments > reservedSegments ? freeSegments - reservedSegments : 0;
     int32_t totalSegments = freeSegments + dirtySegments;
     int32_t finalTargetSegments = 0;
 
diff --git a/KeyUtil.cpp b/KeyUtil.cpp
index 395b6b3..5a8b550 100644
--- a/KeyUtil.cpp
+++ b/KeyUtil.cpp
@@ -28,7 +28,6 @@
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
-#include <android-base/properties.h>
 #include <keyutils.h>
 
 #include "KeyStorage.h"
@@ -99,7 +98,6 @@
         PLOG(WARNING) << "Unexpected error from FS_IOC_ADD_ENCRYPTION_KEY";
     }
     LOG(DEBUG) << "Detected support for FS_IOC_ADD_ENCRYPTION_KEY";
-    android::base::SetProperty("ro.crypto.uses_fs_ioc_add_encryption_key", "true");
     return true;
 }
 
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index 601323f..6e795ed 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -946,5 +946,10 @@
     return translateBool(destroy_dsu_metadata_key(dsuSlot));
 }
 
+binder::Status VoldNativeService::getStorageSize(int64_t* storageSize) {
+    ENFORCE_SYSTEM_OR_ROOT;
+    return translate(GetStorageSize(storageSize));
+}
+
 }  // namespace vold
 }  // namespace android
diff --git a/VoldNativeService.h b/VoldNativeService.h
index 12a93f5..d02b262 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -162,6 +162,8 @@
     binder::Status bindMount(const std::string& sourceDir, const std::string& targetDir) override;
 
     binder::Status destroyDsuMetadataKey(const std::string& dsuSlot) override;
+
+    binder::Status getStorageSize(int64_t* storageSize) override;
 };
 
 }  // namespace vold
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index d47d9f3..db356db 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -35,7 +35,7 @@
 
 #include <linux/kdev_t.h>
 
-#include <ApexProperties.sysprop.h>
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
 #include <android-base/properties.h>
@@ -53,6 +53,7 @@
 #include <private/android_filesystem_config.h>
 
 #include <fscrypt/fscrypt.h>
+#include <libdm/dm.h>
 
 #include "AppFuseUtil.h"
 #include "FsCrypt.h"
@@ -620,12 +621,11 @@
     struct dirent* de;
     std::string rootName;
     std::string pidName;
+    std::string exeName;
     int pidFd;
     int nsFd;
     struct stat sb;
 
-    static bool apexUpdatable = android::sysprop::ApexProperties::updatable().value_or(false);
-
     if (!(dir = opendir("/proc"))) {
         async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to opendir");
         return false;
@@ -673,22 +673,18 @@
             goto next;
         }
 
-        if (apexUpdatable) {
-            std::string exeName;
-            // When ro.apex.bionic_updatable is set to true,
-            // some early native processes have mount namespaces that are different
-            // from that of the init. Therefore, above check can't filter them out.
-            // Since the propagation type of / is 'shared', unmounting /storage
-            // for the early native processes affects other processes including
-            // init. Filter out such processes by skipping if a process is a
-            // non-Java process whose UID is < AID_APP_START. (The UID condition
-            // is required to not filter out child processes spawned by apps.)
-            if (!android::vold::Readlinkat(pidFd, "exe", &exeName)) {
-                goto next;
-            }
-            if (!StartsWith(exeName, "/system/bin/app_process") && sb.st_uid < AID_APP_START) {
-                goto next;
-            }
+        // Some early native processes have mount namespaces that are different
+        // from that of the init. Therefore, above check can't filter them out.
+        // Since the propagation type of / is 'shared', unmounting /storage
+        // for the early native processes affects other processes including
+        // init. Filter out such processes by skipping if a process is a
+        // non-Java process whose UID is < AID_APP_START. (The UID condition
+        // is required to not filter out child processes spawned by apps.)
+        if (!android::vold::Readlinkat(pidFd, "exe", &exeName)) {
+            goto next;
+        }
+        if (!StartsWith(exeName, "/system/bin/app_process") && sb.st_uid < AID_APP_START) {
+            goto next;
         }
 
         // We purposefully leave the namespace open across the fork
@@ -1223,3 +1219,68 @@
 int VolumeManager::openAppFuseFile(uid_t uid, int mountId, int fileId, int flags) {
     return android::vold::OpenAppFuseFile(uid, mountId, fileId, flags);
 }
+
+android::status_t android::vold::GetStorageSize(int64_t* storageSize) {
+    // Start with the /data mount point from fs_mgr
+    auto entry = android::fs_mgr::GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT);
+    if (entry == nullptr) {
+        LOG(ERROR) << "No mount point entry for " << DATA_MNT_POINT;
+        return EINVAL;
+    }
+
+    // Follow any symbolic links
+    std::string blkDevice = entry->blk_device;
+    std::string dataDevice;
+    if (!android::base::Realpath(blkDevice, &dataDevice)) {
+        dataDevice = blkDevice;
+    }
+
+    // Handle mapped volumes.
+    auto& dm = android::dm::DeviceMapper::Instance();
+    for (;;) {
+        auto parent = dm.GetParentBlockDeviceByPath(dataDevice);
+        if (!parent.has_value()) break;
+        dataDevice = *parent;
+    }
+
+    // Get the potential /sys/block entry
+    std::size_t leaf = dataDevice.rfind('/');
+    if (leaf == std::string::npos) {
+        LOG(ERROR) << "data device " << dataDevice << " is not a path";
+        return EINVAL;
+    }
+    if (dataDevice.substr(0, leaf) != "/dev/block") {
+        LOG(ERROR) << "data device " << dataDevice << " is not a block device";
+        return EINVAL;
+    }
+    std::string sysfs = std::string() + "/sys/block/" + dataDevice.substr(leaf + 1);
+
+    // Look for a directory in /sys/block containing size where the name is a shortened
+    // version of the name we now have
+    // Typically we start with something like /sys/block/sda2, and we want /sys/block/sda
+    // Note that this directory only contains actual disks, not partitions, so this is
+    // not going to find anything other than the disks
+    std::string size;
+    std::string sizeFile;
+    for (std::string sysfsDir = sysfs;; sysfsDir = sysfsDir.substr(0, sysfsDir.size() - 1)) {
+        if (sysfsDir.back() == '/') {
+            LOG(ERROR) << "Could not find valid block device from " << sysfs;
+            return EINVAL;
+        }
+        sizeFile = sysfsDir + "/size";
+        if (android::base::ReadFileToString(sizeFile, &size, true)) {
+            break;
+        }
+    }
+
+    // Read the size file and be done
+    std::stringstream ssSize(size);
+    ssSize >> *storageSize;
+    if (ssSize.fail()) {
+        LOG(ERROR) << sizeFile << " cannot be read as an integer";
+        return EINVAL;
+    }
+
+    *storageSize *= 512;
+    return OK;
+}
\ No newline at end of file
diff --git a/VolumeManager.h b/VolumeManager.h
index 943a144..2d6b968 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -242,4 +242,10 @@
     bool mSecureKeyguardShowing;
 };
 
+namespace android {
+namespace vold {
+android::status_t GetStorageSize(int64_t* storageSize);
+}
+}  // namespace android
+
 #endif
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index c798959..c7102e3 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -136,6 +136,8 @@
 
     void destroyDsuMetadataKey(@utf8InCpp String dsuSlot);
 
+    long getStorageSize();
+
     const int FSTRIM_FLAG_DEEP_TRIM = 1;
 
     const int MOUNT_FLAG_PRIMARY = 1;
diff --git a/vdc.cpp b/vdc.cpp
index b63abbb..7d72535 100644
--- a/vdc.cpp
+++ b/vdc.cpp
@@ -62,7 +62,7 @@
 static void checkStatus(std::vector<std::string>& cmd, android::binder::Status status) {
     if (status.isOk()) return;
     std::string command = ::android::base::Join(cmd, " ");
-    LOG(ERROR) << "Command: " << command << " Failed: " << status.toString8().string();
+    LOG(ERROR) << "Command: " << command << " Failed: " << status.toString8().c_str();
     exit(ENOTTY);
 }
 
@@ -122,6 +122,10 @@
         checkStatus(args, vold->shutdown());
     } else if (args[0] == "volume" && args[1] == "reset") {
         checkStatus(args, vold->reset());
+    } else if (args[0] == "volume" && args[1] == "getStorageSize") {
+        int64_t size;
+        checkStatus(args, vold->getStorageSize(&size));
+        LOG(INFO) << size;
     } else if (args[0] == "cryptfs" && args[1] == "bindkeys") {
         bindkeys(args, vold);
     } else if (args[0] == "cryptfs" && args[1] == "mountFstab" && args.size() == 5) {
diff --git a/vold_prepare_subdirs.cpp b/vold_prepare_subdirs.cpp
index 60e82f5..e82a7c2 100644
--- a/vold_prepare_subdirs.cpp
+++ b/vold_prepare_subdirs.cpp
@@ -144,7 +144,12 @@
 static bool prepare_apex_subdirs(struct selabel_handle* sehandle, const std::string& path) {
     if (!prepare_dir(sehandle, 0711, 0, 0, path + "/apexdata")) return false;
 
-    auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/apex"), closedir);
+    // Since vold/vold_prepare_subdirs run in the bootstrap mount namespace
+    // we can't get the full list of APEXes by scanning /apex directory.
+    // Instead, we can look up /data/misc/apexdata for the list of APEXes,
+    // which is populated during `perform_apex_config` in init.
+    // Note: `init_user0` should be invoked after `perform_apex_config`.
+    auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/data/misc/apexdata"), closedir);
     if (!dirp) {
         PLOG(ERROR) << "Unable to open apex directory";
         return false;
@@ -157,8 +162,6 @@
         // skip any starting with "."
         if (name[0] == '.') continue;
 
-        if (strchr(name, '@') != NULL) continue;
-
         if (!prepare_dir(sehandle, 0771, AID_ROOT, AID_SYSTEM, path + "/apexdata/" + name)) {
             return false;
         }