Port the current code to new IncFS
Bug: 146080380
Test: manual, "cmd incremental install-start"
Change-Id: I6761c3f0e58b6d4de1ae3c4b31c23204fba9f740
diff --git a/Android.bp b/Android.bp
index 9411eec..627681c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -922,6 +922,8 @@
srcs: [
"core/java/android/os/incremental/IIncrementalManager.aidl",
"core/java/android/os/incremental/IIncrementalManagerNative.aidl",
+ "core/java/android/os/incremental/IncrementalNewFileParams.aidl",
+ "core/java/android/os/incremental/IncrementalSignature.aidl",
],
path: "core/java",
}
diff --git a/core/java/android/os/incremental/IIncrementalManager.aidl b/core/java/android/os/incremental/IIncrementalManager.aidl
index 17a310a..b415bc0 100644
--- a/core/java/android/os/incremental/IIncrementalManager.aidl
+++ b/core/java/android/os/incremental/IIncrementalManager.aidl
@@ -33,5 +33,7 @@
boolean startDataLoader(int mountId);
void showHealthBlockedUI(int mountId);
void destroyDataLoader(int mountId);
- void newFileForDataLoader(int mountId, long inode, in byte[] metadata);
+
+ // fileId is a 16 byte long identifier.
+ void newFileForDataLoader(int mountId, in byte[] fileId, in byte[] metadata);
}
diff --git a/core/java/android/os/incremental/IIncrementalManagerNative.aidl b/core/java/android/os/incremental/IIncrementalManagerNative.aidl
index 14215b1..2b6cd14 100644
--- a/core/java/android/os/incremental/IIncrementalManagerNative.aidl
+++ b/core/java/android/os/incremental/IIncrementalManagerNative.aidl
@@ -17,6 +17,7 @@
package android.os.incremental;
import android.content.pm.DataLoaderParamsParcel;
+import android.os.incremental.IncrementalNewFileParams;
/** @hide */
interface IIncrementalManagerNative {
@@ -40,7 +41,7 @@
*/
const int BIND_TEMPORARY = 0;
const int BIND_PERMANENT = 1;
- int makeBindMount(int storageId, in @utf8InCpp String pathUnderStorage, in @utf8InCpp String targetFullPath, int bindType);
+ int makeBindMount(int storageId, in @utf8InCpp String sourcePath, in @utf8InCpp String targetFullPath, int bindType);
/**
* Deletes an existing bind mount on a path under a storage. Returns 0 on success, and -errno on failure.
@@ -48,49 +49,50 @@
int deleteBindMount(int storageId, in @utf8InCpp String targetFullPath);
/**
- * Creates a directory under a storage. The target directory is specified by its relative path under the storage.
+ * Creates a directory under a storage. The target directory is specified by its path.
*/
- int makeDirectory(int storageId, in @utf8InCpp String pathUnderStorage);
+ int makeDirectory(int storageId, in @utf8InCpp String path);
/**
- * Recursively creates a directory under a storage. The target directory is specified by its relative path under the storage.
+ * Recursively creates a directory under a storage. The target directory is specified by its path.
* All the parent directories of the target directory will be created if they do not exist already.
*/
- int makeDirectories(int storageId, in @utf8InCpp String pathUnderStorage);
+ int makeDirectories(int storageId, in @utf8InCpp String path);
/**
- * Creates a file under a storage, specifying its name, size and metadata.
+ * Creates a file under a storage.
*/
- int makeFile(int storageId, in @utf8InCpp String pathUnderStorage, long size, in byte[] metadata);
+ int makeFile(int storageId, in @utf8InCpp String path, in IncrementalNewFileParams params);
/**
* Creates a file under a storage. Content of the file is from a range inside another file.
- * Both files are specified by relative paths under storage.
+ * Both files are specified by their paths.
*/
- int makeFileFromRange(int storageId, in @utf8InCpp String targetPathUnderStorage, in @utf8InCpp String sourcePathUnderStorage, long start, long end);
+ int makeFileFromRange(int storageId, in @utf8InCpp String targetPath, in @utf8InCpp String sourcePath, long start, long end);
/**
* Creates a hard link between two files in two storage instances.
- * Source and dest specified by parent storage IDs and their relative paths under the storage.
+ * Source and dest specified by parent storage IDs and their paths.
* The source and dest storage instances should be in the same fs mount.
* Note: destStorageId can be the same as sourceStorageId.
*/
- int makeLink(int sourceStorageId, in @utf8InCpp String sourcePathUnderStorage, int destStorageId, in @utf8InCpp String destPathUnderStorage);
+ int makeLink(int sourceStorageId, in @utf8InCpp String sourcePath, int destStorageId, in @utf8InCpp String destPath);
/**
- * Deletes a hard link in a storage, specified by the relative path of the link target under storage.
+ * Deletes a hard link in a storage, specified by its path.
*/
- int unlink(int storageId, in @utf8InCpp String pathUnderStorage);
+ int unlink(int storageId, in @utf8InCpp String path);
/**
- * Checks if a file's certain range is loaded. File is specified by relative file path under storage.
+ * Checks if a file's certain range is loaded. File is specified by its path.
*/
- boolean isFileRangeLoaded(int storageId, in @utf8InCpp String pathUnderStorage, long start, long end);
+ boolean isFileRangeLoaded(int storageId, in @utf8InCpp String path, long start, long end);
/**
- * Reads the metadata of a file. File is specified by relative path under storage.
+ * Reads the metadata of a file. File is specified by either its path or 16 byte id.
*/
- byte[] getFileMetadata(int storageId, in @utf8InCpp String pathUnderStorage);
+ byte[] getMetadataByPath(int storageId, in @utf8InCpp String path);
+ byte[] getMetadataById(int storageId, in byte[] fileId);
/**
* Starts loading data for a storage.
diff --git a/core/java/android/os/incremental/IncrementalFileStorages.java b/core/java/android/os/incremental/IncrementalFileStorages.java
index 63335a0..a0bfc1b 100644
--- a/core/java/android/os/incremental/IncrementalFileStorages.java
+++ b/core/java/android/os/incremental/IncrementalFileStorages.java
@@ -134,8 +134,8 @@
}
if (!new File(mDefaultDir, apk.getName()).exists()) {
- mDefaultStorage.makeFile(apk.getName(), apk.getSize(),
- apk.getMetadata());
+ mDefaultStorage.makeFile(apk.getName(), apk.getSize(), null,
+ apk.getMetadata(), 0, null, null, null);
}
// Assuming APK files are already named properly, e.g., "base.apk"
mDefaultStorage.makeLink(apk.getName(), mApkStorage, apk.getName());
@@ -167,7 +167,8 @@
current += '/';
}
String libFilePath = current + Paths.get(lib.getName()).getFileName();
- mDefaultStorage.makeFile(libFilePath, lib.getSize(), lib.getMetadata());
+ mDefaultStorage.makeFile(libFilePath, lib.getSize(), null, lib.getMetadata(), 0, null, null,
+ null);
mDefaultStorage.makeLink(libFilePath, mApkStorage, libFilePath);
}
@@ -183,7 +184,8 @@
IncrementalManager.CREATE_MODE_CREATE
| IncrementalManager.CREATE_MODE_TEMPORARY_BIND);
}
- mDefaultStorage.makeFile(obb.getName(), obb.getSize(), obb.getMetadata());
+ mDefaultStorage.makeFile(obb.getName(), obb.getSize(), null, obb.getMetadata(), 0, null,
+ null, null);
mDefaultStorage.makeLink(obb.getName(), mObbStorage, obb.getName());
}
diff --git a/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl b/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl
index 0ae353d..6018ad1 100644
--- a/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl
+++ b/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl
@@ -17,11 +17,12 @@
package android.os.incremental;
/**
- * Wraps two file descriptors that Incremental Service uses to communicate
+ * Wraps the file descriptors Incremental Service uses to communicate
* with Incremental FileSystem.
* @hide
*/
parcelable IncrementalFileSystemControlParcel {
- @nullable ParcelFileDescriptor cmd;
- @nullable ParcelFileDescriptor log;
+ ParcelFileDescriptor cmd;
+ ParcelFileDescriptor pendingReads;
+ ParcelFileDescriptor log;
}
diff --git a/core/java/android/os/incremental/IncrementalNewFileParams.aidl b/core/java/android/os/incremental/IncrementalNewFileParams.aidl
new file mode 100644
index 0000000..182732c
--- /dev/null
+++ b/core/java/android/os/incremental/IncrementalNewFileParams.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.os.incremental;
+
+import android.os.incremental.IncrementalSignature;
+
+/**
+ * All the parameters to create a new file on IncFS
+ * FileId is a 16 byte-long identifier.
+ * @hide
+ */
+parcelable IncrementalNewFileParams {
+ long size;
+ byte[] fileId;
+ byte[] metadata;
+ @nullable IncrementalSignature signature;
+}
diff --git a/core/java/android/os/incremental/IncrementalSignature.aidl b/core/java/android/os/incremental/IncrementalSignature.aidl
new file mode 100644
index 0000000..729e8e5
--- /dev/null
+++ b/core/java/android/os/incremental/IncrementalSignature.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.os.incremental;
+
+/** {@hide} */
+parcelable IncrementalSignature {
+ /*
+ * Stable AIDL doesn't support constants, but here's the possible values
+ * const int HASH_ALGO_NONE = 0;
+ * const int HASH_ALGO_SHA256 = 1;
+ */
+
+ int hashAlgorithm = 0;
+ byte[] rootHash;
+ byte[] additionalData;
+ byte[] signature;
+}
diff --git a/core/java/android/os/incremental/IncrementalStorage.java b/core/java/android/os/incremental/IncrementalStorage.java
index 2750868..91dda08 100644
--- a/core/java/android/os/incremental/IncrementalStorage.java
+++ b/core/java/android/os/incremental/IncrementalStorage.java
@@ -22,6 +22,8 @@
import java.io.File;
import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.UUID;
/**
* Provides operations on an Incremental File System directory, using IncrementalServiceNative.
@@ -64,14 +66,14 @@
* Temporarily bind-mounts a subdir under the current storage directory to a target directory.
* The bind-mount will NOT be preserved between device reboots.
*
- * @param sourcePathUnderStorage Source path as a relative path under current storage
- * directory.
- * @param targetPath Absolute path to the target directory.
+ * @param sourcePath Source path as a relative path under current storage
+ * directory.
+ * @param targetPath Absolute path to the target directory.
*/
- public void bind(@NonNull String sourcePathUnderStorage, @NonNull String targetPath)
+ public void bind(@NonNull String sourcePath, @NonNull String targetPath)
throws IOException {
try {
- int res = mService.makeBindMount(mId, sourcePathUnderStorage, targetPath,
+ int res = mService.makeBindMount(mId, sourcePath, targetPath,
IIncrementalManagerNative.BIND_TEMPORARY);
if (res < 0) {
throw new IOException("bind() failed with errno " + -res);
@@ -96,13 +98,13 @@
* Permanently bind-mounts a subdir under the current storage directory to a target directory.
* The bind-mount WILL be preserved between device reboots.
*
- * @param sourcePathUnderStorage Relative path under the current storage directory.
- * @param targetPath Absolute path to the target directory.
+ * @param sourcePath Relative path under the current storage directory.
+ * @param targetPath Absolute path to the target directory.
*/
- public void bindPermanent(@NonNull String sourcePathUnderStorage, @NonNull String targetPath)
+ public void bindPermanent(@NonNull String sourcePath, @NonNull String targetPath)
throws IOException {
try {
- int res = mService.makeBindMount(mId, sourcePathUnderStorage, targetPath,
+ int res = mService.makeBindMount(mId, sourcePath, targetPath,
IIncrementalManagerNative.BIND_PERMANENT);
if (res < 0) {
throw new IOException("bind() permanent failed with errno " + -res);
@@ -131,11 +133,11 @@
/**
* Creates a sub-directory under the current storage directory.
*
- * @param pathUnderStorage Relative path of the sub-directory, e.g., "subdir"
+ * @param path Relative path of the sub-directory, e.g., "subdir"
*/
- public void makeDirectory(@NonNull String pathUnderStorage) throws IOException {
+ public void makeDirectory(@NonNull String path) throws IOException {
try {
- int res = mService.makeDirectory(mId, pathUnderStorage);
+ int res = mService.makeDirectory(mId, path);
if (res < 0) {
throw new IOException("makeDirectory() failed with errno " + -res);
}
@@ -148,11 +150,11 @@
* Creates a sub-directory under the current storage directory. If its parent dirs do not exist,
* create the parent dirs as well.
*
- * @param pathUnderStorage Relative path of the sub-directory, e.g., "subdir/subsubdir"
+ * @param path Full path.
*/
- public void makeDirectories(@NonNull String pathUnderStorage) throws IOException {
+ public void makeDirectories(@NonNull String path) throws IOException {
try {
- int res = mService.makeDirectories(mId, pathUnderStorage);
+ int res = mService.makeDirectories(mId, path);
if (res < 0) {
throw new IOException("makeDirectory() failed with errno " + -res);
}
@@ -164,15 +166,27 @@
/**
* Creates a file under the current storage directory.
*
- * @param pathUnderStorage Relative path of the new file.
+ * @param path Relative path of the new file.
* @param size Size of the new file in bytes.
* @param metadata Metadata bytes.
*/
- public void makeFile(@NonNull String pathUnderStorage, long size,
- @Nullable byte[] metadata) throws IOException {
+ public void makeFile(@NonNull String path, long size, @Nullable UUID id,
+ @Nullable byte[] metadata, int hashAlgorithm, @Nullable byte[] rootHash,
+ @Nullable byte[] additionalData, @Nullable byte[] signature) throws IOException {
try {
- int res = mService.makeFile(mId, pathUnderStorage, size, metadata);
- if (res < 0) {
+ final IncrementalNewFileParams params = new IncrementalNewFileParams();
+ params.size = size;
+ params.metadata = metadata;
+ params.fileId = idToBytes(id);
+ if (hashAlgorithm != 0 || signature != null) {
+ params.signature = new IncrementalSignature();
+ params.signature.hashAlgorithm = hashAlgorithm;
+ params.signature.rootHash = rootHash;
+ params.signature.additionalData = additionalData;
+ params.signature.signature = signature;
+ }
+ int res = mService.makeFile(mId, path, params);
+ if (res != 0) {
throw new IOException("makeFile() failed with errno " + -res);
}
} catch (RemoteException e) {
@@ -184,15 +198,15 @@
* Creates a file in Incremental storage. The content of the file is mapped from a range inside
* a source file in the same storage.
*
- * @param destRelativePath Target relative path under storage.
- * @param sourceRelativePath Source relative path under storage.
+ * @param destPath Target full path.
+ * @param sourcePath Source full path.
* @param rangeStart Starting offset (in bytes) in the source file.
* @param rangeEnd Ending offset (in bytes) in the source file.
*/
- public void makeFileFromRange(@NonNull String destRelativePath,
- @NonNull String sourceRelativePath, long rangeStart, long rangeEnd) throws IOException {
+ public void makeFileFromRange(@NonNull String destPath,
+ @NonNull String sourcePath, long rangeStart, long rangeEnd) throws IOException {
try {
- int res = mService.makeFileFromRange(mId, destRelativePath, sourceRelativePath,
+ int res = mService.makeFileFromRange(mId, destPath, sourcePath,
rangeStart, rangeEnd);
if (res < 0) {
throw new IOException("makeFileFromRange() failed, errno " + -res);
@@ -206,15 +220,15 @@
* Creates a hard-link between two paths, which can be under different storages but in the same
* Incremental File System.
*
- * @param sourcePathUnderStorage The relative path of the source.
- * @param destStorage The target storage of the link target.
- * @param destPathUnderStorage The relative path of the target.
+ * @param sourcePath The absolute path of the source.
+ * @param destStorage The target storage of the link target.
+ * @param destPath The absolute path of the target.
*/
- public void makeLink(@NonNull String sourcePathUnderStorage, IncrementalStorage destStorage,
- @NonNull String destPathUnderStorage) throws IOException {
+ public void makeLink(@NonNull String sourcePath, IncrementalStorage destStorage,
+ @NonNull String destPath) throws IOException {
try {
- int res = mService.makeLink(mId, sourcePathUnderStorage, destStorage.getId(),
- destPathUnderStorage);
+ int res = mService.makeLink(mId, sourcePath, destStorage.getId(),
+ destPath);
if (res < 0) {
throw new IOException("makeLink() failed with errno " + -res);
}
@@ -226,11 +240,11 @@
/**
* Deletes a hard-link under the current storage directory.
*
- * @param pathUnderStorage The relative path of the target.
+ * @param path The absolute path of the target.
*/
- public void unlink(@NonNull String pathUnderStorage) throws IOException {
+ public void unlink(@NonNull String path) throws IOException {
try {
- int res = mService.unlink(mId, pathUnderStorage);
+ int res = mService.unlink(mId, path);
if (res < 0) {
throw new IOException("unlink() failed with errno " + -res);
}
@@ -242,13 +256,14 @@
/**
* Rename an old file name to a new file name under the current storage directory.
*
- * @param sourcePathUnderStorage Old file path as a relative path to the storage directory.
- * @param destPathUnderStorage New file path as a relative path to the storage directory.
+ * @param sourcepath Old file path as a full path to the storage directory.
+ * @param destpath New file path as a full path to the storage directory.
*/
- public void moveFile(@NonNull String sourcePathUnderStorage,
- @NonNull String destPathUnderStorage) throws IOException {
+ public void moveFile(@NonNull String sourcepath,
+ @NonNull String destpath) throws IOException {
+ //TODO(zyy): implement using rename(2) when confirmed that IncFS supports it.
try {
- int res = mService.makeLink(mId, sourcePathUnderStorage, mId, destPathUnderStorage);
+ int res = mService.makeLink(mId, sourcepath, mId, destpath);
if (res < 0) {
throw new IOException("moveFile() failed at makeLink(), errno " + -res);
}
@@ -256,7 +271,7 @@
e.rethrowFromSystemServer();
}
try {
- mService.unlink(mId, sourcePathUnderStorage);
+ mService.unlink(mId, sourcepath);
} catch (RemoteException ignored) {
}
}
@@ -274,7 +289,7 @@
throw new IOException("moveDir() requires that destination dir already exists.");
}
try {
- int res = mService.makeBindMount(mId, "", destPath,
+ int res = mService.makeBindMount(mId, sourcePath, destPath,
IIncrementalManagerNative.BIND_PERMANENT);
if (res < 0) {
throw new IOException("moveDir() failed at making bind mount, errno " + -res);
@@ -291,24 +306,24 @@
/**
* Checks whether a file under the current storage directory is fully loaded.
*
- * @param pathUnderStorage The relative path of the file.
+ * @param path The relative path of the file.
* @return True if the file is fully loaded.
*/
- public boolean isFileFullyLoaded(@NonNull String pathUnderStorage) {
- return isFileRangeLoaded(pathUnderStorage, 0, -1);
+ public boolean isFileFullyLoaded(@NonNull String path) {
+ return isFileRangeLoaded(path, 0, -1);
}
/**
* Checks whether a range in a file if loaded.
*
- * @param pathUnderStorage The relative path of the file.
+ * @param path The relative path of the file.
* @param start The starting offset of the range.
* @param end The ending offset of the range.
* @return True if the file is fully loaded.
*/
- public boolean isFileRangeLoaded(@NonNull String pathUnderStorage, long start, long end) {
+ public boolean isFileRangeLoaded(@NonNull String path, long start, long end) {
try {
- return mService.isFileRangeLoaded(mId, pathUnderStorage, start, end);
+ return mService.isFileRangeLoaded(mId, path, start, end);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
return false;
@@ -318,13 +333,65 @@
/**
* Returns the metadata object of an IncFs File.
*
- * @param pathUnderStorage The relative path of the file.
+ * @param path The relative path of the file.
* @return Byte array that contains metadata bytes.
*/
@Nullable
- public byte[] getFileMetadata(@NonNull String pathUnderStorage) {
+ public byte[] getFileMetadata(@NonNull String path) {
try {
- return mService.getFileMetadata(mId, pathUnderStorage);
+ return mService.getMetadataByPath(mId, path);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return null;
+ }
+ }
+
+ private static final int UUID_BYTE_SIZE = 16;
+
+ /**
+ * Converts UUID to a byte array usable for Incremental API calls
+ *
+ * @param id The id to convert
+ * @return Byte array that contains the same ID.
+ */
+ public static byte[] idToBytes(UUID id) {
+ if (id == null) {
+ return null;
+ }
+ final ByteBuffer buf = ByteBuffer.wrap(new byte[UUID_BYTE_SIZE]);
+ buf.putLong(id.getMostSignificantBits());
+ buf.putLong(id.getLeastSignificantBits());
+ return buf.array();
+ }
+
+ /**
+ * Converts UUID from a byte array usable for Incremental API calls
+ *
+ * @param bytes The id in byte array format, 16 bytes long
+ * @return UUID constructed from the byte array.
+ */
+ public static UUID bytesToId(byte[] bytes) {
+ if (bytes.length != UUID_BYTE_SIZE) {
+ throw new IllegalArgumentException("Expected array of size " + UUID_BYTE_SIZE
+ + ", got " + bytes.length);
+ }
+ final ByteBuffer buf = ByteBuffer.wrap(bytes);
+ long msb = buf.getLong();
+ long lsb = buf.getLong();
+ return new UUID(msb, lsb);
+ }
+
+ /**
+ * Returns the metadata object of an IncFs File.
+ *
+ * @param id The file id.
+ * @return Byte array that contains metadata bytes.
+ */
+ @Nullable
+ public byte[] getFileMetadata(@NonNull UUID id) {
+ try {
+ final byte[] rawId = idToBytes(id);
+ return mService.getMetadataById(mId, rawId);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
return null;
diff --git a/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp b/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp
index 4e49302..01150b7 100644
--- a/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp
+++ b/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp
@@ -32,6 +32,7 @@
#include <utils/Log.h>
#include <charconv>
+#include <span>
#include <string>
#include <thread>
#include <type_traits>
@@ -92,9 +93,7 @@
static_assert(COMMAND_SIZE == sizeof(RequestCommand));
-static bool sendRequest(int fd,
- RequestType requestType,
- FileId fileId = -1,
+static bool sendRequest(int fd, RequestType requestType, FileId fileId = -1,
BlockIdx blockIdx = -1) {
const RequestCommand command{
.requestType = static_cast<int16_t>(be16toh(requestType)),
@@ -267,25 +266,24 @@
std::lock_guard lock{mMapsMutex};
CHECK(mIfs);
for (auto&& pendingRead : pendingReads) {
- const android::dataloader::Inode ino = pendingRead.file_ino;
- const auto blockIdx =
- static_cast<BlockIdx>(pendingRead.block_index);
+ const android::dataloader::FileId id = pendingRead.id;
+ const auto blockIdx = static_cast<BlockIdx>(pendingRead.block);
/*
ALOGI("[AdbDataLoader] Missing: %d", (int) blockIdx);
*/
- auto fileIdOr = getFileId(ino);
+ auto fileIdOr = getFileId(id);
if (!fileIdOr) {
- ALOGE("[AdbDataLoader] Failed to handle event for inode=%d. "
+ ALOGE("[AdbDataLoader] Failed to handle event for fileid=%s. "
"Ignore.",
- static_cast<int>(ino));
+ android::incfs::toString(id).c_str());
continue;
}
const FileId fileId = *fileIdOr;
if (mRequestedFiles.insert(fileId).second) {
if (!sendRequest(mOutFd, PREFETCH, fileId, blockIdx)) {
ALOGE("[AdbDataLoader] Failed to request prefetch for "
- "inode=%d. Ignore.",
- static_cast<int>(ino));
+ "fileid=%s. Ignore.",
+ android::incfs::toString(id).c_str());
mRequestedFiles.erase(fileId);
mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
}
@@ -296,7 +294,7 @@
struct TracedRead {
uint64_t timestampUs;
- uint64_t fileIno;
+ android::dataloader::FileId fileId;
uint32_t firstBlockIdx;
uint32_t count;
};
@@ -307,26 +305,26 @@
return;
}
- TracedRead last = {0, 0, 0, 0};
+ TracedRead last = {};
std::lock_guard lock{mMapsMutex};
for (auto&& read : pageReads) {
- if (read.file_ino != last.fileIno ||
- read.block_index != last.firstBlockIdx + last.count) {
+ if (read.id != last.fileId || read.block != last.firstBlockIdx + last.count) {
traceOrLogRead(last, trace, log);
- last = {read.timestamp_us, read.file_ino, read.block_index, 1};
+ last = {read.bootClockTsUs, read.id, (uint32_t)read.block, 1};
} else {
++last.count;
}
}
traceOrLogRead(last, trace, log);
}
- void onFileCreated(android::dataloader::Inode inode, const android::dataloader::RawMetadata& metadata) {
- }
+ void onFileCreated(android::dataloader::FileId fileid,
+ const android::dataloader::RawMetadata& metadata) {}
private:
void receiver() {
std::vector<uint8_t> data;
- std::vector<incfs_new_data_block> instructions;
+ std::vector<IncFsDataBlock> instructions;
+ std::unordered_map<android::dataloader::FileId, unique_fd> writeFds;
while (!mStopReceiving) {
const int res = waitForDataOrSignal(mInFd, mEventFd);
if (res == 0) {
@@ -366,21 +364,32 @@
mStopReceiving = true;
break;
}
- const android::dataloader::Inode ino = mIdToNodeMap[header.fileId];
- if (!ino) {
+ const android::dataloader::FileId id = mIdToNodeMap[header.fileId];
+ if (!android::incfs::isValidFileId(id)) {
ALOGE("Unknown data destination for file ID %d. "
"Ignore.",
header.fileId);
continue;
}
- auto inst = incfs_new_data_block{
- .file_ino = static_cast<__aligned_u64>(ino),
- .block_index = static_cast<uint32_t>(header.blockIdx),
- .data_len = static_cast<uint16_t>(header.blockSize),
- .data = reinterpret_cast<uint64_t>(
- remainingData.data()),
- .compression =
- static_cast<uint8_t>(header.compressionType)};
+
+ auto& writeFd = writeFds[id];
+ if (writeFd < 0) {
+ writeFd.reset(this->mIfs->openWrite(id));
+ if (writeFd < 0) {
+ ALOGE("Failed to open file %d for writing (%d). Aboring.", header.fileId,
+ -writeFd);
+ break;
+ }
+ }
+
+ const auto inst = IncFsDataBlock{
+ .fileFd = writeFd,
+ .pageIndex = static_cast<IncFsBlockIndex>(header.blockIdx),
+ .compression = static_cast<IncFsCompressionKind>(header.compressionType),
+ .kind = INCFS_BLOCK_KIND_DATA,
+ .dataSize = static_cast<uint16_t>(header.blockSize),
+ .data = (const char*)remainingData.data(),
+ };
instructions.push_back(inst);
remainingData = remainingData.subspan(header.blockSize);
}
@@ -390,9 +399,8 @@
flushReadLog();
}
- void writeInstructions(std::vector<incfs_new_data_block>& instructions) {
- auto res = this->mIfs->writeBlocks(instructions.data(),
- instructions.size());
+ void writeInstructions(std::vector<IncFsDataBlock>& instructions) {
+ auto res = this->mIfs->writeBlocks(instructions);
if (res != instructions.size()) {
ALOGE("[AdbDataLoader] failed to write data to Incfs (res=%d when "
"expecting %d)",
@@ -406,30 +414,30 @@
FileId fileId;
};
- MetaPair* updateMapsForFile(android::dataloader::Inode ino) {
- android::dataloader::RawMetadata meta = mIfs->getRawMetadata(ino);
+ MetaPair* updateMapsForFile(android::dataloader::FileId id) {
+ android::dataloader::RawMetadata meta = mIfs->getRawMetadata(id);
FileId fileId;
auto res =
std::from_chars(meta.data(), meta.data() + meta.size(), fileId);
if (res.ec != std::errc{} || fileId < 0) {
- ALOGE("[AdbDataLoader] Invalid metadata for inode=%d (%s)",
- static_cast<int>(ino), meta.data());
+ ALOGE("[AdbDataLoader] Invalid metadata for fileid=%s (%s)",
+ android::incfs::toString(id).c_str(), meta.data());
return nullptr;
}
- mIdToNodeMap[fileId] = ino;
- auto& metaPair = mNodeToMetaMap[ino];
+ mIdToNodeMap[fileId] = id;
+ auto& metaPair = mNodeToMetaMap[id];
metaPair.meta = std::move(meta);
metaPair.fileId = fileId;
return &metaPair;
}
- android::dataloader::RawMetadata* getMeta(android::dataloader::Inode ino) {
- auto it = mNodeToMetaMap.find(ino);
+ android::dataloader::RawMetadata* getMeta(android::dataloader::FileId id) {
+ auto it = mNodeToMetaMap.find(id);
if (it != mNodeToMetaMap.end()) {
return &it->second.meta;
}
- auto metaPair = updateMapsForFile(ino);
+ auto metaPair = updateMapsForFile(id);
if (!metaPair) {
return nullptr;
}
@@ -437,13 +445,13 @@
return &metaPair->meta;
}
- FileId* getFileId(android::dataloader::Inode ino) {
- auto it = mNodeToMetaMap.find(ino);
+ FileId* getFileId(android::dataloader::FileId id) {
+ auto it = mNodeToMetaMap.find(id);
if (it != mNodeToMetaMap.end()) {
return &it->second.fileId;
}
- auto* metaPair = updateMapsForFile(ino);
+ auto* metaPair = updateMapsForFile(id);
if (!metaPair) {
return nullptr;
}
@@ -456,7 +464,7 @@
return;
}
if (trace) {
- auto* meta = getMeta(read.fileIno);
+ auto* meta = getMeta(read.fileId);
auto str = android::base::StringPrintf(
"page_read: index=%lld count=%lld meta=%.*s",
static_cast<long long>(read.firstBlockIdx),
@@ -468,7 +476,7 @@
if (log) {
mReadLog.reserve(ReadLogBufferSize);
- auto fileId = getFileId(read.fileIno);
+ auto fileId = getFileId(read.fileId);
android::base::StringAppendF(
&mReadLog, "%lld:%lld:%lld:%lld\n",
static_cast<long long>(read.timestampUs),
@@ -501,8 +509,8 @@
std::string mReadLog;
std::thread mReceiverThread;
std::mutex mMapsMutex;
- std::unordered_map<android::dataloader::Inode, MetaPair> mNodeToMetaMap GUARDED_BY(mMapsMutex);
- std::unordered_map<FileId, android::dataloader::Inode> mIdToNodeMap GUARDED_BY(mMapsMutex);
+ std::unordered_map<android::dataloader::FileId, MetaPair> mNodeToMetaMap GUARDED_BY(mMapsMutex);
+ std::unordered_map<FileId, android::dataloader::FileId> mIdToNodeMap GUARDED_BY(mMapsMutex);
/** Tracks which files have been requested */
std::unordered_set<FileId> mRequestedFiles;
std::atomic<bool> mStopReceiving = false;
diff --git a/services/core/java/com/android/server/incremental/IncrementalManagerService.java b/services/core/java/com/android/server/incremental/IncrementalManagerService.java
index d673ec8..5876d43 100644
--- a/services/core/java/com/android/server/incremental/IncrementalManagerService.java
+++ b/services/core/java/com/android/server/incremental/IncrementalManagerService.java
@@ -134,7 +134,7 @@
// TODO: remove this
@Override
- public void newFileForDataLoader(int mountId, long inode, byte[] metadata) {
+ public void newFileForDataLoader(int mountId, byte[] fileId, byte[] metadata) {
IDataLoader dataLoader = mDataLoaderManager.getDataLoader(mountId);
if (dataLoader == null) {
Slog.e(TAG, "Failed to retrieve data loader for ID=" + mountId);
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 ¶ms,
- 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