diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp index 2d55e14..f98c15d 100644 --- a/VoldNativeService.cpp +++ b/VoldNativeService.cpp @@ -16,6 +16,7 @@ #include "VoldNativeService.h" #include "VolumeManager.h" +#include "MoveTask.h" #include @@ -46,6 +47,19 @@ static binder::Status exception(uint32_t code, const std::string& msg) { return binder::Status::fromExceptionCode(code, String8(msg.c_str())); } +static binder::Status error(const std::string& msg) { + PLOG(ERROR) << msg; + return binder::Status::fromServiceSpecificError(errno, String8(msg.c_str())); +} + +static binder::Status translate(uint32_t status) { + if (status == 0) { + return binder::Status::ok(); + } else { + return binder::Status::fromExceptionCode(status); + } +} + binder::Status checkPermission(const char* permission) { pid_t pid; uid_t uid; @@ -76,6 +90,8 @@ binder::Status checkUid(uid_t expectedUid) { } \ } +#define ACQUIRE_LOCK std::lock_guard lock(VolumeManager::Instance()->getLock()); + } // namespace status_t VoldNativeService::start() { @@ -98,19 +114,169 @@ status_t VoldNativeService::dump(int fd, const Vector & /* args */) { return PERMISSION_DENIED; } + ACQUIRE_LOCK; out << "vold is happy!" << endl; out.flush(); - return NO_ERROR; } binder::Status VoldNativeService::reset() { ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + return translate(VolumeManager::Instance()->reset()); +} + +binder::Status VoldNativeService::shutdown() { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + return translate(VolumeManager::Instance()->shutdown()); +} + +binder::Status VoldNativeService::setDebug(bool debug) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + return translate(VolumeManager::Instance()->setDebug(debug)); +} + +binder::Status VoldNativeService::onUserAdded(int32_t userId, int32_t userSerial) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + return translate(VolumeManager::Instance()->onUserAdded(userId, userSerial)); +} + +binder::Status VoldNativeService::onUserRemoved(int32_t userId) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + return translate(VolumeManager::Instance()->onUserRemoved(userId)); +} + +binder::Status VoldNativeService::onUserStarted(int32_t userId) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + return translate(VolumeManager::Instance()->onUserStarted(userId)); +} + +binder::Status VoldNativeService::onUserStopped(int32_t userId) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + return translate(VolumeManager::Instance()->onUserStopped(userId)); +} + +binder::Status VoldNativeService::partition(const std::string& diskId, int32_t partitionType, int32_t ratio) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + auto disk = VolumeManager::Instance()->findDisk(diskId); + if (disk == nullptr) { + return error("Failed to find disk " + diskId); + } + switch (partitionType) { + case PARTITION_TYPE_PUBLIC: return translate(disk->partitionPublic()); + case PARTITION_TYPE_PRIVATE: return translate(disk->partitionPrivate()); + case PARTITION_TYPE_MIXED: return translate(disk->partitionMixed(ratio)); + default: return error("Unknown type " + std::to_string(partitionType)); + } +} - LOG(INFO) << "reset() via Binder!"; - VolumeManager::Instance()->reset(); +binder::Status VoldNativeService::forgetPartition(const std::string& partGuid) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + return translate(VolumeManager::Instance()->forgetPartition(partGuid)); +} + +binder::Status VoldNativeService::mount(const std::string& volId, int32_t mountFlags, int32_t mountUserId) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + auto vol = VolumeManager::Instance()->findVolume(volId); + if (vol == nullptr) { + return error("Failed to find volume " + volId); + } + + vol->setMountFlags(mountFlags); + vol->setMountUserId(mountUserId); + + int res = vol->mount(); + if (mountFlags & MOUNT_FLAG_PRIMARY) { + VolumeManager::Instance()->setPrimary(vol); + } + return translate(res); +} + +binder::Status VoldNativeService::unmount(const std::string& volId) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + auto vol = VolumeManager::Instance()->findVolume(volId); + if (vol == nullptr) { + return error("Failed to find volume " + volId); + } + return translate(vol->unmount()); +} + +binder::Status VoldNativeService::format(const std::string& volId, const std::string& fsType) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + auto vol = VolumeManager::Instance()->findVolume(volId); + if (vol == nullptr) { + return error("Failed to find volume " + volId); + } + return translate(vol->format(fsType)); +} + +binder::Status VoldNativeService::benchmark(const std::string& volId, int64_t* _aidl_return) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + *_aidl_return = VolumeManager::Instance()->benchmarkPrivate(volId); + return ok(); +} + +binder::Status VoldNativeService::moveStorage(const std::string& fromVolId, const std::string& toVolId) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + auto fromVol = VolumeManager::Instance()->findVolume(fromVolId); + auto toVol = VolumeManager::Instance()->findVolume(toVolId); + if (fromVol == nullptr) { + return error("Failed to find volume " + fromVolId); + } else if (toVol == nullptr) { + return error("Failed to find volume " + toVolId); + } + (new android::vold::MoveTask(fromVol, toVol))->start(); return ok(); } +binder::Status VoldNativeService::remountUid(int32_t uid, int32_t remountMode) { + 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)); +} + +binder::Status VoldNativeService::mkdirs(const std::string& path) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + return translate(VolumeManager::Instance()->mkdirs(path.c_str())); +} + } // namespace vold } // namespace android diff --git a/VoldNativeService.h b/VoldNativeService.h index 1866059..d3bce67 100644 --- a/VoldNativeService.h +++ b/VoldNativeService.h @@ -31,6 +31,28 @@ public: virtual status_t dump(int fd, const Vector &args) override; binder::Status reset(); + binder::Status shutdown(); + + binder::Status setDebug(bool debug); + + binder::Status onUserAdded(int32_t userId, int32_t userSerial); + binder::Status onUserRemoved(int32_t userId); + binder::Status onUserStarted(int32_t userId); + binder::Status onUserStopped(int32_t userId); + + binder::Status partition(const std::string& diskId, int32_t partitionType, int32_t ratio); + binder::Status forgetPartition(const std::string& partGuid); + + binder::Status mount(const std::string& volId, int32_t mountFlags, int32_t mountUserId); + binder::Status unmount(const std::string& volId); + binder::Status format(const std::string& volId, const std::string& fsType); + binder::Status benchmark(const std::string& volId, int64_t* _aidl_return); + + binder::Status moveStorage(const std::string& fromVolId, const std::string& toVolId); + + binder::Status remountUid(int32_t uid, int32_t remountMode); + + binder::Status mkdirs(const std::string& path); }; } // namespace vold diff --git a/VolumeManager.cpp b/VolumeManager.cpp index 13a943f..ddf06eb 100644 --- a/VolumeManager.cpp +++ b/VolumeManager.cpp @@ -1952,7 +1952,7 @@ bool VolumeManager::isMountpointMounted(const char *mp) return found_mp; } -int VolumeManager::mkdirs(char* path) { +int VolumeManager::mkdirs(const char* path) { // Only offer to create directories for paths managed by vold if (strncmp(path, "/storage/", 9) == 0) { // fs_mkdirs() does symlink checking and relative path enforcement diff --git a/VolumeManager.h b/VolumeManager.h index 537aebe..72c470a 100644 --- a/VolumeManager.h +++ b/VolumeManager.h @@ -196,7 +196,7 @@ public: * is treated as filename and ignored, unless the path ends with "/". Also * ensures that path belongs to a volume managed by vold. */ - int mkdirs(char* path); + int mkdirs(const char* path); private: VolumeManager(); diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl index 5f7a3fe..43d88bc 100644 --- a/binder/android/os/IVold.aidl +++ b/binder/android/os/IVold.aidl @@ -19,4 +19,54 @@ package android.os; /** {@hide} */ interface IVold { void reset(); + void shutdown(); + + void setDebug(boolean debug); + + void onUserAdded(int userId, int userSerial); + void onUserRemoved(int userId); + void onUserStarted(int userId); + void onUserStopped(int userId); + + void partition(@utf8InCpp String diskId, int partitionType, int ratio); + void forgetPartition(@utf8InCpp String partGuid); + + void mount(@utf8InCpp String volId, int mountFlags, int mountUserId); + void unmount(@utf8InCpp String volId); + void format(@utf8InCpp String volId, @utf8InCpp String fsType); + long benchmark(@utf8InCpp String volId); + + void moveStorage(@utf8InCpp String fromVolId, @utf8InCpp String toVolId); + + void remountUid(int uid, int remountMode); + + void mkdirs(@utf8InCpp String path); + + const int MOUNT_FLAG_PRIMARY = 1; + const int MOUNT_FLAG_VISIBLE = 2; + + const int PARTITION_TYPE_PUBLIC = 0; + const int PARTITION_TYPE_PRIVATE = 1; + const int PARTITION_TYPE_MIXED = 2; + + const int REMOUNT_MODE_NONE = 0; + const int REMOUNT_MODE_DEFAULT = 1; + const int REMOUNT_MODE_READ = 2; + const int REMOUNT_MODE_WRITE = 3; + + const int STATE_UNMOUNTED = 0; + const int STATE_CHECKING = 1; + const int STATE_MOUNTED = 2; + const int STATE_MOUNTED_READ_ONLY = 3; + const int STATE_FORMATTING = 4; + const int STATE_EJECTING = 5; + const int STATE_UNMOUNTABLE = 6; + const int STATE_REMOVED = 7; + const int STATE_BAD_REMOVAL = 8; + + const int TYPE_PUBLIC = 0; + const int TYPE_PRIVATE = 1; + const int TYPE_EMULATED = 2; + const int TYPE_ASEC = 3; + const int TYPE_OBB = 4; }