Incremental install via adb.

- passing V4 signature to IncFS,
- cleanup and use InstallationFile everywhere,
- pass params to DataLoader creation,
- minor refactor for PackageManagerShellCommandDataLoader to prepare for
Incremental data loading.

Test: atest PackageManagerShellCommandTest
Bug: b/136132412 b/133435829
Change-Id: Iacc3e4c51c0fa3410b076147ce153a1303246189
This commit is contained in:
Alex Buynytskyy
2020-02-08 17:50:50 -08:00
parent 6e406c8ae7
commit cd4d3875e2
14 changed files with 251 additions and 170 deletions

View File

@@ -2007,18 +2007,15 @@ package android.content.pm {
}
public final class InstallationFile implements android.os.Parcelable {
ctor public InstallationFile(@NonNull String, long, @Nullable byte[]);
ctor public InstallationFile(int, @NonNull String, long, @Nullable byte[], @Nullable byte[]);
method public int describeContents();
method public int getFileType();
method public long getLengthBytes();
method public int getLocation();
method @Nullable public byte[] getMetadata();
method @NonNull public String getName();
method public long getSize();
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;
field public static final int FILE_TYPE_APK = 0; // 0x0
field public static final int FILE_TYPE_LIB = 1; // 0x1
field public static final int FILE_TYPE_OBB = 2; // 0x2
field public static final int FILE_TYPE_UNKNOWN = -1; // 0xffffffff
}
public final class InstantAppInfo implements android.os.Parcelable {
@@ -10317,7 +10314,7 @@ package android.service.dataloader {
public abstract class DataLoaderService extends android.app.Service {
ctor public DataLoaderService();
method @Nullable public android.service.dataloader.DataLoaderService.DataLoader onCreateDataLoader();
method @Nullable public android.service.dataloader.DataLoaderService.DataLoader onCreateDataLoader(@NonNull android.content.pm.DataLoaderParams);
}
public static interface DataLoaderService.DataLoader {

View File

@@ -16,82 +16,59 @@
package android.content.pm;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Defines the properties of a file in an installation session.
* TODO(b/136132412): update with new APIs.
*
* @hide
*/
@SystemApi
public final class InstallationFile implements Parcelable {
public static final int FILE_TYPE_UNKNOWN = -1;
public static final int FILE_TYPE_APK = 0;
public static final int FILE_TYPE_LIB = 1;
public static final int FILE_TYPE_OBB = 2;
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;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"FILE_TYPE_"}, value = {
FILE_TYPE_APK,
FILE_TYPE_LIB,
FILE_TYPE_OBB,
})
public @interface FileType {
}
private String mFileName;
private @FileType int mFileType;
private long mFileSize;
private byte[] mMetadata;
public InstallationFile(@NonNull String fileName, long fileSize,
@Nullable byte[] metadata) {
mFileName = fileName;
mFileSize = fileSize;
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;
if (fileName.toLowerCase().endsWith(".apk")) {
mFileType = FILE_TYPE_APK;
} else if (fileName.toLowerCase().endsWith(".obb")) {
mFileType = FILE_TYPE_OBB;
} else if (fileName.toLowerCase().endsWith(".so") && fileName.toLowerCase().startsWith(
"lib/")) {
mFileType = FILE_TYPE_LIB;
} else {
mFileType = FILE_TYPE_UNKNOWN;
}
mSignature = signature;
}
public @FileType int getFileType() {
return mFileType;
public @PackageInstaller.FileLocation int getLocation() {
return mLocation;
}
public @NonNull String getName() {
return mFileName;
return mName;
}
public long getSize() {
return mFileSize;
public long getLengthBytes() {
return mLengthBytes;
}
public @Nullable byte[] getMetadata() {
return mMetadata;
}
public @Nullable byte[] getSignature() {
return mSignature;
}
private InstallationFile(Parcel source) {
mFileName = source.readString();
mFileType = source.readInt();
mFileSize = source.readLong();
mLocation = source.readInt();
mName = source.readString();
mLengthBytes = source.readLong();
mMetadata = source.createByteArray();
mSignature = source.createByteArray();
}
@Override
@@ -101,10 +78,11 @@ public final class InstallationFile implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mFileName);
dest.writeInt(mFileType);
dest.writeLong(mFileSize);
dest.writeInt(mLocation);
dest.writeString(mName);
dest.writeLong(mLengthBytes);
dest.writeByteArray(mMetadata);
dest.writeByteArray(mSignature);
}
public static final @NonNull Creator<InstallationFile> CREATOR =

View File

@@ -29,6 +29,8 @@ package android.os.incremental;
* @throws IllegalStateException the session is not an Incremental installation session.
*/
import static android.content.pm.PackageInstaller.LOCATION_DATA_APP;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -85,7 +87,7 @@ public final class IncrementalFileStorages {
try {
result = new IncrementalFileStorages(stageDir, incrementalManager, dataLoaderParams);
for (InstallationFile file : addedFiles) {
if (file.getFileType() == InstallationFile.FILE_TYPE_APK) {
if (file.getLocation() == LOCATION_DATA_APP) {
try {
result.addApkFile(file);
} catch (IOException e) {
@@ -95,7 +97,7 @@ public final class IncrementalFileStorages {
e);
}
} else {
throw new IOException("Unknown file type: " + file.getFileType());
throw new IOException("Unknown file location: " + file.getLocation());
}
}
@@ -147,8 +149,8 @@ public final class IncrementalFileStorages {
String apkName = apk.getName();
File targetFile = Paths.get(stageDirPath, apkName).toFile();
if (!targetFile.exists()) {
mDefaultStorage.makeFile(apkName, apk.getSize(), null,
apk.getMetadata(), 0, null, null, null);
mDefaultStorage.makeFile(apkName, apk.getLengthBytes(), null, apk.getMetadata(),
apk.getSignature());
}
}

View File

@@ -299,7 +299,16 @@ public final class IncrementalManager {
return nativeIsIncrementalPath(path);
}
/**
* Returns raw signature for file if it's on Incremental File System.
* Unsafe, use only if you are sure what you are doing.
*/
public static @Nullable byte[] unsafeGetFileSignature(@NonNull String path) {
return nativeUnsafeGetFileSignature(path);
}
/* Native methods */
private static native boolean nativeIsEnabled();
private static native boolean nativeIsIncrementalPath(@NonNull String path);
private static native byte[] nativeUnsafeGetFileSignature(@NonNull String path);
}

View File

@@ -20,6 +20,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.RemoteException;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -169,10 +171,11 @@ public final class IncrementalStorage {
* @param path Relative path of the new file.
* @param size Size of the new file in bytes.
* @param metadata Metadata bytes.
* @param v4signatureBytes Serialized V4SignatureProto.
*/
public void makeFile(@NonNull String path, long size, @Nullable UUID id,
@Nullable byte[] metadata, int hashAlgorithm, @Nullable byte[] rootHash,
@Nullable byte[] additionalData, @Nullable byte[] signature) throws IOException {
@Nullable byte[] metadata, @Nullable byte[] v4signatureBytes)
throws IOException {
try {
if (id == null && metadata == null) {
throw new IOException("File ID and metadata cannot both be null");
@@ -181,13 +184,7 @@ public final class IncrementalStorage {
params.size = size;
params.metadata = (metadata == null ? new byte[0] : metadata);
params.fileId = idToBytes(id);
if (hashAlgorithm != 0 || signature != null) {
params.signature = new IncrementalSignature();
params.signature.hashAlgorithm = hashAlgorithm;
params.signature.rootHash = rootHash;
params.signature.additionalData = additionalData;
params.signature.signature = signature;
}
params.signature = parseV4Signature(v4signatureBytes);
int res = mService.makeFile(mId, path, params);
if (res != 0) {
throw new IOException("makeFile() failed with errno " + -res);
@@ -197,6 +194,7 @@ public final class IncrementalStorage {
}
}
/**
* Creates a file in Incremental storage. The content of the file is mapped from a range inside
* a source file in the same storage.
@@ -349,6 +347,37 @@ public final class IncrementalStorage {
}
}
/**
* Returns the metadata object of an IncFs File.
*
* @param id The file id.
* @return Byte array that contains metadata bytes.
*/
@Nullable
public byte[] getFileMetadata(@NonNull UUID id) {
try {
final byte[] rawId = idToBytes(id);
return mService.getMetadataById(mId, rawId);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
return null;
}
}
/**
* Informs the data loader service associated with the current storage to start data loader
*
* @return True if data loader is successfully started.
*/
public boolean startLoading() {
try {
return mService.startLoading(mId);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
return false;
}
}
private static final int UUID_BYTE_SIZE = 16;
/**
@@ -386,35 +415,44 @@ public final class IncrementalStorage {
return new UUID(msb, lsb);
}
/**
* Returns the metadata object of an IncFs File.
*
* @param id The file id.
* @return Byte array that contains metadata bytes.
*/
@Nullable
public byte[] getFileMetadata(@NonNull UUID id) {
try {
final byte[] rawId = idToBytes(id);
return mService.getMetadataById(mId, rawId);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
return null;
}
}
private static final int INCFS_HASH_SHA256 = 1;
private static final int INCFS_MAX_HASH_SIZE = 32; // SHA256
private static final int INCFS_MAX_ADD_DATA_SIZE = 128;
/**
* Informs the data loader service associated with the current storage to start data loader
*
* @return True if data loader is successfully started.
* Deserialize and validate v4 signature bytes.
*/
public boolean startLoading() {
try {
return mService.startLoading(mId);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
return false;
private static IncrementalSignature parseV4Signature(@Nullable byte[] v4signatureBytes)
throws IOException {
if (v4signatureBytes == null) {
return null;
}
final V4Signature signature;
try (DataInputStream input = new DataInputStream(
new ByteArrayInputStream(v4signatureBytes))) {
signature = V4Signature.readFrom(input);
}
final byte[] rootHash = signature.verityRootHash;
final byte[] additionalData = signature.v3Digest;
final byte[] pkcs7Signature = signature.pkcs7SignatureBlock;
if (rootHash.length != INCFS_MAX_HASH_SIZE) {
throw new IOException("rootHash has to be " + INCFS_MAX_HASH_SIZE + " bytes");
}
if (additionalData.length > INCFS_MAX_ADD_DATA_SIZE) {
throw new IOException(
"additionalData has to be at most " + INCFS_MAX_ADD_DATA_SIZE + " bytes");
}
IncrementalSignature result = new IncrementalSignature();
result.hashAlgorithm = INCFS_HASH_SHA256;
result.rootHash = rootHash;
result.additionalData = additionalData;
result.signature = pkcs7Signature;
return result;
}
/**

View File

@@ -0,0 +1,62 @@
/*
* 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.os.incremental;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
/**
* V4 signature fields.
* Keep in sync with APKSig master copy.
* @hide
*/
public class V4Signature {
public final byte[] verityRootHash;
public final byte[] v3Digest;
public final byte[] pkcs7SignatureBlock;
V4Signature(byte[] verityRootHash, byte[] v3Digest, byte[] pkcs7SignatureBlock) {
this.verityRootHash = verityRootHash;
this.v3Digest = v3Digest;
this.pkcs7SignatureBlock = pkcs7SignatureBlock;
}
static byte[] readBytes(DataInputStream stream) throws IOException {
byte[] result = new byte[stream.readInt()];
stream.read(result);
return result;
}
static V4Signature readFrom(DataInputStream stream) throws IOException {
byte[] verityRootHash = readBytes(stream);
byte[] v3Digest = readBytes(stream);
byte[] pkcs7SignatureBlock = readBytes(stream);
return new V4Signature(verityRootHash, v3Digest, pkcs7SignatureBlock);
}
static void writeBytes(DataOutputStream stream, byte[] bytes) throws IOException {
stream.writeInt(bytes.length);
stream.write(bytes);
}
void writeTo(DataOutputStream stream) throws IOException {
writeBytes(stream, this.verityRootHash);
writeBytes(stream, this.v3Digest);
writeBytes(stream, this.pkcs7SignatureBlock);
}
}

View File

@@ -90,7 +90,7 @@ public abstract class DataLoaderService extends Service {
* @hide
*/
@SystemApi
public @Nullable DataLoader onCreateDataLoader() {
public @Nullable DataLoader onCreateDataLoader(@NonNull DataLoaderParams dataLoaderParams) {
return null;
}

View File

@@ -37,10 +37,28 @@ static jboolean nativeIsIncrementalPath(JNIEnv* env,
return (jboolean)IncFs_IsIncFsPath(path.c_str());
}
static const JNINativeMethod method_table[] = {
{"nativeIsEnabled", "()Z", (void*)nativeIsEnabled},
{"nativeIsIncrementalPath", "(Ljava/lang/String;)Z", (void*)nativeIsIncrementalPath},
};
static jbyteArray nativeUnsafeGetFileSignature(JNIEnv* env, jobject clazz, jstring javaPath) {
ScopedUtfChars path(env, javaPath);
char signature[INCFS_MAX_SIGNATURE_SIZE];
size_t size = sizeof(signature);
if (IncFs_UnsafeGetSignatureByPath(path.c_str(), signature, &size) < 0) {
return nullptr;
}
jbyteArray result = env->NewByteArray(size);
if (result != nullptr) {
env->SetByteArrayRegion(result, 0, size, (const jbyte*)signature);
}
return result;
}
static const JNINativeMethod method_table[] = {{"nativeIsEnabled", "()Z", (void*)nativeIsEnabled},
{"nativeIsIncrementalPath", "(Ljava/lang/String;)Z",
(void*)nativeIsIncrementalPath},
{"nativeUnsafeGetFileSignature",
"(Ljava/lang/String;)[B",
(void*)nativeUnsafeGetFileSignature}};
int register_android_os_incremental_IncrementalManager(JNIEnv* env) {
return jniRegisterNativeMethods(env, "android/os/incremental/IncrementalManager",

View File

@@ -16,6 +16,8 @@
package com.android.incremental.nativeadb;
import android.annotation.NonNull;
import android.content.pm.DataLoaderParams;
import android.service.dataloader.DataLoaderService;
/** This code is used for testing only. */
@@ -26,7 +28,7 @@ public class NativeAdbDataLoaderService extends DataLoaderService {
}
@Override
public DataLoader onCreateDataLoader() {
public DataLoader onCreateDataLoader(@NonNull DataLoaderParams dataLoaderParams) {
return null;
}
}

View File

@@ -16,9 +16,7 @@
package com.android.server.incremental;
import static android.content.pm.InstallationFile.FILE_TYPE_OBB;
import static android.content.pm.PackageInstaller.LOCATION_DATA_APP;
import static android.content.pm.PackageInstaller.LOCATION_MEDIA_OBB;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -183,10 +181,8 @@ public final class IncrementalManagerShellCommand extends ShellCommand {
session = packageInstaller.openSession(sessionId);
for (int i = 0; i < numFiles; i++) {
InstallationFile file = installationFiles.get(i);
final int location = file.getFileType() == FILE_TYPE_OBB ? LOCATION_MEDIA_OBB
: LOCATION_DATA_APP;
session.addFile(location, file.getName(), file.getSize(), file.getMetadata(),
null);
session.addFile(file.getLocation(), file.getName(), file.getLengthBytes(),
file.getMetadata(), file.getSignature());
}
session.commit(localReceiver.getIntentSender());
final Intent result = localReceiver.getResult();
@@ -304,7 +300,8 @@ public final class IncrementalManagerShellCommand extends ShellCommand {
}
final byte[] metadata = String.valueOf(index).getBytes(
StandardCharsets.UTF_8);
fileList.add(new InstallationFile(name, size, metadata));
fileList.add(
new InstallationFile(LOCATION_DATA_APP, name, size, metadata, null));
break;
}
default:

View File

@@ -214,7 +214,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill";
private static final int[] EMPTY_CHILD_SESSION_ARRAY = EmptyArray.INT;
private static final FileInfo[] EMPTY_FILE_INFO_ARRAY = {};
private static final InstallationFile[] EMPTY_INSTALLATION_FILE_ARRAY = {};
private static final String SYSTEM_DATA_LOADER_PACKAGE = "android";
@@ -309,33 +309,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@GuardedBy("mLock")
private int mParentSessionId;
static class FileInfo {
public final int location;
public final String name;
public final Long lengthBytes;
public final byte[] metadata;
public final byte[] signature;
public static FileInfo added(int location, String name, Long lengthBytes, byte[] metadata,
byte[] signature) {
return new FileInfo(location, name, lengthBytes, metadata, signature);
}
public static FileInfo removed(int location, String name) {
return new FileInfo(location, name, -1L, null, null);
}
FileInfo(int location, String name, Long lengthBytes, byte[] metadata, byte[] signature) {
this.location = location;
this.name = name;
this.lengthBytes = lengthBytes;
this.metadata = metadata;
this.signature = signature;
}
}
@GuardedBy("mLock")
private ArrayList<FileInfo> mFiles = new ArrayList<>();
private ArrayList<InstallationFile> mFiles = new ArrayList<>();
@GuardedBy("mLock")
private boolean mStagedSessionApplied;
@@ -508,7 +483,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
PackageSessionProvider sessionProvider, Looper looper, StagingManager stagingManager,
int sessionId, int userId, int installerUid, @NonNull InstallSource installSource,
SessionParams params, long createdMillis,
File stageDir, String stageCid, FileInfo[] files, boolean prepared,
File stageDir, String stageCid, InstallationFile[] files, boolean prepared,
boolean committed, boolean sealed,
@Nullable int[] childSessionIds, int parentSessionId, boolean isReady,
boolean isFailed, boolean isApplied, int stagedSessionErrorCode,
@@ -539,7 +514,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
this.mParentSessionId = parentSessionId;
if (files != null) {
for (FileInfo file : files) {
for (InstallationFile file : files) {
mFiles.add(file);
}
}
@@ -738,7 +713,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
String[] result = new String[mFiles.size()];
for (int i = 0, size = mFiles.size(); i < size; ++i) {
result[i] = mFiles.get(i).name;
result[i] = mFiles.get(i).getName();
}
return result;
}
@@ -2425,7 +2400,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
assertCallerIsOwnerOrRootLocked();
assertPreparedAndNotSealedLocked("addFile");
mFiles.add(FileInfo.added(location, name, lengthBytes, metadata, signature));
mFiles.add(new InstallationFile(location, name, lengthBytes, metadata, signature));
}
}
@@ -2443,7 +2418,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
assertCallerIsOwnerOrRootLocked();
assertPreparedAndNotSealedLocked("removeFile");
mFiles.add(FileInfo.removed(location, getRemoveMarkerName(name)));
mFiles.add(new InstallationFile(location, getRemoveMarkerName(name), -1, null, null));
}
}
@@ -2461,17 +2436,16 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
final List<InstallationFile> addedFiles = new ArrayList<>(mFiles.size());
for (FileInfo file : mFiles) {
if (sAddedFilter.accept(new File(this.stageDir, file.name))) {
addedFiles.add(new InstallationFile(
file.name, file.lengthBytes, file.metadata));
for (InstallationFile file : mFiles) {
if (sAddedFilter.accept(new File(this.stageDir, file.getName()))) {
addedFiles.add(file);
}
}
final List<String> removedFiles = new ArrayList<>(mFiles.size());
for (FileInfo file : mFiles) {
if (sRemovedFilter.accept(new File(this.stageDir, file.name))) {
String name = file.name.substring(
0, file.name.length() - REMOVE_MARKER_EXTENSION.length());
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());
removedFiles.add(name);
}
}
@@ -2970,13 +2944,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
writeIntAttribute(out, ATTR_SESSION_ID, childSessionId);
out.endTag(null, TAG_CHILD_SESSION);
}
for (FileInfo fileInfo : mFiles) {
for (InstallationFile file : mFiles) {
out.startTag(null, TAG_SESSION_FILE);
writeIntAttribute(out, ATTR_LOCATION, fileInfo.location);
writeStringAttribute(out, ATTR_NAME, fileInfo.name);
writeLongAttribute(out, ATTR_LENGTH_BYTES, fileInfo.lengthBytes);
writeByteArrayAttribute(out, ATTR_METADATA, fileInfo.metadata);
writeByteArrayAttribute(out, ATTR_SIGNATURE, fileInfo.signature);
writeIntAttribute(out, ATTR_LOCATION, file.getLocation());
writeStringAttribute(out, ATTR_NAME, file.getName());
writeLongAttribute(out, ATTR_LENGTH_BYTES, file.getLengthBytes());
writeByteArrayAttribute(out, ATTR_METADATA, file.getMetadata());
writeByteArrayAttribute(out, ATTR_SIGNATURE, file.getSignature());
out.endTag(null, TAG_SESSION_FILE);
}
}
@@ -3088,7 +3062,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
List<String> grantedRuntimePermissions = new ArrayList<>();
List<String> whitelistedRestrictedPermissions = new ArrayList<>();
List<Integer> childSessionIds = new ArrayList<>();
List<FileInfo> files = new ArrayList<>();
List<InstallationFile> files = new ArrayList<>();
int outerDepth = in.getDepth();
int type;
while ((type = in.next()) != XmlPullParser.END_DOCUMENT
@@ -3107,7 +3081,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
childSessionIds.add(readIntAttribute(in, ATTR_SESSION_ID, SessionInfo.INVALID_ID));
}
if (TAG_SESSION_FILE.equals(in.getName())) {
files.add(new FileInfo(
files.add(new InstallationFile(
readIntAttribute(in, ATTR_LOCATION, 0),
readStringAttribute(in, ATTR_NAME),
readLongAttribute(in, ATTR_LENGTH_BYTES, -1),
@@ -3135,16 +3109,16 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
childSessionIdsArray = EMPTY_CHILD_SESSION_ARRAY;
}
FileInfo[] fileInfosArray = null;
InstallationFile[] fileArray = null;
if (!files.isEmpty()) {
fileInfosArray = files.toArray(EMPTY_FILE_INFO_ARRAY);
fileArray = files.toArray(EMPTY_INSTALLATION_FILE_ARRAY);
}
InstallSource installSource = InstallSource.create(installInitiatingPackageName,
installOriginatingPackageName, installerPackageName);
return new PackageInstallerSession(callback, context, pm, sessionProvider,
installerThread, stagingManager, sessionId, userId, installerUid,
installSource, params, createdMillis, stageDir, stageCid, fileInfosArray,
installSource, params, createdMillis, stageDir, stageCid, fileArray,
prepared, committed, sealed, childSessionIdsArray, parentSessionId,
isReady, isFailed, isApplied, stagedSessionErrorCode, stagedSessionErrorMessage);
}

View File

@@ -1163,7 +1163,7 @@ class PackageManagerShellCommand extends ShellCommand {
final InstallParams params = makeInstallParams();
if (params.sessionParams.dataLoaderParams == null) {
params.sessionParams.setDataLoaderParams(
PackageManagerShellCommandDataLoader.getDataLoaderParams(this));
PackageManagerShellCommandDataLoader.getStreamingDataLoaderParams(this));
}
return doRunInstall(params);
}

View File

@@ -54,7 +54,7 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
private static final String STDIN_PATH = "-";
static DataLoaderParams getDataLoaderParams(ShellCommand shellCommand) {
private static String getDataLoaderParamsArgs(ShellCommand shellCommand) {
int commandId;
synchronized (sShellCommands) {
// Clean up old references.
@@ -78,8 +78,12 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
sShellCommands.put(commandId, new WeakReference<>(shellCommand));
}
final String args = SHELL_COMMAND_ID_PREFIX + commandId;
return DataLoaderParams.forStreaming(new ComponentName(PACKAGE, CLASS), args);
return SHELL_COMMAND_ID_PREFIX + commandId;
}
static DataLoaderParams getStreamingDataLoaderParams(ShellCommand shellCommand) {
return DataLoaderParams.forStreaming(new ComponentName(PACKAGE, CLASS),
getDataLoaderParamsArgs(shellCommand));
}
private static int extractShellCommandId(String args) {
@@ -133,17 +137,17 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
return false;
}
try {
for (InstallationFile fileInfo : addedFiles) {
String filePath = new String(fileInfo.getMetadata(), StandardCharsets.UTF_8);
for (InstallationFile file : addedFiles) {
String filePath = new String(file.getMetadata(), StandardCharsets.UTF_8);
if (STDIN_PATH.equals(filePath) || TextUtils.isEmpty(filePath)) {
final ParcelFileDescriptor inFd = ParcelFileDescriptor.dup(
shellCommand.getInFileDescriptor());
mConnector.writeData(fileInfo.getName(), 0, fileInfo.getSize(), inFd);
mConnector.writeData(file.getName(), 0, file.getLengthBytes(), inFd);
} else {
ParcelFileDescriptor incomingFd = null;
try {
incomingFd = shellCommand.openFileForSystem(filePath, "r");
mConnector.writeData(fileInfo.getName(), 0, incomingFd.getStatSize(),
mConnector.writeData(file.getName(), 0, incomingFd.getStatSize(),
incomingFd);
} finally {
IoUtils.closeQuietly(incomingFd);
@@ -159,7 +163,8 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
}
@Override
public DataLoaderService.DataLoader onCreateDataLoader() {
public DataLoaderService.DataLoader onCreateDataLoader(
@NonNull DataLoaderParams dataLoaderParams) {
return new DataLoader();
}
}

View File

@@ -122,7 +122,6 @@ public:
}
RawMetadata getMetadata(StorageId storage, FileId node) const;
std::string getSignatureData(StorageId storage, FileId node) const;
std::vector<std::string> listFiles(StorageId storage) const;
bool startLoading(StorageId storage) const;