vold: Support internal storage partitions

 * Support nonremovable disks and expose a nonremovable flag in the
   DiskCreated message.
 * New DiskPartition class to hold single partitions.  DiskPartition is
   used when the fs_mgr entry has a partnum (eg. when fs_mgr_flags
   contains voldmanaged=label:#).  Override disk partitioning methods
   to prevent destroying the emmc.

Change-Id: Id7ec3ea409b5c96e691730604e4b1e9cc3aa9d33

vold: Correct base header paths

These headers were moved to android-base

Change-Id: I3eaa8316006b9017c5f5e31cd1e91efc2862106d

DiskPartition.cpp: Add sysmacros.h dependency for major/minor

Change-Id: I22c267c8f12b40fb3e2295becd88f12b75907b69
Signed-off-by: Adrian DC <radian.dc@gmail.com>

[mikeioannina] Adapt for Pie and Q

Change-Id: Id7ec3ea409b5c96e691730604e4b1e9cc3aa9d33
diff --git a/Android.bp b/Android.bp
index 6142d74..f3c2557 100644
--- a/Android.bp
+++ b/Android.bp
@@ -128,6 +128,7 @@
         "fs/Ntfs.cpp",
         "fs/Vfat.cpp",
         "model/Disk.cpp",
+        "model/DiskPartition.cpp",
         "model/EmulatedVolume.cpp",
         "model/ObbVolume.cpp",
         "model/PrivateVolume.cpp",
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 2974949..b998166 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -229,8 +229,12 @@
                         flags |= android::vold::Disk::Flags::kUsb;
                     }
 
-                    auto disk =
-                        new android::vold::Disk(eventPath, device, source->getNickname(), flags);
+                    android::vold::Disk* disk = (source->getPartNum() == -1) ?
+                            new android::vold::Disk(eventPath, device,
+                                    source->getNickname(), flags) :
+                            new android::vold::DiskPartition(eventPath, device,
+                                    source->getNickname(), flags,
+                                    source->getPartNum());
                     handleDiskAdded(std::shared_ptr<android::vold::Disk>(disk));
                     break;
                 }
diff --git a/VolumeManager.h b/VolumeManager.h
index 9bf7599..a7fb5eb 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -36,6 +36,7 @@
 #include "android/os/IVoldListener.h"
 
 #include "model/Disk.h"
+#include "model/DiskPartition.h"
 #include "model/VolumeBase.h"
 
 class VolumeManager {
@@ -61,19 +62,21 @@
 
     class DiskSource {
       public:
-        DiskSource(const std::string& sysPattern, const std::string& nickname, int flags)
-            : mSysPattern(sysPattern), mNickname(nickname), mFlags(flags) {}
+        DiskSource(const std::string& sysPattern, const std::string& nickname, int partnum, int flags)
+            : mSysPattern(sysPattern), mNickname(nickname), mPartNum(partnum), mFlags(flags) {}
 
         bool matches(const std::string& sysPath) {
             return !fnmatch(mSysPattern.c_str(), sysPath.c_str(), 0);
         }
 
         const std::string& getNickname() const { return mNickname; }
+        int getPartNum() const { return mPartNum; }
         int getFlags() const { return mFlags; }
 
       private:
         std::string mSysPattern;
         std::string mNickname;
+        int mPartNum;
         int mFlags;
     };
 
diff --git a/main.cpp b/main.cpp
index 363febe..e6e543a 100644
--- a/main.cpp
+++ b/main.cpp
@@ -242,13 +242,9 @@
         }
 
         if (entry.fs_mgr_flags.vold_managed) {
-            if (entry.fs_mgr_flags.nonremovable) {
-                LOG(WARNING) << "nonremovable no longer supported; ignoring volume";
-                continue;
-            }
-
             std::string sysPattern(entry.blk_device);
             std::string nickname(entry.label);
+            int partnum = entry.partnum;
             int flags = 0;
 
             if (entry.is_encryptable()) {
@@ -259,9 +255,12 @@
                 android::base::GetBoolProperty("vold.debug.default_primary", false)) {
                 flags |= android::vold::Disk::Flags::kDefaultPrimary;
             }
+            if (entry.fs_mgr_flags.nonremovable) {
+                flags |= android::vold::Disk::Flags::kNonRemovable;
+            }
 
             vm->addDiskSource(std::shared_ptr<VolumeManager::DiskSource>(
-                new VolumeManager::DiskSource(sysPattern, nickname, flags)));
+                new VolumeManager::DiskSource(sysPattern, nickname, partnum, flags)));
         }
     }
     return 0;
