Migrating Incremental* APIs to PackageManager APIs.
This is the first step, migrating java parts.
CleanSpec.mk added as a workaround for b/146502407
Test: builds and flashes
Bug: b/136132412
Change-Id: Id0a26aa011b555ea457b5aafe7f5789c36d25bcc
diff --git a/Android.bp b/Android.bp
index 77abad6e..e14a352 100644
--- a/Android.bp
+++ b/Android.bp
@@ -807,9 +807,11 @@
filegroup {
name: "dataloader_aidl",
srcs: [
+ "core/java/android/content/pm/DataLoaderParamsParcel.aidl",
+ "core/java/android/content/pm/FileSystemControlParcel.aidl",
"core/java/android/content/pm/IDataLoaderStatusListener.aidl",
- "core/java/android/os/incremental/IncrementalDataLoaderParamsParcel.aidl",
- "core/java/android/os/incremental/NamedParcelFileDescriptor.aidl",
+ "core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl",
+ "core/java/android/content/pm/NamedParcelFileDescriptor.aidl",
],
path: "core/java",
}
diff --git a/CleanSpec.mk b/CleanSpec.mk
index f94de29..b84e715 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -257,6 +257,8 @@
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony/java/com/google/android/mms)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/*-service.jar)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/service-statsd.jar)
+$(call add-clean-step, rm -rf $(SOONG_OUT_DIR)/.intermediates/frameworks/base/libincremental_aidl-cpp-source/)
+$(call add-clean-step, rm -rf $(SOONG_OUT_DIR)/.intermediates/frameworks/base/libincremental_manager_aidl-cpp-source/)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
# ******************************************************************
diff --git a/core/java/android/os/incremental/IncrementalDataLoaderParams.java b/core/java/android/content/pm/DataLoaderParams.java
similarity index 82%
rename from core/java/android/os/incremental/IncrementalDataLoaderParams.java
rename to core/java/android/content/pm/DataLoaderParams.java
index 701f1cc..b163861 100644
--- a/core/java/android/os/incremental/IncrementalDataLoaderParams.java
+++ b/core/java/android/content/pm/DataLoaderParams.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.os.incremental;
+package android.content.pm;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -29,12 +29,12 @@
* Hide for now.
* @hide
*/
-public class IncrementalDataLoaderParams {
- @NonNull private final IncrementalDataLoaderParamsParcel mData;
+public class DataLoaderParams {
+ @NonNull private final DataLoaderParamsParcel mData;
- public IncrementalDataLoaderParams(@NonNull String url, @NonNull String packageName,
+ public DataLoaderParams(@NonNull String url, @NonNull String packageName,
@Nullable Map<String, ParcelFileDescriptor> namedFds) {
- IncrementalDataLoaderParamsParcel data = new IncrementalDataLoaderParamsParcel();
+ DataLoaderParamsParcel data = new DataLoaderParamsParcel();
data.staticArgs = url;
data.packageName = packageName;
if (namedFds == null || namedFds.isEmpty()) {
@@ -52,7 +52,7 @@
mData = data;
}
- public IncrementalDataLoaderParams(@NonNull IncrementalDataLoaderParamsParcel data) {
+ public DataLoaderParams(@NonNull DataLoaderParamsParcel data) {
mData = data;
}
@@ -70,7 +70,7 @@
return mData.packageName;
}
- public final @NonNull IncrementalDataLoaderParamsParcel getData() {
+ public final @NonNull DataLoaderParamsParcel getData() {
return mData;
}
diff --git a/core/java/android/os/incremental/IncrementalDataLoaderParamsParcel.aidl b/core/java/android/content/pm/DataLoaderParamsParcel.aidl
similarity index 85%
rename from core/java/android/os/incremental/IncrementalDataLoaderParamsParcel.aidl
rename to core/java/android/content/pm/DataLoaderParamsParcel.aidl
index cd988dc..3316398 100644
--- a/core/java/android/os/incremental/IncrementalDataLoaderParamsParcel.aidl
+++ b/core/java/android/content/pm/DataLoaderParamsParcel.aidl
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-package android.os.incremental;
+package android.content.pm;
-import android.os.incremental.NamedParcelFileDescriptor;
+import android.content.pm.NamedParcelFileDescriptor;
/**
* Class for holding data loader configuration parameters.
* @hide
*/
-parcelable IncrementalDataLoaderParamsParcel {
+parcelable DataLoaderParamsParcel {
@utf8InCpp String packageName;
@utf8InCpp String staticArgs;
NamedParcelFileDescriptor[] dynamicArgs;
diff --git a/core/java/android/content/pm/FileSystemControlParcel.aidl b/core/java/android/content/pm/FileSystemControlParcel.aidl
new file mode 100644
index 0000000..f00feae
--- /dev/null
+++ b/core/java/android/content/pm/FileSystemControlParcel.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 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.content.pm;
+
+import android.content.pm.IPackageInstallerSessionFileSystemConnector;
+import android.os.incremental.IncrementalFileSystemControlParcel;
+
+/**
+ * Wraps info needed for DataLoader to provide data.
+ * @hide
+ */
+parcelable FileSystemControlParcel {
+ // Incremental FS control descriptors.
+ @nullable IncrementalFileSystemControlParcel incremental;
+ // Callback-based installation connector.
+ @nullable IPackageInstallerSessionFileSystemConnector callback;
+}
diff --git a/core/java/android/content/pm/IDataLoader.aidl b/core/java/android/content/pm/IDataLoader.aidl
index 60cc9ba9..c65bd6a 100644
--- a/core/java/android/content/pm/IDataLoader.aidl
+++ b/core/java/android/content/pm/IDataLoader.aidl
@@ -30,5 +30,4 @@
void start(in List<InstallationFile> fileInfos);
void stop();
void destroy();
- void onFileCreated(long inode, in byte[] metadata);
}
diff --git a/core/java/android/os/incremental/NamedParcelFileDescriptor.aidl b/core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl
similarity index 76%
copy from core/java/android/os/incremental/NamedParcelFileDescriptor.aidl
copy to core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl
index 038ced1..4b2f29e 100644
--- a/core/java/android/os/incremental/NamedParcelFileDescriptor.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl
@@ -14,15 +14,11 @@
* limitations under the License.
*/
-package android.os.incremental;
+package android.content.pm;
import android.os.ParcelFileDescriptor;
-/**
- * A named ParcelFileDescriptor.
- * @hide
- */
-parcelable NamedParcelFileDescriptor {
- @utf8InCpp String name;
- ParcelFileDescriptor fd;
+/** {@hide} */
+interface IPackageInstallerSessionFileSystemConnector {
+ void writeData(String name, long offsetBytes, long lengthBytes, in ParcelFileDescriptor fd);
}
diff --git a/core/java/android/os/incremental/NamedParcelFileDescriptor.aidl b/core/java/android/content/pm/NamedParcelFileDescriptor.aidl
similarity index 95%
rename from core/java/android/os/incremental/NamedParcelFileDescriptor.aidl
rename to core/java/android/content/pm/NamedParcelFileDescriptor.aidl
index 038ced1..68dd5f5 100644
--- a/core/java/android/os/incremental/NamedParcelFileDescriptor.aidl
+++ b/core/java/android/content/pm/NamedParcelFileDescriptor.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.os.incremental;
+package android.content.pm;
import android.os.ParcelFileDescriptor;
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 898631e..218c876 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -50,8 +50,6 @@
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
-import android.os.incremental.IncrementalDataLoaderParams;
-import android.os.incremental.IncrementalDataLoaderParamsParcel;
import android.system.ErrnoException;
import android.system.Os;
import android.util.ArraySet;
@@ -1459,7 +1457,7 @@
/** {@hide} */
public long requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST;
/** {@hide} */
- public IncrementalDataLoaderParams incrementalParams;
+ public DataLoaderParams incrementalParams;
/** TODO(b/146080380): add a class name to make it fully compatible with ComponentName.
* {@hide} */
public String dataLoaderPackageName;
@@ -1496,10 +1494,10 @@
isMultiPackage = source.readBoolean();
isStaged = source.readBoolean();
requiredInstalledVersionCode = source.readLong();
- IncrementalDataLoaderParamsParcel dataLoaderParamsParcel = source.readParcelable(
- IncrementalDataLoaderParamsParcel.class.getClassLoader());
+ DataLoaderParamsParcel dataLoaderParamsParcel = source.readParcelable(
+ DataLoaderParamsParcel.class.getClassLoader());
if (dataLoaderParamsParcel != null) {
- incrementalParams = new IncrementalDataLoaderParams(
+ incrementalParams = new DataLoaderParams(
dataLoaderParamsParcel);
}
dataLoaderPackageName = source.readString();
@@ -1863,7 +1861,7 @@
* {@hide}
*/
@RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
- public void setIncrementalParams(@NonNull IncrementalDataLoaderParams incrementalParams) {
+ public void setIncrementalParams(@NonNull DataLoaderParams incrementalParams) {
this.incrementalParams = incrementalParams;
}
diff --git a/core/java/android/os/incremental/IIncrementalManager.aidl b/core/java/android/os/incremental/IIncrementalManager.aidl
index f84d7ef..17a310a 100644
--- a/core/java/android/os/incremental/IIncrementalManager.aidl
+++ b/core/java/android/os/incremental/IIncrementalManager.aidl
@@ -16,8 +16,8 @@
package android.os.incremental;
-import android.os.incremental.IncrementalFileSystemControlParcel;
-import android.os.incremental.IncrementalDataLoaderParamsParcel;
+import android.content.pm.FileSystemControlParcel;
+import android.content.pm.DataLoaderParamsParcel;
import android.content.pm.IDataLoaderStatusListener;
/**
@@ -27,8 +27,8 @@
*/
interface IIncrementalManager {
boolean prepareDataLoader(int mountId,
- in IncrementalFileSystemControlParcel control,
- in IncrementalDataLoaderParamsParcel params,
+ in FileSystemControlParcel control,
+ in DataLoaderParamsParcel params,
in IDataLoaderStatusListener listener);
boolean startDataLoader(int mountId);
void showHealthBlockedUI(int mountId);
diff --git a/core/java/android/os/incremental/IIncrementalManagerNative.aidl b/core/java/android/os/incremental/IIncrementalManagerNative.aidl
index d9c7c6b..14215b1 100644
--- a/core/java/android/os/incremental/IIncrementalManagerNative.aidl
+++ b/core/java/android/os/incremental/IIncrementalManagerNative.aidl
@@ -16,7 +16,7 @@
package android.os.incremental;
-import android.os.incremental.IncrementalDataLoaderParamsParcel;
+import android.content.pm.DataLoaderParamsParcel;
/** @hide */
interface IIncrementalManagerNative {
@@ -32,7 +32,7 @@
* 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 IncrementalDataLoaderParamsParcel params, int createMode);
+ int createStorage(in @utf8InCpp String path, in DataLoaderParamsParcel params, int createMode);
int createLinkedStorage(in @utf8InCpp String path, int otherStorageId, int createMode);
/**
diff --git a/core/java/android/os/incremental/IncrementalFileStorages.java b/core/java/android/os/incremental/IncrementalFileStorages.java
index 5bd0748..7987efd 100644
--- a/core/java/android/os/incremental/IncrementalFileStorages.java
+++ b/core/java/android/os/incremental/IncrementalFileStorages.java
@@ -35,6 +35,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.pm.DataLoaderParams;
import android.content.pm.InstallationFile;
import android.os.IVold;
import android.os.RemoteException;
@@ -82,12 +83,12 @@
public IncrementalFileStorages(@NonNull String packageName,
@NonNull File stageDir,
@NonNull IncrementalManager incrementalManager,
- @NonNull IncrementalDataLoaderParams incrementalDataLoaderParams) {
+ @NonNull DataLoaderParams dataLoaderParams) {
mPackageName = packageName;
mStageDir = stageDir;
mIncrementalManager = incrementalManager;
- if (incrementalDataLoaderParams.getPackageName().equals("local")) {
- final String incrementalPath = incrementalDataLoaderParams.getStaticArgs();
+ if (dataLoaderParams.getPackageName().equals("local")) {
+ final String incrementalPath = dataLoaderParams.getStaticArgs();
mDefaultStorage = mIncrementalManager.openStorage(incrementalPath);
mDefaultDir = incrementalPath;
return;
@@ -97,7 +98,7 @@
return;
}
mDefaultStorage = mIncrementalManager.createStorage(mDefaultDir,
- incrementalDataLoaderParams,
+ dataLoaderParams,
IncrementalManager.CREATE_MODE_CREATE
| IncrementalManager.CREATE_MODE_TEMPORARY_BIND, false);
}
diff --git a/core/java/android/os/incremental/IncrementalManager.java b/core/java/android/os/incremental/IncrementalManager.java
index c30f558..c722287 100644
--- a/core/java/android/os/incremental/IncrementalManager.java
+++ b/core/java/android/os/incremental/IncrementalManager.java
@@ -21,6 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.content.Context;
+import android.content.pm.DataLoaderParams;
import android.os.RemoteException;
import android.system.ErrnoException;
import android.system.Os;
@@ -104,7 +105,7 @@
*/
@Nullable
public IncrementalStorage createStorage(@NonNull String path,
- @NonNull IncrementalDataLoaderParams params, @CreateMode int createMode,
+ @NonNull DataLoaderParams params, @CreateMode int createMode,
boolean autoStartDataLoader) {
try {
final int id = mNativeService.createStorage(path, params.getData(), createMode);
diff --git a/core/java/android/service/dataloader/DataLoaderService.java b/core/java/android/service/dataloader/DataLoaderService.java
new file mode 100644
index 0000000..373e1e5
--- /dev/null
+++ b/core/java/android/service/dataloader/DataLoaderService.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2019 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.service.dataloader;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Service;
+import android.content.Intent;
+import android.content.pm.DataLoaderParams;
+import android.content.pm.DataLoaderParamsParcel;
+import android.content.pm.FileSystemControlParcel;
+import android.content.pm.IDataLoader;
+import android.content.pm.IDataLoaderStatusListener;
+import android.content.pm.IPackageInstallerSessionFileSystemConnector;
+import android.content.pm.InstallationFile;
+import android.content.pm.NamedParcelFileDescriptor;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.util.ExceptionUtils;
+import android.util.Slog;
+
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+
+/**
+ * The base class for implementing data loader service to control data loaders. Expecting
+ * Incremental Service to bind to a children class of this.
+ *
+ * @hide
+ *
+ * Hide for now, should be @SystemApi
+ * TODO(b/136132412): update with latest API design
+ */
+public abstract class DataLoaderService extends Service {
+ private static final String TAG = "IncrementalDataLoaderService";
+ private final DataLoaderBinderService mBinder = new DataLoaderBinderService();
+
+ public static final int DATA_LOADER_READY =
+ IDataLoaderStatusListener.DATA_LOADER_READY;
+ public static final int DATA_LOADER_NOT_READY =
+ IDataLoaderStatusListener.DATA_LOADER_NOT_READY;
+ public static final int DATA_LOADER_RUNNING =
+ IDataLoaderStatusListener.DATA_LOADER_RUNNING;
+ public static final int DATA_LOADER_STOPPED =
+ IDataLoaderStatusListener.DATA_LOADER_STOPPED;
+ public static final int DATA_LOADER_SLOW_CONNECTION =
+ IDataLoaderStatusListener.DATA_LOADER_SLOW_CONNECTION;
+ public static final int DATA_LOADER_NO_CONNECTION =
+ IDataLoaderStatusListener.DATA_LOADER_NO_CONNECTION;
+ public static final int DATA_LOADER_CONNECTION_OK =
+ IDataLoaderStatusListener.DATA_LOADER_CONNECTION_OK;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"DATA_LOADER_"}, value = {
+ DATA_LOADER_READY,
+ DATA_LOADER_NOT_READY,
+ DATA_LOADER_RUNNING,
+ DATA_LOADER_STOPPED,
+ DATA_LOADER_SLOW_CONNECTION,
+ DATA_LOADER_NO_CONNECTION,
+ DATA_LOADER_CONNECTION_OK
+ })
+ public @interface DataLoaderStatus {
+ }
+
+ /**
+ * Managed DataLoader interface. Each instance corresponds to a single Incremental File System
+ * instance.
+ */
+ public abstract static class DataLoader {
+ /**
+ * A virtual constructor used to do simple initialization. Not ready to serve any data yet.
+ * All heavy-lifting has to be done in onStart.
+ *
+ * @param params Data loader configuration parameters.
+ * @param connector IncFS API wrapper.
+ * @param listener Used for reporting internal state to IncrementalService.
+ * @return True if initialization of a Data Loader was successful. False will be reported to
+ * IncrementalService and can cause an unmount of an IFS instance.
+ */
+ public abstract boolean onCreate(@NonNull DataLoaderParams params,
+ @NonNull FileSystemConnector connector,
+ @NonNull StatusListener listener);
+
+ /**
+ * Start the data loader. After this method returns data loader is considered to be ready to
+ * receive callbacks from IFS, supply data via connector and send status updates via
+ * callbacks.
+ *
+ * @return True if Data Loader was able to start. False will be reported to
+ * IncrementalService and can cause an unmount of an IFS instance.
+ */
+ public abstract boolean onStart();
+
+ /**
+ * Stop the data loader. Use to stop any additional threads and free up resources. Data
+ * loader is not longer responsible for supplying data. Start/Stop pair can be called
+ * multiple times e.g. if IFS detects corruption and data needs to be re-loaded.
+ */
+ public abstract void onStop();
+
+ /**
+ * Virtual destructor. Use to cleanup all internal state. After this method returns, the
+ * data loader can no longer use connector or callbacks. For any additional operations with
+ * this instance of IFS a new DataLoader will be created using createDataLoader method.
+ */
+ public abstract void onDestroy();
+ }
+
+ /**
+ * DataLoader factory method.
+ *
+ * @return An instance of a DataLoader.
+ */
+ public abstract @Nullable DataLoader onCreateDataLoader();
+
+ /**
+ * @hide
+ */
+ public final @NonNull IBinder onBind(@NonNull Intent intent) {
+ return (IBinder) mBinder;
+ }
+
+ private class DataLoaderBinderService extends IDataLoader.Stub {
+ private int mId;
+
+ @Override
+ public void create(int id, @NonNull Bundle options,
+ @NonNull IDataLoaderStatusListener listener)
+ throws IllegalArgumentException, RuntimeException {
+ mId = id;
+ final DataLoaderParamsParcel params = options.getParcelable("params");
+ if (params == null) {
+ throw new IllegalArgumentException("Must specify Incremental data loader params");
+ }
+ final FileSystemControlParcel control =
+ options.getParcelable("control");
+ if (control == null) {
+ throw new IllegalArgumentException("Must specify Incremental control parcel");
+ }
+ mStatusListener = listener;
+ try {
+ if (!nativeCreateDataLoader(id, control, params, listener)) {
+ Slog.e(TAG, "Failed to create native loader for " + mId);
+ }
+ } catch (Exception ex) {
+ destroy();
+ throw new RuntimeException(ex);
+ } finally {
+ // Closing FDs.
+ if (control.incremental.cmd != null) {
+ try {
+ control.incremental.cmd.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to close IncFs CMD file descriptor " + e);
+ }
+ }
+ if (control.incremental.log != null) {
+ try {
+ control.incremental.log.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to close IncFs LOG file descriptor " + e);
+ }
+ }
+ NamedParcelFileDescriptor[] fds = params.dynamicArgs;
+ for (NamedParcelFileDescriptor nfd : fds) {
+ try {
+ nfd.fd.close();
+ } catch (IOException e) {
+ Slog.e(TAG,
+ "Failed to close DynamicArgs parcel file descriptor " + e);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void start(List<InstallationFile> fileInfos) {
+ if (!nativeStartDataLoader(mId)) {
+ Slog.e(TAG, "Failed to start loader: loader not found for " + mId);
+ }
+ }
+
+ @Override
+ public void stop() {
+ if (!nativeStopDataLoader(mId)) {
+ Slog.w(TAG, "Failed to stop loader: loader not found for " + mId);
+ }
+ }
+
+ @Override
+ public void destroy() {
+ if (!nativeDestroyDataLoader(mId)) {
+ Slog.w(TAG, "Failed to destroy loader: loader not found for " + mId);
+ }
+ }
+ }
+
+ /**
+ *
+ * Used by the DataLoaderService implementations.
+ *
+ * @hide
+ *
+ * TODO(b/136132412) Should be @SystemApi
+ */
+ public static final class FileSystemConnector {
+ /**
+ * Creates a wrapper for an installation session connector.
+ * @hide
+ */
+ FileSystemConnector(IPackageInstallerSessionFileSystemConnector connector) {
+ mConnector = connector;
+ }
+
+ /**
+ * Write data to an installation file from an arbitrary FD.
+ *
+ * @param name name of file previously added to the installation session.
+ * @param offsetBytes offset into the file to begin writing at, or 0 to
+ * start at the beginning of the file.
+ * @param lengthBytes total size of the file being written, used to
+ * preallocate the underlying disk space, or -1 if unknown.
+ * The system may clear various caches as needed to allocate
+ * this space.
+ * @param incomingFd FD to read bytes from.
+ * @throws IOException if trouble opening the file for writing, such as
+ * lack of disk space or unavailable media.
+ */
+ public void writeData(String name, long offsetBytes, long lengthBytes,
+ ParcelFileDescriptor incomingFd) throws IOException {
+ try {
+ mConnector.writeData(name, offsetBytes, lengthBytes, incomingFd);
+ } catch (RuntimeException e) {
+ ExceptionUtils.maybeUnwrapIOException(e);
+ throw e;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private final IPackageInstallerSessionFileSystemConnector mConnector;
+ }
+
+ /**
+ * Wrapper for native reporting DataLoader statuses.
+ * @hide
+ * TODO(b/136132412) Should be @SystemApi
+ */
+ public static final class StatusListener {
+ /**
+ * Creates a wrapper for a native instance.
+ * @hide
+ */
+ StatusListener(long nativeInstance) {
+ mNativeInstance = nativeInstance;
+ }
+
+ /**
+ * Report the status of DataLoader. Used for system-wide notifications e.g., disabling
+ * applications which rely on this data loader to function properly.
+ *
+ * @param status status to report.
+ * @return True if status was reported successfully.
+ */
+ public boolean onStatusChanged(@DataLoaderStatus int status) {
+ return nativeReportStatus(mNativeInstance, status);
+ }
+
+ private final long mNativeInstance;
+ }
+
+ private IDataLoaderStatusListener mStatusListener = null;
+
+ /* Native methods */
+ private native boolean nativeCreateDataLoader(int storageId,
+ @NonNull FileSystemControlParcel control,
+ @NonNull DataLoaderParamsParcel params,
+ IDataLoaderStatusListener listener);
+
+ private native boolean nativeStartDataLoader(int storageId);
+
+ private native boolean nativeStopDataLoader(int storageId);
+
+ private native boolean nativeDestroyDataLoader(int storageId);
+
+ private static native boolean nativeReportStatus(long nativeInstance, int status);
+}
diff --git a/core/java/android/service/incremental/IncrementalDataLoaderService.java b/core/java/android/service/incremental/IncrementalDataLoaderService.java
deleted file mode 100644
index c4a06c8..0000000
--- a/core/java/android/service/incremental/IncrementalDataLoaderService.java
+++ /dev/null
@@ -1,563 +0,0 @@
-/*
- * Copyright (C) 2019 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.service.incremental;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.Service;
-import android.content.Intent;
-import android.content.pm.IDataLoader;
-import android.content.pm.IDataLoaderStatusListener;
-import android.content.pm.InstallationFile;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.incremental.IncrementalDataLoaderParams;
-import android.os.incremental.IncrementalDataLoaderParamsParcel;
-import android.os.incremental.IncrementalFileSystemControlParcel;
-import android.os.incremental.NamedParcelFileDescriptor;
-import android.util.Slog;
-
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Collection;
-import java.util.List;
-
-
-/**
- * The base class for implementing data loader service to control data loaders. Expecting
- * Incremental Service to bind to a children class of this.
- *
- * @hide
- *
- * Hide for now, should be @SystemApi
- * TODO(b/136132412): update with latest API design
- */
-public abstract class IncrementalDataLoaderService extends Service {
- private static final String TAG = "IncrementalDataLoaderService";
- private final DataLoaderBinderService mBinder = new DataLoaderBinderService();
-
- public static final int DATA_LOADER_READY =
- IDataLoaderStatusListener.DATA_LOADER_READY;
- public static final int DATA_LOADER_NOT_READY =
- IDataLoaderStatusListener.DATA_LOADER_NOT_READY;
- public static final int DATA_LOADER_RUNNING =
- IDataLoaderStatusListener.DATA_LOADER_RUNNING;
- public static final int DATA_LOADER_STOPPED =
- IDataLoaderStatusListener.DATA_LOADER_STOPPED;
- public static final int DATA_LOADER_SLOW_CONNECTION =
- IDataLoaderStatusListener.DATA_LOADER_SLOW_CONNECTION;
- public static final int DATA_LOADER_NO_CONNECTION =
- IDataLoaderStatusListener.DATA_LOADER_NO_CONNECTION;
- public static final int DATA_LOADER_CONNECTION_OK =
- IDataLoaderStatusListener.DATA_LOADER_CONNECTION_OK;
-
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = {"DATA_LOADER_"}, value = {
- DATA_LOADER_READY,
- DATA_LOADER_NOT_READY,
- DATA_LOADER_RUNNING,
- DATA_LOADER_STOPPED,
- DATA_LOADER_SLOW_CONNECTION,
- DATA_LOADER_NO_CONNECTION,
- DATA_LOADER_CONNECTION_OK
- })
- public @interface DataLoaderStatus {
- }
-
- /**
- * Incremental FileSystem block size.
- **/
- public static final int BLOCK_SIZE = 4096;
-
- /**
- * Data compression types
- */
- public static final int COMPRESSION_NONE = 0;
- public static final int COMPRESSION_LZ4 = 1;
-
- /**
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({COMPRESSION_NONE, COMPRESSION_LZ4})
- public @interface CompressionType {
- }
-
- /**
- * Managed DataLoader interface. Each instance corresponds to a single Incremental File System
- * instance.
- */
- public abstract static class DataLoader {
- /**
- * A virtual constructor used to do simple initialization. Not ready to serve any data yet.
- * All heavy-lifting has to be done in onStart.
- *
- * @param params Data loader configuration parameters.
- * @param connector IncFS API wrapper.
- * @param listener Used for reporting internal state to IncrementalService.
- * @return True if initialization of a Data Loader was successful. False will be reported to
- * IncrementalService and can cause an unmount of an IFS instance.
- */
- public abstract boolean onCreate(@NonNull IncrementalDataLoaderParams params,
- @NonNull FileSystemConnector connector,
- @NonNull StatusListener listener);
-
- /**
- * Start the data loader. After this method returns data loader is considered to be ready to
- * receive callbacks from IFS, supply data via connector and send status updates via
- * callbacks.
- *
- * @return True if Data Loader was able to start. False will be reported to
- * IncrementalService and can cause an unmount of an IFS instance.
- */
- public abstract boolean onStart();
-
- /**
- * Stop the data loader. Use to stop any additional threads and free up resources. Data
- * loader is not longer responsible for supplying data. Start/Stop pair can be called
- * multiple times e.g. if IFS detects corruption and data needs to be re-loaded.
- */
- public abstract void onStop();
-
- /**
- * Virtual destructor. Use to cleanup all internal state. After this method returns, the
- * data loader can no longer use connector or callbacks. For any additional operations with
- * this instance of IFS a new DataLoader will be created using createDataLoader method.
- */
- public abstract void onDestroy();
-
- /**
- * IFS reports a pending read each time the page needs to be loaded, e.g. missing.
- *
- * @param pendingReads array of blocks to load.
- *
- * TODO(b/136132412): avoid using collections
- */
- public abstract void onPendingReads(
- @NonNull Collection<FileSystemConnector.PendingReadInfo> pendingReads);
-
- /**
- * IFS tracks all reads and reports them using onPageReads.
- *
- * @param reads array of blocks.
- *
- * TODO(b/136132412): avoid using collections
- */
- public abstract void onPageReads(@NonNull Collection<FileSystemConnector.ReadInfo> reads);
-
- /**
- * IFS informs data loader that a new file has been created.
- * <p>
- * This can be used to prepare the data loader before it starts loading data. For example,
- * the data loader can keep a list of newly created files, so that it knows what files to
- * download from the server.
- *
- * @param inode The inode value of the new file.
- * @param metadata The metadata of the new file.
- */
- public abstract void onFileCreated(long inode, byte[] metadata);
- }
-
- /**
- * DataLoader factory method.
- *
- * @return An instance of a DataLoader.
- */
- public abstract @Nullable DataLoader onCreateDataLoader();
-
- /**
- * @hide
- */
- public final @NonNull IBinder onBind(@NonNull Intent intent) {
- return (IBinder) mBinder;
- }
-
- private class DataLoaderBinderService extends IDataLoader.Stub {
- private int mId;
-
- @Override
- public void create(int id, @NonNull Bundle options,
- @NonNull IDataLoaderStatusListener listener)
- throws IllegalArgumentException, RuntimeException {
- mId = id;
- final IncrementalDataLoaderParamsParcel params = options.getParcelable("params");
- if (params == null) {
- throw new IllegalArgumentException("Must specify Incremental data loader params");
- }
- final IncrementalFileSystemControlParcel control =
- options.getParcelable("control");
- if (control == null) {
- throw new IllegalArgumentException("Must specify Incremental control parcel");
- }
- mStatusListener = listener;
- try {
- if (!nativeCreateDataLoader(id, control, params, listener)) {
- Slog.e(TAG, "Failed to create native loader for " + mId);
- }
- } catch (Exception ex) {
- destroy();
- throw new RuntimeException(ex);
- } finally {
- // Closing FDs.
- if (control.cmd != null) {
- try {
- control.cmd.close();
- } catch (IOException e) {
- Slog.e(TAG, "Failed to close IncFs CMD file descriptor " + e);
- }
- }
- if (control.log != null) {
- try {
- control.log.close();
- } catch (IOException e) {
- Slog.e(TAG, "Failed to close IncFs LOG file descriptor " + e);
- }
- }
- NamedParcelFileDescriptor[] fds = params.dynamicArgs;
- for (NamedParcelFileDescriptor nfd : fds) {
- try {
- nfd.fd.close();
- } catch (IOException e) {
- Slog.e(TAG,
- "Failed to close DynamicArgs parcel file descriptor " + e);
- }
- }
- }
- }
-
- @Override
- public void start(List<InstallationFile> fileInfos) {
- if (!nativeStartDataLoader(mId)) {
- Slog.e(TAG, "Failed to start loader: loader not found for " + mId);
- }
- }
-
- @Override
- public void stop() {
- if (!nativeStopDataLoader(mId)) {
- Slog.w(TAG, "Failed to stop loader: loader not found for " + mId);
- }
- }
-
- @Override
- public void destroy() {
- if (!nativeDestroyDataLoader(mId)) {
- Slog.w(TAG, "Failed to destroy loader: loader not found for " + mId);
- }
- }
-
- @Override
- // TODO(b/136132412): remove this
- public void onFileCreated(long inode, byte[] metadata) {
- if (!nativeOnFileCreated(mId, inode, metadata)) {
- Slog.w(TAG, "Failed to handle onFileCreated for storage:" + mId
- + " inode:" + inode);
- }
- }
- }
-
- /**
- * IncFs API wrapper for writing pages and getting page missing info. Non-hidden methods are
- * expected to be called by the IncrementalDataLoaderService implemented by developers.
- *
- * @hide
- *
- * TODO(b/136132412) Should be @SystemApi
- */
- public static final class FileSystemConnector {
- /**
- * Defines a block address. A block is the unit of data chunk that IncFs operates with.
- *
- * @hide
- */
- public static class BlockAddress {
- /**
- * Linux inode uniquely identifies file within a single IFS instance.
- */
- private final long mFileIno;
- /**
- * Index of a 4K block within a file.
- */
- private final int mBlockIndex;
-
- public BlockAddress(long fileIno, int blockIndex) {
- this.mFileIno = fileIno;
- this.mBlockIndex = blockIndex;
- }
-
- public long getFileIno() {
- return mFileIno;
- }
-
- public int getBlockIndex() {
- return mBlockIndex;
- }
- }
-
- /**
- * A block is the unit of data chunk that IncFs operates with.
- *
- * @hide
- */
- public static class Block extends BlockAddress {
- /**
- * Data content of the block.
- */
- private final @NonNull byte[] mDataBytes;
-
- public Block(long fileIno, int blockIndex, @NonNull byte[] dataBytes) {
- super(fileIno, blockIndex);
- this.mDataBytes = dataBytes;
- }
- }
-
- /**
- * Defines a page/block inside a file.
- */
- public static class DataBlock extends Block {
- /**
- * Compression type of the data block.
- */
- private final @CompressionType int mCompressionType;
-
- public DataBlock(long fileIno, int blockIndex, @NonNull byte[] dataBytes,
- @CompressionType int compressionType) {
- super(fileIno, blockIndex, dataBytes);
- this.mCompressionType = compressionType;
- }
- }
-
- /**
- * Defines a hash block for a certain file. A hash block index is the index in an array of
- * hashes which is the 1-d representation of the hash tree. One DataBlock might be
- * associated with multiple HashBlocks.
- */
- public static class HashBlock extends Block {
- public HashBlock(long fileIno, int blockIndex, @NonNull byte[] dataBytes) {
- super(fileIno, blockIndex, dataBytes);
- }
- }
-
- /**
- * Information about a page that is pending to be read.
- */
- public static class PendingReadInfo extends BlockAddress {
- PendingReadInfo(long fileIno, int blockIndex) {
- super(fileIno, blockIndex);
- }
- }
-
- /**
- * Information about a page that is read.
- */
- public static class ReadInfo extends BlockAddress {
- /**
- * A monotonically increasing read timestamp.
- */
- private final long mTimePoint;
- /**
- * Number of blocks read starting from blockIndex.
- */
- private final int mBlockCount;
-
- ReadInfo(long timePoint, long fileIno, int firstBlockIndex, int blockCount) {
- super(fileIno, firstBlockIndex);
- this.mTimePoint = timePoint;
- this.mBlockCount = blockCount;
- }
-
- public long getTimePoint() {
- return mTimePoint;
- }
-
- public int getBlockCount() {
- return mBlockCount;
- }
- }
-
- /**
- * Defines the dynamic information about an IncFs file.
- */
- public static class FileInfo {
- /**
- * BitSet to show if any block is available at each block index.
- */
- private final @NonNull
- byte[] mBlockBitmap;
-
- /**
- * @hide
- */
- public FileInfo(@NonNull byte[] blockBitmap) {
- this.mBlockBitmap = blockBitmap;
- }
- }
-
- /**
- * Creates a wrapper for a native instance.
- */
- FileSystemConnector(long nativeInstance) {
- mNativeInstance = nativeInstance;
- }
-
- /**
- * Checks whether a range in a file if loaded.
- *
- * @param node inode 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(long node, long start, long end) {
- return nativeIsFileRangeLoadedNode(mNativeInstance, node, start, end);
- }
-
- /**
- * Gets the metadata of a file.
- *
- * @param node inode of the file.
- * @return The metadata object.
- */
- @NonNull
- public byte[] getFileMetadata(long node) throws IOException {
- final byte[] metadata = nativeGetFileMetadataNode(mNativeInstance, node);
- if (metadata == null || metadata.length == 0) {
- throw new IOException(
- "IncrementalFileSystem failed to obtain metadata for node: " + node);
- }
- return metadata;
- }
-
- /**
- * Gets the dynamic information of a file, such as page bitmaps. Can be used to get missing
- * page indices by the FileSystemConnector.
- *
- * @param node inode of the file.
- * @return Dynamic file info.
- */
- @NonNull
- public FileInfo getDynamicFileInfo(long node) throws IOException {
- final byte[] blockBitmap = nativeGetFileInfoNode(mNativeInstance, node);
- if (blockBitmap == null || blockBitmap.length == 0) {
- throw new IOException(
- "IncrementalFileSystem failed to obtain dynamic file info for node: "
- + node);
- }
- return new FileInfo(blockBitmap);
- }
-
- /**
- * Writes a page's data and/or hashes.
- *
- * @param dataBlocks the DataBlock objects that contain data block index and data bytes.
- * @param hashBlocks the HashBlock objects that contain hash indices and hash bytes.
- *
- * TODO(b/136132412): change API to avoid dynamic allocation of data block objects
- */
- public void writeMissingData(@NonNull DataBlock[] dataBlocks,
- @Nullable HashBlock[] hashBlocks) throws IOException {
- if (!nativeWriteMissingData(mNativeInstance, dataBlocks, hashBlocks)) {
- throw new IOException("IncrementalFileSystem failed to write missing data.");
- }
- }
-
- /**
- * Writes the signer block of a file. Expecting the connector to call this when it got
- * signing data from data loader.
- *
- * @param node the file to be written to.
- * @param signerData the raw signer data byte array.
- */
- public void writeSignerData(long node, @NonNull byte[] signerData)
- throws IOException {
- if (!nativeWriteSignerDataNode(mNativeInstance, node, signerData)) {
- throw new IOException(
- "IncrementalFileSystem failed to write signer data of node " + node);
- }
- }
-
- private final long mNativeInstance;
- }
-
- /**
- * Wrapper for native reporting DataLoader statuses.
- *
- * @hide
- *
- * TODO(b/136132412) Should be @SystemApi
- */
- public static final class StatusListener {
- /**
- * Creates a wrapper for a native instance.
- *
- * @hide
- */
- StatusListener(long nativeInstance) {
- mNativeInstance = nativeInstance;
- }
-
- /**
- * Report the status of DataLoader. Used for system-wide notifications e.g., disabling
- * applications which rely on this data loader to function properly.
- *
- * @param status status to report.
- * @return True if status was reported successfully.
- */
- public boolean onStatusChanged(@DataLoaderStatus int status) {
- return nativeReportStatus(mNativeInstance, status);
- }
-
- private final long mNativeInstance;
- }
-
- private IDataLoaderStatusListener mStatusListener = null;
-
- /* Native methods */
- private native boolean nativeCreateDataLoader(int storageId,
- @NonNull IncrementalFileSystemControlParcel control,
- @NonNull IncrementalDataLoaderParamsParcel params,
- IDataLoaderStatusListener listener);
-
- private native boolean nativeStartDataLoader(int storageId);
-
- private native boolean nativeStopDataLoader(int storageId);
-
- private native boolean nativeDestroyDataLoader(int storageId);
-
- private static native boolean nativeOnFileCreated(int storageId,
- long inode, byte[] metadata);
-
- private static native boolean nativeIsFileRangeLoadedNode(
- long nativeInstance, long node, long start, long end);
-
- private static native boolean nativeWriteMissingData(
- long nativeInstance, FileSystemConnector.DataBlock[] dataBlocks,
- FileSystemConnector.HashBlock[] hashBlocks);
-
- private static native boolean nativeWriteSignerDataNode(
- long nativeInstance, long node, byte[] signerData);
-
- private static native byte[] nativeGetFileMetadataNode(
- long nativeInstance, long node);
-
- private static native byte[] nativeGetFileInfoNode(
- long nativeInstance, long node);
-
- private static native boolean nativeReportStatus(long nativeInstance, int status);
-}
diff --git a/core/jni/android_service_DataLoaderService.cpp b/core/jni/android_service_DataLoaderService.cpp
index 4c0f55f..381b386 100644
--- a/core/jni/android_service_DataLoaderService.cpp
+++ b/core/jni/android_service_DataLoaderService.cpp
@@ -16,83 +16,18 @@
#define LOG_TAG "dataloader-jni"
-#include <vector>
-
#include "core_jni_helpers.h"
#include "dataloader_ndk.h"
-#include "jni.h"
namespace android {
namespace {
-struct JniIds {
- jfieldID dataBlockFileIno;
- jfieldID dataBlockBlockIndex;
- jfieldID dataBlockDataBytes;
- jfieldID dataBlockCompressionType;
-
- JniIds(JNIEnv* env) {
- const auto dataBlock =
- FindClassOrDie(env,
- "android/service/incremental/"
- "IncrementalDataLoaderService$FileSystemConnector$DataBlock");
- dataBlockFileIno = GetFieldIDOrDie(env, dataBlock, "mFileIno", "J");
- dataBlockBlockIndex =
- GetFieldIDOrDie(env, dataBlock, "mBlockIndex", "I");
- dataBlockDataBytes = GetFieldIDOrDie(env, dataBlock, "mDataBytes", "[B");
- dataBlockCompressionType =
- GetFieldIDOrDie(env, dataBlock, "mCompressionType", "I");
- }
-};
-
-const JniIds& jniIds(JNIEnv* env) {
- static const JniIds ids(env);
- return ids;
-}
-
-class ScopedJniArrayCritical {
-public:
- ScopedJniArrayCritical(JNIEnv* env, jarray array) : mEnv(env), mArr(array) {
- mPtr = array ? env->GetPrimitiveArrayCritical(array, nullptr) : nullptr;
- }
- ~ScopedJniArrayCritical() {
- if (mPtr) {
- mEnv->ReleasePrimitiveArrayCritical(mArr, mPtr, 0);
- mPtr = nullptr;
- }
- }
-
- ScopedJniArrayCritical(const ScopedJniArrayCritical&) = delete;
- void operator=(const ScopedJniArrayCritical&) = delete;
-
- ScopedJniArrayCritical(ScopedJniArrayCritical&& other)
- : mEnv(other.mEnv),
- mArr(std::exchange(mArr, nullptr)),
- mPtr(std::exchange(mPtr, nullptr)) {}
- ScopedJniArrayCritical& operator=(ScopedJniArrayCritical&& other) {
- mEnv = other.mEnv;
- mArr = std::exchange(other.mArr, nullptr);
- mPtr = std::exchange(other.mPtr, nullptr);
- return *this;
- }
-
- void* ptr() const { return mPtr; }
- jsize size() const { return mArr ? mEnv->GetArrayLength(mArr) : 0; }
-
-private:
- JNIEnv* mEnv;
- jarray mArr;
- void* mPtr;
-};
-
static jboolean nativeCreateDataLoader(JNIEnv* env,
jobject thiz,
jint storageId,
jobject control,
jobject params,
jobject callback) {
- ALOGE("nativeCreateDataLoader: %p/%d, %d, %p, %p, %p", thiz,
- env->GetObjectRefType(thiz), storageId, params, control, callback);
return DataLoaderService_OnCreate(env, thiz,
storageId, control, params, callback);
}
@@ -100,130 +35,22 @@
static jboolean nativeStartDataLoader(JNIEnv* env,
jobject thiz,
jint storageId) {
- ALOGE("nativeStartDataLoader: %p/%d, %d", thiz, env->GetObjectRefType(thiz),
- storageId);
return DataLoaderService_OnStart(storageId);
}
static jboolean nativeStopDataLoader(JNIEnv* env,
jobject thiz,
jint storageId) {
- ALOGE("nativeStopDataLoader: %p/%d, %d", thiz, env->GetObjectRefType(thiz),
- storageId);
return DataLoaderService_OnStop(storageId);
}
static jboolean nativeDestroyDataLoader(JNIEnv* env,
jobject thiz,
jint storageId) {
- ALOGE("nativeDestroyDataLoader: %p/%d, %d", thiz,
- env->GetObjectRefType(thiz), storageId);
return DataLoaderService_OnDestroy(storageId);
}
-static jboolean nativeOnFileCreated(JNIEnv* env,
- jobject thiz,
- jint storageId,
- jlong inode,
- jbyteArray metadata) {
- ALOGE("nativeOnFileCreated: %p/%d, %d", thiz,
- env->GetObjectRefType(thiz), storageId);
- return DataLoaderService_OnFileCreated(storageId, inode, metadata);
-}
-
-static jboolean nativeIsFileRangeLoadedNode(JNIEnv* env,
- jobject clazz,
- jlong self,
- jlong node,
- jlong start,
- jlong end) {
- // TODO(b/136132412): implement this
- return JNI_FALSE;
-}
-
-static jboolean nativeWriteMissingData(JNIEnv* env,
- jobject clazz,
- jlong self,
- jobjectArray data_block,
- jobjectArray hash_blocks) {
- const auto& jni = jniIds(env);
- auto length = env->GetArrayLength(data_block);
- std::vector<incfs_new_data_block> instructions(length);
-
- // May not call back into Java after even a single jniArrayCritical, so
- // let's collect the Java pointers to byte buffers first and lock them in
- // memory later.
-
- std::vector<jbyteArray> blockBuffers(length);
- for (int i = 0; i != length; ++i) {
- auto& inst = instructions[i];
- auto jniBlock = env->GetObjectArrayElement(data_block, i);
- inst.file_ino = env->GetLongField(jniBlock, jni.dataBlockFileIno);
- inst.block_index = env->GetIntField(jniBlock, jni.dataBlockBlockIndex);
- blockBuffers[i] = (jbyteArray)env->GetObjectField(
- jniBlock, jni.dataBlockDataBytes);
- inst.compression = (incfs_compression_alg)env->GetIntField(
- jniBlock, jni.dataBlockCompressionType);
- }
-
- std::vector<ScopedJniArrayCritical> jniScopedArrays;
- jniScopedArrays.reserve(length);
- for (int i = 0; i != length; ++i) {
- auto buffer = blockBuffers[i];
- jniScopedArrays.emplace_back(env, buffer);
- auto& inst = instructions[i];
- inst.data = (uint64_t)jniScopedArrays.back().ptr();
- inst.data_len = jniScopedArrays.back().size();
- }
-
- auto connector = (DataLoaderFilesystemConnectorPtr)self;
- if (auto err = DataLoader_FilesystemConnector_writeBlocks(
- connector, instructions.data(), length);
- err < 0) {
- jniScopedArrays.clear();
- return JNI_FALSE;
- }
-
- return JNI_TRUE;
-}
-
-static jboolean nativeWriteSignerDataNode(JNIEnv* env,
- jobject clazz,
- jlong self,
- jstring relative_path,
- jbyteArray signer_data) {
- // TODO(b/136132412): implement this
- return JNI_TRUE;
-}
-
-static jbyteArray nativeGetFileMetadataNode(JNIEnv* env,
- jobject clazz,
- jlong self,
- jlong inode) {
- auto connector = (DataLoaderFilesystemConnectorPtr)self;
- std::vector<char> metadata(INCFS_MAX_FILE_ATTR_SIZE);
- size_t size = metadata.size();
- if (DataLoader_FilesystemConnector_getRawMetadata(connector, inode,
- metadata.data(), &size) < 0) {
- size = 0;
- }
- metadata.resize(size);
-
- auto buffer = env->NewByteArray(metadata.size());
- env->SetByteArrayRegion(buffer, 0, metadata.size(),
- (jbyte*)metadata.data());
- return buffer;
-}
-
-static jbyteArray nativeGetFileInfoNode(JNIEnv* env,
- jobject clazz,
- jlong self,
- jlong inode) {
- // TODO(b/136132412): implement this
- return nullptr;
-}
-
static jboolean nativeReportStatus(JNIEnv* env,
jobject clazz,
jlong self,
@@ -235,34 +62,21 @@
static const JNINativeMethod dlc_method_table[] = {
{"nativeCreateDataLoader",
- "(ILandroid/os/incremental/IncrementalFileSystemControlParcel;"
- "Landroid/os/incremental/IncrementalDataLoaderParamsParcel;"
+ "(ILandroid/content/pm/FileSystemControlParcel;"
+ "Landroid/content/pm/DataLoaderParamsParcel;"
"Landroid/content/pm/IDataLoaderStatusListener;)Z",
(void*)nativeCreateDataLoader},
{"nativeStartDataLoader", "(I)Z", (void*)nativeStartDataLoader},
{"nativeStopDataLoader", "(I)Z", (void*)nativeStopDataLoader},
{"nativeDestroyDataLoader", "(I)Z", (void*)nativeDestroyDataLoader},
- {"nativeIsFileRangeLoadedNode", "(JJJJ)Z",
- (void*)nativeIsFileRangeLoadedNode},
- {"nativeWriteMissingData",
- "(J[Landroid/service/incremental/"
- "IncrementalDataLoaderService$FileSystemConnector$DataBlock;[Landroid/service/incremental/"
- "IncrementalDataLoaderService$FileSystemConnector$HashBlock;)Z",
- (void*)nativeWriteMissingData},
- {"nativeWriteSignerDataNode", "(JJ[B)Z",
- (void*)nativeWriteSignerDataNode},
- {"nativeGetFileMetadataNode", "(JJ)[B",
- (void*)nativeGetFileMetadataNode},
- {"nativeGetFileInfoNode", "(JJ)[B", (void*)nativeGetFileInfoNode},
{"nativeReportStatus", "(JI)Z", (void*)nativeReportStatus},
- {"nativeOnFileCreated", "(IJ[B)Z", (void*)nativeOnFileCreated},
};
} // namespace
int register_android_service_DataLoaderService(JNIEnv* env) {
return jniRegisterNativeMethods(env,
- "android/service/incremental/IncrementalDataLoaderService",
+ "android/service/dataloader/DataLoaderService",
dlc_method_table, NELEM(dlc_method_table));
}
diff --git a/packages/Incremental/NativeAdbDataLoader/src/com/android/incremental/nativeadb/NativeAdbDataLoaderService.java b/packages/Incremental/NativeAdbDataLoader/src/com/android/incremental/nativeadb/NativeAdbDataLoaderService.java
index 1f88114..bd5b795 100644
--- a/packages/Incremental/NativeAdbDataLoader/src/com/android/incremental/nativeadb/NativeAdbDataLoaderService.java
+++ b/packages/Incremental/NativeAdbDataLoader/src/com/android/incremental/nativeadb/NativeAdbDataLoaderService.java
@@ -16,10 +16,10 @@
package com.android.incremental.nativeadb;
-import android.service.incremental.IncrementalDataLoaderService;
+import android.service.dataloader.DataLoaderService;
/** This code is used for testing only. */
-public class NativeAdbDataLoaderService extends IncrementalDataLoaderService {
+public class NativeAdbDataLoaderService extends DataLoaderService {
public static final String TAG = "NativeAdbDataLoaderService";
static {
System.loadLibrary("nativeadbdataloaderservice_jni");
diff --git a/services/core/java/com/android/server/incremental/IncrementalManagerService.java b/services/core/java/com/android/server/incremental/IncrementalManagerService.java
index 1b1a292..789551b 100644
--- a/services/core/java/com/android/server/incremental/IncrementalManagerService.java
+++ b/services/core/java/com/android/server/incremental/IncrementalManagerService.java
@@ -19,6 +19,8 @@
import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.DataLoaderManager;
+import android.content.pm.DataLoaderParamsParcel;
+import android.content.pm.FileSystemControlParcel;
import android.content.pm.IDataLoader;
import android.content.pm.IDataLoaderStatusListener;
import android.os.Bundle;
@@ -27,8 +29,6 @@
import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.incremental.IIncrementalManager;
-import android.os.incremental.IncrementalDataLoaderParamsParcel;
-import android.os.incremental.IncrementalFileSystemControlParcel;
import android.util.Slog;
import java.io.FileDescriptor;
@@ -80,8 +80,8 @@
* Finds data loader service provider and binds to it. This requires PackageManager.
*/
@Override
- public boolean prepareDataLoader(int mountId, IncrementalFileSystemControlParcel control,
- IncrementalDataLoaderParamsParcel params,
+ public boolean prepareDataLoader(int mountId, FileSystemControlParcel control,
+ DataLoaderParamsParcel params,
IDataLoaderStatusListener listener) {
Bundle dataLoaderParams = new Bundle();
dataLoaderParams.putCharSequence("packageName", params.packageName);
@@ -138,10 +138,6 @@
Slog.e(TAG, "Failed to retrieve data loader for ID=" + mountId);
return;
}
- try {
- dataLoader.onFileCreated(inode, metadata);
- } catch (RemoteException ex) {
- }
}
@Override
diff --git a/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java b/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java
index d35e806..6a8434a 100644
--- a/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java
+++ b/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java
@@ -24,6 +24,7 @@
import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.DataLoaderParams;
import android.content.pm.InstallationFile;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
@@ -31,7 +32,6 @@
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.ShellCommand;
-import android.os.incremental.IncrementalDataLoaderParams;
import android.util.Slog;
import java.io.FileDescriptor;
@@ -111,7 +111,7 @@
pw.println("File names and sizes don't match.");
return ERROR_DATA_LOADER_INIT;
}
- final IncrementalDataLoaderParams params = new IncrementalDataLoaderParams(
+ final DataLoaderParams params = new DataLoaderParams(
"", LOADER_PACKAGE_NAME, dataLoaderDynamicArgs);
PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 286d291..dfdc29c 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -57,6 +57,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageInstallObserver2;
import android.content.pm.IPackageInstallerSession;
+import android.content.pm.IPackageInstallerSessionFileSystemConnector;
import android.content.pm.InstallationFile;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
@@ -1003,6 +1004,21 @@
mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
}
+ private class FileSystemConnector extends IPackageInstallerSessionFileSystemConnector.Stub {
+ @Override
+ public void writeData(String name, long offsetBytes, long lengthBytes,
+ ParcelFileDescriptor incomingFd) {
+ if (incomingFd == null) {
+ throw new IllegalArgumentException("incomingFd can't be null");
+ }
+ try {
+ doWriteInternal(name, offsetBytes, lengthBytes, incomingFd);
+ } catch (IOException e) {
+ throw ExceptionUtils.wrap(e);
+ }
+ }
+ }
+
private class ChildStatusIntentReceiver {
private final SparseIntArray mChildSessionsRemaining;
private final IntentSender mStatusReceiver;
@@ -2405,7 +2421,7 @@
return;
}
- FilesystemConnector connector = new FilesystemConnector();
+ FileSystemConnector connector = new FileSystemConnector();
FileInfo[] addedFiles = mFiles.stream().filter(
file -> sAddedFilter.accept(new File(file.name))).toArray(FileInfo[]::new);
@@ -2430,19 +2446,11 @@
}
}
- // TODO(b/146080380): implement DataLoader using Incremental infrastructure.
- class FilesystemConnector {
- void writeData(FileInfo fileInfo, long offset, long lengthBytes,
- ParcelFileDescriptor incomingFd) throws IOException {
- doWriteInternal(fileInfo.name, offset, lengthBytes, incomingFd);
- }
- }
-
static class DataLoader {
private ParcelFileDescriptor mInFd = null;
- private FilesystemConnector mConnector = null;
+ private FileSystemConnector mConnector = null;
- void onCreate(FilesystemConnector connector) throws IOException {
+ void onCreate(FileSystemConnector connector) throws IOException {
mConnector = connector;
}
@@ -2460,14 +2468,14 @@
return false;
}
ParcelFileDescriptor inFd = ParcelFileDescriptor.dup(mInFd.getFileDescriptor());
- mConnector.writeData(fileInfo, 0, fileInfo.lengthBytes, inFd);
+ mConnector.writeData(fileInfo.name, 0, fileInfo.lengthBytes, inFd);
} else {
File localFile = new File(filePath);
ParcelFileDescriptor incomingFd = null;
try {
incomingFd = ParcelFileDescriptor.open(localFile,
ParcelFileDescriptor.MODE_READ_ONLY);
- mConnector.writeData(fileInfo, 0, localFile.length(), incomingFd);
+ mConnector.writeData(fileInfo.name, 0, localFile.length(), incomingFd);
} finally {
IoUtils.closeQuietly(incomingFd);
}