Check if storage app data and obb directories exist in vold

As storage is not mounted in system server, we use vold
to check if storage app data and obb directories exist instead.

We add a method in vold so it only creates app data and obb dirs
if dirs do not exist to speed up app starting time.

Bug: 160336374
Test: Data and obb directories are created when a new app is started
Change-Id: I1bd784d9c9e05463f71433fc782ac4e0c831cbf1
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index f0fc388..714122d 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -984,7 +984,25 @@
     return 0;
 }
 
-int VolumeManager::setupAppDir(const std::string& path, int32_t appUid, bool fixupExistingOnly) {
+int VolumeManager::ensureAppDirsCreated(const std::vector<std::string>& paths, int32_t appUid) {
+    if (IsSdcardfsUsed()) {
+        // sdcardfs magically does this for us
+        return OK;
+    }
+
+    int size = paths.size();
+    for (int i = 0; i < size; i++) {
+        int result = setupAppDir(paths[i], appUid, false /* fixupExistingOnly */,
+                true /* skipIfDirExists */);
+        if (result != OK) {
+            return result;
+        }
+    }
+    return OK;
+}
+
+int VolumeManager::setupAppDir(const std::string& path, int32_t appUid, bool fixupExistingOnly,
+        bool skipIfDirExists) {
     // Only offer to create directories for paths managed by vold
     if (!StartsWith(path, "/storage/")) {
         LOG(ERROR) << "Failed to find mounted volume for " << path;
@@ -1029,11 +1047,18 @@
 
     const std::string volumeRoot = volume->getRootPath();  // eg /data/media/0
 
-    if (fixupExistingOnly && (access(lowerPath.c_str(), F_OK) != 0)) {
+    const int access_result = access(lowerPath.c_str(), F_OK);
+    if (fixupExistingOnly && access_result != 0) {
         // Nothing to fixup
         return OK;
     }
 
+    if (skipIfDirExists && access_result == 0) {
+        // It's safe to assume it's ok as it will be used for zygote to bind mount dir only,
+        // which the dir doesn't need to have correct permission for now yet.
+        return OK;
+    }
+
     if (volume->getType() == VolumeBase::Type::kPublic) {
         // On public volumes, we don't need to setup permissions, as everything goes through
         // FUSE; just create the dirs and be done with it.