Merge "Add disk for StubVolume"
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index dbe1d98..6aa9670 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -486,9 +486,12 @@
     return translate(VolumeManager::Instance()->destroyObb(volId));
 }
 
-binder::Status VoldNativeService::createStubVolume(
-    const std::string& sourcePath, const std::string& mountPath, const std::string& fsType,
-    const std::string& fsUuid, const std::string& fsLabel, std::string* _aidl_return) {
+binder::Status VoldNativeService::createStubVolume(const std::string& sourcePath,
+                                                   const std::string& mountPath,
+                                                   const std::string& fsType,
+                                                   const std::string& fsUuid,
+                                                   const std::string& fsLabel, int32_t flags,
+                                                   std::string* _aidl_return) {
     ENFORCE_SYSTEM_OR_ROOT;
     CHECK_ARGUMENT_PATH(sourcePath);
     CHECK_ARGUMENT_PATH(mountPath);
@@ -497,8 +500,8 @@
     // is quite meaningless.
     ACQUIRE_LOCK;
 
-    return translate(VolumeManager::Instance()->createStubVolume(sourcePath, mountPath, fsType,
-                                                                 fsUuid, fsLabel, _aidl_return));
+    return translate(VolumeManager::Instance()->createStubVolume(
+            sourcePath, mountPath, fsType, fsUuid, fsLabel, flags, _aidl_return));
 }
 
 binder::Status VoldNativeService::destroyStubVolume(const std::string& volId) {
diff --git a/VoldNativeService.h b/VoldNativeService.h
index 36b2717..6d00d2d 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -73,7 +73,8 @@
 
     binder::Status createStubVolume(const std::string& sourcePath, const std::string& mountPath,
                                     const std::string& fsType, const std::string& fsUuid,
-                                    const std::string& fsLabel, std::string* _aidl_return);
+                                    const std::string& fsLabel, int32_t flags,
+                                    std::string* _aidl_return);
     binder::Status destroyStubVolume(const std::string& volId);
 
     binder::Status fstrim(int32_t fstrimFlags,
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 9eb7852..0c81cb7 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -114,7 +114,7 @@
 VolumeManager::VolumeManager() {
     mDebug = false;
     mNextObbId = 0;
-    mNextStubVolumeId = 0;
+    mNextStubId = 0;
     // For security reasons, assume that a secure keyguard is
     // showing until we hear otherwise
     mSecureKeyguardShowing = true;
@@ -340,11 +340,6 @@
             return vol;
         }
     }
-    for (const auto& vol : mStubVolumes) {
-        if (vol->getId() == id) {
-            return vol;
-        }
-    }
     for (const auto& vol : mObbVolumes) {
         if (vol->getId() == id) {
             return vol;
@@ -767,7 +762,6 @@
     }
 
     mInternalEmulatedVolumes.clear();
-    mStubVolumes.clear();
     mDisks.clear();
     mPendingDisks.clear();
     android::vold::sSleepOnUnmount = true;
@@ -782,9 +776,6 @@
     for (const auto& vol : mInternalEmulatedVolumes) {
         vol->unmount();
     }
-    for (const auto& stub : mStubVolumes) {
-        stub->unmount();
-    }
     for (const auto& disk : mDisks) {
         disk->unmountAll();
     }
@@ -908,27 +899,30 @@
 
 int VolumeManager::createStubVolume(const std::string& sourcePath, const std::string& mountPath,
                                     const std::string& fsType, const std::string& fsUuid,
-                                    const std::string& fsLabel, std::string* outVolId) {
-    int id = mNextStubVolumeId++;
-    auto vol = std::shared_ptr<android::vold::VolumeBase>(
-        new android::vold::StubVolume(id, sourcePath, mountPath, fsType, fsUuid, fsLabel));
-    vol->create();
+                                    const std::string& fsLabel, int32_t flags __unused,
+                                    std::string* outVolId) {
+    dev_t stubId = --mNextStubId;
+    auto vol = std::shared_ptr<android::vold::StubVolume>(
+            new android::vold::StubVolume(stubId, sourcePath, mountPath, fsType, fsUuid, fsLabel));
 
-    mStubVolumes.push_back(vol);
+    // TODO (b/132796154): Passed each supported flags explicitly here.
+    // StubDisk doesn't have device node corresponds to it. So, a fake device
+    // number is used. The supported flags will be infered from the
+    // currently-unused flags parameter.
+    auto disk = std::shared_ptr<android::vold::Disk>(
+            new android::vold::Disk("stub", stubId, "stub", android::vold::Disk::Flags::kStub));
+    disk->initializePartition(vol);
+    handleDiskAdded(disk);
     *outVolId = vol->getId();
     return android::OK;
 }
 
 int VolumeManager::destroyStubVolume(const std::string& volId) {
-    auto i = mStubVolumes.begin();
-    while (i != mStubVolumes.end()) {
-        if ((*i)->getId() == volId) {
-            (*i)->destroy();
-            i = mStubVolumes.erase(i);
-        } else {
-            ++i;
-        }
-    }
+    auto tokens = android::base::Split(volId, ":");
+    CHECK(tokens.size() == 2);
+    dev_t stubId;
+    CHECK(android::base::ParseUint(tokens[1], &stubId));
+    handleDiskRemoved(stubId);
     return android::OK;
 }
 
diff --git a/VolumeManager.h b/VolumeManager.h
index 5a2a481..765349d 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -170,7 +170,7 @@
 
     int createStubVolume(const std::string& sourcePath, const std::string& mountPath,
                          const std::string& fsType, const std::string& fsUuid,
-                         const std::string& fsLabel, std::string* outVolId);
+                         const std::string& fsLabel, int32_t flags, std::string* outVolId);
     int destroyStubVolume(const std::string& volId);
 
     int mountAppFuse(uid_t uid, int mountId, android::base::unique_fd* device_fd);
@@ -199,7 +199,6 @@
     std::list<std::shared_ptr<android::vold::Disk>> mDisks;
     std::list<std::shared_ptr<android::vold::Disk>> mPendingDisks;
     std::list<std::shared_ptr<android::vold::VolumeBase>> mObbVolumes;
-    std::list<std::shared_ptr<android::vold::VolumeBase>> mStubVolumes;
     std::list<std::shared_ptr<android::vold::VolumeBase>> mInternalEmulatedVolumes;
 
     std::unordered_map<userid_t, int> mAddedUsers;
@@ -212,7 +211,7 @@
     std::shared_ptr<android::vold::VolumeBase> mPrimary;
 
     int mNextObbId;
-    int mNextStubVolumeId;
+    int mNextStubId;
     bool mSecureKeyguardShowing;
 };
 
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 29a63af..78598b3 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -125,7 +125,7 @@
 
     @utf8InCpp String createStubVolume(@utf8InCpp String sourcePath,
             @utf8InCpp String mountPath, @utf8InCpp String fsType,
-            @utf8InCpp String fsUuid, @utf8InCpp String fsLabel);
+            @utf8InCpp String fsUuid, @utf8InCpp String fsLabel, int flags);
     void destroyStubVolume(@utf8InCpp String volId);
 
     FileDescriptor openAppFuseFile(int uid, int mountId, int fileId, int flags);
