Add disk for StubVolume

StubVolume is a volume type for ARC++ external storage. Named StubVolume
because it is managed from outside Android (not through Android kernel).

Previously, StubVolume is a diskless volume. However, as mentioned in
jsharkey@ email, a disk is needed for StubVolume to hold "kInternal"
(external storage type that is "external" from Android perspective,
but is "internal" to the device. For example shared directory from
ChromeOS to Android) and "kIndexable" (whether or not a disk should be
indexed by MediaStore).

The addition of disk means we could expose the createStubVolume API to
add a disk flags, which is also introduced in this CL.

Both kInternal and kIndexable will be introduced in separate CL.

Bug: 132796154
Test: Mount/unmount ARC++ removable device in ChromeOS.
Change-Id: I8b77fa1cf50ab38a2892272154dafdb78f079378
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 4427c9b..7be5e4f 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();
     }
@@ -941,27 +932,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;
 }