Port the current code to new IncFS

Bug: 146080380
Test: manual, "cmd incremental install-start"

Change-Id: I6761c3f0e58b6d4de1ae3c4b31c23204fba9f740
diff --git a/services/incremental/Android.bp b/services/incremental/Android.bp
index ddf4dd5..323e7f1 100644
--- a/services/incremental/Android.bp
+++ b/services/incremental/Android.bp
@@ -47,6 +47,8 @@
     shared_libs: [
         "libandroidfw",
         "libbinder",
+        "libcrypto",
+        "libcutils",
         "libincfs",
         "liblog",
         "libz",
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
index bb26c1f..f1b637f 100644
--- a/services/incremental/BinderIncrementalService.cpp
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -46,10 +46,10 @@
     return incfs::enabled();
 }
 
-static bool incFsVersionValid(const sp<IVold>& vold) {
-    int version = -1;
-    auto status = vold->incFsVersion(&version);
-    if (!status.isOk() || version <= 0) {
+static bool incFsValid(const sp<IVold>& vold) {
+    bool enabled = false;
+    auto status = vold->incFsEnabled(&enabled);
+    if (!status.isOk() || !enabled) {
         return false;
     }
     return true;
@@ -74,7 +74,7 @@
         return nullptr;
     }
     sp<IVold> vold = interface_cast<IVold>(voldBinder);
-    if (!incFsVersionValid(vold)) {
+    if (!incFsValid(vold)) {
         return nullptr;
     }
 
@@ -86,6 +86,7 @@
     sp<ProcessState> ps(ProcessState::self());
     ps->startThreadPool();
     ps->giveThreadPoolName();
+    // sm->addService increments the reference count, and now we're OK with returning the pointer.
     return self.get();
 }
 
@@ -107,9 +108,9 @@
     return ok();
 }
 
-binder::Status BinderIncrementalService::createStorage(
-        const std::string& path, const DataLoaderParamsParcel& params,
-        int32_t createMode, int32_t* _aidl_return) {
+binder::Status BinderIncrementalService::createStorage(const std::string& path,
+                                                       const DataLoaderParamsParcel& params,
+                                                       int32_t createMode, int32_t* _aidl_return) {
     *_aidl_return =
             mImpl.createStorage(path, const_cast<DataLoaderParamsParcel&&>(params),
                                 android::incremental::IncrementalService::CreateOptions(
@@ -129,10 +130,10 @@
 }
 
 binder::Status BinderIncrementalService::makeBindMount(int32_t storageId,
-                                                       const std::string& pathUnderStorage,
+                                                       const std::string& sourcePath,
                                                        const std::string& targetFullPath,
                                                        int32_t bindType, int32_t* _aidl_return) {
-    *_aidl_return = mImpl.bind(storageId, pathUnderStorage, targetFullPath,
+    *_aidl_return = mImpl.bind(storageId, sourcePath, targetFullPath,
                                android::incremental::IncrementalService::BindKind(bindType));
     return ok();
 }
@@ -149,75 +150,127 @@
     return ok();
 }
 
-binder::Status BinderIncrementalService::makeDirectory(int32_t storageId,
-                                                       const std::string& pathUnderStorage,
+binder::Status BinderIncrementalService::makeDirectory(int32_t storageId, const std::string& path,
                                                        int32_t* _aidl_return) {
-    auto inode = mImpl.makeDir(storageId, pathUnderStorage);
-    *_aidl_return = inode < 0 ? inode : 0;
+    *_aidl_return = mImpl.makeDir(storageId, path);
     return ok();
 }
 
-binder::Status BinderIncrementalService::makeDirectories(int32_t storageId,
-                                                         const std::string& pathUnderStorage,
-                                                         int32_t* _aidl_return) {
-    auto inode = mImpl.makeDirs(storageId, pathUnderStorage);
-    *_aidl_return = inode < 0 ? inode : 0;
-    return ok();
+static std::tuple<int, incfs::FileId, incfs::NewFileParams> toMakeFileParams(
+        const android::os::incremental::IncrementalNewFileParams& params) {
+    incfs::FileId id;
+    if (params.fileId.empty()) {
+        if (params.metadata.empty()) {
+            return {EINVAL, {}, {}};
+        }
+        id = IncrementalService::idFromMetadata(params.metadata);
+    } else if (params.fileId.size() != sizeof(id)) {
+        return {EINVAL, {}, {}};
+    } else {
+        memcpy(&id, params.fileId.data(), sizeof(id));
+    }
+    incfs::NewFileParams nfp;
+    nfp.size = params.size;
+    nfp.metadata = {(const char*)params.metadata.data(), (IncFsSize)params.metadata.size()};
+    if (!params.signature) {
+        nfp.verification = {};
+    } else {
+        nfp.verification.hashAlgorithm = IncFsHashAlgortithm(params.signature->hashAlgorithm);
+        nfp.verification.rootHash = {(const char*)params.signature->rootHash.data(),
+                                     (IncFsSize)params.signature->rootHash.size()};
+        nfp.verification.additionalData = {(const char*)params.signature->additionalData.data(),
+                                           (IncFsSize)params.signature->additionalData.size()};
+        nfp.verification.signature = {(const char*)params.signature->signature.data(),
+                                      (IncFsSize)params.signature->signature.size()};
+    }
+    return {0, id, nfp};
 }
 
-binder::Status BinderIncrementalService::makeFile(int32_t storageId,
-                                                  const std::string& pathUnderStorage, int64_t size,
-                                                  const std::vector<uint8_t>& metadata,
-                                                  int32_t* _aidl_return) {
-    auto inode = mImpl.makeFile(storageId, pathUnderStorage, size,
-                                {(const char*)metadata.data(), metadata.size()}, {});
-    *_aidl_return = inode < 0 ? inode : 0;
+binder::Status BinderIncrementalService::makeFile(
+        int32_t storageId, const std::string& path,
+        const ::android::os::incremental::IncrementalNewFileParams& params, int32_t* _aidl_return) {
+    auto [err, fileId, nfp] = toMakeFileParams(params);
+    if (err) {
+        *_aidl_return = err;
+        return ok();
+    }
+
+    *_aidl_return = mImpl.makeFile(storageId, path, 0555, fileId, nfp);
     return ok();
 }
-binder::Status BinderIncrementalService::makeFileFromRange(
-        int32_t storageId, const std::string& pathUnderStorage,
-        const std::string& sourcePathUnderStorage, int64_t start, int64_t end,
-        int32_t* _aidl_return) {
-    // TODO(b/136132412): implement this
-    *_aidl_return = -1;
-    return ok();
-}
-binder::Status BinderIncrementalService::makeLink(int32_t sourceStorageId,
-                                                  const std::string& relativeSourcePath,
-                                                  int32_t destStorageId,
-                                                  const std::string& relativeDestPath,
-                                                  int32_t* _aidl_return) {
-    auto sourceInode = mImpl.nodeFor(sourceStorageId, relativeSourcePath);
-    auto [targetParentInode, name] = mImpl.parentAndNameFor(destStorageId, relativeDestPath);
-    *_aidl_return = mImpl.link(sourceStorageId, sourceInode, targetParentInode, name);
-    return ok();
-}
-binder::Status BinderIncrementalService::unlink(int32_t storageId,
-                                                const std::string& pathUnderStorage,
-                                                int32_t* _aidl_return) {
-    auto [parentNode, name] = mImpl.parentAndNameFor(storageId, pathUnderStorage);
-    *_aidl_return = mImpl.unlink(storageId, parentNode, name);
-    return ok();
-}
-binder::Status BinderIncrementalService::isFileRangeLoaded(int32_t storageId,
-                                                           const std::string& relativePath,
+binder::Status BinderIncrementalService::makeFileFromRange(int32_t storageId,
+                                                           const std::string& targetPath,
+                                                           const std::string& sourcePath,
                                                            int64_t start, int64_t end,
-                                                           bool* _aidl_return) {
+                                                           int32_t* _aidl_return) {
+    // TODO(b/136132412): implement this
+    *_aidl_return = ENOSYS; // not implemented
+    return ok();
+}
+
+binder::Status BinderIncrementalService::makeLink(int32_t sourceStorageId,
+                                                  const std::string& sourcePath,
+                                                  int32_t destStorageId,
+                                                  const std::string& destPath,
+                                                  int32_t* _aidl_return) {
+    *_aidl_return = mImpl.link(sourceStorageId, sourcePath, destStorageId, destPath);
+    return ok();
+}
+
+binder::Status BinderIncrementalService::unlink(int32_t storageId, const std::string& path,
+                                                int32_t* _aidl_return) {
+    *_aidl_return = mImpl.unlink(storageId, path);
+    return ok();
+}
+
+binder::Status BinderIncrementalService::isFileRangeLoaded(int32_t storageId,
+                                                           const std::string& path, int64_t start,
+                                                           int64_t end, bool* _aidl_return) {
+    // TODO: implement
     *_aidl_return = false;
     return ok();
 }
-binder::Status BinderIncrementalService::getFileMetadata(int32_t storageId,
-                                                         const std::string& relativePath,
+
+binder::Status BinderIncrementalService::getMetadataByPath(int32_t storageId,
+                                                           const std::string& path,
+                                                           std::vector<uint8_t>* _aidl_return) {
+    auto fid = mImpl.nodeFor(storageId, path);
+    if (fid != kIncFsInvalidFileId) {
+        auto metadata = mImpl.getMetadata(storageId, fid);
+        _aidl_return->assign(metadata.begin(), metadata.end());
+    }
+    return ok();
+}
+
+static FileId toFileId(const std::vector<uint8_t>& id) {
+    FileId fid;
+    memcpy(&fid, id.data(), id.size());
+    return fid;
+}
+
+binder::Status BinderIncrementalService::getMetadataById(int32_t storageId,
+                                                         const std::vector<uint8_t>& id,
                                                          std::vector<uint8_t>* _aidl_return) {
-    auto inode = mImpl.nodeFor(storageId, relativePath);
-    auto metadata = mImpl.getMetadata(storageId, inode);
+    if (id.size() != sizeof(incfs::FileId)) {
+        return ok();
+    }
+    auto fid = toFileId(id);
+    auto metadata = mImpl.getMetadata(storageId, fid);
     _aidl_return->assign(metadata.begin(), metadata.end());
     return ok();
 }
+
+binder::Status BinderIncrementalService::makeDirectories(int32_t storageId, const std::string& path,
+                                                         int32_t* _aidl_return) {
+    *_aidl_return = mImpl.makeDirs(storageId, path);
+    return ok();
+}
+
 binder::Status BinderIncrementalService::startLoading(int32_t storageId, bool* _aidl_return) {
     *_aidl_return = mImpl.startLoading(storageId);
     return ok();
 }
+
 } // namespace android::os::incremental
 
 jlong Incremental_IncrementalService_Start() {
diff --git a/services/incremental/BinderIncrementalService.h b/services/incremental/BinderIncrementalService.h
index 37c9661d..a94a75a 100644
--- a/services/incremental/BinderIncrementalService.h
+++ b/services/incremental/BinderIncrementalService.h
@@ -37,38 +37,39 @@
     void onSystemReady();
     void onInvalidStorage(int mountId);
 
-    binder::Status openStorage(const std::string &path, int32_t *_aidl_return) final;
-    binder::Status createStorage(
-            const std::string &path,
-            const ::android::content::pm::DataLoaderParamsParcel &params,
-            int32_t createMode, int32_t *_aidl_return) final;
-    binder::Status createLinkedStorage(const std::string &path, int32_t otherStorageId,
-                                       int32_t createMode, int32_t *_aidl_return) final;
-    binder::Status makeBindMount(int32_t storageId, const std::string &pathUnderStorage,
-                                 const std::string &targetFullPath, int32_t bindType,
-                                 int32_t *_aidl_return) final;
-    binder::Status deleteBindMount(int32_t storageId, const std::string &targetFullPath,
-                                   int32_t *_aidl_return) final;
+    binder::Status openStorage(const std::string& path, int32_t* _aidl_return) final;
+    binder::Status createStorage(const std::string& path,
+                                 const ::android::content::pm::DataLoaderParamsParcel& params,
+                                 int32_t createMode, int32_t* _aidl_return) final;
+    binder::Status createLinkedStorage(const std::string& path, int32_t otherStorageId,
+                                       int32_t createMode, int32_t* _aidl_return) final;
+    binder::Status makeBindMount(int32_t storageId, const std::string& sourcePath,
+                                 const std::string& targetFullPath, int32_t bindType,
+                                 int32_t* _aidl_return) final;
+    binder::Status deleteBindMount(int32_t storageId, const std::string& targetFullPath,
+                                   int32_t* _aidl_return) final;
+    binder::Status makeDirectory(int32_t storageId, const std::string& path,
+                                 int32_t* _aidl_return) final;
+    binder::Status makeDirectories(int32_t storageId, const std::string& path,
+                                   int32_t* _aidl_return) final;
+    binder::Status makeFile(int32_t storageId, const std::string& path,
+                            const ::android::os::incremental::IncrementalNewFileParams& params,
+                            int32_t* _aidl_return) final;
+    binder::Status makeFileFromRange(int32_t storageId, const std::string& targetPath,
+                                     const std::string& sourcePath, int64_t start, int64_t end,
+                                     int32_t* _aidl_return) final;
+    binder::Status makeLink(int32_t sourceStorageId, const std::string& sourcePath,
+                            int32_t destStorageId, const std::string& destPath,
+                            int32_t* _aidl_return) final;
+    binder::Status unlink(int32_t storageId, const std::string& path, int32_t* _aidl_return) final;
+    binder::Status isFileRangeLoaded(int32_t storageId, const std::string& path, int64_t start,
+                                     int64_t end, bool* _aidl_return) final;
+    binder::Status getMetadataByPath(int32_t storageId, const std::string& path,
+                                     std::vector<uint8_t>* _aidl_return) final;
+    binder::Status getMetadataById(int32_t storageId, const std::vector<uint8_t>& id,
+                                   std::vector<uint8_t>* _aidl_return) final;
+    binder::Status startLoading(int32_t storageId, bool* _aidl_return) final;
     binder::Status deleteStorage(int32_t storageId) final;
-    binder::Status makeDirectory(int32_t storageId, const std::string &pathUnderStorage,
-                                 int32_t *_aidl_return) final;
-    binder::Status makeDirectories(int32_t storageId, const std::string &pathUnderStorage,
-                                   int32_t *_aidl_return) final;
-    binder::Status makeFile(int32_t storageId, const std::string &pathUnderStorage, int64_t size,
-                            const std::vector<uint8_t> &metadata, int32_t *_aidl_return) final;
-    binder::Status makeFileFromRange(int32_t storageId, const std::string &pathUnderStorage,
-                                     const std::string &sourcePathUnderStorage, int64_t start,
-                                     int64_t end, int32_t *_aidl_return);
-    binder::Status makeLink(int32_t sourceStorageId, const std::string &relativeSourcePath,
-                            int32_t destStorageId, const std::string &relativeDestPath,
-                            int32_t *_aidl_return) final;
-    binder::Status unlink(int32_t storageId, const std::string &pathUnderStorage,
-                          int32_t *_aidl_return) final;
-    binder::Status isFileRangeLoaded(int32_t storageId, const std::string &relativePath,
-                                     int64_t start, int64_t end, bool *_aidl_return) final;
-    binder::Status getFileMetadata(int32_t storageId, const std::string &relativePath,
-                                   std::vector<uint8_t> *_aidl_return) final;
-    binder::Status startLoading(int32_t storageId, bool *_aidl_return) final;
 
 private:
     android::incremental::IncrementalService mImpl;
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index afce260..414c66c 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -30,6 +30,8 @@
 #include <binder/BinderService.h>
 #include <binder/ParcelFileDescriptor.h>
 #include <binder/Status.h>
+
+#include <openssl/sha.h>
 #include <sys/stat.h>
 #include <uuid/uuid.h>
 #include <zlib.h>
@@ -55,7 +57,6 @@
 struct Constants {
     static constexpr auto backing = "backing_store"sv;
     static constexpr auto mount = "mount"sv;
-    static constexpr auto image = "incfs.img"sv;
     static constexpr auto storagePrefix = "st"sv;
     static constexpr auto mountpointMdPrefix = ".mountpoint."sv;
     static constexpr auto infoMdName = ".info"sv;
@@ -70,7 +71,7 @@
 bool mkdirOrLog(std::string_view name, int mode = 0770, bool allowExisting = true) {
     auto cstr = path::c_str(name);
     if (::mkdir(cstr, mode)) {
-        if (errno != EEXIST) {
+        if (!allowExisting || errno != EEXIST) {
             PLOG(level) << "Can't create directory '" << name << '\'';
             return false;
         }
@@ -80,6 +81,11 @@
             return false;
         }
     }
+    if (::chmod(cstr, mode)) {
+        PLOG(level) << "Changing permission failed for '" << name << '\'';
+        return false;
+    }
+
     return true;
 }
 
@@ -106,7 +112,7 @@
     for (int counter = 0; counter < 1000;
          mountKey.resize(prefixSize), base::StringAppendF(&mountKey, "%d", counter++)) {
         auto mountRoot = path::join(incrementalDir, mountKey);
-        if (mkdirOrLog(mountRoot, 0770, false)) {
+        if (mkdirOrLog(mountRoot, 0777, false)) {
             return {mountKey, mountRoot};
         }
     }
@@ -116,11 +122,7 @@
 template <class ProtoMessage, class Control>
 static ProtoMessage parseFromIncfs(const IncFsWrapper* incfs, Control&& control,
                                    std::string_view path) {
-    struct stat st;
-    if (::stat(path::c_str(path), &st)) {
-        return {};
-    }
-    auto md = incfs->getMetadata(control, st.st_ino);
+    auto md = incfs->getMetadata(control, path);
     ProtoMessage message;
     return message.ParseFromArray(md.data(), md.size()) ? message : ProtoMessage{};
 }
@@ -161,35 +163,66 @@
 }
 
 auto IncrementalService::IncFsMount::makeStorage(StorageId id) -> StorageMap::iterator {
-    metadata::Storage st;
-    st.set_id(id);
-    auto metadata = st.SerializeAsString();
-
     std::string name;
     for (int no = nextStorageDirNo.fetch_add(1, std::memory_order_relaxed), i = 0;
          i < 1024 && no >= 0; no = nextStorageDirNo.fetch_add(1, std::memory_order_relaxed), ++i) {
         name.clear();
-        base::StringAppendF(&name, "%.*s%d", int(constants().storagePrefix.size()),
-                            constants().storagePrefix.data(), no);
-        if (auto node =
-                    incrementalService.mIncFs->makeDir(control, name, INCFS_ROOT_INODE, metadata);
-            node >= 0) {
+        base::StringAppendF(&name, "%.*s_%d_%d", int(constants().storagePrefix.size()),
+                            constants().storagePrefix.data(), id, no);
+        auto fullName = path::join(root, constants().mount, name);
+        if (auto err = incrementalService.mIncFs->makeDir(control, fullName); !err) {
             std::lock_guard l(lock);
-            return storages.insert_or_assign(id, Storage{std::move(name), node}).first;
+            return storages.insert_or_assign(id, Storage{std::move(fullName)}).first;
+        } else if (err != EEXIST) {
+            LOG(ERROR) << __func__ << "(): failed to create dir |" << fullName << "| " << err;
+            break;
         }
     }
     nextStorageDirNo = 0;
     return storages.end();
 }
 
+static std::unique_ptr<DIR, decltype(&::closedir)> openDir(const char* path) {
+    return {::opendir(path), ::closedir};
+}
+
+static int rmDirContent(const char* path) {
+    auto dir = openDir(path);
+    if (!dir) {
+        return -EINVAL;
+    }
+    while (auto entry = ::readdir(dir.get())) {
+        if (entry->d_name == "."sv || entry->d_name == ".."sv) {
+            continue;
+        }
+        auto fullPath = android::base::StringPrintf("%s/%s", path, entry->d_name);
+        if (entry->d_type == DT_DIR) {
+            if (const auto err = rmDirContent(fullPath.c_str()); err != 0) {
+                PLOG(WARNING) << "Failed to delete " << fullPath << " content";
+                return err;
+            }
+            if (const auto err = ::rmdir(fullPath.c_str()); err != 0) {
+                PLOG(WARNING) << "Failed to rmdir " << fullPath;
+                return err;
+            }
+        } else {
+            if (const auto err = ::unlink(fullPath.c_str()); err != 0) {
+                PLOG(WARNING) << "Failed to delete " << fullPath;
+                return err;
+            }
+        }
+    }
+    return 0;
+}
+
 void IncrementalService::IncFsMount::cleanupFilesystem(std::string_view root) {
-    ::unlink(path::join(root, constants().backing, constants().image).c_str());
+    rmDirContent(path::join(root, constants().backing).c_str());
     ::rmdir(path::join(root, constants().backing).c_str());
     ::rmdir(path::join(root, constants().mount).c_str());
     ::rmdir(path::c_str(root));
 }
 
-IncrementalService::IncrementalService(const ServiceManagerWrapper& sm, std::string_view rootDir)
+IncrementalService::IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir)
       : mVold(sm.getVoldService()),
         mIncrementalManager(sm.getIncrementalManager()),
         mIncFs(sm.getIncFs()),
@@ -205,6 +238,23 @@
     // mountExistingImages();
 }
 
+FileId IncrementalService::idFromMetadata(std::span<const uint8_t> metadata) {
+    incfs::FileId id = {};
+    if (size_t(metadata.size()) <= sizeof(id)) {
+        memcpy(&id, metadata.data(), metadata.size());
+    } else {
+        uint8_t buffer[SHA_DIGEST_LENGTH];
+        static_assert(sizeof(buffer) >= sizeof(id));
+
+        SHA_CTX ctx;
+        SHA1_Init(&ctx);
+        SHA1_Update(&ctx, metadata.data(), metadata.size());
+        SHA1_Final(buffer, &ctx);
+        memcpy(&id, buffer, sizeof(id));
+    }
+    return id;
+}
+
 IncrementalService::~IncrementalService() = default;
 
 std::optional<std::future<void>> IncrementalService::onSystemReady() {
@@ -300,26 +350,36 @@
             std::unique_ptr<std::string, decltype(firstCleanup)>(&mountRoot, firstCleanup);
 
     auto mountTarget = path::join(mountRoot, constants().mount);
-    if (!mkdirOrLog(path::join(mountRoot, constants().backing)) || !mkdirOrLog(mountTarget)) {
+    const auto backing = path::join(mountRoot, constants().backing);
+    if (!mkdirOrLog(backing, 0777) || !mkdirOrLog(mountTarget)) {
         return kInvalidStorageId;
     }
 
-    const auto image = path::join(mountRoot, constants().backing, constants().image);
     IncFsMount::Control control;
     {
         std::lock_guard l(mMountOperationLock);
         IncrementalFileSystemControlParcel controlParcel;
-        auto status = mVold->mountIncFs(image, mountTarget, incfs::truncate, &controlParcel);
+
+        if (auto err = rmDirContent(backing.c_str())) {
+            LOG(ERROR) << "Coudn't clean the backing directory " << backing << ": " << err;
+            return kInvalidStorageId;
+        }
+        if (!mkdirOrLog(path::join(backing, ".index"), 0777)) {
+            return kInvalidStorageId;
+        }
+        auto status = mVold->mountIncFs(backing, mountTarget, 0, &controlParcel);
         if (!status.isOk()) {
             LOG(ERROR) << "Vold::mountIncFs() failed: " << status.toString8();
             return kInvalidStorageId;
         }
-        if (!controlParcel.cmd || !controlParcel.log) {
+        if (controlParcel.cmd.get() < 0 || controlParcel.pendingReads.get() < 0 ||
+            controlParcel.log.get() < 0) {
             LOG(ERROR) << "Vold::mountIncFs() returned invalid control parcel.";
             return kInvalidStorageId;
         }
-        control.cmdFd = controlParcel.cmd->release();
-        control.logFd = controlParcel.log->release();
+        control.cmd = controlParcel.cmd.release().release();
+        control.pendingReads = controlParcel.pendingReads.release().release();
+        control.logs = controlParcel.log.release().release();
     }
 
     std::unique_lock l(mLock);
@@ -344,7 +404,7 @@
 
     const auto storageIt = ifs->makeStorage(ifs->mountId);
     if (storageIt == ifs->storages.end()) {
-        LOG(ERROR) << "Can't create default storage directory";
+        LOG(ERROR) << "Can't create a default storage directory";
         return kInvalidStorageId;
     }
 
@@ -359,9 +419,12 @@
         m.mutable_loader()->release_arguments();
         m.mutable_loader()->release_class_name();
         m.mutable_loader()->release_package_name();
-        if (auto err = mIncFs->makeFile(ifs->control, constants().infoMdName, INCFS_ROOT_INODE, 0,
-                                        metadata);
-            err < 0) {
+        if (auto err =
+                    mIncFs->makeFile(ifs->control,
+                                     path::join(ifs->root, constants().mount,
+                                                constants().infoMdName),
+                                     0777, idFromMetadata(metadata),
+                                     {.metadata = {metadata.data(), (IncFsSize)metadata.size()}})) {
             LOG(ERROR) << "Saving mount metadata failed: " << -err;
             return kInvalidStorageId;
         }
@@ -369,8 +432,8 @@
 
     const auto bk =
             (options & CreateOptions::PermanentBind) ? BindKind::Permanent : BindKind::Temporary;
-    if (auto err = addBindMount(*ifs, storageIt->first, std::string(storageIt->second.name),
-                                std::move(mountNorm), bk, l);
+    if (auto err = addBindMount(*ifs, storageIt->first, storageIt->second.name,
+                                std::string(storageIt->second.name), std::move(mountNorm), bk, l);
         err < 0) {
         LOG(ERROR) << "adding bind mount failed: " << -err;
         return kInvalidStorageId;
@@ -419,8 +482,9 @@
 
     const auto bk =
             (options & CreateOptions::PermanentBind) ? BindKind::Permanent : BindKind::Temporary;
-    if (auto err = addBindMount(*ifs, storageIt->first, std::string(storageIt->second.name),
-                                path::normalize(mountPoint), bk, l);
+    if (auto err = addBindMount(*ifs, storageIt->first, storageIt->second.name,
+                                std::string(storageIt->second.name), path::normalize(mountPoint),
+                                bk, l);
         err < 0) {
         LOG(ERROR) << "bindMount failed with error: " << err;
         return kInvalidStorageId;
@@ -492,40 +556,36 @@
     return findStorageId(path::normalize(pathInMount));
 }
 
-Inode IncrementalService::nodeFor(StorageId storage, std::string_view subpath) const {
+FileId IncrementalService::nodeFor(StorageId storage, std::string_view subpath) const {
     const auto ifs = getIfs(storage);
     if (!ifs) {
-        return -1;
+        return kIncFsInvalidFileId;
     }
     std::unique_lock l(ifs->lock);
     auto storageIt = ifs->storages.find(storage);
     if (storageIt == ifs->storages.end()) {
-        return -1;
+        return kIncFsInvalidFileId;
     }
     if (subpath.empty() || subpath == "."sv) {
-        return storageIt->second.node;
+        return kIncFsInvalidFileId;
     }
     auto path = path::join(ifs->root, constants().mount, storageIt->second.name, subpath);
     l.unlock();
-    struct stat st;
-    if (::stat(path.c_str(), &st)) {
-        return -1;
-    }
-    return st.st_ino;
+    return mIncFs->getFileId(ifs->control, path);
 }
 
-std::pair<Inode, std::string_view> IncrementalService::parentAndNameFor(
+std::pair<FileId, std::string_view> IncrementalService::parentAndNameFor(
         StorageId storage, std::string_view subpath) const {
     auto name = path::basename(subpath);
     if (name.empty()) {
-        return {-1, {}};
+        return {kIncFsInvalidFileId, {}};
     }
     auto dir = path::dirname(subpath);
     if (dir.empty() || dir == "/"sv) {
-        return {-1, {}};
+        return {kIncFsInvalidFileId, {}};
     }
-    auto inode = nodeFor(storage, dir);
-    return {inode, name};
+    auto id = nodeFor(storage, dir);
+    return {id, name};
 }
 
 IncrementalService::IfsMountPtr IncrementalService::getIfs(StorageId storage) const {
@@ -542,8 +602,8 @@
     return it->second;
 }
 
-int IncrementalService::bind(StorageId storage, std::string_view sourceSubdir,
-                             std::string_view target, BindKind kind) {
+int IncrementalService::bind(StorageId storage, std::string_view source, std::string_view target,
+                             BindKind kind) {
     if (!isValidMountTarget(target)) {
         return -EINVAL;
     }
@@ -552,15 +612,20 @@
     if (!ifs) {
         return -EINVAL;
     }
+    auto normSource = path::normalize(source);
+
     std::unique_lock l(ifs->lock);
     const auto storageInfo = ifs->storages.find(storage);
     if (storageInfo == ifs->storages.end()) {
         return -EINVAL;
     }
-    auto source = path::join(storageInfo->second.name, sourceSubdir);
+    if (!path::startsWith(normSource, storageInfo->second.name)) {
+        return -EINVAL;
+    }
     l.unlock();
     std::unique_lock l2(mLock, std::defer_lock);
-    return addBindMount(*ifs, storage, std::move(source), path::normalize(target), kind, l2);
+    return addBindMount(*ifs, storage, storageInfo->second.name, std::move(normSource),
+                        path::normalize(target), kind, l2);
 }
 
 int IncrementalService::unbind(StorageId storage, std::string_view target) {
@@ -599,90 +664,72 @@
         ifs->bindPoints.erase(bindIt);
         l2.unlock();
         if (!savedFile.empty()) {
-            mIncFs->unlink(ifs->control, INCFS_ROOT_INODE, savedFile);
+            mIncFs->unlink(ifs->control, path::join(ifs->root, constants().mount, savedFile));
         }
     }
     return 0;
 }
 
-Inode IncrementalService::makeFile(StorageId storageId, std::string_view pathUnderStorage,
-                                   long size, std::string_view metadata,
-                                   std::string_view signature) {
-    (void)signature;
-    auto [parentInode, name] = parentAndNameFor(storageId, pathUnderStorage);
-    if (parentInode < 0) {
-        return -EINVAL;
-    }
-    if (auto ifs = getIfs(storageId)) {
-        auto inode = mIncFs->makeFile(ifs->control, name, parentInode, size, metadata);
-        if (inode < 0) {
-            return inode;
+int IncrementalService::makeFile(StorageId storage, std::string_view path, int mode, FileId id,
+                                 incfs::NewFileParams params) {
+    if (auto ifs = getIfs(storage)) {
+        auto err = mIncFs->makeFile(ifs->control, path, mode, id, params);
+        if (err) {
+            return err;
         }
-        auto metadataBytes = std::vector<uint8_t>();
-        if (metadata.data() != nullptr && metadata.size() > 0) {
-            metadataBytes.insert(metadataBytes.end(), &metadata.data()[0],
-                                 &metadata.data()[metadata.size()]);
+        std::vector<uint8_t> metadataBytes;
+        if (params.metadata.data && params.metadata.size > 0) {
+            metadataBytes.assign(params.metadata.data, params.metadata.data + params.metadata.size);
         }
-        mIncrementalManager->newFileForDataLoader(ifs->mountId, inode, metadataBytes);
-        return inode;
+        mIncrementalManager->newFileForDataLoader(ifs->mountId, id, metadataBytes);
+        return 0;
     }
     return -EINVAL;
 }
 
-Inode IncrementalService::makeDir(StorageId storageId, std::string_view pathUnderStorage,
-                                  std::string_view metadata) {
-    auto [parentInode, name] = parentAndNameFor(storageId, pathUnderStorage);
-    if (parentInode < 0) {
-        return -EINVAL;
-    }
+int IncrementalService::makeDir(StorageId storageId, std::string_view path, int mode) {
     if (auto ifs = getIfs(storageId)) {
-        return mIncFs->makeDir(ifs->control, name, parentInode, metadata);
+        return mIncFs->makeDir(ifs->control, path, mode);
     }
     return -EINVAL;
 }
 
-Inode IncrementalService::makeDirs(StorageId storageId, std::string_view pathUnderStorage,
-                                   std::string_view metadata) {
+int IncrementalService::makeDirs(StorageId storageId, std::string_view path, int mode) {
     const auto ifs = getIfs(storageId);
     if (!ifs) {
         return -EINVAL;
     }
-    std::string_view parentDir(pathUnderStorage);
-    auto p = parentAndNameFor(storageId, pathUnderStorage);
-    std::stack<std::string> pathsToCreate;
-    while (p.first < 0) {
-        parentDir = path::dirname(parentDir);
-        pathsToCreate.emplace(parentDir);
-        p = parentAndNameFor(storageId, parentDir);
+
+    auto err = mIncFs->makeDir(ifs->control, path, mode);
+    if (err == -EEXIST) {
+        return 0;
+    } else if (err != -ENOENT) {
+        return err;
     }
-    Inode inode;
-    while (!pathsToCreate.empty()) {
-        p = parentAndNameFor(storageId, pathsToCreate.top());
-        pathsToCreate.pop();
-        inode = mIncFs->makeDir(ifs->control, p.second, p.first, metadata);
-        if (inode < 0) {
-            return inode;
-        }
+    if (auto err = makeDirs(storageId, path::dirname(path), mode)) {
+        return err;
     }
-    return mIncFs->makeDir(ifs->control, path::basename(pathUnderStorage), inode, metadata);
+    return mIncFs->makeDir(ifs->control, path, mode);
 }
 
-int IncrementalService::link(StorageId storage, Inode item, Inode newParent,
-                             std::string_view newName) {
-    if (auto ifs = getIfs(storage)) {
-        return mIncFs->link(ifs->control, item, newParent, newName);
+int IncrementalService::link(StorageId sourceStorageId, std::string_view oldPath,
+                             StorageId destStorageId, std::string_view newPath) {
+    if (auto ifsSrc = getIfs(sourceStorageId), ifsDest = getIfs(destStorageId);
+        ifsSrc && ifsSrc == ifsDest) {
+        return mIncFs->link(ifsSrc->control, oldPath, newPath);
     }
     return -EINVAL;
 }
 
-int IncrementalService::unlink(StorageId storage, Inode parent, std::string_view name) {
+int IncrementalService::unlink(StorageId storage, std::string_view path) {
     if (auto ifs = getIfs(storage)) {
-        return mIncFs->unlink(ifs->control, parent, name);
+        return mIncFs->unlink(ifs->control, path);
     }
     return -EINVAL;
 }
 
-int IncrementalService::addBindMount(IncFsMount& ifs, StorageId storage, std::string&& sourceSubdir,
+int IncrementalService::addBindMount(IncFsMount& ifs, StorageId storage,
+                                     std::string_view storageRoot, std::string&& source,
                                      std::string&& target, BindKind kind,
                                      std::unique_lock<std::mutex>& mainLock) {
     if (!isValidMountTarget(target)) {
@@ -694,30 +741,30 @@
         metadata::BindPoint bp;
         bp.set_storage_id(storage);
         bp.set_allocated_dest_path(&target);
-        bp.set_allocated_source_subdir(&sourceSubdir);
+        bp.set_source_subdir(std::string(path::relativize(storageRoot, source)));
         const auto metadata = bp.SerializeAsString();
-        bp.release_source_subdir();
         bp.release_dest_path();
         mdFileName = makeBindMdName();
-        auto node = mIncFs->makeFile(ifs.control, mdFileName, INCFS_ROOT_INODE, 0, metadata);
-        if (node < 0) {
+        auto node =
+                mIncFs->makeFile(ifs.control, path::join(ifs.root, constants().mount, mdFileName),
+                                 0444, idFromMetadata(metadata),
+                                 {.metadata = {metadata.data(), (IncFsSize)metadata.size()}});
+        if (node) {
             return int(node);
         }
     }
 
-    return addBindMountWithMd(ifs, storage, std::move(mdFileName), std::move(sourceSubdir),
+    return addBindMountWithMd(ifs, storage, std::move(mdFileName), std::move(source),
                               std::move(target), kind, mainLock);
 }
 
 int IncrementalService::addBindMountWithMd(IncrementalService::IncFsMount& ifs, StorageId storage,
-                                           std::string&& metadataName, std::string&& sourceSubdir,
+                                           std::string&& metadataName, std::string&& source,
                                            std::string&& target, BindKind kind,
                                            std::unique_lock<std::mutex>& mainLock) {
-    LOG(INFO) << "Adding bind mount: " << sourceSubdir << " -> " << target;
     {
-        auto path = path::join(ifs.root, constants().mount, sourceSubdir);
         std::lock_guard l(mMountOperationLock);
-        const auto status = mVold->bindMount(path, target);
+        const auto status = mVold->bindMount(source, target);
         if (!status.isOk()) {
             LOG(ERROR) << "Calling Vold::bindMount() failed: " << status.toString8();
             return status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC
@@ -736,12 +783,12 @@
     const auto [it, _] =
             ifs.bindPoints.insert_or_assign(target,
                                             IncFsMount::Bind{storage, std::move(metadataName),
-                                                             std::move(sourceSubdir), kind});
+                                                             std::move(source), kind});
     mBindsByPath[std::move(target)] = it;
     return 0;
 }
 
-RawMetadata IncrementalService::getMetadata(StorageId storage, Inode node) const {
+RawMetadata IncrementalService::getMetadata(StorageId storage, FileId node) const {
     const auto ifs = getIfs(storage);
     if (!ifs) {
         return {};
@@ -831,21 +878,18 @@
     LOG(INFO) << "Trying to mount: " << key;
 
     auto mountTarget = path::join(root, constants().mount);
-    const auto image = path::join(root, constants().backing, constants().image);
+    const auto backing = path::join(root, constants().backing);
 
     IncFsMount::Control control;
     IncrementalFileSystemControlParcel controlParcel;
-    auto status = mVold->mountIncFs(image, mountTarget, 0, &controlParcel);
+    auto status = mVold->mountIncFs(backing, mountTarget, 0, &controlParcel);
     if (!status.isOk()) {
         LOG(ERROR) << "Vold::mountIncFs() failed: " << status.toString8();
         return false;
     }
-    if (controlParcel.cmd) {
-        control.cmdFd = controlParcel.cmd->release();
-    }
-    if (controlParcel.log) {
-        control.logFd = controlParcel.log->release();
-    }
+    control.cmd = controlParcel.cmd.release().release();
+    control.pendingReads = controlParcel.pendingReads.release().release();
+    control.logs = controlParcel.log.release().release();
 
     auto ifs = std::make_shared<IncFsMount>(std::string(root), -1, std::move(control), *this);
 
@@ -860,8 +904,7 @@
     mNextId = std::max(mNextId, ifs->mountId + 1);
 
     std::vector<std::pair<std::string, metadata::BindPoint>> bindPoints;
-    auto d = std::unique_ptr<DIR, decltype(&::closedir)>(::opendir(path::c_str(mountTarget)),
-                                                         ::closedir);
+    auto d = openDir(path::c_str(mountTarget));
     while (auto e = ::readdir(d.get())) {
         if (e->d_type == DT_REG) {
             auto name = std::string_view(e->d_name);
@@ -874,7 +917,7 @@
                 if (bindPoints.back().second.dest_path().empty() ||
                     bindPoints.back().second.source_subdir().empty()) {
                     bindPoints.pop_back();
-                    mIncFs->unlink(ifs->control, INCFS_ROOT_INODE, name);
+                    mIncFs->unlink(ifs->control, path::join(ifs->root, constants().mount, name));
                 }
             }
         } else if (e->d_type == DT_DIR) {
@@ -891,9 +934,7 @@
                                  << " for mount " << root;
                     continue;
                 }
-                ifs->storages.insert_or_assign(md.id(),
-                                               IncFsMount::Storage{std::string(name),
-                                                                   Inode(e->d_ino)});
+                ifs->storages.insert_or_assign(md.id(), IncFsMount::Storage{std::string(name)});
                 mNextId = std::max(mNextId, md.id() + 1);
             }
         }
@@ -973,10 +1014,10 @@
     }
     FileSystemControlParcel fsControlParcel;
     fsControlParcel.incremental = std::make_unique<IncrementalFileSystemControlParcel>();
-    fsControlParcel.incremental->cmd =
-            std::make_unique<os::ParcelFileDescriptor>(base::unique_fd(::dup(ifs.control.cmdFd)));
-    fsControlParcel.incremental->log =
-            std::make_unique<os::ParcelFileDescriptor>(base::unique_fd(::dup(ifs.control.logFd)));
+    fsControlParcel.incremental->cmd.reset(base::unique_fd(::dup(ifs.control.cmd)));
+    fsControlParcel.incremental->pendingReads.reset(
+            base::unique_fd(::dup(ifs.control.pendingReads)));
+    fsControlParcel.incremental->log.reset(base::unique_fd(::dup(ifs.control.logs)));
     sp<IncrementalDataLoaderListener> listener = new IncrementalDataLoaderListener(*this);
     bool created = false;
     auto status = mIncrementalManager->prepareDataLoader(ifs.mountId, fsControlParcel, *dlp,
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index a03ffa0..ca5e4db 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -52,16 +52,16 @@
 
 using MountId = int;
 using StorageId = int;
-using Inode = incfs::Inode;
+using FileId = incfs::FileId;
 using BlockIndex = incfs::BlockIndex;
 using RawMetadata = incfs::RawMetadata;
 using Clock = std::chrono::steady_clock;
 using TimePoint = std::chrono::time_point<Clock>;
 using Seconds = std::chrono::seconds;
 
-class IncrementalService {
+class IncrementalService final {
 public:
-    explicit IncrementalService(const ServiceManagerWrapper& sm, std::string_view rootDir);
+    explicit IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir);
 
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
@@ -85,6 +85,11 @@
         Permanent = 1,
     };
 
+    static FileId idFromMetadata(std::span<const uint8_t> metadata);
+    static inline FileId idFromMetadata(std::span<const char> metadata) {
+        return idFromMetadata({(const uint8_t*)metadata.data(), metadata.size()});
+    }
+
     std::optional<std::future<void>> onSystemReady();
 
     StorageId createStorage(std::string_view mountPoint,
@@ -92,30 +97,31 @@
                             CreateOptions options = CreateOptions::Default);
     StorageId createLinkedStorage(std::string_view mountPoint, StorageId linkedStorage,
                                   CreateOptions options = CreateOptions::Default);
-    StorageId openStorage(std::string_view pathInMount);
+    StorageId openStorage(std::string_view path);
 
-    Inode nodeFor(StorageId storage, std::string_view subpath) const;
-    std::pair<Inode, std::string_view> parentAndNameFor(StorageId storage,
-                                                        std::string_view subpath) const;
+    FileId nodeFor(StorageId storage, std::string_view path) const;
+    std::pair<FileId, std::string_view> parentAndNameFor(StorageId storage,
+                                                         std::string_view path) const;
 
-    int bind(StorageId storage, std::string_view subdir, std::string_view target, BindKind kind);
+    int bind(StorageId storage, std::string_view source, std::string_view target, BindKind kind);
     int unbind(StorageId storage, std::string_view target);
     void deleteStorage(StorageId storage);
 
-    Inode makeFile(StorageId storage, std::string_view name, long size, std::string_view metadata,
-                   std::string_view signature);
-    Inode makeDir(StorageId storage, std::string_view name, std::string_view metadata = {});
-    Inode makeDirs(StorageId storage, std::string_view name, std::string_view metadata = {});
+    int makeFile(StorageId storage, std::string_view path, int mode, FileId id,
+                 incfs::NewFileParams params);
+    int makeDir(StorageId storage, std::string_view path, int mode = 0555);
+    int makeDirs(StorageId storage, std::string_view path, int mode = 0555);
 
-    int link(StorageId storage, Inode item, Inode newParent, std::string_view newName);
-    int unlink(StorageId storage, Inode parent, std::string_view name);
+    int link(StorageId sourceStorageId, std::string_view oldPath, StorageId destStorageId,
+             std::string_view newPath);
+    int unlink(StorageId storage, std::string_view path);
 
-    bool isRangeLoaded(StorageId storage, Inode file, std::pair<BlockIndex, BlockIndex> range) {
+    bool isRangeLoaded(StorageId storage, FileId file, std::pair<BlockIndex, BlockIndex> range) {
         return false;
     }
 
-    RawMetadata getMetadata(StorageId storage, Inode node) const;
-    std::string getSigngatureData(StorageId storage, Inode node) const { return {}; }
+    RawMetadata getMetadata(StorageId storage, FileId node) const;
+    std::string getSignatureData(StorageId storage, FileId node) const;
 
     std::vector<std::string> listFiles(StorageId storage) const;
     bool startLoading(StorageId storage) const;
@@ -142,19 +148,9 @@
 
         struct Storage {
             std::string name;
-            Inode node;
         };
 
-        struct Control {
-            operator IncFsControl() const { return {cmdFd, logFd}; }
-            void reset() {
-                cmdFd.reset();
-                logFd.reset();
-            }
-
-            base::unique_fd cmdFd;
-            base::unique_fd logFd;
-        };
+        using Control = incfs::UniqueControl;
 
         using BindMap = std::map<std::string, Bind>;
         using StorageMap = std::unordered_map<StorageId, Storage>;
@@ -196,11 +192,12 @@
 
     IfsMountPtr getIfs(StorageId storage) const;
     const IfsMountPtr& getIfsLocked(StorageId storage) const;
-    int addBindMount(IncFsMount& ifs, StorageId storage, std::string&& sourceSubdir,
-                     std::string&& target, BindKind kind, std::unique_lock<std::mutex>& mainLock);
+    int addBindMount(IncFsMount& ifs, StorageId storage, std::string_view storageRoot,
+                     std::string&& source, std::string&& target, BindKind kind,
+                     std::unique_lock<std::mutex>& mainLock);
 
     int addBindMountWithMd(IncFsMount& ifs, StorageId storage, std::string&& metadataName,
-                           std::string&& sourceSubdir, std::string&& target, BindKind kind,
+                           std::string&& source, std::string&& target, BindKind kind,
                            std::unique_lock<std::mutex>& mainLock);
 
     bool prepareDataLoader(IncFsMount& ifs, DataLoaderParamsParcel* params);
@@ -212,10 +209,9 @@
     MountMap::iterator getStorageSlotLocked();
 
     // Member variables
-    // These are shared pointers for the sake of unit testing
-    std::shared_ptr<VoldServiceWrapper> mVold;
-    std::shared_ptr<IncrementalManagerWrapper> mIncrementalManager;
-    std::shared_ptr<IncFsWrapper> mIncFs;
+    std::unique_ptr<VoldServiceWrapper> mVold;
+    std::unique_ptr<IncrementalManagerWrapper> mIncrementalManager;
+    std::unique_ptr<IncFsWrapper> mIncFs;
     const std::string mIncrementalDir;
 
     mutable std::mutex mLock;
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index a79b26a..5d978a1c 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -16,14 +16,8 @@
 
 #include "ServiceWrappers.h"
 
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
-#include <binder/IServiceManager.h>
 #include <utils/String16.h>
 
-#include <string>
-#include <string_view>
-
 using namespace std::literals;
 
 namespace android::os::incremental {
@@ -31,37 +25,38 @@
 static constexpr auto kVoldServiceName = "vold"sv;
 static constexpr auto kIncrementalManagerName = "incremental"sv;
 
-RealServiceManager::RealServiceManager(const sp<IServiceManager>& serviceManager)
-      : mServiceManager(serviceManager) {}
+RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager)
+      : mServiceManager(std::move(serviceManager)) {}
 
 template <class INTERFACE>
 sp<INTERFACE> RealServiceManager::getRealService(std::string_view serviceName) const {
-    sp<IBinder> binder = mServiceManager->getService(String16(serviceName.data()));
-    if (binder == 0) {
-        return 0;
+    sp<IBinder> binder =
+            mServiceManager->getService(String16(serviceName.data(), serviceName.size()));
+    if (!binder) {
+        return nullptr;
     }
     return interface_cast<INTERFACE>(binder);
 }
 
-std::shared_ptr<VoldServiceWrapper> RealServiceManager::getVoldService() const {
+std::unique_ptr<VoldServiceWrapper> RealServiceManager::getVoldService() {
     sp<os::IVold> vold = RealServiceManager::getRealService<os::IVold>(kVoldServiceName);
     if (vold != 0) {
-        return std::make_shared<RealVoldService>(vold);
+        return std::make_unique<RealVoldService>(vold);
     }
     return nullptr;
 }
 
-std::shared_ptr<IncrementalManagerWrapper> RealServiceManager::getIncrementalManager() const {
+std::unique_ptr<IncrementalManagerWrapper> RealServiceManager::getIncrementalManager() {
     sp<IIncrementalManager> manager =
             RealServiceManager::getRealService<IIncrementalManager>(kIncrementalManagerName);
-    if (manager != 0) {
-        return std::make_shared<RealIncrementalManager>(manager);
+    if (manager) {
+        return std::make_unique<RealIncrementalManager>(manager);
     }
     return nullptr;
 }
 
-std::shared_ptr<IncFsWrapper> RealServiceManager::getIncFs() const {
-    return std::make_shared<RealIncFs>();
+std::unique_ptr<IncFsWrapper> RealServiceManager::getIncFs() {
+    return std::make_unique<RealIncFs>();
 }
 
 } // namespace android::os::incremental
diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h
index 5704582..ae3739d 100644
--- a/services/incremental/ServiceWrappers.h
+++ b/services/incremental/ServiceWrappers.h
@@ -26,6 +26,7 @@
 #include <binder/IServiceManager.h>
 #include <incfs.h>
 
+#include <memory>
 #include <string>
 #include <string_view>
 
@@ -36,10 +37,12 @@
 
 // --- Wrapper interfaces ---
 
+using MountId = int32_t;
+
 class VoldServiceWrapper {
 public:
-    virtual ~VoldServiceWrapper(){};
-    virtual binder::Status mountIncFs(const std::string& imagePath, const std::string& targetDir,
+    virtual ~VoldServiceWrapper() = default;
+    virtual binder::Status mountIncFs(const std::string& backingPath, const std::string& targetDir,
                                       int32_t flags,
                                       IncrementalFileSystemControlParcel* _aidl_return) const = 0;
     virtual binder::Status unmountIncFs(const std::string& dir) const = 0;
@@ -49,52 +52,52 @@
 
 class IncrementalManagerWrapper {
 public:
-    virtual ~IncrementalManagerWrapper() {}
-    virtual binder::Status prepareDataLoader(
-            int32_t mountId, const FileSystemControlParcel& control,
-            const DataLoaderParamsParcel& params,
-            const sp<IDataLoaderStatusListener>& listener,
-            bool* _aidl_return) const = 0;
-    virtual binder::Status startDataLoader(int32_t mountId, bool* _aidl_return) const = 0;
-    virtual binder::Status destroyDataLoader(int32_t mountId) const = 0;
-    virtual binder::Status newFileForDataLoader(int32_t mountId, int64_t inode,
-                                                const ::std::vector<uint8_t>& metadata) const = 0;
-    virtual binder::Status showHealthBlockedUI(int32_t mountId) const = 0;
+    virtual ~IncrementalManagerWrapper() = default;
+    virtual binder::Status prepareDataLoader(MountId mountId,
+                                             const FileSystemControlParcel& control,
+                                             const DataLoaderParamsParcel& params,
+                                             const sp<IDataLoaderStatusListener>& listener,
+                                             bool* _aidl_return) const = 0;
+    virtual binder::Status startDataLoader(MountId mountId, bool* _aidl_return) const = 0;
+    virtual binder::Status destroyDataLoader(MountId mountId) const = 0;
+    virtual binder::Status newFileForDataLoader(MountId mountId, FileId fileid,
+                                                const std::vector<uint8_t>& metadata) const = 0;
+    virtual binder::Status showHealthBlockedUI(MountId mountId) const = 0;
 };
 
 class IncFsWrapper {
 public:
-    virtual ~IncFsWrapper() {}
-    virtual Inode makeFile(Control control, std::string_view name, Inode parent, Size size,
-                           std::string_view metadata) const = 0;
-    virtual Inode makeDir(Control control, std::string_view name, Inode parent,
-                          std::string_view metadata, int mode = 0555) const = 0;
-    virtual RawMetadata getMetadata(Control control, Inode inode) const = 0;
-    virtual ErrorCode link(Control control, Inode item, Inode targetParent,
-                           std::string_view name) const = 0;
-    virtual ErrorCode unlink(Control control, Inode parent, std::string_view name) const = 0;
-    virtual ErrorCode writeBlocks(Control control, const incfs_new_data_block blocks[],
-                                  int blocksCount) const = 0;
+    virtual ~IncFsWrapper() = default;
+    virtual ErrorCode makeFile(Control control, std::string_view path, int mode, FileId id,
+                               NewFileParams params) const = 0;
+    virtual ErrorCode makeDir(Control control, std::string_view path, int mode = 0555) const = 0;
+    virtual RawMetadata getMetadata(Control control, FileId fileid) const = 0;
+    virtual RawMetadata getMetadata(Control control, std::string_view path) const = 0;
+    virtual FileId getFileId(Control control, std::string_view path) const = 0;
+    virtual ErrorCode link(Control control, std::string_view from, std::string_view to) const = 0;
+    virtual ErrorCode unlink(Control control, std::string_view path) const = 0;
+    virtual base::unique_fd openWrite(Control control, FileId id) const = 0;
+    virtual ErrorCode writeBlocks(std::span<const DataBlock> blocks) const = 0;
 };
 
 class ServiceManagerWrapper {
 public:
-    virtual ~ServiceManagerWrapper() {}
-    virtual std::shared_ptr<VoldServiceWrapper> getVoldService() const = 0;
-    virtual std::shared_ptr<IncrementalManagerWrapper> getIncrementalManager() const = 0;
-    virtual std::shared_ptr<IncFsWrapper> getIncFs() const = 0;
+    virtual ~ServiceManagerWrapper() = default;
+    virtual std::unique_ptr<VoldServiceWrapper> getVoldService() = 0;
+    virtual std::unique_ptr<IncrementalManagerWrapper> getIncrementalManager() = 0;
+    virtual std::unique_ptr<IncFsWrapper> getIncFs() = 0;
 };
 
 // --- Real stuff ---
 
 class RealVoldService : public VoldServiceWrapper {
 public:
-    RealVoldService(const sp<os::IVold> vold) : mInterface(vold) {}
+    RealVoldService(const sp<os::IVold> vold) : mInterface(std::move(vold)) {}
     ~RealVoldService() = default;
-    binder::Status mountIncFs(const std::string& imagePath, const std::string& targetDir,
+    binder::Status mountIncFs(const std::string& backingPath, const std::string& targetDir,
                               int32_t flags,
                               IncrementalFileSystemControlParcel* _aidl_return) const override {
-        return mInterface->mountIncFs(imagePath, targetDir, flags, _aidl_return);
+        return mInterface->mountIncFs(backingPath, targetDir, flags, _aidl_return);
     }
     binder::Status unmountIncFs(const std::string& dir) const override {
         return mInterface->unmountIncFs(dir);
@@ -113,24 +116,26 @@
     RealIncrementalManager(const sp<os::incremental::IIncrementalManager> manager)
           : mInterface(manager) {}
     ~RealIncrementalManager() = default;
-    binder::Status prepareDataLoader(
-            int32_t mountId, const FileSystemControlParcel& control,
-            const DataLoaderParamsParcel& params,
-            const sp<IDataLoaderStatusListener>& listener,
-            bool* _aidl_return) const override {
+    binder::Status prepareDataLoader(MountId mountId, const FileSystemControlParcel& control,
+                                     const DataLoaderParamsParcel& params,
+                                     const sp<IDataLoaderStatusListener>& listener,
+                                     bool* _aidl_return) const override {
         return mInterface->prepareDataLoader(mountId, control, params, listener, _aidl_return);
     }
-    binder::Status startDataLoader(int32_t mountId, bool* _aidl_return) const override {
+    binder::Status startDataLoader(MountId mountId, bool* _aidl_return) const override {
         return mInterface->startDataLoader(mountId, _aidl_return);
     }
-    binder::Status destroyDataLoader(int32_t mountId) const override {
+    binder::Status destroyDataLoader(MountId mountId) const override {
         return mInterface->destroyDataLoader(mountId);
     }
-    binder::Status newFileForDataLoader(int32_t mountId, int64_t inode,
-                                        const ::std::vector<uint8_t>& metadata) const override {
-        return mInterface->newFileForDataLoader(mountId, inode, metadata);
+    binder::Status newFileForDataLoader(MountId mountId, FileId fileid,
+                                        const std::vector<uint8_t>& metadata) const override {
+        return mInterface->newFileForDataLoader(mountId,
+                                                {(const uint8_t*)fileid.data,
+                                                 (const uint8_t*)fileid.data + sizeof(fileid.data)},
+                                                metadata);
     }
-    binder::Status showHealthBlockedUI(int32_t mountId) const override {
+    binder::Status showHealthBlockedUI(MountId mountId) const override {
         return mInterface->showHealthBlockedUI(mountId);
     }
 
@@ -140,11 +145,11 @@
 
 class RealServiceManager : public ServiceManagerWrapper {
 public:
-    RealServiceManager(const sp<IServiceManager>& serviceManager);
+    RealServiceManager(sp<IServiceManager> serviceManager);
     ~RealServiceManager() = default;
-    std::shared_ptr<VoldServiceWrapper> getVoldService() const override;
-    std::shared_ptr<IncrementalManagerWrapper> getIncrementalManager() const override;
-    std::shared_ptr<IncFsWrapper> getIncFs() const override;
+    std::unique_ptr<VoldServiceWrapper> getVoldService() override;
+    std::unique_ptr<IncrementalManagerWrapper> getIncrementalManager() override;
+    std::unique_ptr<IncFsWrapper> getIncFs() override;
 
 private:
     template <class INTERFACE>
@@ -156,27 +161,33 @@
 public:
     RealIncFs() = default;
     ~RealIncFs() = default;
-    Inode makeFile(Control control, std::string_view name, Inode parent, Size size,
-                   std::string_view metadata) const override {
-        return incfs::makeFile(control, name, parent, size, metadata);
+    ErrorCode makeFile(Control control, std::string_view path, int mode, FileId id,
+                       NewFileParams params) const override {
+        return incfs::makeFile(control, path, mode, id, params);
     }
-    Inode makeDir(Control control, std::string_view name, Inode parent, std::string_view metadata,
-                  int mode) const override {
-        return incfs::makeDir(control, name, parent, metadata, mode);
+    ErrorCode makeDir(Control control, std::string_view path, int mode) const override {
+        return incfs::makeDir(control, path, mode);
     }
-    RawMetadata getMetadata(Control control, Inode inode) const override {
-        return incfs::getMetadata(control, inode);
+    RawMetadata getMetadata(Control control, FileId fileid) const override {
+        return incfs::getMetadata(control, fileid);
     }
-    ErrorCode link(Control control, Inode item, Inode targetParent,
-                   std::string_view name) const override {
-        return incfs::link(control, item, targetParent, name);
+    RawMetadata getMetadata(Control control, std::string_view path) const override {
+        return incfs::getMetadata(control, path);
     }
-    ErrorCode unlink(Control control, Inode parent, std::string_view name) const override {
-        return incfs::unlink(control, parent, name);
+    FileId getFileId(Control control, std::string_view path) const override {
+        return incfs::getFileId(control, path);
     }
-    ErrorCode writeBlocks(Control control, const incfs_new_data_block blocks[],
-                          int blocksCount) const override {
-        return incfs::writeBlocks(control, blocks, blocksCount);
+    ErrorCode link(Control control, std::string_view from, std::string_view to) const override {
+        return incfs::link(control, from, to);
+    }
+    ErrorCode unlink(Control control, std::string_view path) const override {
+        return incfs::unlink(control, path);
+    }
+    base::unique_fd openWrite(Control control, FileId id) const override {
+        return base::unique_fd{incfs::openWrite(control, id)};
+    }
+    ErrorCode writeBlocks(std::span<const DataBlock> blocks) const override {
+        return incfs::writeBlocks(blocks);
     }
 };
 
diff --git a/services/incremental/path.cpp b/services/incremental/path.cpp
index c529d61..0d86f2a 100644
--- a/services/incremental/path.cpp
+++ b/services/incremental/path.cpp
@@ -44,16 +44,45 @@
                                         PathCharsLess());
 }
 
+static void preparePathComponent(std::string_view path, bool trimFront) {
+    if (trimFront) {
+        while (!path.empty() && path.front() == '/') {
+            path.remove_prefix(1);
+        }
+    }
+    while (!path.empty() && path.back() == '/') {
+        path.remove_suffix(1);
+    }
+}
+
 void details::append_next_path(std::string& target, std::string_view path) {
+    preparePathComponent(path, true);
     if (path.empty()) {
         return;
     }
-    if (!target.empty()) {
+    if (!target.empty() && !target.ends_with('/')) {
         target.push_back('/');
     }
     target += path;
 }
 
+std::string_view relativize(std::string_view parent, std::string_view nested) {
+    if (!nested.starts_with(parent)) {
+        return nested;
+    }
+    if (nested.size() == parent.size()) {
+        return {};
+    }
+    if (nested[parent.size()] != '/') {
+        return nested;
+    }
+    auto relative = nested.substr(parent.size());
+    while (relative.front() == '/') {
+        relative.remove_prefix(1);
+    }
+    return relative;
+}
+
 bool isAbsolute(std::string_view path) {
     return !path.empty() && path[0] == '/';
 }
diff --git a/services/incremental/path.h b/services/incremental/path.h
index a1f4b8e..3e5fd21 100644
--- a/services/incremental/path.h
+++ b/services/incremental/path.h
@@ -67,6 +67,20 @@
     return {sv};
 }
 
+std::string_view relativize(std::string_view parent, std::string_view nested);
+inline std::string_view relativize(const char* parent, const char* nested) {
+    return relativize(std::string_view(parent), std::string_view(nested));
+}
+inline std::string_view relativize(std::string_view parent, const char* nested) {
+    return relativize(parent, std::string_view(nested));
+}
+inline std::string_view relativize(const char* parent, std::string_view nested) {
+    return relativize(std::string_view(parent), nested);
+}
+
+std::string_view relativize(std::string&& parent, std::string_view nested) = delete;
+std::string_view relativize(std::string_view parent, std::string&& nested) = delete;
+
 bool isAbsolute(std::string_view path);
 std::string normalize(std::string_view path);
 std::string_view dirname(std::string_view path);
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index ca1e1a9..2826818 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -46,7 +46,7 @@
 class MockVoldService : public VoldServiceWrapper {
 public:
     MOCK_CONST_METHOD4(mountIncFs,
-                       binder::Status(const std::string& imagePath, const std::string& targetDir,
+                       binder::Status(const std::string& backingPath, const std::string& targetDir,
                                       int32_t flags,
                                       IncrementalFileSystemControlParcel* _aidl_return));
     MOCK_CONST_METHOD1(unmountIncFs, binder::Status(const std::string& dir));
@@ -77,22 +77,20 @@
     binder::Status getInvalidControlParcel(const std::string& imagePath,
                                            const std::string& targetDir, int32_t flags,
                                            IncrementalFileSystemControlParcel* _aidl_return) {
-        _aidl_return->cmd = nullptr;
-        _aidl_return->log = nullptr;
+        _aidl_return = {};
         return binder::Status::ok();
     }
     binder::Status incFsSuccess(const std::string& imagePath, const std::string& targetDir,
                                 int32_t flags, IncrementalFileSystemControlParcel* _aidl_return) {
-        _aidl_return->cmd = std::make_unique<os::ParcelFileDescriptor>(std::move(cmdFd));
-        _aidl_return->log = std::make_unique<os::ParcelFileDescriptor>(std::move(logFd));
+        _aidl_return->pendingReads.reset(base::unique_fd(dup(STDIN_FILENO)));
+        _aidl_return->cmd.reset(base::unique_fd(dup(STDIN_FILENO)));
+        _aidl_return->log.reset(base::unique_fd(dup(STDIN_FILENO)));
         return binder::Status::ok();
     }
 
 private:
     TemporaryFile cmdFile;
     TemporaryFile logFile;
-    base::unique_fd cmdFd;
-    base::unique_fd logFd;
 };
 
 class MockIncrementalManager : public IncrementalManagerWrapper {
@@ -105,7 +103,7 @@
     MOCK_CONST_METHOD2(startDataLoader, binder::Status(int32_t mountId, bool* _aidl_return));
     MOCK_CONST_METHOD1(destroyDataLoader, binder::Status(int32_t mountId));
     MOCK_CONST_METHOD3(newFileForDataLoader,
-                       binder::Status(int32_t mountId, int64_t inode,
+                       binder::Status(int32_t mountId, FileId fileId,
                                       const ::std::vector<uint8_t>& metadata));
     MOCK_CONST_METHOD1(showHealthBlockedUI, binder::Status(int32_t mountId));
 
@@ -152,23 +150,21 @@
 class MockIncFs : public IncFsWrapper {
 public:
     MOCK_CONST_METHOD5(makeFile,
-                       Inode(Control control, std::string_view name, Inode parent, Size size,
-                             std::string_view metadata));
-    MOCK_CONST_METHOD5(makeDir,
-                       Inode(Control control, std::string_view name, Inode parent,
-                             std::string_view metadata, int mode));
-    MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, Inode inode));
-    MOCK_CONST_METHOD4(link,
-                       ErrorCode(Control control, Inode item, Inode targetParent,
-                                 std::string_view name));
-    MOCK_CONST_METHOD3(unlink, ErrorCode(Control control, Inode parent, std::string_view name));
-    MOCK_CONST_METHOD3(writeBlocks,
-                       ErrorCode(Control control, const incfs_new_data_block blocks[],
-                                 int blocksCount));
+                       ErrorCode(Control control, std::string_view path, int mode, FileId id,
+                                 NewFileParams params));
+    MOCK_CONST_METHOD3(makeDir, ErrorCode(Control control, std::string_view path, int mode));
+    MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, FileId fileid));
+    MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, std::string_view path));
+    MOCK_CONST_METHOD2(getFileId, FileId(Control control, std::string_view path));
+    MOCK_CONST_METHOD3(link,
+                       ErrorCode(Control control, std::string_view from, std::string_view to));
+    MOCK_CONST_METHOD2(unlink, ErrorCode(Control control, std::string_view path));
+    MOCK_CONST_METHOD2(openWrite, base::unique_fd(Control control, FileId id));
+    MOCK_CONST_METHOD1(writeBlocks, ErrorCode(std::span<const DataBlock> blocks));
 
     void makeFileFails() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(-1)); }
     void makeFileSuccess() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(0)); }
-    RawMetadata getMountInfoMetadata(Control control, Inode inode) {
+    RawMetadata getMountInfoMetadata(Control control, std::string_view path) {
         metadata::Mount m;
         m.mutable_storage()->set_id(100);
         m.mutable_loader()->set_package_name("com.test");
@@ -176,15 +172,15 @@
         const auto metadata = m.SerializeAsString();
         m.mutable_loader()->release_arguments();
         m.mutable_loader()->release_package_name();
-        return std::vector<char>(metadata.begin(), metadata.end());
+        return {metadata.begin(), metadata.end()};
     }
-    RawMetadata getStorageMetadata(Control control, Inode inode) {
+    RawMetadata getStorageMetadata(Control control, std::string_view path) {
         metadata::Storage st;
         st.set_id(100);
         auto metadata = st.SerializeAsString();
-        return std::vector<char>(metadata.begin(), metadata.end());
+        return {metadata.begin(), metadata.end()};
     }
-    RawMetadata getBindPointMetadata(Control control, Inode inode) {
+    RawMetadata getBindPointMetadata(Control control, std::string_view path) {
         metadata::BindPoint bp;
         std::string destPath = "dest";
         std::string srcPath = "src";
@@ -200,40 +196,41 @@
 
 class MockServiceManager : public ServiceManagerWrapper {
 public:
-    MockServiceManager(std::shared_ptr<MockVoldService> vold,
-                       std::shared_ptr<MockIncrementalManager> manager,
-                       std::shared_ptr<MockIncFs> incfs)
-          : mVold(vold), mIncrementalManager(manager), mIncFs(incfs) {}
-    std::shared_ptr<VoldServiceWrapper> getVoldService() const override { return mVold; }
-    std::shared_ptr<IncrementalManagerWrapper> getIncrementalManager() const override {
-        return mIncrementalManager;
+    MockServiceManager(std::unique_ptr<MockVoldService> vold,
+                       std::unique_ptr<MockIncrementalManager> manager,
+                       std::unique_ptr<MockIncFs> incfs)
+          : mVold(std::move(vold)),
+            mIncrementalManager(std::move(manager)),
+            mIncFs(std::move(incfs)) {}
+    std::unique_ptr<VoldServiceWrapper> getVoldService() final { return std::move(mVold); }
+    std::unique_ptr<IncrementalManagerWrapper> getIncrementalManager() final {
+        return std::move(mIncrementalManager);
     }
-    std::shared_ptr<IncFsWrapper> getIncFs() const override { return mIncFs; }
+    std::unique_ptr<IncFsWrapper> getIncFs() final { return std::move(mIncFs); }
 
 private:
-    std::shared_ptr<MockVoldService> mVold;
-    std::shared_ptr<MockIncrementalManager> mIncrementalManager;
-    std::shared_ptr<MockIncFs> mIncFs;
+    std::unique_ptr<MockVoldService> mVold;
+    std::unique_ptr<MockIncrementalManager> mIncrementalManager;
+    std::unique_ptr<MockIncFs> mIncFs;
 };
 
 // --- IncrementalServiceTest ---
 
-static Inode inode(std::string_view path) {
-    struct stat st;
-    if (::stat(path::c_str(path), &st)) {
-        return -1;
-    }
-    return st.st_ino;
-}
-
 class IncrementalServiceTest : public testing::Test {
 public:
     void SetUp() override {
-        mVold = std::make_shared<NiceMock<MockVoldService>>();
-        mIncrementalManager = std::make_shared<NiceMock<MockIncrementalManager>>();
-        mIncFs = std::make_shared<NiceMock<MockIncFs>>();
-        MockServiceManager serviceManager = MockServiceManager(mVold, mIncrementalManager, mIncFs);
-        mIncrementalService = std::make_unique<IncrementalService>(serviceManager, mRootDir.path);
+        auto vold = std::make_unique<NiceMock<MockVoldService>>();
+        mVold = vold.get();
+        auto incrementalManager = std::make_unique<NiceMock<MockIncrementalManager>>();
+        mIncrementalManager = incrementalManager.get();
+        auto incFs = std::make_unique<NiceMock<MockIncFs>>();
+        mIncFs = incFs.get();
+        mIncrementalService =
+                std::make_unique<IncrementalService>(MockServiceManager(std::move(vold),
+                                                                        std::move(
+                                                                                incrementalManager),
+                                                                        std::move(incFs)),
+                                                     mRootDir.path);
         mDataLoaderParcel.packageName = "com.test";
         mDataLoaderParcel.arguments = "uri";
         mIncrementalService->onSystemReady();
@@ -252,20 +249,18 @@
         const auto mountPointsFile = rootDir + "/dir1/mount/.mountpoint.abcd";
         ASSERT_TRUE(base::WriteStringToFile("info", mountInfoFile));
         ASSERT_TRUE(base::WriteStringToFile("mounts", mountPointsFile));
-        ASSERT_GE(inode(mountInfoFile), 0);
-        ASSERT_GE(inode(mountPointsFile), 0);
-        ON_CALL(*mIncFs, getMetadata(_, inode(mountInfoFile)))
-                .WillByDefault(Invoke(mIncFs.get(), &MockIncFs::getMountInfoMetadata));
-        ON_CALL(*mIncFs, getMetadata(_, inode(mountPointsFile)))
-                .WillByDefault(Invoke(mIncFs.get(), &MockIncFs::getBindPointMetadata));
-        ON_CALL(*mIncFs, getMetadata(_, inode(rootDir + "/dir1/mount/st0")))
-                .WillByDefault(Invoke(mIncFs.get(), &MockIncFs::getStorageMetadata));
+        ON_CALL(*mIncFs, getMetadata(_, std::string_view(mountInfoFile)))
+                .WillByDefault(Invoke(mIncFs, &MockIncFs::getMountInfoMetadata));
+        ON_CALL(*mIncFs, getMetadata(_, std::string_view(mountPointsFile)))
+                .WillByDefault(Invoke(mIncFs, &MockIncFs::getBindPointMetadata));
+        ON_CALL(*mIncFs, getMetadata(_, std::string_view(rootDir + "/dir1/mount/st0")))
+                .WillByDefault(Invoke(mIncFs, &MockIncFs::getStorageMetadata));
     }
 
 protected:
-    std::shared_ptr<NiceMock<MockVoldService>> mVold;
-    std::shared_ptr<NiceMock<MockIncFs>> mIncFs;
-    std::shared_ptr<NiceMock<MockIncrementalManager>> mIncrementalManager;
+    NiceMock<MockVoldService>* mVold;
+    NiceMock<MockIncFs>* mIncFs;
+    NiceMock<MockIncrementalManager>* mIncrementalManager;
     std::unique_ptr<IncrementalService> mIncrementalService;
     TemporaryDir mRootDir;
     DataLoaderParamsParcel mDataLoaderParcel;
@@ -412,12 +407,12 @@
             mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                IncrementalService::CreateOptions::CreateNew);
     std::string_view dir_path("test");
-    EXPECT_CALL(*mIncFs, makeDir(_, dir_path, _, _, _));
-    int fileIno = mIncrementalService->makeDir(storageId, dir_path, "");
-    ASSERT_GE(fileIno, 0);
+    EXPECT_CALL(*mIncFs, makeDir(_, dir_path, _));
+    auto res = mIncrementalService->makeDir(storageId, dir_path, 0555);
+    ASSERT_EQ(res, 0);
 }
 
-TEST_F(IncrementalServiceTest, testMakeDirectoryNoParent) {
+TEST_F(IncrementalServiceTest, testMakeDirectoryNested) {
     mVold->mountIncFsSuccess();
     mIncFs->makeFileSuccess();
     mVold->bindMountSuccess();
@@ -427,13 +422,15 @@
     int storageId =
             mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                IncrementalService::CreateOptions::CreateNew);
-    std::string_view first("first");
-    std::string_view second("second");
+    auto first = "first"sv;
+    auto second = "second"sv;
     std::string dir_path = std::string(first) + "/" + std::string(second);
-    EXPECT_CALL(*mIncFs, makeDir(_, first, _, _, _)).Times(0);
-    EXPECT_CALL(*mIncFs, makeDir(_, second, _, _, _)).Times(0);
-    int fileIno = mIncrementalService->makeDir(storageId, dir_path, "");
-    ASSERT_LT(fileIno, 0);
+    EXPECT_CALL(*mIncFs, makeDir(_, first, _)).Times(0);
+    EXPECT_CALL(*mIncFs, makeDir(_, second, _)).Times(0);
+    EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(dir_path), _)).Times(1);
+
+    auto res = mIncrementalService->makeDir(storageId, dir_path, 0555);
+    ASSERT_EQ(res, 0);
 }
 
 TEST_F(IncrementalServiceTest, testMakeDirectories) {
@@ -446,16 +443,18 @@
     int storageId =
             mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                IncrementalService::CreateOptions::CreateNew);
-    std::string_view first("first");
-    std::string_view second("second");
-    std::string_view third("third");
+    auto first = "first"sv;
+    auto second = "second"sv;
+    auto third = "third"sv;
     InSequence seq;
-    EXPECT_CALL(*mIncFs, makeDir(_, first, _, _, _));
-    EXPECT_CALL(*mIncFs, makeDir(_, second, _, _, _));
-    EXPECT_CALL(*mIncFs, makeDir(_, third, _, _, _));
-    std::string dir_path =
-            std::string(first) + "/" + std::string(second) + "/" + std::string(third);
-    int fileIno = mIncrementalService->makeDirs(storageId, dir_path, "");
-    ASSERT_GE(fileIno, 0);
+    auto parent_path = std::string(first) + "/" + std::string(second);
+    auto dir_path = parent_path + "/" + std::string(third);
+    EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(dir_path), _)).WillOnce(Return(-ENOENT));
+    EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(parent_path), _)).WillOnce(Return(-ENOENT));
+    EXPECT_CALL(*mIncFs, makeDir(_, first, _)).WillOnce(Return(0));
+    EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(parent_path), _)).WillOnce(Return(0));
+    EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(dir_path), _)).WillOnce(Return(0));
+    auto res = mIncrementalService->makeDirs(storageId, dir_path, 0555);
+    ASSERT_EQ(res, 0);
 }
 } // namespace android::os::incremental