From ea14d19106b06cc5d28fad2c779b914caeeeb31f Mon Sep 17 00:00:00 2001 From: Alex Buynytskyy <alexbuy@google.com> Date: Fri, 13 Dec 2019 15:42:18 -0800 Subject: [PATCH] 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 --- Android.bp | 6 +- CleanSpec.mk | 2 + .../pm/DataLoaderParams.java} | 14 +- .../pm/DataLoaderParamsParcel.aidl} | 6 +- .../content/pm/FileSystemControlParcel.aidl | 31 + core/java/android/content/pm/IDataLoader.aidl | 1 - ...geInstallerSessionFileSystemConnector.aidl | 24 + .../pm}/NamedParcelFileDescriptor.aidl | 2 +- .../android/content/pm/PackageInstaller.java | 12 +- .../os/incremental/IIncrementalManager.aidl | 8 +- .../IIncrementalManagerNative.aidl | 4 +- .../incremental/IncrementalFileStorages.java | 9 +- .../os/incremental/IncrementalManager.java | 3 +- .../service/dataloader/DataLoaderService.java | 307 ++++++++++ .../IncrementalDataLoaderService.java | 563 ------------------ .../jni/android_service_DataLoaderService.cpp | 192 +----- .../nativeadb/NativeAdbDataLoaderService.java | 4 +- .../IncrementalManagerService.java | 12 +- .../IncrementalManagerShellCommand.java | 4 +- .../server/pm/PackageInstallerSession.java | 34 +- 20 files changed, 429 insertions(+), 809 deletions(-) rename core/java/android/{os/incremental/IncrementalDataLoaderParams.java => content/pm/DataLoaderParams.java} (82%) rename core/java/android/{os/incremental/IncrementalDataLoaderParamsParcel.aidl => content/pm/DataLoaderParamsParcel.aidl} (85%) create mode 100644 core/java/android/content/pm/FileSystemControlParcel.aidl create mode 100644 core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl rename core/java/android/{os/incremental => content/pm}/NamedParcelFileDescriptor.aidl (96%) create mode 100644 core/java/android/service/dataloader/DataLoaderService.java delete mode 100644 core/java/android/service/incremental/IncrementalDataLoaderService.java diff --git a/Android.bp b/Android.bp index 77abad6e0fd9b..e14a3520dcc71 100644 --- a/Android.bp +++ b/Android.bp @@ -807,9 +807,11 @@ filegroup { 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 f94de29d41b1d..b84e71526a144 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -257,6 +257,8 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/ext.jar) $(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 701f1cc8de023..b163861c53b50 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 @@ import java.util.stream.Collectors; * 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 @@ public class IncrementalDataLoaderParams { mData = data; } - public IncrementalDataLoaderParams(@NonNull IncrementalDataLoaderParamsParcel data) { + public DataLoaderParams(@NonNull DataLoaderParamsParcel data) { mData = data; } @@ -70,7 +70,7 @@ public class IncrementalDataLoaderParams { 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 cd988dcace5b3..33163980b9157 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 0000000000000..f00feaeb2f5a0 --- /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 60cc9ba9e1413..c65bd6acbaf8c 100644 --- a/core/java/android/content/pm/IDataLoader.aidl +++ b/core/java/android/content/pm/IDataLoader.aidl @@ -30,5 +30,4 @@ oneway interface IDataLoader { void start(in List<InstallationFile> fileInfos); void stop(); void destroy(); - void onFileCreated(long inode, in byte[] metadata); } diff --git a/core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl b/core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl new file mode 100644 index 0000000000000..4b2f29e5ae785 --- /dev/null +++ b/core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl @@ -0,0 +1,24 @@ +/* + * 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.os.ParcelFileDescriptor; + +/** {@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 96% rename from core/java/android/os/incremental/NamedParcelFileDescriptor.aidl rename to core/java/android/content/pm/NamedParcelFileDescriptor.aidl index 038ced1744a1c..68dd5f54654b2 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 898631e9a3b1d..218c8765f3bb2 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -50,8 +50,6 @@ import android.os.ParcelableException; 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 @@ public class PackageInstaller { /** {@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 @@ public class PackageInstaller { 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 @@ public class PackageInstaller { * {@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 f84d7efe06b1f..17a310a5beb01 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 @@ import android.content.pm.IDataLoaderStatusListener; */ 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 d9c7c6b5cc212..14215b1ea84de 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 @@ interface IIncrementalManagerNative { * 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 5bd0748b8d977..7987efd6b3870 100644 --- a/core/java/android/os/incremental/IncrementalFileStorages.java +++ b/core/java/android/os/incremental/IncrementalFileStorages.java @@ -35,6 +35,7 @@ import static dalvik.system.VMRuntime.getInstructionSet; 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 final class IncrementalFileStorages { 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 @@ public final class IncrementalFileStorages { 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 c30f5589a8353..c72228708b4cf 100644 --- a/core/java/android/os/incremental/IncrementalManager.java +++ b/core/java/android/os/incremental/IncrementalManager.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; 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 @@ public final class IncrementalManager { */ @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 0000000000000..373e1e5f979f5 --- /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 c4a06c8f53db7..0000000000000 --- 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 4c0f55f2bf23e..381b386d7f62c 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 nativeCreateDataLoader(JNIEnv* env, 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 jboolean nativeReportStatus(JNIEnv* env, 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 1f88114becd89..bd5b79594c194 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 1b1a292936397..789551bb2263c 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 @@ package com.android.server.incremental; 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.ResultReceiver; 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 @@ public class IncrementalManagerService extends IIncrementalManager.Stub { * 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 @@ public class IncrementalManagerService extends IIncrementalManager.Stub { 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 d35e806b2685c..6a8434aad88bf 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.IIntentReceiver; 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.Bundle; 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 @@ public final class IncrementalManagerShellCommand extends ShellCommand { 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 286d291836ec1..dfdc29cd6b7ae 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.IntentSender; 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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { 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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { 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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } - // 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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { 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); } -- GitLab