Move "volume" commands over to Binder.

Keep the old socket-based commands intact for awhile so we can
rapidly disable this change using the ENABLE_BINDER feature flag.

Define constants in AIDL to keep Java and C++ in sync.

Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.ExternalStorageHostTest
Test: cts-tradefed run commandAndExit cts-dev --abi armeabi-v7a -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.AdoptableHostTest
Bug: 13758960
Change-Id: I0d6f82cbebe67f671b60949fd727409aeb1fdc0d
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 <fstream>
 
@@ -46,6 +47,19 @@
     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 @@
     }                                                       \
 }
 
+#define ACQUIRE_LOCK std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock());
+
 }  // namespace
 
 status_t VoldNativeService::start() {
@@ -98,19 +114,169 @@
         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;
 
-    LOG(INFO) << "reset() via Binder!";
-    VolumeManager::Instance()->reset();
+    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));
+    }
+}
+
+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 @@
     virtual status_t dump(int fd, const Vector<String16> &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 @@
     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 @@
      * 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 @@
 /** {@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;
 }