Merge "make IDataLoaderManager and IDataLoader stable interfaces" into rvc-dev

This commit is contained in:
Songchun Fan
2020-03-04 22:53:12 +00:00
committed by Android (Google) Code Review
15 changed files with 146 additions and 139 deletions

View File

@@ -967,6 +967,10 @@ filegroup {
"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/IDataLoader.aidl",
"core/java/android/content/pm/IDataLoaderManager.aidl",
"core/java/android/content/pm/InstallationFileParcel.aidl",
"core/java/android/content/pm/InstallationFileLocation.aidl",
"core/java/android/content/pm/IDataLoaderStatusListener.aidl",
"core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl",
"core/java/android/content/pm/NamedParcelFileDescriptor.aidl",

View File

@@ -2018,16 +2018,13 @@ package android.content.pm {
method @NonNull public final int getType();
}
public final class InstallationFile implements android.os.Parcelable {
public final class InstallationFile {
ctor public InstallationFile(int, @NonNull String, long, @Nullable byte[], @Nullable byte[]);
method public int describeContents();
method public long getLengthBytes();
method public int getLocation();
method @Nullable public byte[] getMetadata();
method @NonNull public String getName();
method @Nullable public byte[] getSignature();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.InstallationFile> CREATOR;
}
public final class InstantAppInfo implements android.os.Parcelable {

View File

@@ -18,7 +18,6 @@ package android.content.pm;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.RemoteException;
/**
@@ -40,22 +39,19 @@ public class DataLoaderManager {
* Finds a data loader binder service and binds to it. This requires PackageManager.
*
* @param dataLoaderId ID for the new data loader binder service.
* @param params Bundle that contains parameters to configure the data loader service.
* Must contain:
* key: "packageName", value: String, package name of data loader service
* package;
* key: "extras", value: Bundle, client-specific data structures
*
* @param params DataLoaderParamsParcel object that contains data loader params, including
* its package name, class name, and additional parameters.
* @param control FileSystemControlParcel that contains filesystem control handlers.
* @param listener Callback for the data loader service to report status back to the
* caller.
* @return false if 1) target ID collides with a data loader that is already bound to data
* loader manager; 2) package name is not specified; 3) fails to find data loader package;
* or 4) fails to bind to the specified data loader service, otherwise return true.
*/
public boolean initializeDataLoader(int dataLoaderId, @NonNull Bundle params,
@NonNull IDataLoaderStatusListener listener) {
public boolean initializeDataLoader(int dataLoaderId, @NonNull DataLoaderParamsParcel params,
@NonNull FileSystemControlParcel control, @NonNull IDataLoaderStatusListener listener) {
try {
return mService.initializeDataLoader(dataLoaderId, params, listener);
return mService.initializeDataLoader(dataLoaderId, params, control, listener);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}

View File

@@ -16,20 +16,22 @@
package android.content.pm;
import android.os.Bundle;
import android.content.pm.DataLoaderParamsParcel;
import android.content.pm.FileSystemControlParcel;
import android.content.pm.IDataLoaderStatusListener;
import android.content.pm.InstallationFile;
import android.content.pm.InstallationFileParcel;
import java.util.List;
/**
* TODO: update with new APIs
* @hide
*/
oneway interface IDataLoader {
void create(int id, in Bundle params, IDataLoaderStatusListener listener);
void create(int id, in DataLoaderParamsParcel params,
in FileSystemControlParcel control,
IDataLoaderStatusListener listener);
void start();
void stop();
void destroy();
void prepareImage(in List<InstallationFile> addedFiles, in List<String> removedFiles);
void prepareImage(in InstallationFileParcel[] addedFiles, in @utf8InCpp String[] removedFiles);
}

View File

@@ -16,14 +16,15 @@
package android.content.pm;
import android.os.Bundle;
import android.content.pm.DataLoaderParamsParcel;
import android.content.pm.FileSystemControlParcel;
import android.content.pm.IDataLoader;
import android.content.pm.IDataLoaderStatusListener;
import java.util.List;
/** @hide */
interface IDataLoaderManager {
boolean initializeDataLoader(int id, in Bundle params, IDataLoaderStatusListener listener);
boolean initializeDataLoader(int id, in DataLoaderParamsParcel params,
in FileSystemControlParcel control, IDataLoaderStatusListener listener);
IDataLoader getDataLoader(int dataLoaderId);
void destroyDataLoader(int dataLoaderId);
}

View File

@@ -19,81 +19,47 @@ package android.content.pm;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Defines the properties of a file in an installation session.
* @hide
*/
@SystemApi
public final class InstallationFile implements Parcelable {
private final @PackageInstaller.FileLocation int mLocation;
private final @NonNull String mName;
private final long mLengthBytes;
private final @Nullable byte[] mMetadata;
private final @Nullable byte[] mSignature;
public final class InstallationFile {
private final @NonNull InstallationFileParcel mParcel;
public InstallationFile(@PackageInstaller.FileLocation int location, @NonNull String name,
long lengthBytes, @Nullable byte[] metadata, @Nullable byte[] signature) {
mLocation = location;
mName = name;
mLengthBytes = lengthBytes;
mMetadata = metadata;
mSignature = signature;
mParcel = new InstallationFileParcel();
mParcel.location = location;
mParcel.name = name;
mParcel.size = lengthBytes;
mParcel.metadata = metadata;
mParcel.signature = signature;
}
public @PackageInstaller.FileLocation int getLocation() {
return mLocation;
return mParcel.location;
}
public @NonNull String getName() {
return mName;
return mParcel.name;
}
public long getLengthBytes() {
return mLengthBytes;
return mParcel.size;
}
public @Nullable byte[] getMetadata() {
return mMetadata;
return mParcel.metadata;
}
public @Nullable byte[] getSignature() {
return mSignature;
return mParcel.signature;
}
private InstallationFile(Parcel source) {
mLocation = source.readInt();
mName = source.readString();
mLengthBytes = source.readLong();
mMetadata = source.createByteArray();
mSignature = source.createByteArray();
/** @hide */
public @NonNull InstallationFileParcel getData() {
return mParcel;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mLocation);
dest.writeString(mName);
dest.writeLong(mLengthBytes);
dest.writeByteArray(mMetadata);
dest.writeByteArray(mSignature);
}
public static final @NonNull Creator<InstallationFile> CREATOR =
new Creator<InstallationFile>() {
public InstallationFile createFromParcel(Parcel source) {
return new InstallationFile(source);
}
public InstallationFile[] newArray(int size) {
return new InstallationFile[size];
}
};
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2020 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;
/** @hide */
@Backing(type="int")
enum InstallationFileLocation {
UNKNOWN = -1,
DATA_APP = 0,
MEDIA_OBB = 1,
MEDIA_DATA = 2
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2020 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.InstallationFileLocation;
/**
* Describes a file which is part of a package installation.
* @hide
*/
parcelable InstallationFileParcel {
String name;
InstallationFileLocation location;
long size;
byte[] metadata;
byte[] signature;
}

View File

@@ -372,7 +372,7 @@ public class PackageInstaller {
* {@hide}
*/
@SystemApi
public static final int LOCATION_DATA_APP = 0;
public static final int LOCATION_DATA_APP = InstallationFileLocation.DATA_APP;
/**
* Target location for the file in installation session is
@@ -380,7 +380,7 @@ public class PackageInstaller {
* {@hide}
*/
@SystemApi
public static final int LOCATION_MEDIA_OBB = 1;
public static final int LOCATION_MEDIA_OBB = InstallationFileLocation.MEDIA_OBB;
/**
* Target location for the file in installation session is
@@ -390,7 +390,7 @@ public class PackageInstaller {
* {@hide}
*/
@SystemApi
public static final int LOCATION_MEDIA_DATA = 2;
public static final int LOCATION_MEDIA_DATA = InstallationFileLocation.MEDIA_DATA;
/** @hide */
@IntDef(prefix = { "LOCATION_" }, value = {

View File

@@ -36,7 +36,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.DataLoaderParams;
import android.content.pm.IDataLoaderStatusListener;
import android.content.pm.InstallationFile;
import android.content.pm.InstallationFileParcel;
import android.text.TextUtils;
import android.util.Slog;
@@ -76,7 +76,7 @@ public final class IncrementalFileStorages {
@NonNull File stageDir,
@NonNull DataLoaderParams dataLoaderParams,
@Nullable IDataLoaderStatusListener dataLoaderStatusListener,
List<InstallationFile> addedFiles) throws IOException {
List<InstallationFileParcel> addedFiles) throws IOException {
// TODO(b/136132412): sanity check if session should not be incremental
IncrementalManager incrementalManager = (IncrementalManager) context.getSystemService(
Context.INCREMENTAL_SERVICE);
@@ -94,17 +94,17 @@ public final class IncrementalFileStorages {
result.mDefaultStorage.bind(stageDir.getAbsolutePath());
}
for (InstallationFile file : addedFiles) {
if (file.getLocation() == LOCATION_DATA_APP) {
for (InstallationFileParcel file : addedFiles) {
if (file.location == LOCATION_DATA_APP) {
try {
result.addApkFile(file);
} catch (IOException e) {
// TODO(b/146080380): add incremental-specific error code
throw new IOException(
"Failed to add file to IncFS: " + file.getName() + ", reason: ", e);
"Failed to add file to IncFS: " + file.name + ", reason: ", e);
}
} else {
throw new IOException("Unknown file location: " + file.getLocation());
throw new IOException("Unknown file location: " + file.location);
}
}
@@ -154,12 +154,11 @@ public final class IncrementalFileStorages {
}
}
private void addApkFile(@NonNull InstallationFile apk) throws IOException {
final String apkName = apk.getName();
private void addApkFile(@NonNull InstallationFileParcel apk) throws IOException {
final String apkName = apk.name;
final File targetFile = new File(mStageDir, apkName);
if (!targetFile.exists()) {
mDefaultStorage.makeFile(apkName, apk.getLengthBytes(), null, apk.getMetadata(),
apk.getSignature());
mDefaultStorage.makeFile(apkName, apk.size, null, apk.metadata, apk.signature);
}
}

View File

@@ -27,8 +27,8 @@ 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.content.pm.NamedParcelFileDescriptor;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.util.ExceptionUtils;
@@ -36,7 +36,6 @@ import android.util.Slog;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
/**
* The base class for implementing data loader service to control data loaders. Expecting
@@ -105,18 +104,11 @@ public abstract class DataLoaderService extends Service {
private int mId;
@Override
public void create(int id, @NonNull Bundle options,
public void create(int id, @NonNull DataLoaderParamsParcel params,
@NonNull FileSystemControlParcel control,
@NonNull IDataLoaderStatusListener listener)
throws IllegalArgumentException, RuntimeException {
throws RuntimeException {
mId = id;
final DataLoaderParamsParcel params = options.getParcelable("params");
if (params == null) {
throw new IllegalArgumentException("Must specify data loader params");
}
final FileSystemControlParcel control = options.getParcelable("control");
if (control == null) {
throw new IllegalArgumentException("Must specify control parcel");
}
try {
if (!nativeCreateDataLoader(id, control, params, listener)) {
Slog.e(TAG, "Failed to create native loader for " + mId);
@@ -178,7 +170,7 @@ public abstract class DataLoaderService extends Service {
}
@Override
public void prepareImage(List<InstallationFile> addedFiles, List<String> removedFiles) {
public void prepareImage(InstallationFileParcel[] addedFiles, String[] removedFiles) {
if (!nativePrepareImage(mId, addedFiles, removedFiles)) {
Slog.w(TAG, "Failed to destroy loader: " + mId);
}
@@ -240,7 +232,7 @@ public abstract class DataLoaderService extends Service {
private native boolean nativeDestroyDataLoader(int storageId);
private native boolean nativePrepareImage(int storageId,
List<InstallationFile> addedFiles, List<String> removedFiles);
InstallationFileParcel[] addedFiles, String[] removedFiles);
private static native void nativeWriteData(long nativeInstance, String name, long offsetBytes,
long lengthBytes, ParcelFileDescriptor incomingFd);

View File

@@ -50,8 +50,8 @@ static jboolean nativeDestroyDataLoader(JNIEnv* env,
return DataLoaderService_OnDestroy(env, storageId);
}
static jboolean nativePrepareImage(JNIEnv* env, jobject thiz, jint storageId, jobject addedFiles, jobject removedFiles) {
static jboolean nativePrepareImage(JNIEnv* env, jobject thiz, jint storageId,
jobjectArray addedFiles, jobjectArray removedFiles) {
return DataLoaderService_OnPrepareImage(env, storageId, addedFiles, removedFiles);
}
@@ -75,7 +75,9 @@ static const JNINativeMethod dlc_method_table[] = {
{"nativeStartDataLoader", "(I)Z", (void*)nativeStartDataLoader},
{"nativeStopDataLoader", "(I)Z", (void*)nativeStopDataLoader},
{"nativeDestroyDataLoader", "(I)Z", (void*)nativeDestroyDataLoader},
{"nativePrepareImage", "(ILjava/util/List;Ljava/util/List;)Z", (void*)nativePrepareImage},
{"nativePrepareImage",
"(I[Landroid/content/pm/InstallationFileParcel;[Ljava/lang/String;)Z",
(void*)nativePrepareImage},
{"nativeWriteData", "(JLjava/lang/String;JJLandroid/os/ParcelFileDescriptor;)V",
(void*)nativeWriteData},
};

View File

@@ -17,14 +17,12 @@
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;
import android.content.pm.FileSystemControlParcel;
import android.content.pm.IDataLoader;
import android.content.pm.IDataLoaderStatusListener;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.incremental.IIncrementalManager;
@@ -93,17 +91,12 @@ public class IncrementalManagerService extends IIncrementalManager.Stub {
public boolean prepareDataLoader(int mountId, FileSystemControlParcel control,
DataLoaderParamsParcel params,
IDataLoaderStatusListener listener) {
Bundle dataLoaderParams = new Bundle();
dataLoaderParams.putParcelable("componentName",
new ComponentName(params.packageName, params.className));
dataLoaderParams.putParcelable("control", control);
dataLoaderParams.putParcelable("params", params);
DataLoaderManager dataLoaderManager = mContext.getSystemService(DataLoaderManager.class);
if (dataLoaderManager == null) {
Slog.e(TAG, "Failed to find data loader manager service");
return false;
}
if (!dataLoaderManager.initializeDataLoader(mountId, dataLoaderParams, listener)) {
if (!dataLoaderManager.initializeDataLoader(mountId, params, control, listener)) {
Slog.e(TAG, "Failed to initialize data loader");
return false;
}

View File

@@ -22,12 +22,13 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.DataLoaderParamsParcel;
import android.content.pm.FileSystemControlParcel;
import android.content.pm.IDataLoader;
import android.content.pm.IDataLoaderManager;
import android.content.pm.IDataLoaderStatusListener;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -65,26 +66,22 @@ public class DataLoaderManagerService extends SystemService {
final class DataLoaderManagerBinderService extends IDataLoaderManager.Stub {
@Override
public boolean initializeDataLoader(int dataLoaderId, Bundle params,
IDataLoaderStatusListener listener) {
public boolean initializeDataLoader(int dataLoaderId, DataLoaderParamsParcel params,
FileSystemControlParcel control, IDataLoaderStatusListener listener) {
synchronized (mLock) {
if (mServiceConnections.get(dataLoaderId) != null) {
Slog.e(TAG, "Data loader of ID=" + dataLoaderId + " already exists.");
return false;
}
}
ComponentName componentName = params.getParcelable("componentName");
if (componentName == null) {
Slog.e(TAG, "Must specify component name.");
return false;
}
ComponentName componentName = new ComponentName(params.packageName, params.className);
ComponentName dataLoaderComponent = resolveDataLoaderComponentName(componentName);
if (dataLoaderComponent == null) {
return false;
}
// Binds to the specific data loader service
DataLoaderServiceConnection connection =
new DataLoaderServiceConnection(dataLoaderId, params, listener);
new DataLoaderServiceConnection(dataLoaderId, params, control, listener);
Intent intent = new Intent();
intent.setComponent(dataLoaderComponent);
if (!mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE,
@@ -181,13 +178,16 @@ public class DataLoaderManagerService extends SystemService {
class DataLoaderServiceConnection implements ServiceConnection {
final int mId;
final Bundle mParams;
final DataLoaderParamsParcel mParams;
final FileSystemControlParcel mControl;
final IDataLoaderStatusListener mListener;
IDataLoader mDataLoader;
DataLoaderServiceConnection(int id, Bundle params, IDataLoaderStatusListener listener) {
DataLoaderServiceConnection(int id, DataLoaderParamsParcel params,
FileSystemControlParcel control, IDataLoaderStatusListener listener) {
mId = id;
mParams = params;
mControl = control;
mListener = listener;
mDataLoader = null;
}
@@ -199,7 +199,7 @@ public class DataLoaderManagerService extends SystemService {
mServiceConnections.append(mId, this);
}
try {
mDataLoader.create(mId, mParams, mListener);
mDataLoader.create(mId, mParams, mControl, mListener);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to create data loader service.", e);
}
@@ -226,7 +226,6 @@ public class DataLoaderManagerService extends SystemService {
synchronized (mLock) {
mServiceConnections.remove(mId);
}
mParams.clear();
}
}
}

View File

@@ -69,6 +69,7 @@ import android.content.pm.IPackageInstallObserver2;
import android.content.pm.IPackageInstallerSession;
import android.content.pm.IPackageInstallerSessionFileSystemConnector;
import android.content.pm.InstallationFile;
import android.content.pm.InstallationFileParcel;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
@@ -1052,9 +1053,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
IPackageInstallerSessionFileSystemConnector.Stub {
final Set<String> mAddedFiles = new ArraySet<>();
FileSystemConnector(List<InstallationFile> addedFiles) {
for (InstallationFile file : addedFiles) {
mAddedFiles.add(file.getName());
FileSystemConnector(List<InstallationFileParcel> addedFiles) {
for (InstallationFileParcel file : addedFiles) {
mAddedFiles.add(file.name);
}
}
@@ -2444,14 +2445,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return true;
}
final List<InstallationFile> addedFiles = new ArrayList<>(mFiles.size());
final List<InstallationFileParcel> addedFiles = new ArrayList<>();
final List<String> removedFiles = new ArrayList<>();
for (InstallationFile file : mFiles) {
if (sAddedFilter.accept(new File(this.stageDir, file.getName()))) {
addedFiles.add(file);
addedFiles.add(file.getData());
continue;
}
}
final List<String> removedFiles = new ArrayList<>(mFiles.size());
for (InstallationFile file : mFiles) {
if (sRemovedFilter.accept(new File(this.stageDir, file.getName()))) {
String name = file.getName().substring(
0, file.getName().length() - REMOVE_MARKER_EXTENSION.length());
@@ -2494,7 +2495,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
break;
}
case IDataLoaderStatusListener.DATA_LOADER_STARTED: {
dataLoader.prepareImage(addedFiles, removedFiles);
dataLoader.prepareImage(
addedFiles.toArray(
new InstallationFileParcel[addedFiles.size()]),
removedFiles.toArray(new String[removedFiles.size()]));
break;
}
case IDataLoaderStatusListener.DATA_LOADER_IMAGE_READY: {
@@ -2547,13 +2551,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
control.callback = connector;
final DataLoaderParams params = this.params.dataLoaderParams;
Bundle dataLoaderParams = new Bundle();
dataLoaderParams.putParcelable("componentName", params.getComponentName());
dataLoaderParams.putParcelable("control", control);
dataLoaderParams.putParcelable("params", params.getData());
if (!dataLoaderManager.initializeDataLoader(sessionId, dataLoaderParams, listener)) {
if (!dataLoaderManager.initializeDataLoader(
sessionId, params.getData(), control, listener)) {
throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"Failed to initialize data loader");
}