summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/os/incremental/IIncrementalService.aidl29
-rw-r--r--core/java/android/os/incremental/IncrementalFileStorages.java91
-rw-r--r--core/java/android/os/incremental/IncrementalManager.java26
-rw-r--r--core/java/android/os/incremental/IncrementalStorage.java39
4 files changed, 119 insertions, 66 deletions
diff --git a/core/java/android/os/incremental/IIncrementalService.aidl b/core/java/android/os/incremental/IIncrementalService.aidl
index 7db5a80b6cf9..3fbc28402405 100644
--- a/core/java/android/os/incremental/IIncrementalService.aidl
+++ b/core/java/android/os/incremental/IIncrementalService.aidl
@@ -38,14 +38,20 @@ interface IIncrementalService {
* Opens or creates a storage given a target path and data loader params. Returns the storage ID.
*/
int openStorage(in @utf8InCpp String path);
- int createStorage(in @utf8InCpp String path, in DataLoaderParamsParcel params, int createMode,
- in IDataLoaderStatusListener statusListener,
- in StorageHealthCheckParams healthCheckParams,
- in IStorageHealthListener healthListener,
- in PerUidReadTimeouts[] perUidReadTimeouts);
+ int createStorage(in @utf8InCpp String path, in DataLoaderParamsParcel params, int createMode);
int createLinkedStorage(in @utf8InCpp String path, int otherStorageId, int createMode);
/**
+ * Loops DataLoader through bind/create/start with params.
+ */
+ boolean startLoading(int storageId,
+ in DataLoaderParamsParcel params,
+ in IDataLoaderStatusListener statusListener,
+ in StorageHealthCheckParams healthCheckParams,
+ in IStorageHealthListener healthListener,
+ in PerUidReadTimeouts[] perUidReadTimeouts);
+
+ /**
* Bind-mounts a path under a storage to a full path. Can be permanent or temporary.
*/
const int BIND_TEMPORARY = 0;
@@ -101,6 +107,14 @@ interface IIncrementalService {
int isFileFullyLoaded(int storageId, in @utf8InCpp String path);
/**
+ * Checks if all files in the storage are fully loaded.
+ * 0 - fully loaded
+ * >0 - certain pages missing
+ * <0 - -errcode
+ */
+ int isFullyLoaded(int storageId);
+
+ /**
* Returns overall loading progress of all the files on a storage, progress value between [0,1].
* Returns a negative value on error.
*/
@@ -113,11 +127,6 @@ interface IIncrementalService {
byte[] getMetadataById(int storageId, in byte[] fileId);
/**
- * Starts loading data for a storage.
- */
- boolean startLoading(int storageId);
-
- /**
* Deletes a storage given its ID. Deletes its bind mounts and unmount it. Stop its data loader.
*/
void deleteStorage(int storageId);
diff --git a/core/java/android/os/incremental/IncrementalFileStorages.java b/core/java/android/os/incremental/IncrementalFileStorages.java
index 59292baa110c..f2fe71913bb1 100644
--- a/core/java/android/os/incremental/IncrementalFileStorages.java
+++ b/core/java/android/os/incremental/IncrementalFileStorages.java
@@ -37,7 +37,6 @@ import android.content.Context;
import android.content.pm.DataLoaderParams;
import android.content.pm.IDataLoaderStatusListener;
import android.content.pm.InstallationFileParcel;
-import android.text.TextUtils;
import java.io.File;
import java.io.IOException;
@@ -53,6 +52,7 @@ public final class IncrementalFileStorages {
private @NonNull final IncrementalManager mIncrementalManager;
private @NonNull final File mStageDir;
+ private @Nullable IncrementalStorage mInheritedStorage;
private @Nullable IncrementalStorage mDefaultStorage;
/**
@@ -65,6 +65,7 @@ public final class IncrementalFileStorages {
*/
public static IncrementalFileStorages initialize(Context context,
@NonNull File stageDir,
+ @Nullable File inheritedDir,
@NonNull DataLoaderParams dataLoaderParams,
@Nullable IDataLoaderStatusListener statusListener,
@Nullable StorageHealthCheckParams healthCheckParams,
@@ -79,9 +80,8 @@ public final class IncrementalFileStorages {
throw new IOException("Failed to obtain incrementalManager.");
}
- final IncrementalFileStorages result = new IncrementalFileStorages(stageDir,
- incrementalManager, dataLoaderParams, statusListener, healthCheckParams,
- healthListener, perUidReadTimeouts);
+ final IncrementalFileStorages result = new IncrementalFileStorages(stageDir, inheritedDir,
+ incrementalManager, dataLoaderParams);
for (InstallationFileParcel file : addedFiles) {
if (file.location == LOCATION_DATA_APP) {
try {
@@ -95,43 +95,46 @@ public final class IncrementalFileStorages {
throw new IOException("Unknown file location: " + file.location);
}
}
-
- result.startLoading();
+ result.startLoading(dataLoaderParams, statusListener, healthCheckParams, healthListener,
+ perUidReadTimeouts);
return result;
}
private IncrementalFileStorages(@NonNull File stageDir,
+ @Nullable File inheritedDir,
@NonNull IncrementalManager incrementalManager,
- @NonNull DataLoaderParams dataLoaderParams,
- @Nullable IDataLoaderStatusListener statusListener,
- @Nullable StorageHealthCheckParams healthCheckParams,
- @Nullable IStorageHealthListener healthListener,
- @NonNull PerUidReadTimeouts[] perUidReadTimeouts) throws IOException {
+ @NonNull DataLoaderParams dataLoaderParams) throws IOException {
try {
mStageDir = stageDir;
mIncrementalManager = incrementalManager;
- if (dataLoaderParams.getComponentName().getPackageName().equals("local")) {
- final String incrementalPath = dataLoaderParams.getArguments();
- if (TextUtils.isEmpty(incrementalPath)) {
- throw new IOException("Failed to create storage: incrementalPath is empty");
- }
- mDefaultStorage = mIncrementalManager.openStorage(incrementalPath);
- if (mDefaultStorage == null) {
- throw new IOException(
- "Couldn't open incremental storage at " + incrementalPath);
- }
- mDefaultStorage.bind(stageDir.getAbsolutePath());
- } else {
- mDefaultStorage = mIncrementalManager.createStorage(stageDir.getAbsolutePath(),
- dataLoaderParams, IncrementalManager.CREATE_MODE_CREATE
- | IncrementalManager.CREATE_MODE_TEMPORARY_BIND, false,
- statusListener, healthCheckParams, healthListener, perUidReadTimeouts);
- if (mDefaultStorage == null) {
- throw new IOException(
- "Couldn't create incremental storage at " + stageDir);
+ if (inheritedDir != null && IncrementalManager.isIncrementalPath(
+ inheritedDir.getAbsolutePath())) {
+ mInheritedStorage = mIncrementalManager.openStorage(
+ inheritedDir.getAbsolutePath());
+ if (mInheritedStorage != null) {
+ if (!mInheritedStorage.isFullyLoaded()) {
+ throw new IOException("Inherited storage has missing pages.");
+ }
+
+ mDefaultStorage = mIncrementalManager.createStorage(stageDir.getAbsolutePath(),
+ mInheritedStorage, IncrementalManager.CREATE_MODE_CREATE
+ | IncrementalManager.CREATE_MODE_TEMPORARY_BIND);
+ if (mDefaultStorage == null) {
+ throw new IOException(
+ "Couldn't create linked incremental storage at " + stageDir);
+ }
+ return;
}
}
+
+ mDefaultStorage = mIncrementalManager.createStorage(stageDir.getAbsolutePath(),
+ dataLoaderParams, IncrementalManager.CREATE_MODE_CREATE
+ | IncrementalManager.CREATE_MODE_TEMPORARY_BIND);
+ if (mDefaultStorage == null) {
+ throw new IOException(
+ "Couldn't create incremental storage at " + stageDir);
+ }
} catch (IOException e) {
cleanUp();
throw e;
@@ -149,9 +152,16 @@ public final class IncrementalFileStorages {
/**
* Starts or re-starts loading of data.
*/
- public void startLoading() throws IOException {
- if (!mDefaultStorage.startLoading()) {
- throw new IOException("Failed to start loading data for Incremental installation.");
+ void startLoading(
+ @NonNull DataLoaderParams dataLoaderParams,
+ @Nullable IDataLoaderStatusListener statusListener,
+ @Nullable StorageHealthCheckParams healthCheckParams,
+ @Nullable IStorageHealthListener healthListener,
+ @NonNull PerUidReadTimeouts[] perUidReadTimeouts) throws IOException {
+ if (!mDefaultStorage.startLoading(dataLoaderParams, statusListener, healthCheckParams,
+ healthListener, perUidReadTimeouts)) {
+ throw new IOException(
+ "Failed to start or restart loading data for Incremental installation.");
}
}
@@ -163,6 +173,21 @@ public final class IncrementalFileStorages {
}
/**
+ * Creates a hardlink from inherited storage to default.
+ */
+ public boolean makeLink(@NonNull String relativePath, @NonNull String fromBase,
+ @NonNull String toBase) throws IOException {
+ if (mInheritedStorage == null) {
+ return false;
+ }
+ final File sourcePath = new File(fromBase, relativePath);
+ final File destPath = new File(toBase, relativePath);
+ mInheritedStorage.makeLink(sourcePath.getAbsolutePath(), mDefaultStorage,
+ destPath.getAbsolutePath());
+ return true;
+ }
+
+ /**
* Permanently disables readlogs.
*/
public void disallowReadLogs() {
diff --git a/core/java/android/os/incremental/IncrementalManager.java b/core/java/android/os/incremental/IncrementalManager.java
index 4b9327021cb0..7e7057fe56cb 100644
--- a/core/java/android/os/incremental/IncrementalManager.java
+++ b/core/java/android/os/incremental/IncrementalManager.java
@@ -22,7 +22,6 @@ import android.annotation.Nullable;
import android.annotation.SystemService;
import android.content.Context;
import android.content.pm.DataLoaderParams;
-import android.content.pm.IDataLoaderStatusListener;
import android.content.pm.IPackageLoadingProgressCallback;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -95,32 +94,20 @@ public final class IncrementalManager {
* @param params IncrementalDataLoaderParams object to configure data loading.
* @param createMode Mode for opening an old Incremental File System mount or creating
* a new mount.
- * @param autoStartDataLoader Set true to immediately start data loader after creating storage.
* @return IncrementalStorage object corresponding to the mounted directory.
*/
@Nullable
public IncrementalStorage createStorage(@NonNull String path,
@NonNull DataLoaderParams params,
- @CreateMode int createMode,
- boolean autoStartDataLoader,
- @Nullable IDataLoaderStatusListener statusListener,
- @Nullable StorageHealthCheckParams healthCheckParams,
- @Nullable IStorageHealthListener healthListener,
- @NonNull PerUidReadTimeouts[] perUidReadTimeouts) {
+ @CreateMode int createMode) {
Objects.requireNonNull(path);
Objects.requireNonNull(params);
- Objects.requireNonNull(perUidReadTimeouts);
try {
- final int id = mService.createStorage(path, params.getData(), createMode,
- statusListener, healthCheckParams, healthListener, perUidReadTimeouts);
+ final int id = mService.createStorage(path, params.getData(), createMode);
if (id < 0) {
return null;
}
- final IncrementalStorage storage = new IncrementalStorage(mService, id);
- if (autoStartDataLoader) {
- storage.startLoading();
- }
- return storage;
+ return new IncrementalStorage(mService, id);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -281,15 +268,18 @@ public final class IncrementalManager {
* Unbinds the target dir and deletes the corresponding storage instance.
* Deletes the package name and associated storage id from maps.
*/
- public void onPackageRemoved(@NonNull String codePath) {
+ public void onPackageRemoved(@NonNull File codeFile) {
try {
+ final String codePath = codeFile.getAbsolutePath();
final IncrementalStorage storage = openStorage(codePath);
if (storage == null) {
return;
}
mLoadingProgressCallbacks.cleanUpCallbacks(storage);
unregisterHealthListener(codePath);
- mService.deleteStorage(storage.getId());
+
+ // Parent since we bind-mount a folder one level above.
+ mService.deleteBindMount(storage.getId(), codeFile.getParent());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/os/incremental/IncrementalStorage.java b/core/java/android/os/incremental/IncrementalStorage.java
index 5b688bbd0655..e6ce8cd56d28 100644
--- a/core/java/android/os/incremental/IncrementalStorage.java
+++ b/core/java/android/os/incremental/IncrementalStorage.java
@@ -18,11 +18,14 @@ package android.os.incremental;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.pm.DataLoaderParams;
+import android.content.pm.IDataLoaderStatusListener;
import android.os.RemoteException;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.Objects;
import java.util.UUID;
/**
@@ -323,6 +326,24 @@ public final class IncrementalStorage {
}
}
+
+ /**
+ * Checks if all files in the storage are fully loaded.
+ */
+ public boolean isFullyLoaded() throws IOException {
+ try {
+ final int res = mService.isFullyLoaded(mId);
+ if (res < 0) {
+ throw new IOException(
+ "isFullyLoaded() failed at querying loading progress, errno " + -res);
+ }
+ return res == 0;
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return false;
+ }
+ }
+
/**
* Returns the loading progress of a storage
*
@@ -376,13 +397,21 @@ public final class IncrementalStorage {
}
/**
- * Informs the data loader service associated with the current storage to start data loader
- *
- * @return True if data loader is successfully started.
+ * Iinitializes and starts the DataLoader.
+ * This makes sure all install-time parameters are applied.
+ * Does not affect persistent DataLoader params.
+ * @return True if start request was successfully queued.
*/
- public boolean startLoading() {
+ public boolean startLoading(
+ @NonNull DataLoaderParams dataLoaderParams,
+ @Nullable IDataLoaderStatusListener statusListener,
+ @Nullable StorageHealthCheckParams healthCheckParams,
+ @Nullable IStorageHealthListener healthListener,
+ @NonNull PerUidReadTimeouts[] perUidReadTimeouts) {
+ Objects.requireNonNull(perUidReadTimeouts);
try {
- return mService.startLoading(mId);
+ return mService.startLoading(mId, dataLoaderParams.getData(), statusListener,
+ healthCheckParams, healthListener, perUidReadTimeouts);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
return false;