diff --git a/model/Disk.h b/model/Disk.h
index 13168e5..01c7a69 100644
--- a/model/Disk.h
+++ b/model/Disk.h
@@ -54,6 +54,8 @@
         kEmmc = 1 << 4,
         /* Flag that disk is UFS Card */
         kUfsCard = 1 << 5,
+        /* Flag that disk is non-removable */
+        kNonRemovable = 1 << 6,
     };
 
     const std::string& getId() const { return mId; }
@@ -69,19 +71,19 @@
 
     void listVolumes(VolumeBase::Type type, std::list<std::string>& list) const;
 
-    status_t create();
-    status_t destroy();
+    virtual status_t create();
+    virtual status_t destroy();
 
-    status_t readMetadata();
-    status_t readPartitions();
+    virtual status_t readMetadata();
+    virtual status_t readPartitions();
 
     status_t unmountAll();
 
-    status_t partitionPublic();
-    status_t partitionPrivate();
-    status_t partitionMixed(int8_t ratio);
+    virtual status_t partitionPublic();
+    virtual status_t partitionPrivate();
+    virtual status_t partitionMixed(int8_t ratio);
 
-  private:
+  protected:
     /* ID that uniquely references this disk */
     std::string mId;
     /* Original event path */
diff --git a/model/DiskPartition.cpp b/model/DiskPartition.cpp
new file mode 100644
index 0000000..1cbcfbb
--- /dev/null
+++ b/model/DiskPartition.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2015 Cyanogen, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DiskPartition.h"
+#include "PublicVolume.h"
+#include "PrivateVolume.h"
+#include "Utils.h"
+#include "VolumeBase.h"
+#include "VolumeManager.h"
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/logging.h>
+#include <diskconfig/diskconfig.h>
+
+#include <vector>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+
+using android::base::ReadFileToString;
+using android::base::WriteStringToFile;
+using android::base::StringPrintf;
+
+namespace android {
+namespace vold {
+
+DiskPartition::DiskPartition(const std::string& eventPath, dev_t device,
+            const std::string& nickname, int flags, int partnum) :
+        Disk(eventPath, device, nickname, flags),
+        mPartNum(partnum) {
+    // Empty
+}
+
+DiskPartition::~DiskPartition() {
+    // Empty
+}
+
+status_t DiskPartition::create() {
+    CHECK(!mCreated);
+    mCreated = true;
+    auto listener = VolumeManager::Instance()->getListener();
+    if (listener) listener->onDiskCreated(getId(), mFlags);
+    dev_t partDevice = makedev(major(mDevice), minor(mDevice) + mPartNum);
+    createPublicVolume(partDevice);
+    return OK;
+}
+
+status_t DiskPartition::destroy() {
+    CHECK(mCreated);
+    destroyAllVolumes();
+    mCreated = false;
+    auto listener = VolumeManager::Instance()->getListener();
+    if (listener) listener->onDiskDestroyed(getId());
+    return OK;
+}
+
+status_t DiskPartition::partitionPublic() {
+    return -1;
+}
+
+status_t DiskPartition::partitionPrivate() {
+    return -1;
+}
+
+status_t DiskPartition::partitionMixed(int8_t ratio) {
+    return -1;
+}
+
+}  // namespace vold
+}  // namespace android
+
diff --git a/model/DiskPartition.h b/model/DiskPartition.h
new file mode 100644
index 0000000..274d6be
--- /dev/null
+++ b/model/DiskPartition.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 Cyanogen, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VOLD_DISKPARTITION_H
+#define ANDROID_VOLD_DISKPARTITION_H
+
+#include "Disk.h"
+
+namespace android {
+namespace vold {
+
+/*
+ * Representation of a single partition on physical media.  Useful for
+ * single media partitions such as "internal" sdcard partitions.
+ */
+
+class DiskPartition : public Disk {
+public:
+    DiskPartition(const std::string& eventPath, dev_t device,
+            const std::string& nickname,
+            int flags, int partnum);
+    virtual ~DiskPartition();
+
+    virtual status_t create();
+    virtual status_t destroy();
+
+    virtual status_t partitionPublic();
+    virtual status_t partitionPrivate();
+    virtual status_t partitionMixed(int8_t ratio);
+
+private:
+    /* Partition number */
+    int mPartNum;
+};
+
+}  // namespace vold
+}  // namespace android
+
+#endif
+