Migrating Incremental* APIs to PackageManager APIs.
Step 2, merging Data Loader params. Test: builds and flashes Bug: b/136132412 Change-Id: I2102554316dadcdcb49790c133ece110c43c29b3
This commit is contained in:
@@ -833,6 +833,7 @@ filegroup {
|
||||
name: "dataloader_aidl",
|
||||
srcs: [
|
||||
"core/java/android/content/pm/DataLoaderParamsParcel.aidl",
|
||||
"core/java/android/content/pm/DataLoaderType.aidl",
|
||||
"core/java/android/content/pm/FileSystemControlParcel.aidl",
|
||||
"core/java/android/content/pm/IDataLoaderStatusListener.aidl",
|
||||
"core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl",
|
||||
|
||||
@@ -1934,10 +1934,12 @@ package android.content.pm {
|
||||
}
|
||||
|
||||
public class DataLoaderParams {
|
||||
ctor public DataLoaderParams(@NonNull String, @NonNull String, @Nullable java.util.Map<java.lang.String,android.os.ParcelFileDescriptor>);
|
||||
method @NonNull public static final android.content.pm.DataLoaderParams forIncremental(@NonNull android.content.ComponentName, @NonNull String, @Nullable java.util.Map<java.lang.String,android.os.ParcelFileDescriptor>);
|
||||
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();
|
||||
method @NonNull public final java.util.Map<java.lang.String,android.os.ParcelFileDescriptor> getDynamicArgs();
|
||||
method @NonNull public final String getPackageName();
|
||||
method @NonNull public final String getStaticArgs();
|
||||
method @NonNull public final int getType();
|
||||
}
|
||||
|
||||
public final class InstantAppInfo implements android.os.Parcelable {
|
||||
@@ -2050,11 +2052,11 @@ package android.content.pm {
|
||||
public static class PackageInstaller.SessionParams implements android.os.Parcelable {
|
||||
method @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) public void setAllocateAggressive(boolean);
|
||||
method @Deprecated public void setAllowDowngrade(boolean);
|
||||
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setDataLoaderParams(@NonNull android.content.pm.DataLoaderParams);
|
||||
method public void setDontKillApp(boolean);
|
||||
method public void setEnableRollback(boolean);
|
||||
method public void setEnableRollback(boolean, int);
|
||||
method @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) public void setGrantedRuntimePermissions(String[]);
|
||||
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setIncrementalParams(@NonNull android.content.pm.DataLoaderParams);
|
||||
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setInstallAsApex();
|
||||
method public void setInstallAsInstantApp(boolean);
|
||||
method public void setInstallAsVirtualPreload();
|
||||
|
||||
@@ -19,6 +19,7 @@ package android.content.pm;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
import android.content.ComponentName;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -26,7 +27,7 @@ import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* This class represents the parameters used to configure an Incremental Data Loader.
|
||||
* This class represents the parameters used to configure a Data Loader.
|
||||
*
|
||||
* WARNING: This is a system API to aid internal development.
|
||||
* Use at your own risk. It will change or be removed without warning.
|
||||
@@ -34,13 +35,41 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
@SystemApi
|
||||
public class DataLoaderParams {
|
||||
@NonNull private final DataLoaderParamsParcel mData;
|
||||
@NonNull
|
||||
private final DataLoaderParamsParcel mData;
|
||||
|
||||
public DataLoaderParams(@NonNull String url, @NonNull String packageName,
|
||||
/**
|
||||
* Creates and populates set of Data Loader parameters for Streaming installation.
|
||||
*
|
||||
* @param componentName Data Loader component supporting Streaming installation.
|
||||
* @param arguments free form installation arguments
|
||||
*/
|
||||
public static final @NonNull DataLoaderParams forStreaming(@NonNull ComponentName componentName,
|
||||
@NonNull String arguments) {
|
||||
return new DataLoaderParams(DataLoaderType.STREAMING, componentName, arguments, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and populates set of Data Loader parameters for Incremental installation.
|
||||
*
|
||||
* @param componentName Data Loader component supporting Incremental installation.
|
||||
* @param arguments free form installation arguments
|
||||
* @param namedFds TODO(b/146080380) remove
|
||||
*/
|
||||
public static final @NonNull DataLoaderParams forIncremental(
|
||||
@NonNull ComponentName componentName, @NonNull String arguments,
|
||||
@Nullable Map<String, ParcelFileDescriptor> namedFds) {
|
||||
return new DataLoaderParams(DataLoaderType.INCREMENTAL, componentName, arguments, namedFds);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public DataLoaderParams(@NonNull @DataLoaderType int type, @NonNull ComponentName componentName,
|
||||
@NonNull String arguments, @Nullable Map<String, ParcelFileDescriptor> namedFds) {
|
||||
DataLoaderParamsParcel data = new DataLoaderParamsParcel();
|
||||
data.staticArgs = url;
|
||||
data.packageName = packageName;
|
||||
data.type = type;
|
||||
data.packageName = componentName.getPackageName();
|
||||
data.className = componentName.getClassName();
|
||||
data.arguments = arguments;
|
||||
if (namedFds == null || namedFds.isEmpty()) {
|
||||
data.dynamicArgs = new NamedParcelFileDescriptor[0];
|
||||
} else {
|
||||
@@ -56,39 +85,42 @@ public class DataLoaderParams {
|
||||
mData = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public DataLoaderParams(@NonNull DataLoaderParamsParcel data) {
|
||||
/** @hide */
|
||||
DataLoaderParams(@NonNull DataLoaderParamsParcel data) {
|
||||
mData = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return static server's URL
|
||||
*/
|
||||
public final @NonNull String getStaticArgs() {
|
||||
return mData.staticArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return data loader's package name
|
||||
*/
|
||||
public final @NonNull String getPackageName() {
|
||||
return mData.packageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
/** @hide */
|
||||
public final @NonNull DataLoaderParamsParcel getData() {
|
||||
return mData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return data loader's dynamic arguments such as file descriptors
|
||||
* @return data loader type
|
||||
*/
|
||||
public final @NonNull @DataLoaderType int getType() {
|
||||
return mData.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return data loader's component name
|
||||
*/
|
||||
public final @NonNull ComponentName getComponentName() {
|
||||
return new ComponentName(mData.packageName, mData.className);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return data loader's arguments
|
||||
*/
|
||||
public final @NonNull String getArguments() {
|
||||
return mData.arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return data loader's dynamic arguments such as file descriptors TODO: remove
|
||||
*/
|
||||
public final @NonNull Map<String, ParcelFileDescriptor> getDynamicArgs() {
|
||||
return Arrays.stream(mData.dynamicArgs).collect(
|
||||
Collectors.toMap(p->p.name, p->p.fd));
|
||||
Collectors.toMap(p -> p.name, p -> p.fd));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.content.pm;
|
||||
|
||||
import android.content.pm.DataLoaderType;
|
||||
import android.content.pm.NamedParcelFileDescriptor;
|
||||
|
||||
/**
|
||||
@@ -23,7 +24,9 @@ import android.content.pm.NamedParcelFileDescriptor;
|
||||
* @hide
|
||||
*/
|
||||
parcelable DataLoaderParamsParcel {
|
||||
DataLoaderType type;
|
||||
@utf8InCpp String packageName;
|
||||
@utf8InCpp String staticArgs;
|
||||
@utf8InCpp String className;
|
||||
@utf8InCpp String arguments;
|
||||
NamedParcelFileDescriptor[] dynamicArgs;
|
||||
}
|
||||
|
||||
37
core/java/android/content/pm/DataLoaderType.aidl
Normal file
37
core/java/android/content/pm/DataLoaderType.aidl
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Types of Data Loader for an installation session.
|
||||
* @hide
|
||||
*/
|
||||
@Backing(type="int")
|
||||
enum DataLoaderType {
|
||||
/**
|
||||
* Default value, legacy installation.
|
||||
*/
|
||||
NONE = 0,
|
||||
/**
|
||||
* Streaming installation using data loader.
|
||||
*/
|
||||
STREAMING = 1,
|
||||
/**
|
||||
* Streaming installation using Incremental FileSystem.
|
||||
*/
|
||||
INCREMENTAL = 2,
|
||||
}
|
||||
@@ -27,7 +27,9 @@ import java.util.List;
|
||||
*/
|
||||
oneway interface IDataLoader {
|
||||
void create(int id, in Bundle params, IDataLoaderStatusListener listener);
|
||||
void start(in List<InstallationFile> fileInfos);
|
||||
void start();
|
||||
void stop();
|
||||
void destroy();
|
||||
|
||||
void prepareImage(in List<InstallationFile> addedFiles, in List<String> removedFiles);
|
||||
}
|
||||
|
||||
@@ -22,13 +22,18 @@ package android.content.pm;
|
||||
*/
|
||||
oneway interface IDataLoaderStatusListener {
|
||||
/** Data loader status */
|
||||
const int DATA_LOADER_READY = 0;
|
||||
const int DATA_LOADER_NOT_READY = 1;
|
||||
const int DATA_LOADER_RUNNING = 2;
|
||||
const int DATA_LOADER_CREATED = 0;
|
||||
const int DATA_LOADER_DESTROYED = 1;
|
||||
|
||||
const int DATA_LOADER_STARTED = 2;
|
||||
const int DATA_LOADER_STOPPED = 3;
|
||||
const int DATA_LOADER_SLOW_CONNECTION = 4;
|
||||
const int DATA_LOADER_NO_CONNECTION = 5;
|
||||
const int DATA_LOADER_CONNECTION_OK = 6;
|
||||
|
||||
const int DATA_LOADER_IMAGE_READY = 4;
|
||||
const int DATA_LOADER_IMAGE_NOT_READY = 5;
|
||||
|
||||
const int DATA_LOADER_SLOW_CONNECTION = 6;
|
||||
const int DATA_LOADER_NO_CONNECTION = 7;
|
||||
const int DATA_LOADER_CONNECTION_OK = 8;
|
||||
|
||||
/** Data loader status callback */
|
||||
void onStatusChanged(in int dataLoaderId, in int status);
|
||||
|
||||
@@ -1461,10 +1461,7 @@ public class PackageInstaller {
|
||||
/** {@hide} */
|
||||
public long requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST;
|
||||
/** {@hide} */
|
||||
public DataLoaderParams incrementalParams;
|
||||
/** TODO(b/146080380): add a class name to make it fully compatible with ComponentName.
|
||||
* {@hide} */
|
||||
public String dataLoaderPackageName;
|
||||
public DataLoaderParams dataLoaderParams;
|
||||
/** {@hide} */
|
||||
public int rollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE;
|
||||
|
||||
@@ -1503,10 +1500,8 @@ public class PackageInstaller {
|
||||
DataLoaderParamsParcel dataLoaderParamsParcel = source.readParcelable(
|
||||
DataLoaderParamsParcel.class.getClassLoader());
|
||||
if (dataLoaderParamsParcel != null) {
|
||||
incrementalParams = new DataLoaderParams(
|
||||
dataLoaderParamsParcel);
|
||||
dataLoaderParams = new DataLoaderParams(dataLoaderParamsParcel);
|
||||
}
|
||||
dataLoaderPackageName = source.readString();
|
||||
rollbackDataPolicy = source.readInt();
|
||||
}
|
||||
|
||||
@@ -1531,8 +1526,7 @@ public class PackageInstaller {
|
||||
ret.isMultiPackage = isMultiPackage;
|
||||
ret.isStaged = isStaged;
|
||||
ret.requiredInstalledVersionCode = requiredInstalledVersionCode;
|
||||
ret.incrementalParams = incrementalParams;
|
||||
ret.dataLoaderPackageName = dataLoaderPackageName;
|
||||
ret.dataLoaderParams = dataLoaderParams;
|
||||
ret.rollbackDataPolicy = rollbackDataPolicy;
|
||||
return ret;
|
||||
}
|
||||
@@ -1893,29 +1887,18 @@ public class PackageInstaller {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Incremental data loader params.
|
||||
* Set the data loader params for the session.
|
||||
* This also switches installation into data provider mode and disallow direct writes into
|
||||
* staging folder.
|
||||
*
|
||||
* WARNING: This is a system API to aid internal development.
|
||||
* Use at your own risk. It will change or be removed without warning.
|
||||
* {@hide}
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
|
||||
public void setIncrementalParams(@NonNull DataLoaderParams incrementalParams) {
|
||||
this.incrementalParams = incrementalParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the data provider params for the session.
|
||||
* This also switches installation into callback mode and disallow direct writes into
|
||||
* staging folder.
|
||||
* TODO(b/146080380): unify dataprovider params with Incremental.
|
||||
*
|
||||
* @param dataLoaderPackageName name of the dataLoader package
|
||||
* {@hide}
|
||||
*/
|
||||
@RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
|
||||
public void setDataLoaderPackageName(String dataLoaderPackageName) {
|
||||
this.dataLoaderPackageName = dataLoaderPackageName;
|
||||
public void setDataLoaderParams(@NonNull DataLoaderParams dataLoaderParams) {
|
||||
this.dataLoaderParams = dataLoaderParams;
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
@@ -1938,7 +1921,7 @@ public class PackageInstaller {
|
||||
pw.printPair("isMultiPackage", isMultiPackage);
|
||||
pw.printPair("isStaged", isStaged);
|
||||
pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode);
|
||||
pw.printPair("dataLoaderPackageName", dataLoaderPackageName);
|
||||
pw.printPair("dataLoaderParams", dataLoaderParams);
|
||||
pw.printPair("rollbackDataPolicy", rollbackDataPolicy);
|
||||
pw.println();
|
||||
}
|
||||
@@ -1969,12 +1952,11 @@ public class PackageInstaller {
|
||||
dest.writeBoolean(isMultiPackage);
|
||||
dest.writeBoolean(isStaged);
|
||||
dest.writeLong(requiredInstalledVersionCode);
|
||||
if (incrementalParams != null) {
|
||||
dest.writeParcelable(incrementalParams.getData(), flags);
|
||||
if (dataLoaderParams != null) {
|
||||
dest.writeParcelable(dataLoaderParams.getData(), flags);
|
||||
} else {
|
||||
dest.writeParcelable(null, flags);
|
||||
}
|
||||
dest.writeString(dataLoaderPackageName);
|
||||
dest.writeInt(rollbackDataPolicy);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,8 +87,8 @@ public final class IncrementalFileStorages {
|
||||
mPackageName = packageName;
|
||||
mStageDir = stageDir;
|
||||
mIncrementalManager = incrementalManager;
|
||||
if (dataLoaderParams.getPackageName().equals("local")) {
|
||||
final String incrementalPath = dataLoaderParams.getStaticArgs();
|
||||
if (dataLoaderParams.getComponentName().getPackageName().equals("local")) {
|
||||
final String incrementalPath = dataLoaderParams.getArguments();
|
||||
mDefaultStorage = mIncrementalManager.openStorage(incrementalPath);
|
||||
mDefaultDir = incrementalPath;
|
||||
return;
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package android.service.dataloader;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
@@ -27,19 +26,16 @@ 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.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -55,88 +51,35 @@ import java.util.List;
|
||||
*/
|
||||
@SystemApi
|
||||
public abstract class DataLoaderService extends Service {
|
||||
private static final String TAG = "IncrementalDataLoaderService";
|
||||
private static final String TAG = "DataLoaderService";
|
||||
private final DataLoaderBinderService mBinder = new DataLoaderBinderService();
|
||||
|
||||
/** @hide */
|
||||
public static final int DATA_LOADER_READY =
|
||||
IDataLoaderStatusListener.DATA_LOADER_READY;
|
||||
/** @hide */
|
||||
public static final int DATA_LOADER_NOT_READY =
|
||||
IDataLoaderStatusListener.DATA_LOADER_NOT_READY;
|
||||
/** @hide */
|
||||
public static final int DATA_LOADER_RUNNING =
|
||||
IDataLoaderStatusListener.DATA_LOADER_RUNNING;
|
||||
/** @hide */
|
||||
public static final int DATA_LOADER_STOPPED =
|
||||
IDataLoaderStatusListener.DATA_LOADER_STOPPED;
|
||||
/** @hide */
|
||||
public static final int DATA_LOADER_SLOW_CONNECTION =
|
||||
IDataLoaderStatusListener.DATA_LOADER_SLOW_CONNECTION;
|
||||
/** @hide */
|
||||
public static final int DATA_LOADER_NO_CONNECTION =
|
||||
IDataLoaderStatusListener.DATA_LOADER_NO_CONNECTION;
|
||||
/** @hide */
|
||||
public static final int DATA_LOADER_CONNECTION_OK =
|
||||
IDataLoaderStatusListener.DATA_LOADER_CONNECTION_OK;
|
||||
|
||||
/** @hide */
|
||||
@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.
|
||||
* Managed DataLoader interface. Each instance corresponds to a single installation session.
|
||||
* @hide
|
||||
*/
|
||||
public abstract static class DataLoader {
|
||||
public interface 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.
|
||||
* A virtual constructor.
|
||||
*
|
||||
* @param params Data loader configuration parameters.
|
||||
* @param connector IncFS API wrapper.
|
||||
* @param listener Used for reporting internal state to IncrementalService.
|
||||
* @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
|
||||
* IncrementalService and can cause an unmount of an IFS instance.
|
||||
* PackageManager and fail the installation
|
||||
*/
|
||||
public abstract boolean onCreate(@NonNull DataLoaderParams params,
|
||||
@NonNull FileSystemConnector connector,
|
||||
@NonNull StatusListener listener);
|
||||
boolean onCreate(@NonNull DataLoaderParams dataLoaderParams,
|
||||
@NonNull FileSystemConnector connector);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Prepare installation image. After this method succeeds installer will validate the files
|
||||
* and continue installation.
|
||||
*
|
||||
* @return True if Data Loader was able to start. False will be reported to
|
||||
* IncrementalService and can cause an unmount of an IFS instance.
|
||||
* @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.
|
||||
*/
|
||||
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();
|
||||
boolean onPrepareImage(Collection<InstallationFile> addedFiles,
|
||||
Collection<String> removedFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,7 +88,9 @@ public abstract class DataLoaderService extends Service {
|
||||
* @return An instance of a DataLoader.
|
||||
* @hide
|
||||
*/
|
||||
public abstract @Nullable DataLoader onCreateDataLoader();
|
||||
public @Nullable DataLoader onCreateDataLoader() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
@@ -160,148 +105,125 @@ public abstract class DataLoaderService extends Service {
|
||||
@Override
|
||||
public void create(int id, @NonNull Bundle options,
|
||||
@NonNull IDataLoaderStatusListener listener)
|
||||
throws IllegalArgumentException, RuntimeException {
|
||||
throws IllegalArgumentException, RuntimeException {
|
||||
mId = id;
|
||||
final DataLoaderParamsParcel params = options.getParcelable("params");
|
||||
final DataLoaderParamsParcel params = options.getParcelable("params");
|
||||
if (params == null) {
|
||||
throw new IllegalArgumentException("Must specify Incremental data loader params");
|
||||
throw new IllegalArgumentException("Must specify data loader params");
|
||||
}
|
||||
final FileSystemControlParcel control =
|
||||
options.getParcelable("control");
|
||||
final FileSystemControlParcel control = options.getParcelable("control");
|
||||
if (control == null) {
|
||||
throw new IllegalArgumentException("Must specify Incremental control parcel");
|
||||
throw new IllegalArgumentException("Must specify control parcel");
|
||||
}
|
||||
mStatusListener = listener;
|
||||
try {
|
||||
if (!nativeCreateDataLoader(id, control, params, listener)) {
|
||||
Slog.e(TAG, "Failed to create native loader for " + mId);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Slog.e(TAG, "Failed to create native loader for " + mId, 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 != null) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
if (params.dynamicArgs != null) {
|
||||
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) {
|
||||
public void start() {
|
||||
if (!nativeStartDataLoader(mId)) {
|
||||
Slog.e(TAG, "Failed to start loader: loader not found for " + mId);
|
||||
Slog.e(TAG, "Failed to start loader: " + mId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
if (!nativeStopDataLoader(mId)) {
|
||||
Slog.w(TAG, "Failed to stop loader: loader not found for " + mId);
|
||||
Slog.w(TAG, "Failed to stop loader: " + mId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
if (!nativeDestroyDataLoader(mId)) {
|
||||
Slog.w(TAG, "Failed to destroy loader: loader not found for " + mId);
|
||||
Slog.w(TAG, "Failed to destroy loader: " + mId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareImage(List<InstallationFile> addedFiles, List<String> removedFiles) {
|
||||
if (!nativePrepareImage(mId, addedFiles, removedFiles)) {
|
||||
Slog.w(TAG, "Failed to destroy loader: " + mId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Used by the DataLoaderService implementations.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final class FileSystemConnector {
|
||||
/**
|
||||
* Creates a wrapper for an installation session connector.
|
||||
* Create a wrapper for a native instance.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
FileSystemConnector(IPackageInstallerSessionFileSystemConnector connector) {
|
||||
mConnector = connector;
|
||||
FileSystemConnector(long nativeInstance) {
|
||||
mNativeInstance = nativeInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @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);
|
||||
nativeWriteData(mNativeInstance, 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
|
||||
*/
|
||||
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,
|
||||
@@ -314,5 +236,10 @@ public abstract class DataLoaderService extends Service {
|
||||
|
||||
private native boolean nativeDestroyDataLoader(int storageId);
|
||||
|
||||
private static native boolean nativeReportStatus(long nativeInstance, int status);
|
||||
private native boolean nativePrepareImage(int storageId,
|
||||
Collection<InstallationFile> addedFiles, Collection<String> removedFiles);
|
||||
|
||||
private static native void nativeWriteData(long nativeInstance, String name, long offsetBytes,
|
||||
long lengthBytes, ParcelFileDescriptor incomingFd);
|
||||
|
||||
}
|
||||
|
||||
@@ -51,13 +51,19 @@ static jboolean nativeDestroyDataLoader(JNIEnv* env,
|
||||
}
|
||||
|
||||
|
||||
static jboolean nativeReportStatus(JNIEnv* env,
|
||||
jobject clazz,
|
||||
jlong self,
|
||||
jint status) {
|
||||
auto listener = (DataLoaderStatusListenerPtr)self;
|
||||
return DataLoader_StatusListener_reportStatus(listener,
|
||||
(DataLoaderStatus)status);
|
||||
static jboolean nativePrepareImage(JNIEnv* env, jobject thiz, jint storageId, jobject addedFiles, jobject removedFiles) {
|
||||
return DataLoaderService_OnPrepareImage(storageId, addedFiles, removedFiles);
|
||||
}
|
||||
|
||||
static void nativeWriteData(JNIEnv* env,
|
||||
jobject clazz,
|
||||
jlong self,
|
||||
jstring name,
|
||||
jlong offsetBytes,
|
||||
jlong lengthBytes,
|
||||
jobject incomingFd) {
|
||||
auto connector = (DataLoaderFilesystemConnectorPtr)self;
|
||||
return DataLoader_FilesystemConnector_writeData(connector, name, offsetBytes, lengthBytes, incomingFd);
|
||||
}
|
||||
|
||||
static const JNINativeMethod dlc_method_table[] = {
|
||||
@@ -69,7 +75,8 @@ static const JNINativeMethod dlc_method_table[] = {
|
||||
{"nativeStartDataLoader", "(I)Z", (void*)nativeStartDataLoader},
|
||||
{"nativeStopDataLoader", "(I)Z", (void*)nativeStopDataLoader},
|
||||
{"nativeDestroyDataLoader", "(I)Z", (void*)nativeDestroyDataLoader},
|
||||
{"nativeReportStatus", "(JI)Z", (void*)nativeReportStatus},
|
||||
{"nativePrepareImage", "(ILjava/util/Collection;Ljava/util/Collection;)Z", (void*)nativePrepareImage},
|
||||
{"nativeWriteData", "(JLjava/lang/String;JJLandroid/os/ParcelFileDescriptor;)V", (void*)nativeWriteData},
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -4113,7 +4113,7 @@
|
||||
<permission android:name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"
|
||||
android:protectionLevel="signature|privileged" />
|
||||
|
||||
<!-- Must be required by intent filter verifier receiver, to ensure that only the
|
||||
<!-- Must be required by intent filter verifier rintent-filtereceiver, to ensure that only the
|
||||
system can interact with it.
|
||||
@hide
|
||||
-->
|
||||
@@ -5143,6 +5143,12 @@
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" >
|
||||
</service>
|
||||
|
||||
</application>
|
||||
<service android:name="com.android.server.pm.PackageManagerShellCommandDataLoader">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.LOAD_DATA" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
@@ -177,8 +177,7 @@ private:
|
||||
android::dataloader::ServiceParamsPtr) final {
|
||||
CHECK(ifs) << "ifs can't be null";
|
||||
CHECK(statusListener) << "statusListener can't be null";
|
||||
ALOGE("[AdbDataLoader] onCreate: %s/%s/%d", params.staticArgs().c_str(),
|
||||
params.packageName().c_str(), (int)params.dynamicArgs().size());
|
||||
ALOGE("[AdbDataLoader] onCreate: %d/%s/%s/%s/%d", params.type(), params.packageName().c_str(), params.className().c_str(), params.arguments().c_str(), (int)params.dynamicArgs().size());
|
||||
|
||||
if (params.dynamicArgs().empty()) {
|
||||
ALOGE("[AdbDataLoader] Invalid DataLoaderParams. Need in/out FDs.");
|
||||
@@ -204,7 +203,7 @@ private:
|
||||
}
|
||||
|
||||
std::string logFile;
|
||||
if (const auto packageName = extractPackageName(params.staticArgs()); !packageName.empty()) {
|
||||
if (const auto packageName = extractPackageName(params.arguments()); !packageName.empty()) {
|
||||
logFile = android::base::GetProperty("adb.readlog." + packageName, "");
|
||||
}
|
||||
if (logFile.empty()) {
|
||||
@@ -288,8 +287,7 @@ private:
|
||||
"inode=%d. Ignore.",
|
||||
static_cast<int>(ino));
|
||||
mRequestedFiles.erase(fileId);
|
||||
mStatusListener->reportStatus(
|
||||
INCREMENTAL_DATA_LOADER_NO_CONNECTION);
|
||||
mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
|
||||
}
|
||||
}
|
||||
sendRequest(mOutFd, BLOCK_MISSING, fileId, blockIdx);
|
||||
@@ -337,7 +335,7 @@ private:
|
||||
}
|
||||
if (res < 0) {
|
||||
ALOGE("[AdbDataLoader] failed to poll. Abort.");
|
||||
mStatusListener->reportStatus(INCREMENTAL_DATA_LOADER_NO_CONNECTION);
|
||||
mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
|
||||
break;
|
||||
}
|
||||
if (res == mEventFd) {
|
||||
@@ -346,7 +344,7 @@ private:
|
||||
}
|
||||
if (!readChunk(mInFd, data)) {
|
||||
ALOGE("[AdbDataLoader] failed to read a message. Abort.");
|
||||
mStatusListener->reportStatus(INCREMENTAL_DATA_LOADER_NO_CONNECTION);
|
||||
mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
|
||||
break;
|
||||
}
|
||||
auto remainingData = std::span(data);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.incremental;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.DataLoaderManager;
|
||||
import android.content.pm.DataLoaderParamsParcel;
|
||||
@@ -85,7 +86,8 @@ public class IncrementalManagerService extends IIncrementalManager.Stub {
|
||||
DataLoaderParamsParcel params,
|
||||
IDataLoaderStatusListener listener) {
|
||||
Bundle dataLoaderParams = new Bundle();
|
||||
dataLoaderParams.putCharSequence("packageName", params.packageName);
|
||||
dataLoaderParams.putParcelable("componentName",
|
||||
new ComponentName(params.packageName, params.className));
|
||||
dataLoaderParams.putParcelable("control", control);
|
||||
dataLoaderParams.putParcelable("params", params);
|
||||
DataLoaderManager dataLoaderManager = mContext.getSystemService(DataLoaderManager.class);
|
||||
@@ -109,8 +111,7 @@ public class IncrementalManagerService extends IIncrementalManager.Stub {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
// TODO: fix file list
|
||||
dataLoader.start(null);
|
||||
dataLoader.start();
|
||||
return true;
|
||||
} catch (RemoteException ex) {
|
||||
return false;
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server.incremental;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.IIntentReceiver;
|
||||
import android.content.IIntentSender;
|
||||
@@ -111,14 +112,14 @@ public final class IncrementalManagerShellCommand extends ShellCommand {
|
||||
pw.println("File names and sizes don't match.");
|
||||
return ERROR_DATA_LOADER_INIT;
|
||||
}
|
||||
final DataLoaderParams params = new DataLoaderParams(
|
||||
"", LOADER_PACKAGE_NAME, dataLoaderDynamicArgs);
|
||||
final DataLoaderParams params = DataLoaderParams.forIncremental(
|
||||
new ComponentName(LOADER_PACKAGE_NAME, ""), "", dataLoaderDynamicArgs);
|
||||
PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams(
|
||||
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
|
||||
sessionParams.installFlags |= PackageManager.INSTALL_ALL_USERS;
|
||||
// Replace existing if same package is already installed
|
||||
sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
|
||||
sessionParams.setIncrementalParams(params);
|
||||
sessionParams.setDataLoaderParams(params);
|
||||
|
||||
try {
|
||||
int sessionId = packageInstaller.createSession(sessionParams);
|
||||
|
||||
@@ -76,13 +76,12 @@ public class DataLoaderManagerService extends SystemService {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
CharSequence packageNameSeq = params.getCharSequence("packageName");
|
||||
if (packageNameSeq == null) {
|
||||
Slog.e(TAG, "Must specify package name.");
|
||||
ComponentName componentName = params.getParcelable("componentName");
|
||||
if (componentName == null) {
|
||||
Slog.e(TAG, "Must specify component name.");
|
||||
return false;
|
||||
}
|
||||
String packageName = packageNameSeq.toString();
|
||||
ComponentName dataLoaderComponent = getDataLoaderServiceName(packageName);
|
||||
ComponentName dataLoaderComponent = resolveDataLoaderComponentName(componentName);
|
||||
if (dataLoaderComponent == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -103,22 +102,23 @@ public class DataLoaderManagerService extends SystemService {
|
||||
/**
|
||||
* Find the ComponentName of the data loader service provider, given its package name.
|
||||
*
|
||||
* @param packageName the package name of the provider.
|
||||
* @param componentName the name of the provider.
|
||||
* @return ComponentName of the data loader service provider. Null if provider not found.
|
||||
*/
|
||||
private @Nullable ComponentName getDataLoaderServiceName(String packageName) {
|
||||
private @Nullable ComponentName resolveDataLoaderComponentName(
|
||||
ComponentName componentName) {
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
if (pm == null) {
|
||||
Slog.e(TAG, "PackageManager is not available.");
|
||||
return null;
|
||||
}
|
||||
Intent intent = new Intent(Intent.ACTION_LOAD_DATA);
|
||||
intent.setPackage(packageName);
|
||||
intent.setComponent(componentName);
|
||||
List<ResolveInfo> services =
|
||||
pm.queryIntentServicesAsUser(intent, 0, UserHandle.getCallingUserId());
|
||||
if (services == null || services.isEmpty()) {
|
||||
Slog.e(TAG,
|
||||
"Failed to find data loader service provider in package " + packageName);
|
||||
"Failed to find data loader service provider in " + componentName);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -128,23 +128,21 @@ public class DataLoaderManagerService extends SystemService {
|
||||
int numServices = services.size();
|
||||
for (int i = 0; i < numServices; i++) {
|
||||
ResolveInfo ri = services.get(i);
|
||||
ComponentName componentName = new ComponentName(
|
||||
ComponentName resolved = new ComponentName(
|
||||
ri.serviceInfo.packageName, ri.serviceInfo.name);
|
||||
// There should only be one matching provider inside the given package.
|
||||
// If there's more than one, return the first one found.
|
||||
try {
|
||||
ApplicationInfo ai = pm.getApplicationInfo(componentName.getPackageName(), 0);
|
||||
ApplicationInfo ai = pm.getApplicationInfo(resolved.getPackageName(), 0);
|
||||
if (checkLoader && !ai.isPrivilegedApp()) {
|
||||
Slog.w(TAG,
|
||||
"Data loader: " + componentName.getPackageName()
|
||||
+ " is not a privileged app, skipping.");
|
||||
"Data loader: " + resolved + " is not a privileged app, skipping.");
|
||||
continue;
|
||||
}
|
||||
return componentName;
|
||||
return resolved;
|
||||
} catch (PackageManager.NameNotFoundException ex) {
|
||||
Slog.w(TAG,
|
||||
"Privileged data loader: " + componentName.getPackageName()
|
||||
+ " not found, skipping.");
|
||||
"Privileged data loader: " + resolved + " not found, skipping.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import static android.content.pm.DataLoaderType.INCREMENTAL;
|
||||
import static android.content.pm.DataLoaderType.STREAMING;
|
||||
import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
|
||||
import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_SIGNATURE;
|
||||
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
|
||||
@@ -49,12 +51,18 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.admin.DevicePolicyEventLogger;
|
||||
import android.app.admin.DevicePolicyManagerInternal;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.IIntentReceiver;
|
||||
import android.content.IIntentSender;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.DataLoaderManager;
|
||||
import android.content.pm.DataLoaderParams;
|
||||
import android.content.pm.FileSystemControlParcel;
|
||||
import android.content.pm.IDataLoader;
|
||||
import android.content.pm.IDataLoaderStatusListener;
|
||||
import android.content.pm.IPackageInstallObserver2;
|
||||
import android.content.pm.IPackageInstallerSession;
|
||||
import android.content.pm.IPackageInstallerSessionFileSystemConnector;
|
||||
@@ -84,6 +92,7 @@ import android.os.Message;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.ParcelableException;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.RevocableFileDescriptor;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
@@ -127,12 +136,12 @@ import java.io.FileDescriptor;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
private static final String TAG = "PackageInstallerSession";
|
||||
@@ -189,7 +198,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
private static final String ATTR_VOLUME_UUID = "volumeUuid";
|
||||
private static final String ATTR_NAME = "name";
|
||||
private static final String ATTR_INSTALL_REASON = "installRason";
|
||||
private static final String ATTR_DATA_LOADER_PACKAGE_NAME = "dataLoaderPackageName";
|
||||
private static final String ATTR_IS_DATALOADER = "isDataLoader";
|
||||
private static final String ATTR_DATALOADER_TYPE = "dataLoaderType";
|
||||
private static final String ATTR_DATALOADER_PACKAGE_NAME = "dataLoaderPackageName";
|
||||
private static final String ATTR_DATALOADER_CLASS_NAME = "dataLoaderClassName";
|
||||
private static final String ATTR_DATALOADER_ARGUMENTS = "dataLoaderArguments";
|
||||
private static final String ATTR_LENGTH_BYTES = "lengthBytes";
|
||||
private static final String ATTR_METADATA = "metadata";
|
||||
|
||||
@@ -414,7 +427,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
};
|
||||
|
||||
private boolean isDataLoaderInstallation() {
|
||||
return !TextUtils.isEmpty(params.dataLoaderPackageName);
|
||||
return params.dataLoaderParams != null;
|
||||
}
|
||||
|
||||
private boolean isStreamingInstallation() {
|
||||
return isDataLoaderInstallation() && params.dataLoaderParams.getType() == STREAMING;
|
||||
}
|
||||
|
||||
private boolean isIncrementalInstallation() {
|
||||
return isDataLoaderInstallation() && params.dataLoaderParams.getType() == INCREMENTAL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,14 +546,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
stagedSessionErrorMessage != null ? stagedSessionErrorMessage : "";
|
||||
|
||||
// TODO(b/136132412): sanity check if session should not be incremental
|
||||
if (!params.isStaged && params.incrementalParams != null
|
||||
&& !params.incrementalParams.getPackageName().isEmpty()) {
|
||||
if (!params.isStaged && isIncrementalInstallation()) {
|
||||
IncrementalManager incrementalManager = (IncrementalManager) mContext.getSystemService(
|
||||
Context.INCREMENTAL_SERVICE);
|
||||
if (incrementalManager != null) {
|
||||
mIncrementalFileStorages =
|
||||
new IncrementalFileStorages(mPackageName, stageDir, incrementalManager,
|
||||
params.incrementalParams);
|
||||
params.dataLoaderParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -714,7 +734,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
public void removeSplit(String splitName) {
|
||||
if (isDataLoaderInstallation()) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot remove splits in a callback installation session.");
|
||||
"Cannot remove splits in a data loader installation session.");
|
||||
}
|
||||
if (TextUtils.isEmpty(params.appPackageName)) {
|
||||
throw new IllegalStateException("Must specify package name to remove a split");
|
||||
@@ -753,7 +773,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
private void assertCanWrite(boolean reverseMode) {
|
||||
if (isDataLoaderInstallation()) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot write regular files in a callback installation session.");
|
||||
"Cannot write regular files in a data loader installation session.");
|
||||
}
|
||||
synchronized (mLock) {
|
||||
assertCallerIsOwnerOrRootLocked();
|
||||
@@ -894,7 +914,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
public ParcelFileDescriptor openRead(String name) {
|
||||
if (isDataLoaderInstallation()) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot read regular files in a callback installation session.");
|
||||
"Cannot read regular files in a data loader installation session.");
|
||||
}
|
||||
synchronized (mLock) {
|
||||
assertCallerIsOwnerOrRootLocked();
|
||||
@@ -1663,7 +1683,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
computeProgressLocked(true);
|
||||
|
||||
// Unpack native libraries for non-incremental installation
|
||||
if (params.incrementalParams == null) {
|
||||
if (isIncrementalInstallation()) {
|
||||
extractNativeLibraries(stageDir, params.abiOverride, mayInheritNativeLibs());
|
||||
}
|
||||
}
|
||||
@@ -2382,7 +2402,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
}
|
||||
if (!isDataLoaderInstallation()) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot add files to non-callback installation session.");
|
||||
"Cannot add files to non-data loader installation session.");
|
||||
}
|
||||
// Use installer provided name for now; we always rename later
|
||||
if (!FileUtils.isValidExtFilename(name)) {
|
||||
@@ -2401,7 +2421,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
public void removeFile(String name) {
|
||||
if (!isDataLoaderInstallation()) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot add files to non-callback installation session.");
|
||||
"Cannot add files to non-data loader installation session.");
|
||||
}
|
||||
if (TextUtils.isEmpty(params.appPackageName)) {
|
||||
throw new IllegalStateException("Must specify package name to remove a split");
|
||||
@@ -2415,76 +2435,121 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
static class Notificator {
|
||||
private int mValue = 0;
|
||||
|
||||
void setValue(int value) {
|
||||
synchronized (this) {
|
||||
mValue = value;
|
||||
this.notify();
|
||||
}
|
||||
}
|
||||
int waitForValue() {
|
||||
synchronized (this) {
|
||||
while (mValue == 0) {
|
||||
try {
|
||||
this.wait();
|
||||
} catch (InterruptedException e) {
|
||||
// Happens if someone interrupts your thread.
|
||||
}
|
||||
}
|
||||
return mValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure files are present in staging location.
|
||||
*/
|
||||
private void prepareDataLoader()
|
||||
throws PackageManagerException, StreamingException {
|
||||
if (!isDataLoaderInstallation()) {
|
||||
if (!isStreamingInstallation()) {
|
||||
return;
|
||||
}
|
||||
|
||||
FileSystemConnector connector = new FileSystemConnector();
|
||||
|
||||
FileInfo[] addedFiles = mFiles.stream().filter(
|
||||
file -> sAddedFilter.accept(new File(file.name))).toArray(FileInfo[]::new);
|
||||
String[] removedFiles = mFiles.stream().filter(
|
||||
List<InstallationFile> addedFiles = mFiles.stream().filter(
|
||||
file -> sAddedFilter.accept(new File(file.name))).map(
|
||||
file -> new InstallationFile(
|
||||
file.name, file.lengthBytes, file.metadata)).collect(
|
||||
Collectors.toList());
|
||||
List<String> removedFiles = mFiles.stream().filter(
|
||||
file -> sRemovedFilter.accept(new File(file.name))).map(
|
||||
file -> file.name.substring(0,
|
||||
file.name.length() - REMOVE_MARKER_EXTENSION.length())).toArray(
|
||||
String[]::new);
|
||||
file -> file.name.substring(
|
||||
0, file.name.length() - REMOVE_MARKER_EXTENSION.length())).collect(
|
||||
Collectors.toList());
|
||||
|
||||
DataLoader dataLoader = new DataLoader();
|
||||
try {
|
||||
dataLoader.onCreate(connector);
|
||||
|
||||
if (!dataLoader.onPrepareImage(addedFiles, removedFiles)) {
|
||||
throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
|
||||
"Failed to prepare image.");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new StreamingException(e);
|
||||
} finally {
|
||||
dataLoader.onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
static class DataLoader {
|
||||
private ParcelFileDescriptor mInFd = null;
|
||||
private FileSystemConnector mConnector = null;
|
||||
|
||||
void onCreate(FileSystemConnector connector) throws IOException {
|
||||
mConnector = connector;
|
||||
DataLoaderManager dataLoaderManager = mContext.getSystemService(DataLoaderManager.class);
|
||||
if (dataLoaderManager == null) {
|
||||
throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
|
||||
"Failed to find data loader manager service");
|
||||
}
|
||||
|
||||
void onDestroy() {
|
||||
IoUtils.closeQuietly(mInFd);
|
||||
}
|
||||
// TODO(b/146080380): make this code async.
|
||||
final Notificator created = new Notificator();
|
||||
final Notificator started = new Notificator();
|
||||
final Notificator imageReady = new Notificator();
|
||||
|
||||
private static final String STDIN_PATH = "-";
|
||||
boolean onPrepareImage(FileInfo[] addedFiles, String[] removedFiles) throws IOException {
|
||||
for (FileInfo fileInfo : addedFiles) {
|
||||
String filePath = new String(fileInfo.metadata, StandardCharsets.UTF_8);
|
||||
if (STDIN_PATH.equals(filePath) || TextUtils.isEmpty(filePath)) {
|
||||
if (mInFd == null) {
|
||||
Slog.e(TAG, "Invalid stdin file descriptor.");
|
||||
return false;
|
||||
IDataLoaderStatusListener listener = new IDataLoaderStatusListener.Stub() {
|
||||
@Override
|
||||
public void onStatusChanged(int dataLoaderId, int status) {
|
||||
switch (status) {
|
||||
case IDataLoaderStatusListener.DATA_LOADER_CREATED: {
|
||||
created.setValue(1);
|
||||
break;
|
||||
}
|
||||
ParcelFileDescriptor inFd = ParcelFileDescriptor.dup(mInFd.getFileDescriptor());
|
||||
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.name, 0, localFile.length(), incomingFd);
|
||||
} finally {
|
||||
IoUtils.closeQuietly(incomingFd);
|
||||
case IDataLoaderStatusListener.DATA_LOADER_STARTED: {
|
||||
started.setValue(1);
|
||||
break;
|
||||
}
|
||||
case IDataLoaderStatusListener.DATA_LOADER_IMAGE_READY: {
|
||||
imageReady.setValue(1);
|
||||
break;
|
||||
}
|
||||
case IDataLoaderStatusListener.DATA_LOADER_IMAGE_NOT_READY: {
|
||||
imageReady.setValue(2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
final DataLoaderParams params = this.params.dataLoaderParams;
|
||||
|
||||
final FileSystemControlParcel control = new FileSystemControlParcel();
|
||||
control.callback = connector;
|
||||
|
||||
Bundle dataLoaderParams = new Bundle();
|
||||
dataLoaderParams.putParcelable("componentName", params.getComponentName());
|
||||
dataLoaderParams.putParcelable("control", control);
|
||||
dataLoaderParams.putParcelable("params", params.getData());
|
||||
|
||||
if (!dataLoaderManager.initializeDataLoader(sessionId, dataLoaderParams, listener)) {
|
||||
throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
|
||||
"Failed to initialize data loader");
|
||||
}
|
||||
created.waitForValue();
|
||||
|
||||
IDataLoader dataLoader = dataLoaderManager.getDataLoader(sessionId);
|
||||
if (dataLoader == null) {
|
||||
throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
|
||||
"Failure to obtain data loader");
|
||||
}
|
||||
|
||||
try {
|
||||
dataLoader.start();
|
||||
started.waitForValue();
|
||||
|
||||
dataLoader.prepareImage(addedFiles, removedFiles);
|
||||
if (imageReady.waitForValue() == 2) {
|
||||
throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
|
||||
"Failed to prepare image.");
|
||||
}
|
||||
|
||||
dataLoader.destroy();
|
||||
} catch (RemoteException e) {
|
||||
throw new StreamingException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2846,7 +2911,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
writeStringAttribute(out, ATTR_VOLUME_UUID, params.volumeUuid);
|
||||
writeIntAttribute(out, ATTR_INSTALL_REASON, params.installReason);
|
||||
|
||||
writeStringAttribute(out, ATTR_DATA_LOADER_PACKAGE_NAME, params.dataLoaderPackageName);
|
||||
final boolean isDataLoader = params.dataLoaderParams != null;
|
||||
writeBooleanAttribute(out, ATTR_IS_DATALOADER, isDataLoader);
|
||||
if (isDataLoader) {
|
||||
writeIntAttribute(out, ATTR_DATALOADER_TYPE, params.dataLoaderParams.getType());
|
||||
writeStringAttribute(out, ATTR_DATALOADER_PACKAGE_NAME,
|
||||
params.dataLoaderParams.getComponentName().getPackageName());
|
||||
writeStringAttribute(out, ATTR_DATALOADER_CLASS_NAME,
|
||||
params.dataLoaderParams.getComponentName().getClassName());
|
||||
writeStringAttribute(out, ATTR_DATALOADER_ARGUMENTS,
|
||||
params.dataLoaderParams.getArguments());
|
||||
}
|
||||
|
||||
writeGrantedRuntimePermissionsLocked(out, params.grantedRuntimePermissions);
|
||||
writeWhitelistedRestrictedPermissionsLocked(out,
|
||||
@@ -2957,7 +3032,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
params.volumeUuid = readStringAttribute(in, ATTR_VOLUME_UUID);
|
||||
params.installReason = readIntAttribute(in, ATTR_INSTALL_REASON);
|
||||
|
||||
params.dataLoaderPackageName = readStringAttribute(in, ATTR_DATA_LOADER_PACKAGE_NAME);
|
||||
if (readBooleanAttribute(in, ATTR_IS_DATALOADER)) {
|
||||
params.dataLoaderParams = new DataLoaderParams(
|
||||
readIntAttribute(in, ATTR_DATALOADER_TYPE),
|
||||
new ComponentName(
|
||||
readStringAttribute(in, ATTR_DATALOADER_PACKAGE_NAME),
|
||||
readStringAttribute(in, ATTR_DATALOADER_CLASS_NAME)),
|
||||
readStringAttribute(in, ATTR_DATALOADER_ARGUMENTS),
|
||||
null);
|
||||
}
|
||||
|
||||
final File appIconFile = buildAppIconFile(sessionId, sessionsDir);
|
||||
if (appIconFile.exists()) {
|
||||
|
||||
@@ -34,6 +34,7 @@ import android.content.IIntentSender;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.DataLoaderParams;
|
||||
import android.content.pm.FeatureInfo;
|
||||
import android.content.pm.IPackageDataObserver;
|
||||
import android.content.pm.IPackageInstaller;
|
||||
@@ -136,7 +137,9 @@ class PackageManagerShellCommand extends ShellCommand {
|
||||
private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/";
|
||||
private static final int DEFAULT_WAIT_MS = 60 * 1000;
|
||||
|
||||
private static final String PM_SHELL_DATALOADER = "com.android.pm.dataloader";
|
||||
private static final String DATA_LOADER_PACKAGE = "android";
|
||||
private static final String DATA_LOADER_CLASS =
|
||||
"com.android.server.pm.PackageManagerShellCommandDataLoader";
|
||||
|
||||
final IPackageManager mInterface;
|
||||
final IPermissionManager mPermissionManager;
|
||||
@@ -1159,8 +1162,10 @@ class PackageManagerShellCommand extends ShellCommand {
|
||||
|
||||
private int runStreamingInstall() throws RemoteException {
|
||||
final InstallParams params = makeInstallParams();
|
||||
if (TextUtils.isEmpty(params.sessionParams.dataLoaderPackageName)) {
|
||||
params.sessionParams.setDataLoaderPackageName(PM_SHELL_DATALOADER);
|
||||
if (params.sessionParams.dataLoaderParams == null) {
|
||||
final DataLoaderParams dataLoaderParams = DataLoaderParams.forStreaming(
|
||||
new ComponentName(DATA_LOADER_PACKAGE, DATA_LOADER_CLASS), "");
|
||||
params.sessionParams.setDataLoaderParams(dataLoaderParams);
|
||||
}
|
||||
return doRunInstall(params);
|
||||
}
|
||||
@@ -1171,7 +1176,7 @@ class PackageManagerShellCommand extends ShellCommand {
|
||||
|
||||
private int doRunInstall(final InstallParams params) throws RemoteException {
|
||||
final PrintWriter pw = getOutPrintWriter();
|
||||
final boolean streaming = !TextUtils.isEmpty(params.sessionParams.dataLoaderPackageName);
|
||||
final boolean streaming = params.sessionParams.dataLoaderParams != null;
|
||||
|
||||
ArrayList<String> inPaths = getRemainingArgs();
|
||||
if (inPaths.isEmpty()) {
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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 com.android.server.pm;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.pm.DataLoaderParams;
|
||||
import android.content.pm.InstallationFile;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.service.dataloader.DataLoaderService;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Slog;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Callback data loader for PackageManagerShellCommand installations.
|
||||
*/
|
||||
public class PackageManagerShellCommandDataLoader extends DataLoaderService {
|
||||
public static final String TAG = "PackageManagerShellCommandDataLoader";
|
||||
|
||||
static class DataLoader implements DataLoaderService.DataLoader {
|
||||
private ParcelFileDescriptor mInFd = null;
|
||||
private FileSystemConnector mConnector = null;
|
||||
|
||||
private static final String STDIN_PATH = "-";
|
||||
|
||||
@Override
|
||||
public boolean onCreate(@NonNull DataLoaderParams dataLoaderParams,
|
||||
@NonNull FileSystemConnector connector) {
|
||||
mConnector = connector;
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean onPrepareImage(Collection<InstallationFile> addedFiles,
|
||||
Collection<String> removedFiles) {
|
||||
try {
|
||||
for (InstallationFile fileInfo : addedFiles) {
|
||||
String filePath = new String(fileInfo.getMetadata(), StandardCharsets.UTF_8);
|
||||
if (STDIN_PATH.equals(filePath) || TextUtils.isEmpty(filePath)) {
|
||||
// TODO(b/146080380): add support for STDIN installations.
|
||||
if (mInFd == null) {
|
||||
Slog.e(TAG, "Invalid stdin file descriptor.");
|
||||
return false;
|
||||
}
|
||||
ParcelFileDescriptor inFd = ParcelFileDescriptor.dup(
|
||||
mInFd.getFileDescriptor());
|
||||
mConnector.writeData(fileInfo.getName(), 0, fileInfo.getSize(), inFd);
|
||||
} else {
|
||||
File localFile = new File(filePath);
|
||||
ParcelFileDescriptor incomingFd = null;
|
||||
try {
|
||||
// TODO(b/146080380): open files via callback into shell command.
|
||||
incomingFd = ParcelFileDescriptor.open(localFile,
|
||||
ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
mConnector.writeData(fileInfo.getName(), 0, localFile.length(),
|
||||
incomingFd);
|
||||
} finally {
|
||||
IoUtils.closeQuietly(incomingFd);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataLoaderService.DataLoader onCreateDataLoader() {
|
||||
return new DataLoader();
|
||||
}
|
||||
}
|
||||
@@ -351,10 +351,13 @@ StorageId IncrementalService::createStorage(std::string_view mountPoint,
|
||||
{
|
||||
metadata::Mount m;
|
||||
m.mutable_storage()->set_id(ifs->mountId);
|
||||
m.mutable_loader()->set_type((int)dataLoaderParams.type);
|
||||
m.mutable_loader()->set_package_name(dataLoaderParams.packageName);
|
||||
m.mutable_loader()->set_arguments(dataLoaderParams.staticArgs);
|
||||
m.mutable_loader()->set_class_name(dataLoaderParams.className);
|
||||
m.mutable_loader()->set_arguments(dataLoaderParams.arguments);
|
||||
const auto metadata = m.SerializeAsString();
|
||||
m.mutable_loader()->release_arguments();
|
||||
m.mutable_loader()->release_class_name();
|
||||
m.mutable_loader()->release_package_name();
|
||||
if (auto err = mIncFs->makeFile(ifs->control, constants().infoMdName, INCFS_ROOT_INODE, 0,
|
||||
metadata);
|
||||
@@ -794,7 +797,7 @@ bool IncrementalService::startLoading(StorageId storage) const {
|
||||
}
|
||||
bool started = false;
|
||||
std::unique_lock l(ifs->lock);
|
||||
if (ifs->dataLoaderStatus != IDataLoaderStatusListener::DATA_LOADER_READY) {
|
||||
if (ifs->dataLoaderStatus != IDataLoaderStatusListener::DATA_LOADER_CREATED) {
|
||||
if (ifs->dataLoaderReady.wait_for(l, Seconds(5)) == std::cv_status::timeout) {
|
||||
LOG(ERROR) << "Timeout waiting for data loader to be ready";
|
||||
return false;
|
||||
@@ -917,8 +920,10 @@ bool IncrementalService::mountExistingImage(std::string_view root, std::string_v
|
||||
}
|
||||
|
||||
DataLoaderParamsParcel dlParams;
|
||||
dlParams.type = (DataLoaderType)m.loader().type();
|
||||
dlParams.packageName = std::move(*m.mutable_loader()->mutable_package_name());
|
||||
dlParams.staticArgs = std::move(*m.mutable_loader()->mutable_arguments());
|
||||
dlParams.className = std::move(*m.mutable_loader()->mutable_class_name());
|
||||
dlParams.arguments = std::move(*m.mutable_loader()->mutable_arguments());
|
||||
if (!prepareDataLoader(*ifs, &dlParams)) {
|
||||
deleteStorage(*ifs);
|
||||
return false;
|
||||
@@ -955,7 +960,7 @@ bool IncrementalService::prepareDataLoader(IncrementalService::IncFsMount& ifs,
|
||||
}
|
||||
|
||||
std::unique_lock l(ifs.lock);
|
||||
if (ifs.dataLoaderStatus == IDataLoaderStatusListener::DATA_LOADER_READY) {
|
||||
if (ifs.dataLoaderStatus == IDataLoaderStatusListener::DATA_LOADER_CREATED) {
|
||||
LOG(INFO) << "Skipped data loader preparation because it already exists";
|
||||
return true;
|
||||
}
|
||||
@@ -1008,20 +1013,20 @@ binder::Status IncrementalService::IncrementalDataLoaderListener::onStatusChange
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IDataLoaderStatusListener::DATA_LOADER_READY: {
|
||||
case IDataLoaderStatusListener::DATA_LOADER_CONNECTION_OK: {
|
||||
ifs->dataLoaderStatus = IDataLoaderStatusListener::DATA_LOADER_STARTED;
|
||||
break;
|
||||
}
|
||||
case IDataLoaderStatusListener::DATA_LOADER_CREATED: {
|
||||
ifs->dataLoaderReady.notify_one();
|
||||
break;
|
||||
}
|
||||
case IDataLoaderStatusListener::DATA_LOADER_NOT_READY: {
|
||||
case IDataLoaderStatusListener::DATA_LOADER_DESTROYED: {
|
||||
ifs->dataLoaderStatus = IDataLoaderStatusListener::DATA_LOADER_STOPPED;
|
||||
incrementalService.deleteStorageLocked(*ifs, std::move(l));
|
||||
break;
|
||||
}
|
||||
case IDataLoaderStatusListener::DATA_LOADER_RUNNING: {
|
||||
break;
|
||||
}
|
||||
case IDataLoaderStatusListener::DATA_LOADER_CONNECTION_OK: {
|
||||
ifs->dataLoaderStatus = IDataLoaderStatusListener::DATA_LOADER_RUNNING;
|
||||
case IDataLoaderStatusListener::DATA_LOADER_STARTED: {
|
||||
break;
|
||||
}
|
||||
case IDataLoaderStatusListener::DATA_LOADER_STOPPED: {
|
||||
|
||||
@@ -10,7 +10,9 @@ message BindPoint {
|
||||
|
||||
message DataLoader {
|
||||
string package_name = 1;
|
||||
string class_name = 3;
|
||||
string arguments = 2;
|
||||
int32 type = 4;
|
||||
}
|
||||
|
||||
message Storage {
|
||||
|
||||
@@ -138,10 +138,10 @@ public:
|
||||
.WillByDefault(Invoke(this, &MockIncrementalManager::startDataLoaderOk));
|
||||
}
|
||||
void setDataLoaderStatusNotReady() {
|
||||
mListener->onStatusChanged(mId, IDataLoaderStatusListener::DATA_LOADER_NOT_READY);
|
||||
mListener->onStatusChanged(mId, IDataLoaderStatusListener::DATA_LOADER_DESTROYED);
|
||||
}
|
||||
void setDataLoaderStatusReady() {
|
||||
mListener->onStatusChanged(mId, IDataLoaderStatusListener::DATA_LOADER_READY);
|
||||
mListener->onStatusChanged(mId, IDataLoaderStatusListener::DATA_LOADER_CREATED);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -235,7 +235,7 @@ public:
|
||||
MockServiceManager serviceManager = MockServiceManager(mVold, mIncrementalManager, mIncFs);
|
||||
mIncrementalService = std::make_unique<IncrementalService>(serviceManager, mRootDir.path);
|
||||
mDataLoaderParcel.packageName = "com.test";
|
||||
mDataLoaderParcel.staticArgs = "uri";
|
||||
mDataLoaderParcel.arguments = "uri";
|
||||
mIncrementalService->onSystemReady();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user