Merge "Merged-In Revert "vold: use RAII wake locks"" am: 2ebb5c5b96
am: fce081efa6
Change-Id: If58a55eecb04453f69e51cdc242f5ab71fb7ddc1
diff --git a/AppFuseUtil.cpp b/AppFuseUtil.cpp
index c491ecd..711e70b 100644
--- a/AppFuseUtil.cpp
+++ b/AppFuseUtil.cpp
@@ -49,9 +49,6 @@
}
static android::status_t Mount(int device_fd, const std::string& path) {
- // Remove existing mount.
- android::vold::ForceUnmount(path);
-
const auto opts = StringPrintf(
"fd=%i,"
"rootmode=40000,"
@@ -115,6 +112,11 @@
return -1;
}
+ // Forcibly remove the existing mount before we attempt to prepare the
+ // directory. If we have a dangling mount, then PrepareDir may fail if the
+ // indirection to FUSE doesn't work.
+ android::vold::ForceUnmount(path);
+
// Create directories.
const android::status_t result = android::vold::PrepareDir(path, 0700, 0, 0);
if (result != android::OK) {
diff --git a/Checkpoint.cpp b/Checkpoint.cpp
index 56ec782..0605c72 100644
--- a/Checkpoint.cpp
+++ b/Checkpoint.cpp
@@ -153,6 +153,11 @@
if (!isCheckpointing) {
return Status::ok();
}
+ if (android::base::GetProperty("persist.vold.dont_commit_checkpoint", "0") == "1") {
+ LOG(WARNING)
+ << "NOT COMMITTING CHECKPOINT BECAUSE persist.vold.dont_commit_checkpoint IS 1";
+ return Status::ok();
+ }
sp<IBootControl> module = IBootControl::getService();
if (module) {
CommandResult cr;
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index 5f659a8..3028b60 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -269,7 +269,7 @@
std::string* raw_ref) {
auto refi = key_map.find(user_id);
if (refi == key_map.end()) {
- LOG(ERROR) << "Cannot find key for " << user_id;
+ LOG(DEBUG) << "Cannot find key for " << user_id;
return false;
}
*raw_ref = refi->second;
diff --git a/IdleMaint.cpp b/IdleMaint.cpp
index a2d0f91..bca22f6 100644
--- a/IdleMaint.cpp
+++ b/IdleMaint.cpp
@@ -49,8 +49,8 @@
using android::fs_mgr::ReadDefaultFstab;
using android::hardware::Return;
using android::hardware::Void;
-using android::hardware::health::storage::V1_0::IGarbageCollectCallback;
using android::hardware::health::storage::V1_0::IStorage;
+using android::hardware::health::storage::V1_0::IGarbageCollectCallback;
using android::hardware::health::storage::V1_0::Result;
namespace android {
diff --git a/Utils.cpp b/Utils.cpp
index 6a3830f..1616d80 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -36,6 +36,7 @@
#include <mntent.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
@@ -194,13 +195,55 @@
}
status_t BindMount(const std::string& source, const std::string& target) {
- if (::mount(source.c_str(), target.c_str(), "", MS_BIND, NULL)) {
+ if (UnmountTree(target) < 0) {
+ return -errno;
+ }
+ if (TEMP_FAILURE_RETRY(mount(source.c_str(), target.c_str(), nullptr, MS_BIND, nullptr)) < 0) {
PLOG(ERROR) << "Failed to bind mount " << source << " to " << target;
return -errno;
}
return OK;
}
+status_t Symlink(const std::string& target, const std::string& linkpath) {
+ if (Unlink(linkpath) < 0) {
+ return -errno;
+ }
+ if (TEMP_FAILURE_RETRY(symlink(target.c_str(), linkpath.c_str())) < 0) {
+ PLOG(ERROR) << "Failed to create symlink " << linkpath << " to " << target;
+ return -errno;
+ }
+ return OK;
+}
+
+status_t Unlink(const std::string& linkpath) {
+ if (TEMP_FAILURE_RETRY(unlink(linkpath.c_str())) < 0 && errno != EINVAL && errno != ENOENT) {
+ PLOG(ERROR) << "Failed to unlink " << linkpath;
+ return -errno;
+ }
+ return OK;
+}
+
+status_t CreateDir(const std::string& dir, mode_t mode) {
+ struct stat sb;
+ if (TEMP_FAILURE_RETRY(stat(dir.c_str(), &sb)) == 0) {
+ if (S_ISDIR(sb.st_mode)) {
+ return OK;
+ } else if (TEMP_FAILURE_RETRY(unlink(dir.c_str())) == -1) {
+ PLOG(ERROR) << "Failed to unlink " << dir;
+ return -errno;
+ }
+ } else if (errno != ENOENT) {
+ PLOG(ERROR) << "Failed to stat " << dir;
+ return -errno;
+ }
+ if (TEMP_FAILURE_RETRY(mkdir(dir.c_str(), mode)) == -1 && errno != EEXIST) {
+ PLOG(ERROR) << "Failed to mkdir " << dir;
+ return -errno;
+ }
+ return OK;
+}
+
bool FindValue(const std::string& raw, const std::string& key, std::string* value) {
auto qual = key + "=\"";
size_t start = 0;
@@ -801,13 +844,87 @@
}
status_t UnmountTree(const std::string& mountPoint) {
- if (umount2(mountPoint.c_str(), MNT_DETACH)) {
+ if (TEMP_FAILURE_RETRY(umount2(mountPoint.c_str(), MNT_DETACH)) < 0 && errno != EINVAL &&
+ errno != ENOENT) {
PLOG(ERROR) << "Failed to unmount " << mountPoint;
return -errno;
}
return OK;
}
+static status_t delete_dir_contents(DIR* dir) {
+ // Shamelessly borrowed from android::installd
+ int dfd = dirfd(dir);
+ if (dfd < 0) {
+ return -errno;
+ }
+
+ status_t result = OK;
+ struct dirent* de;
+ while ((de = readdir(dir))) {
+ const char* name = de->d_name;
+ if (de->d_type == DT_DIR) {
+ /* always skip "." and ".." */
+ if (name[0] == '.') {
+ if (name[1] == 0) continue;
+ if ((name[1] == '.') && (name[2] == 0)) continue;
+ }
+
+ android::base::unique_fd subfd(
+ openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC));
+ if (subfd.get() == -1) {
+ PLOG(ERROR) << "Couldn't openat " << name;
+ result = -errno;
+ continue;
+ }
+ std::unique_ptr<DIR, decltype(&closedir)> subdirp(
+ android::base::Fdopendir(std::move(subfd)), closedir);
+ if (!subdirp) {
+ PLOG(ERROR) << "Couldn't fdopendir " << name;
+ result = -errno;
+ continue;
+ }
+ result = delete_dir_contents(subdirp.get());
+ if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
+ PLOG(ERROR) << "Couldn't unlinkat " << name;
+ result = -errno;
+ }
+ } else {
+ if (unlinkat(dfd, name, 0) < 0) {
+ PLOG(ERROR) << "Couldn't unlinkat " << name;
+ result = -errno;
+ }
+ }
+ }
+ return result;
+}
+
+status_t DeleteDirContentsAndDir(const std::string& pathname) {
+ status_t res = DeleteDirContents(pathname);
+ if (res < 0) {
+ return res;
+ }
+ if (TEMP_FAILURE_RETRY(rmdir(pathname.c_str())) < 0 && errno != ENOENT) {
+ PLOG(ERROR) << "rmdir failed on " << pathname;
+ return -errno;
+ }
+ LOG(VERBOSE) << "Success: rmdir on " << pathname;
+ return OK;
+}
+
+status_t DeleteDirContents(const std::string& pathname) {
+ // Shamelessly borrowed from android::installd
+ std::unique_ptr<DIR, decltype(&closedir)> dirp(opendir(pathname.c_str()), closedir);
+ if (!dirp) {
+ if (errno == ENOENT) {
+ return OK;
+ }
+ PLOG(ERROR) << "Failed to opendir " << pathname;
+ return -errno;
+ }
+ return delete_dir_contents(dirp.get());
+}
+
// TODO(118708649): fix duplication with init/util.h
status_t WaitForFile(const char* filename, std::chrono::nanoseconds timeout) {
android::base::Timer t;
diff --git a/Utils.h b/Utils.h
index c083021..af4e401 100644
--- a/Utils.h
+++ b/Utils.h
@@ -57,6 +57,15 @@
/* Creates bind mount from source to target */
status_t BindMount(const std::string& source, const std::string& target);
+/** Creates a symbolic link to target */
+status_t Symlink(const std::string& target, const std::string& linkpath);
+
+/** Calls unlink(2) at linkpath */
+status_t Unlink(const std::string& linkpath);
+
+/** Creates the given directory if it is not already available */
+status_t CreateDir(const std::string& dir, mode_t mode);
+
bool FindValue(const std::string& raw, const std::string& key, std::string* value);
/* Reads filesystem metadata from device at path */
@@ -130,6 +139,9 @@
status_t UnmountTreeWithPrefix(const std::string& prefix);
status_t UnmountTree(const std::string& mountPoint);
+status_t DeleteDirContentsAndDir(const std::string& pathname);
+status_t DeleteDirContents(const std::string& pathname);
+
status_t WaitForFile(const char* filename, std::chrono::nanoseconds timeout);
bool FsyncDirectory(const std::string& dirname);
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index 623cced..84c06f1 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -276,6 +276,16 @@
return translate(VolumeManager::Instance()->onUserStopped(userId));
}
+binder::Status VoldNativeService::addAppIds(const std::vector<std::string>& packageNames,
+ const std::vector<int32_t>& appIds) {
+ return ok();
+}
+
+binder::Status VoldNativeService::addSandboxIds(const std::vector<int32_t>& appIds,
+ const std::vector<std::string>& sandboxIds) {
+ return ok();
+}
+
binder::Status VoldNativeService::onSecureKeyguardStateChanged(bool isShowing) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_LOCK;
@@ -330,10 +340,16 @@
vol->setMountUserId(mountUserId);
int res = vol->mount();
- if ((mountFlags & MOUNT_FLAG_PRIMARY) != 0) {
- VolumeManager::Instance()->setPrimary(vol);
+ if (res != OK) {
+ return translate(res);
}
- return translate(res);
+ if ((mountFlags & MOUNT_FLAG_PRIMARY) != 0) {
+ res = VolumeManager::Instance()->setPrimary(vol);
+ if (res != OK) {
+ return translate(res);
+ }
+ }
+ return translate(OK);
}
binder::Status VoldNativeService::unmount(const std::string& volId) {
@@ -431,24 +447,7 @@
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_LOCK;
- std::string tmp;
- switch (remountMode) {
- case REMOUNT_MODE_NONE:
- tmp = "none";
- break;
- case REMOUNT_MODE_DEFAULT:
- tmp = "default";
- break;
- case REMOUNT_MODE_READ:
- tmp = "read";
- break;
- case REMOUNT_MODE_WRITE:
- tmp = "write";
- break;
- default:
- return error("Unknown mode " + std::to_string(remountMode));
- }
- return translate(VolumeManager::Instance()->remountUid(uid, tmp));
+ return translate(VolumeManager::Instance()->remountUid(uid, remountMode));
}
binder::Status VoldNativeService::mkdirs(const std::string& path) {
@@ -805,6 +804,18 @@
return translateBool(fscrypt_destroy_user_storage(uuid_, userId, flags));
}
+binder::Status VoldNativeService::prepareSandboxForApp(const std::string& packageName,
+ int32_t appId, const std::string& sandboxId,
+ int32_t userId) {
+ return ok();
+}
+
+binder::Status VoldNativeService::destroySandboxForApp(const std::string& packageName,
+ const std::string& sandboxId,
+ int32_t userId) {
+ return ok();
+}
+
binder::Status VoldNativeService::startCheckpoint(int32_t retry) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_LOCK;
diff --git a/VoldNativeService.h b/VoldNativeService.h
index b90c5b8..5ca298e 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -42,6 +42,11 @@
binder::Status onUserStarted(int32_t userId);
binder::Status onUserStopped(int32_t userId);
+ binder::Status addAppIds(const std::vector<std::string>& packageNames,
+ const std::vector<int32_t>& appIds);
+ binder::Status addSandboxIds(const std::vector<int32_t>& appIds,
+ const std::vector<std::string>& sandboxIds);
+
binder::Status onSecureKeyguardStateChanged(bool isShowing);
binder::Status partition(const std::string& diskId, int32_t partitionType, int32_t ratio);
@@ -118,8 +123,10 @@
binder::Status destroyUserStorage(const std::unique_ptr<std::string>& uuid, int32_t userId,
int32_t flags);
- binder::Status mountExternalStorageForApp(const std::string& packageName, int32_t appId,
- const std::string& sandboxId, int32_t userId);
+ binder::Status prepareSandboxForApp(const std::string& packageName, int32_t appId,
+ const std::string& sandboxId, int32_t userId);
+ binder::Status destroySandboxForApp(const std::string& packageName,
+ const std::string& sandboxId, int32_t userId);
binder::Status startCheckpoint(int32_t retry);
binder::Status needsCheckpoint(bool* _aidl_return);
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 897c2a8..44bff5a 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -30,6 +30,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
+#include <array>
#include <linux/kdev_t.h>
@@ -58,6 +59,7 @@
#include "NetlinkManager.h"
#include "Process.h"
#include "Utils.h"
+#include "VoldNativeService.h"
#include "VoldUtil.h"
#include "VolumeManager.h"
#include "cryptfs.h"
@@ -67,15 +69,28 @@
#include "model/ObbVolume.h"
#include "model/StubVolume.h"
+using android::OK;
+using android::base::GetBoolProperty;
using android::base::StartsWith;
+using android::base::StringAppendF;
using android::base::StringPrintf;
using android::base::unique_fd;
+using android::vold::BindMount;
+using android::vold::CreateDir;
+using android::vold::DeleteDirContents;
+using android::vold::DeleteDirContentsAndDir;
+using android::vold::Symlink;
+using android::vold::Unlink;
+using android::vold::UnmountTree;
+using android::vold::VoldNativeService;
static const char* kPathUserMount = "/mnt/user";
static const char* kPathVirtualDisk = "/data/misc/vold/virtual_disk";
static const char* kPropVirtualDisk = "persist.sys.virtual_disk";
+static const std::string kEmptyString("");
+
/* 512MiB is large enough for testing purposes */
static const unsigned int kSizeVirtualDisk = 536870912;
@@ -103,7 +118,7 @@
int VolumeManager::updateVirtualDisk() {
ATRACE_NAME("VolumeManager::updateVirtualDisk");
- if (android::base::GetBoolProperty(kPropVirtualDisk, false)) {
+ if (GetBoolProperty(kPropVirtualDisk, false)) {
if (access(kPathVirtualDisk, F_OK) != 0) {
Loop::createImageFile(kPathVirtualDisk, kSizeVirtualDisk / 512);
}
@@ -351,22 +366,14 @@
int VolumeManager::linkPrimary(userid_t userId) {
std::string source(mPrimary->getPath());
- if (mPrimary->getType() == android::vold::VolumeBase::Type::kEmulated) {
+ if (mPrimary->isEmulated()) {
source = StringPrintf("%s/%d", source.c_str(), userId);
fs_prepare_dir(source.c_str(), 0755, AID_ROOT, AID_ROOT);
}
std::string target(StringPrintf("/mnt/user/%d/primary", userId));
- if (TEMP_FAILURE_RETRY(unlink(target.c_str()))) {
- if (errno != ENOENT) {
- PLOG(WARNING) << "Failed to unlink " << target;
- }
- }
LOG(DEBUG) << "Linking " << source << " to " << target;
- if (TEMP_FAILURE_RETRY(symlink(source.c_str(), target.c_str()))) {
- PLOG(WARNING) << "Failed to link";
- return -errno;
- }
+ Symlink(source, target);
return 0;
}
@@ -381,6 +388,7 @@
}
int VolumeManager::onUserStarted(userid_t userId) {
+ LOG(VERBOSE) << "onUserStarted: " << userId;
// Note that sometimes the system will spin up processes from Zygote
// before actually starting the user, so we're okay if Zygote
// already created this directory.
@@ -395,6 +403,7 @@
}
int VolumeManager::onUserStopped(userid_t userId) {
+ LOG(VERBOSE) << "onUserStopped: " << userId;
mStartedUsers.erase(userId);
return 0;
}
@@ -421,7 +430,30 @@
return 0;
}
-int VolumeManager::remountUid(uid_t uid, const std::string& mode) {
+int VolumeManager::remountUid(uid_t uid, int32_t mountMode) {
+ std::string mode;
+ switch (mountMode) {
+ case VoldNativeService::REMOUNT_MODE_NONE:
+ mode = "none";
+ break;
+ case VoldNativeService::REMOUNT_MODE_DEFAULT:
+ mode = "default";
+ break;
+ case VoldNativeService::REMOUNT_MODE_READ:
+ mode = "read";
+ break;
+ case VoldNativeService::REMOUNT_MODE_WRITE:
+ case VoldNativeService::REMOUNT_MODE_LEGACY:
+ case VoldNativeService::REMOUNT_MODE_INSTALLER:
+ mode = "write";
+ break;
+ case VoldNativeService::REMOUNT_MODE_FULL:
+ mode = "full";
+ break;
+ default:
+ PLOG(ERROR) << "Unknown mode " << std::to_string(mountMode);
+ return -1;
+ }
LOG(DEBUG) << "Remounting " << uid << " as mode " << mode;
DIR* dir;
@@ -522,6 +554,8 @@
storageSource = "/mnt/runtime/read";
} else if (mode == "write") {
storageSource = "/mnt/runtime/write";
+ } else if (mode == "full") {
+ storageSource = "/mnt/runtime/full";
} else {
// Sane default of no storage visible
_exit(0);
diff --git a/VolumeManager.h b/VolumeManager.h
index e0a1bd6..9bf7599 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -95,7 +95,7 @@
int setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol);
- int remountUid(uid_t uid, const std::string& mode);
+ int remountUid(uid_t uid, int32_t remountMode);
/* Reset all internal state, typically during framework boot */
int reset();
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 72f2643..75fef06 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -32,6 +32,9 @@
void onUserStarted(int userId);
void onUserStopped(int userId);
+ void addAppIds(in @utf8InCpp String[] packageNames, in int[] appIds);
+ void addSandboxIds(in int[] appIds, in @utf8InCpp String[] sandboxIds);
+
void onSecureKeyguardStateChanged(boolean isShowing);
void partition(@utf8InCpp String diskId, int partitionType, int ratio);
@@ -96,6 +99,11 @@
int storageFlags);
void destroyUserStorage(@nullable @utf8InCpp String uuid, int userId, int storageFlags);
+ void prepareSandboxForApp(in @utf8InCpp String packageName, int appId,
+ in @utf8InCpp String sandboxId, int userId);
+ void destroySandboxForApp(in @utf8InCpp String packageName,
+ in @utf8InCpp String sandboxId, int userId);
+
void startCheckpoint(int retry);
boolean needsCheckpoint();
boolean needsRollback();
@@ -146,6 +154,9 @@
const int REMOUNT_MODE_DEFAULT = 1;
const int REMOUNT_MODE_READ = 2;
const int REMOUNT_MODE_WRITE = 3;
+ const int REMOUNT_MODE_LEGACY = 4;
+ const int REMOUNT_MODE_INSTALLER = 5;
+ const int REMOUNT_MODE_FULL = 6;
const int VOLUME_STATE_UNMOUNTED = 0;
const int VOLUME_STATE_CHECKING = 1;
diff --git a/main.cpp b/main.cpp
index accaa01..7555276 100644
--- a/main.cpp
+++ b/main.cpp
@@ -54,7 +54,7 @@
int main(int argc, char** argv) {
atrace_set_tracing_enabled(false);
- setenv("ANDROID_LOG_TAGS", "*:d", 1);
+ setenv("ANDROID_LOG_TAGS", "*:d", 1); // Do not submit with verbose logs enabled
android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
LOG(INFO) << "Vold 3.0 (the awakening) firing up";
diff --git a/model/EmulatedVolume.cpp b/model/EmulatedVolume.cpp
index f933982..552fe2f 100644
--- a/model/EmulatedVolume.cpp
+++ b/model/EmulatedVolume.cpp
@@ -16,9 +16,10 @@
#include "EmulatedVolume.h"
#include "Utils.h"
+#include "VolumeManager.h"
-#include <android-base/stringprintf.h>
#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include <cutils/fs.h>
#include <private/android_filesystem_config.h>
#include <utils/Timers.h>
@@ -89,6 +90,7 @@
"-w",
"-G",
"-i",
+ "-o",
mRawPath.c_str(),
label.c_str(),
NULL)) {
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index 1339eb3..0a6b351 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -21,6 +21,7 @@
#include "fs/Vfat.h"
#include <android-base/logging.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <cutils/fs.h>
#include <private/android_filesystem_config.h>
@@ -34,6 +35,7 @@
#include <sys/types.h>
#include <sys/wait.h>
+using android::base::GetBoolProperty;
using android::base::StringPrintf;
namespace android {
diff --git a/model/VolumeBase.cpp b/model/VolumeBase.cpp
index b04dd70..ffc7900 100644
--- a/model/VolumeBase.cpp
+++ b/model/VolumeBase.cpp
@@ -35,7 +35,7 @@
VolumeBase::VolumeBase(Type type)
: mType(type),
mMountFlags(0),
- mMountUserId(-1),
+ mMountUserId(USER_UNKNOWN),
mCreated(false),
mState(State::kUnmounted),
mSilent(false) {}
@@ -219,11 +219,7 @@
setState(State::kChecking);
status_t res = doMount();
- if (res == OK) {
- setState(State::kMounted);
- } else {
- setState(State::kUnmountable);
- }
+ setState(res == OK ? State::kMounted : State::kUnmountable);
return res;
}
@@ -267,5 +263,10 @@
return -ENOTSUP;
}
+std::ostream& VolumeBase::operator<<(std::ostream& stream) const {
+ return stream << " VolumeBase{id=" << mId << ",mountFlags=" << mMountFlags
+ << ",mountUserId=" << mMountUserId << "}";
+}
+
} // namespace vold
} // namespace android
diff --git a/model/VolumeBase.h b/model/VolumeBase.h
index 28802d4..53eeb6f 100644
--- a/model/VolumeBase.h
+++ b/model/VolumeBase.h
@@ -27,6 +27,8 @@
#include <list>
#include <string>
+static constexpr userid_t USER_UNKNOWN = ((userid_t)-1);
+
namespace android {
namespace vold {
@@ -97,12 +99,16 @@
std::shared_ptr<VolumeBase> findVolume(const std::string& id);
+ bool isEmulated() { return mType == Type::kEmulated; }
+
status_t create();
status_t destroy();
status_t mount();
status_t unmount();
status_t format(const std::string& fsType);
+ std::ostream& operator<<(std::ostream& stream) const;
+
protected:
explicit VolumeBase(Type type);
diff --git a/vold_prepare_subdirs.cpp b/vold_prepare_subdirs.cpp
index a7c5e3d..a620edd 100644
--- a/vold_prepare_subdirs.cpp
+++ b/vold_prepare_subdirs.cpp
@@ -134,6 +134,10 @@
if (!prepare_dir(sehandle, 0700, AID_SYSTEM, AID_SYSTEM, vendor_de_path + "/fpdata")) {
return false;
}
+ auto facedata_path = vendor_de_path + "/facedata";
+ if (!prepare_dir(sehandle, 0700, AID_SYSTEM, AID_SYSTEM, facedata_path)) {
+ return false;
+ }
}
if (flags & android::os::IVold::STORAGE_FLAG_CE) {
auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id);
@@ -149,6 +153,11 @@
system_ce_path + "/backup_stage")) {
return false;
}
+ auto vendor_ce_path = android::vold::BuildDataVendorCePath(user_id);
+ auto facedata_path = vendor_ce_path + "/facedata";
+ if (!prepare_dir(sehandle, 0700, AID_SYSTEM, AID_SYSTEM, facedata_path)) {
+ return false;
+ }
}
}
return true;