diff --git a/core/api/current.txt b/core/api/current.txt index dfc98a7915157..acf4350534f52 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -12086,7 +12086,6 @@ package android.content.pm { } public class DataLoaderParams { - method @NonNull public static final android.content.pm.DataLoaderParams forIncremental(@NonNull android.content.ComponentName, @NonNull String); method @NonNull public static final android.content.pm.DataLoaderParams forStreaming(@NonNull android.content.ComponentName, @NonNull String); method @NonNull public final String getArguments(); method @NonNull public final android.content.ComponentName getComponentName(); @@ -12331,7 +12330,6 @@ package android.content.pm { field public static final String ACTION_SESSION_COMMITTED = "android.content.pm.action.SESSION_COMMITTED"; field public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS"; field public static final String ACTION_SESSION_UPDATED = "android.content.pm.action.SESSION_UPDATED"; - field public static final int DATA_LOADER_TYPE_INCREMENTAL = 2; // 0x2 field public static final int DATA_LOADER_TYPE_NONE = 0; // 0x0 field public static final int DATA_LOADER_TYPE_STREAMING = 1; // 0x1 field public static final String EXTRA_DATA_LOADER_TYPE = "android.content.pm.extra.DATA_LOADER_TYPE"; diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 1a41e41c05d7a..ba72e13950674 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -2523,6 +2523,10 @@ package android.content.pm { method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_PROFILES) public void startActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle); } + public class DataLoaderParams { + method @NonNull public static final android.content.pm.DataLoaderParams forIncremental(@NonNull android.content.ComponentName, @NonNull String); + } + public final class InstantAppInfo implements android.os.Parcelable { ctor public InstantAppInfo(android.content.pm.ApplicationInfo, String[], String[]); ctor public InstantAppInfo(String, CharSequence, String[], String[]); @@ -2613,6 +2617,7 @@ package android.content.pm { public class PackageInstaller { method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setPermissionsResult(int, boolean); + field public static final int DATA_LOADER_TYPE_INCREMENTAL = 2; // 0x2 } public static class PackageInstaller.Session implements java.io.Closeable { diff --git a/core/java/android/content/pm/DataLoaderParams.java b/core/java/android/content/pm/DataLoaderParams.java index 93db1e16aea0e..f808cfda48356 100644 --- a/core/java/android/content/pm/DataLoaderParams.java +++ b/core/java/android/content/pm/DataLoaderParams.java @@ -17,20 +17,24 @@ package android.content.pm; import android.annotation.NonNull; +import android.annotation.SystemApi; import android.content.ComponentName; /** - * This class represents the parameters used to configure a Data Loader. + * This class represents the parameters used to configure a DataLoader. + * + * {@see android.service.dataloader.DataLoaderService.DataLoader} */ public class DataLoaderParams { @NonNull private final DataLoaderParamsParcel mData; /** - * Creates and populates set of Data Loader parameters for Streaming installation. + * Creates and populates set of DataLoader parameters for Streaming installation. * - * @param componentName Data Loader component supporting Streaming installation. - * @param arguments free form installation arguments + * @param componentName the component implementing a DataLoaderService that is responsible + * for providing data blocks while streaming. + * @param arguments free form installation arguments. */ public static final @NonNull DataLoaderParams forStreaming(@NonNull ComponentName componentName, @NonNull String arguments) { @@ -40,9 +44,12 @@ public class DataLoaderParams { /** * Creates and populates set of Data Loader parameters for Incremental installation. * - * @param componentName Data Loader component supporting Incremental installation. + * @param componentName DataLoaderService component supporting Incremental installation. * @param arguments free form installation arguments + * + * @hide */ + @SystemApi public static final @NonNull DataLoaderParams forIncremental( @NonNull ComponentName componentName, @NonNull String arguments) { return new DataLoaderParams(DataLoaderType.INCREMENTAL, componentName, arguments); diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 0be77e01340a7..8b380b79e8c78 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -229,8 +229,7 @@ public class PackageInstaller { /** * Type of DataLoader for this session. Will be one of - * {@link #DATA_LOADER_TYPE_NONE}, {@link #DATA_LOADER_TYPE_STREAMING}, - * {@link #DATA_LOADER_TYPE_INCREMENTAL}. + * {@link #DATA_LOADER_TYPE_NONE}, {@link #DATA_LOADER_TYPE_STREAMING}. *
* See the individual types documentation for details. * @@ -359,7 +358,9 @@ public class PackageInstaller { * Streaming installation using Incremental FileSystem. * * @see #EXTRA_DATA_LOADER_TYPE + * @hide */ + @SystemApi public static final int DATA_LOADER_TYPE_INCREMENTAL = DataLoaderType.INCREMENTAL; /** @@ -1165,7 +1166,7 @@ public class PackageInstaller { } /** - * Adds a file to session. On commit this file will be pulled from dataLoader {@code + * Adds a file to session. On commit this file will be pulled from DataLoader {@code * android.service.dataloader.DataLoaderService.DataLoader}. * * @param location target location for the file. Possible values: @@ -1180,7 +1181,7 @@ public class PackageInstaller { * @param lengthBytes total size of the file being written. * The system may clear various caches as needed to allocate * this space. - * @param metadata additional info use by dataLoader to pull data for the file. + * @param metadata additional info use by DataLoader to pull data for the file. * @param signature additional file signature, e.g. * APK Signature Scheme v4 * @throws SecurityException if called after the session has been @@ -2021,7 +2022,7 @@ public class PackageInstaller { /** * Set the data loader params for the session. - * This also switches installation into data provider mode and disallow direct writes into + * This also switches installation into data loading mode and disallow direct writes into * staging folder. * * @see android.service.dataloader.DataLoaderService.DataLoader diff --git a/core/java/android/service/dataloader/DataLoaderService.java b/core/java/android/service/dataloader/DataLoaderService.java index 3ad80d3e97fac..63ec252c2fa80 100644 --- a/core/java/android/service/dataloader/DataLoaderService.java +++ b/core/java/android/service/dataloader/DataLoaderService.java @@ -39,24 +39,35 @@ import java.io.IOException; import java.util.Collection; /** - * The base class for implementing data loader service to control data loaders. Expecting - * Installation Session to bind to a children class of this. + * The base class for implementing a data loader service. + *
+ * After calling commit() on the install session, the DataLoaderService is started and bound to
+ * provide the actual data bytes for the streaming session.
+ * The service will automatically be rebound until the streaming session has enough data to
+ * proceed with the installation.
+ *
+ * @see android.content.pm.DataLoaderParams
+ * @see android.content.pm.PackageInstaller.SessionParams#setDataLoaderParams
*/
public abstract class DataLoaderService extends Service {
private static final String TAG = "DataLoaderService";
private final DataLoaderBinderService mBinder = new DataLoaderBinderService();
/**
- * Managed DataLoader interface. Each instance corresponds to a single installation session.
+ * DataLoader interface. Each instance corresponds to a single installation session.
*/
public interface DataLoader {
/**
* A virtual constructor.
*
* @param dataLoaderParams parameters set in the installation session
- * @param connector FS API wrapper
- * @return True if initialization of a Data Loader was successful. False will be reported to
- * PackageManager and fail the installation
+ * {@link android.content.pm.PackageInstaller.SessionParams#setDataLoaderParams}
+ * @param connector Wrapper providing access to the installation image.
+ * @return true if initialization of a DataLoader was successful. False will notify the
+ * Installer {@link android.content.pm.PackageInstaller#STATUS_PENDING_STREAMING} and
+ * interrupt the session commit. The Installer is supposed to make sure DataLoader can
+ * proceed and then commit the session
+ * {@link android.content.pm.PackageInstaller.Session#commit}.
*/
boolean onCreate(@NonNull DataLoaderParams dataLoaderParams,
@NonNull FileSystemConnector connector);
@@ -64,10 +75,35 @@ public abstract class DataLoaderService extends Service {
/**
* Prepare installation image. After this method succeeds installer will validate the files
* and continue installation.
+ * The method should block until the files are prepared for installation.
+ * This can take up to session lifetime (~day). If the session lifetime is exceeded then
+ * any attempts to write new data will fail.
*
- * @param addedFiles list of files created in this installation session.
- * @param removedFiles list of files removed in this installation session.
- * @return false if unable to create and populate all addedFiles.
+ * Example implementation:
+ *
+ * String localPath = "/data/local/tmp/base.apk";
+ * session.addFile(LOCATION_DATA_APP, "base", 123456, localPath.getBytes(UTF_8), null);
+ * ...
+ * // onPrepareImage
+ * for (InstallationFile file : addedFiles) {
+ * String localPath = new String(file.getMetadata(), UTF_8);
+ * File source = new File(localPath);
+ * ParcelFileDescriptor fd = ParcelFileDescriptor.open(source, MODE_READ_ONLY);
+ * try {
+ * mConnector.writeData(file.getName(), 0, fd.getStatSize(), fd);
+ * } finally {
+ * IoUtils.closeQuietly(fd);
+ * }
+ * }
+ *
+ * It is recommended to stream data into installation session directly from source, e.g.
+ * cloud data storage, to save local disk space.
+ *
+ * @param addedFiles list of files created in this installation session
+ * {@link android.content.pm.PackageInstaller.Session#addFile}
+ * @param removedFiles list of files removed in this installation session
+ * {@link android.content.pm.PackageInstaller.Session#removeFile}
+ * @return false if unable to create and populate all addedFiles. Installation will fail.
*/
boolean onPrepareImage(@NonNull Collection