/* * 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.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; 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.InstallationFile; import android.content.pm.InstallationFileParcel; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.util.ExceptionUtils; import android.util.Slog; import libcore.io.IoUtils; import java.io.IOException; import java.util.Collection; /** * 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
*
* @hide
*/
@SystemApi
public abstract class DataLoaderService extends Service {
private static final String TAG = "DataLoaderService";
private final DataLoaderBinderService mBinder = new DataLoaderBinderService();
/**
* DataLoader interface. Each instance corresponds to a single installation session.
* @hide
*/
@SystemApi
public interface DataLoader {
/**
* A virtual constructor.
*
* @param dataLoaderParams parameters set in the installation session
* {@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);
/**
* 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.
*
* 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