diff --git a/model/Disk.cpp b/model/Disk.cpp
index 3f3a84d..7ecc89e 100644
--- a/model/Disk.cpp
+++ b/model/Disk.cpp
@@ -180,6 +180,10 @@
     auto listener = VolumeManager::Instance()->getListener();
     if (listener) listener->onDiskCreated(getId(), mFlags);
 
+    if (isStub()) {
+        createStubVolume();
+        return OK;
+    }
     readMetadata();
     readPartitions();
     return OK;
@@ -244,6 +248,15 @@
     vol->create();
 }
 
+void Disk::createStubVolume() {
+    CHECK(mVolumes.size() == 1);
+    auto listener = VolumeManager::Instance()->getListener();
+    if (listener) listener->onDiskMetadataChanged(getId(), mSize, mLabel, mSysPath);
+    if (listener) listener->onDiskScanned(getId());
+    mVolumes[0]->setDiskId(getId());
+    mVolumes[0]->create();
+}
+
 void Disk::destroyAllVolumes() {
     for (const auto& vol : mVolumes) {
         vol->destroy();
@@ -444,6 +457,12 @@
     return OK;
 }
 
+void Disk::initializePartition(std::shared_ptr<StubVolume> vol) {
+    CHECK(isStub());
+    CHECK(mVolumes.empty());
+    mVolumes.push_back(vol);
+}
+
 status_t Disk::unmountAll() {
     for (const auto& vol : mVolumes) {
         vol->unmount();
diff --git a/model/Disk.h b/model/Disk.h
index d82d141..99c98fc 100644
--- a/model/Disk.h
+++ b/model/Disk.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_VOLD_DISK_H
 #define ANDROID_VOLD_DISK_H
 
+#include "StubVolume.h"
 #include "Utils.h"
 #include "VolumeBase.h"
 
@@ -52,6 +53,9 @@
         kUsb = 1 << 3,
         /* Flag that disk is EMMC internal */
         kEmmc = 1 << 4,
+        /* Flag that disk is Stub disk, i.e., disk that is managed from outside
+         * Android (e.g., ARC++). */
+        kStub = 1 << 5,
     };
 
     const std::string& getId() const { return mId; }
@@ -74,6 +78,7 @@
 
     status_t readMetadata();
     status_t readPartitions();
+    void initializePartition(std::shared_ptr<StubVolume> vol);
 
     status_t unmountAll();
 
@@ -109,11 +114,14 @@
 
     void createPublicVolume(dev_t device);
     void createPrivateVolume(dev_t device, const std::string& partGuid);
+    void createStubVolume();
 
     void destroyAllVolumes();
 
     int getMaxMinors();
 
+    bool isStub() { return mFlags & kStub; }
+
     DISALLOW_COPY_AND_ASSIGN(Disk);
 };
 
diff --git a/model/StubVolume.cpp b/model/StubVolume.cpp
index edd0861..d2cd8a8 100644
--- a/model/StubVolume.cpp
+++ b/model/StubVolume.cpp
@@ -16,6 +16,8 @@
 
 #include "StubVolume.h"
 
+#include <inttypes.h>
+
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 
@@ -24,7 +26,7 @@
 namespace android {
 namespace vold {
 
-StubVolume::StubVolume(int id, const std::string& sourcePath, const std::string& mountPath,
+StubVolume::StubVolume(dev_t id, const std::string& sourcePath, const std::string& mountPath,
                        const std::string& fsType, const std::string& fsUuid,
                        const std::string& fsLabel)
     : VolumeBase(Type::kStub),
@@ -33,7 +35,7 @@
       mFsType(fsType),
       mFsUuid(fsUuid),
       mFsLabel(fsLabel) {
-    setId(StringPrintf("stub:%d", id));
+    setId(StringPrintf("stub:%llu", (unsigned long long)id));
 }
 
 StubVolume::~StubVolume() {}
diff --git a/model/StubVolume.h b/model/StubVolume.h
index 538cae9..3697b53 100644
--- a/model/StubVolume.h
+++ b/model/StubVolume.h
@@ -31,7 +31,7 @@
  */
 class StubVolume : public VolumeBase {
   public:
-    StubVolume(int id, const std::string& sourcePath, const std::string& mountPath,
+    StubVolume(dev_t id, const std::string& sourcePath, const std::string& mountPath,
                const std::string& fsType, const std::string& fsUuid, const std::string& fsLabel);
     virtual ~StubVolume();