Merge "Digest API: support for certificate rotation."
This commit is contained in:
committed by
Android (Google) Code Review
commit
13189ac1dd
@@ -36,12 +36,14 @@ import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.ApkChecksum;
|
||||
import android.content.pm.Checksum;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.content.pm.PackageParser;
|
||||
import android.content.pm.Signature;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemClock;
|
||||
import android.os.incremental.IncrementalManager;
|
||||
import android.os.incremental.IncrementalStorage;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Pair;
|
||||
@@ -57,6 +59,7 @@ import android.util.apk.SignatureNotFoundException;
|
||||
import android.util.apk.VerityBuilder;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
||||
import com.android.server.security.VerityUtils;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
@@ -121,12 +124,15 @@ public class ApkChecksums {
|
||||
private final Producer<Context> mContext;
|
||||
private final Producer<Handler> mHandlerProducer;
|
||||
private final Producer<IncrementalManager> mIncrementalManagerProducer;
|
||||
private final Producer<PackageManagerInternal> mPackageManagerInternalProducer;
|
||||
|
||||
Injector(Producer<Context> context, Producer<Handler> handlerProducer,
|
||||
Producer<IncrementalManager> incrementalManagerProducer) {
|
||||
Producer<IncrementalManager> incrementalManagerProducer,
|
||||
Producer<PackageManagerInternal> packageManagerInternalProducer) {
|
||||
mContext = context;
|
||||
mHandlerProducer = handlerProducer;
|
||||
mIncrementalManagerProducer = incrementalManagerProducer;
|
||||
mPackageManagerInternalProducer = packageManagerInternalProducer;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
@@ -140,6 +146,10 @@ public class ApkChecksums {
|
||||
public IncrementalManager getIncrementalManager() {
|
||||
return mIncrementalManagerProducer.produce();
|
||||
}
|
||||
|
||||
public PackageManagerInternal getPackageManagerInternal() {
|
||||
return mPackageManagerInternalProducer.produce();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,104 +179,56 @@ public class ApkChecksums {
|
||||
/**
|
||||
* Serialize checksums to the stream in binary format.
|
||||
*/
|
||||
public static void writeChecksums(OutputStream os, ApkChecksum[] checksums)
|
||||
public static void writeChecksums(OutputStream os, Checksum[] checksums)
|
||||
throws IOException, CertificateException {
|
||||
try (DataOutputStream dos = new DataOutputStream(os)) {
|
||||
dos.writeInt(checksums.length);
|
||||
for (ApkChecksum checksum : checksums) {
|
||||
final String splitName = checksum.getSplitName();
|
||||
if (splitName == null) {
|
||||
dos.writeInt(-1);
|
||||
} else {
|
||||
dos.writeInt(splitName.length());
|
||||
dos.writeUTF(splitName);
|
||||
}
|
||||
|
||||
for (Checksum checksum : checksums) {
|
||||
dos.writeInt(checksum.getType());
|
||||
|
||||
final byte[] valueBytes = checksum.getValue();
|
||||
dos.writeInt(valueBytes.length);
|
||||
dos.write(valueBytes);
|
||||
|
||||
final String packageName = checksum.getInstallerPackageName();
|
||||
if (packageName == null) {
|
||||
dos.writeInt(-1);
|
||||
} else {
|
||||
dos.writeInt(packageName.length());
|
||||
dos.writeUTF(packageName);
|
||||
}
|
||||
|
||||
final Certificate cert = checksum.getInstallerCertificate();
|
||||
final byte[] certBytes = (cert == null) ? null : cert.getEncoded();
|
||||
if (certBytes == null) {
|
||||
dos.writeInt(-1);
|
||||
} else {
|
||||
dos.writeInt(certBytes.length);
|
||||
dos.write(certBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize array of checksums previously stored in
|
||||
* {@link #writeChecksums(File, ApkChecksum[])}.
|
||||
* {@link #writeChecksums(OutputStream, Checksum[])}.
|
||||
*/
|
||||
private static ApkChecksum[] readChecksums(File file) throws IOException {
|
||||
private static Checksum[] readChecksums(File file) throws IOException {
|
||||
try (InputStream is = new FileInputStream(file);
|
||||
DataInputStream dis = new DataInputStream(is)) {
|
||||
final int size = dis.readInt();
|
||||
ApkChecksum[] checksums = new ApkChecksum[size];
|
||||
Checksum[] checksums = new Checksum[size];
|
||||
for (int i = 0; i < size; ++i) {
|
||||
final String splitName;
|
||||
if (dis.readInt() < 0) {
|
||||
splitName = null;
|
||||
} else {
|
||||
splitName = dis.readUTF();
|
||||
}
|
||||
|
||||
final int type = dis.readInt();
|
||||
|
||||
final byte[] valueBytes = new byte[dis.readInt()];
|
||||
dis.read(valueBytes);
|
||||
|
||||
final String packageName;
|
||||
if (dis.readInt() < 0) {
|
||||
packageName = null;
|
||||
} else {
|
||||
packageName = dis.readUTF();
|
||||
}
|
||||
|
||||
final byte[] certBytes;
|
||||
final int certBytesLength = dis.readInt();
|
||||
if (certBytesLength < 0) {
|
||||
certBytes = null;
|
||||
} else {
|
||||
certBytes = new byte[certBytesLength];
|
||||
dis.read(certBytes);
|
||||
}
|
||||
checksums[i] = new ApkChecksum(splitName, new Checksum(type, valueBytes),
|
||||
packageName, certBytes);
|
||||
checksums[i] = new Checksum(type, valueBytes);
|
||||
}
|
||||
return checksums;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch or calculate checksums for the collection of files.
|
||||
*
|
||||
* @param filesToChecksum split name, null for base and File to fetch checksums for
|
||||
* @param optional mask to fetch readily available checksums
|
||||
* @param required mask to forcefully calculate if not available
|
||||
* @param trustedInstallers array of certificate to trust, two specific cases:
|
||||
* null - trust anybody,
|
||||
* [] - trust nobody.
|
||||
* @param statusReceiver to receive the resulting checksums
|
||||
* @param filesToChecksum split name, null for base and File to fetch checksums for
|
||||
* @param optional mask to fetch readily available checksums
|
||||
* @param required mask to forcefully calculate if not available
|
||||
* @param installerPackageName package name of the installer of the packages
|
||||
* @param trustedInstallers array of certificate to trust, two specific cases:
|
||||
* null - trust anybody,
|
||||
* [] - trust nobody.
|
||||
* @param statusReceiver to receive the resulting checksums
|
||||
*/
|
||||
public static void getChecksums(List<Pair<String, File>> filesToChecksum,
|
||||
@Checksum.Type int optional,
|
||||
@Checksum.Type int required,
|
||||
@Nullable String installerPackageName,
|
||||
@Nullable Certificate[] trustedInstallers,
|
||||
@NonNull IntentSender statusReceiver,
|
||||
@NonNull Injector injector) {
|
||||
@@ -278,8 +240,8 @@ public class ApkChecksums {
|
||||
result.add(checksums);
|
||||
|
||||
try {
|
||||
getAvailableApkChecksums(split, file, optional | required, trustedInstallers,
|
||||
checksums);
|
||||
getAvailableApkChecksums(split, file, optional | required, installerPackageName,
|
||||
trustedInstallers, checksums, injector);
|
||||
} catch (Throwable e) {
|
||||
Slog.e(TAG, "Preferred checksum calculation error", e);
|
||||
}
|
||||
@@ -337,18 +299,21 @@ public class ApkChecksums {
|
||||
/**
|
||||
* Fetch readily available checksums - enforced by kernel or provided by Installer.
|
||||
*
|
||||
* @param split split name, null for base
|
||||
* @param file to fetch checksums for
|
||||
* @param types mask to fetch checksums
|
||||
* @param trustedInstallers array of certificate to trust, two specific cases:
|
||||
* null - trust anybody,
|
||||
* [] - trust nobody.
|
||||
* @param checksums resulting checksums
|
||||
* @param split split name, null for base
|
||||
* @param file to fetch checksums for
|
||||
* @param types mask to fetch checksums
|
||||
* @param installerPackageName package name of the installer of the packages
|
||||
* @param trustedInstallers array of certificate to trust, two specific cases:
|
||||
* null - trust anybody,
|
||||
* [] - trust nobody.
|
||||
* @param checksums resulting checksums
|
||||
*/
|
||||
private static void getAvailableApkChecksums(String split, File file,
|
||||
@Checksum.Type int types,
|
||||
@Nullable String installerPackageName,
|
||||
@Nullable Certificate[] trustedInstallers,
|
||||
Map<Integer, ApkChecksum> checksums) {
|
||||
Map<Integer, ApkChecksum> checksums,
|
||||
@NonNull Injector injector) {
|
||||
final String filePath = file.getAbsolutePath();
|
||||
|
||||
// Always available: FSI or IncFs.
|
||||
@@ -370,24 +335,72 @@ public class ApkChecksums {
|
||||
}
|
||||
}
|
||||
|
||||
if (trustedInstallers == null || trustedInstallers.length > 0) {
|
||||
final File digestsFile = new File(buildDigestsPathForApk(filePath));
|
||||
if (digestsFile.exists()) {
|
||||
try {
|
||||
final ApkChecksum[] digests = readChecksums(digestsFile);
|
||||
final Set<Signature> trusted = convertToSet(trustedInstallers);
|
||||
for (ApkChecksum digest : digests) {
|
||||
if (isRequired(digest.getType(), types, checksums) && isTrusted(digest,
|
||||
trusted)) {
|
||||
checksums.put(digest.getType(), digest);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG, "Error reading .digests", e);
|
||||
} catch (CertificateEncodingException e) {
|
||||
Slog.e(TAG, "Error encoding trustedInstallers", e);
|
||||
getInstallerChecksums(split, file, types, installerPackageName, trustedInstallers,
|
||||
checksums, injector);
|
||||
}
|
||||
|
||||
private static void getInstallerChecksums(String split, File file,
|
||||
@Checksum.Type int types,
|
||||
@Nullable String installerPackageName,
|
||||
@Nullable Certificate[] trustedInstallers,
|
||||
Map<Integer, ApkChecksum> checksums,
|
||||
@NonNull Injector injector) {
|
||||
if (TextUtils.isEmpty(installerPackageName)) {
|
||||
return;
|
||||
}
|
||||
if (trustedInstallers != null && trustedInstallers.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final File digestsFile = new File(buildDigestsPathForApk(file.getAbsolutePath()));
|
||||
if (!digestsFile.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final AndroidPackage installer = injector.getPackageManagerInternal().getPackage(
|
||||
installerPackageName);
|
||||
if (installer == null) {
|
||||
Slog.e(TAG, "Installer package not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Obtaining array of certificates used for signing the installer package.
|
||||
final Signature[] certs = installer.getSigningDetails().signatures;
|
||||
final Signature[] pastCerts = installer.getSigningDetails().pastSigningCertificates;
|
||||
if (certs == null || certs.length == 0 || certs[0] == null) {
|
||||
Slog.e(TAG, "Can't obtain calling installer package's certificates.");
|
||||
return;
|
||||
}
|
||||
// According to V2/V3 signing schema, the first certificate corresponds to the public key
|
||||
// in the signing block.
|
||||
byte[] trustedCertBytes = certs[0].toByteArray();
|
||||
|
||||
try {
|
||||
final Checksum[] digests = readChecksums(digestsFile);
|
||||
final Set<Signature> trusted = convertToSet(trustedInstallers);
|
||||
|
||||
if (trusted != null && !trusted.isEmpty()) {
|
||||
// Obtaining array of certificates used for signing the installer package.
|
||||
Signature trustedCert = isTrusted(certs, trusted);
|
||||
if (trustedCert == null) {
|
||||
trustedCert = isTrusted(pastCerts, trusted);
|
||||
}
|
||||
if (trustedCert == null) {
|
||||
return;
|
||||
}
|
||||
trustedCertBytes = trustedCert.toByteArray();
|
||||
}
|
||||
|
||||
for (Checksum digest : digests) {
|
||||
if (isRequired(digest.getType(), types, checksums)) {
|
||||
checksums.put(digest.getType(),
|
||||
new ApkChecksum(split, digest, installerPackageName, trustedCertBytes));
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG, "Error reading .digests", e);
|
||||
} catch (CertificateEncodingException e) {
|
||||
Slog.e(TAG, "Error encoding trustedInstallers", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,12 +507,16 @@ public class ApkChecksums {
|
||||
return set;
|
||||
}
|
||||
|
||||
private static boolean isTrusted(ApkChecksum checksum, Set<Signature> trusted) {
|
||||
if (trusted == null) {
|
||||
return true;
|
||||
private static Signature isTrusted(Signature[] signatures, Set<Signature> trusted) {
|
||||
if (signatures == null) {
|
||||
return null;
|
||||
}
|
||||
final Signature signature = new Signature(checksum.getInstallerCertificateBytes());
|
||||
return trusted.contains(signature);
|
||||
for (Signature signature : signatures) {
|
||||
if (trusted.contains(signature)) {
|
||||
return signature;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static ApkChecksum extractHashFromFS(String split, String filePath) {
|
||||
|
||||
@@ -85,7 +85,6 @@ import android.content.pm.PackageParser;
|
||||
import android.content.pm.PackageParser.ApkLite;
|
||||
import android.content.pm.PackageParser.PackageLite;
|
||||
import android.content.pm.PackageParser.PackageParserException;
|
||||
import android.content.pm.Signature;
|
||||
import android.content.pm.dex.DexMetadataHelper;
|
||||
import android.content.pm.parsing.ApkLiteParseUtils;
|
||||
import android.content.pm.parsing.result.ParseResult;
|
||||
@@ -245,8 +244,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
private static final String ATTR_SIGNATURE = "signature";
|
||||
private static final String ATTR_CHECKSUM_KIND = "checksumKind";
|
||||
private static final String ATTR_CHECKSUM_VALUE = "checksumValue";
|
||||
private static final String ATTR_CHECKSUM_PACKAGE = "checksumPackage";
|
||||
private static final String ATTR_CHECKSUM_CERTIFICATE = "checksumCertificate";
|
||||
|
||||
private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill";
|
||||
private static final int[] EMPTY_CHILD_SESSION_ARRAY = EmptyArray.INT;
|
||||
@@ -402,33 +399,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
@GuardedBy("mLock")
|
||||
private ArraySet<FileEntry> mFiles = new ArraySet<>();
|
||||
|
||||
static class CertifiedChecksum {
|
||||
final @NonNull Checksum mChecksum;
|
||||
final @NonNull String mPackageName;
|
||||
final @NonNull byte[] mCertificate;
|
||||
|
||||
CertifiedChecksum(@NonNull Checksum checksum, @NonNull String packageName,
|
||||
@NonNull byte[] certificate) {
|
||||
mChecksum = checksum;
|
||||
mPackageName = packageName;
|
||||
mCertificate = certificate;
|
||||
}
|
||||
|
||||
Checksum getChecksum() {
|
||||
return mChecksum;
|
||||
}
|
||||
|
||||
String getPackageName() {
|
||||
return mPackageName;
|
||||
}
|
||||
|
||||
byte[] getCertificate() {
|
||||
return mCertificate;
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private ArrayMap<String, List<CertifiedChecksum>> mChecksums = new ArrayMap<>();
|
||||
private ArrayMap<String, Checksum[]> mChecksums = new ArrayMap<>();
|
||||
|
||||
@Nullable
|
||||
final StagedSession mStagedSession;
|
||||
@@ -946,7 +918,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
int sessionId, int userId, int installerUid, @NonNull InstallSource installSource,
|
||||
SessionParams params, long createdMillis, long committedMillis,
|
||||
File stageDir, String stageCid, InstallationFile[] files,
|
||||
ArrayMap<String, List<CertifiedChecksum>> checksums,
|
||||
ArrayMap<String, List<Checksum>> checksums,
|
||||
boolean prepared, boolean committed, boolean destroyed, boolean sealed,
|
||||
@Nullable int[] childSessionIds, int parentSessionId, boolean isReady,
|
||||
boolean isFailed, boolean isApplied, int stagedSessionErrorCode,
|
||||
@@ -992,7 +964,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
}
|
||||
|
||||
if (checksums != null) {
|
||||
mChecksums.putAll(checksums);
|
||||
for (int i = 0, isize = checksums.size(); i < isize; ++i) {
|
||||
final String fileName = checksums.keyAt(i);
|
||||
final List<Checksum> fileChecksums = checksums.valueAt(i);
|
||||
mChecksums.put(fileName, fileChecksums.toArray(new Checksum[fileChecksums.size()]));
|
||||
}
|
||||
}
|
||||
|
||||
if (!params.isMultiPackage && (stageDir == null) == (stageCid == null)) {
|
||||
@@ -1290,16 +1266,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
throw new IllegalStateException("Can't obtain calling installer's package.");
|
||||
}
|
||||
|
||||
// Obtaining array of certificates used for signing the installer package.
|
||||
final Signature[] certs = callingInstaller.getSigningDetails().signatures;
|
||||
if (certs == null || certs.length == 0 || certs[0] == null) {
|
||||
throw new IllegalStateException(
|
||||
"Can't obtain calling installer package's certificates.");
|
||||
}
|
||||
// According to V2/V3 signing schema, the first certificate corresponds to the public key
|
||||
// in the signing block.
|
||||
final byte[] mainCertificateBytes = certs[0].toByteArray();
|
||||
|
||||
synchronized (mLock) {
|
||||
assertCallerIsOwnerOrRootLocked();
|
||||
assertPreparedAndNotCommittedOrDestroyedLocked("addChecksums");
|
||||
@@ -1308,13 +1274,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
throw new IllegalStateException("Duplicate checksums.");
|
||||
}
|
||||
|
||||
List<CertifiedChecksum> fileChecksums = new ArrayList<>();
|
||||
mChecksums.put(name, fileChecksums);
|
||||
|
||||
for (Checksum checksum : checksums) {
|
||||
fileChecksums.add(new CertifiedChecksum(checksum, initiatingPackageName,
|
||||
mainCertificateBytes));
|
||||
}
|
||||
mChecksums.put(name, checksums);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3069,34 +3029,23 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
maybeStageFsveritySignatureLocked(dexMetadataFile, targetDexMetadataFile);
|
||||
}
|
||||
|
||||
private static ApkChecksum[] createApkChecksums(String splitName,
|
||||
List<CertifiedChecksum> checksums) {
|
||||
ApkChecksum[] result = new ApkChecksum[checksums.size()];
|
||||
for (int i = 0, size = checksums.size(); i < size; ++i) {
|
||||
CertifiedChecksum checksum = checksums.get(i);
|
||||
result[i] = new ApkChecksum(splitName, checksum.getChecksum(),
|
||||
checksum.getPackageName(), checksum.getCertificate());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private void maybeStageDigestsLocked(File origFile, File targetFile, String splitName)
|
||||
throws PackageManagerException {
|
||||
final List<CertifiedChecksum> checksums = mChecksums.get(origFile.getName());
|
||||
final Checksum[] checksums = mChecksums.get(origFile.getName());
|
||||
if (checksums == null) {
|
||||
return;
|
||||
}
|
||||
mChecksums.remove(origFile.getName());
|
||||
|
||||
if (checksums.isEmpty()) {
|
||||
if (checksums.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String targetDigestsPath = ApkChecksums.buildDigestsPathForApk(targetFile.getName());
|
||||
final File targetDigestsFile = new File(stageDir, targetDigestsPath);
|
||||
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
|
||||
ApkChecksums.writeChecksums(os, createApkChecksums(splitName, checksums));
|
||||
ApkChecksums.writeChecksums(os, checksums);
|
||||
final byte[] checksumsBytes = os.toByteArray();
|
||||
|
||||
if (!isIncrementalInstallation() || mIncrementalFileStorages == null) {
|
||||
@@ -4338,18 +4287,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
}
|
||||
|
||||
for (int i = 0, isize = mChecksums.size(); i < isize; ++i) {
|
||||
String fileName = mChecksums.keyAt(i);
|
||||
List<CertifiedChecksum> checksums = mChecksums.valueAt(i);
|
||||
for (int j = 0, jsize = checksums.size(); j < jsize; ++j) {
|
||||
CertifiedChecksum checksum = checksums.get(j);
|
||||
final String fileName = mChecksums.keyAt(i);
|
||||
final Checksum[] checksums = mChecksums.valueAt(i);
|
||||
for (Checksum checksum : checksums) {
|
||||
out.startTag(null, TAG_SESSION_CHECKSUM);
|
||||
writeStringAttribute(out, ATTR_NAME, fileName);
|
||||
out.attributeInt(null, ATTR_CHECKSUM_KIND, checksum.getChecksum().getType());
|
||||
writeByteArrayAttribute(out, ATTR_CHECKSUM_VALUE,
|
||||
checksum.getChecksum().getValue());
|
||||
writeStringAttribute(out, ATTR_CHECKSUM_PACKAGE, checksum.getPackageName());
|
||||
writeByteArrayAttribute(out, ATTR_CHECKSUM_CERTIFICATE,
|
||||
checksum.getCertificate());
|
||||
out.attributeInt(null, ATTR_CHECKSUM_KIND, checksum.getType());
|
||||
writeByteArrayAttribute(out, ATTR_CHECKSUM_VALUE, checksum.getValue());
|
||||
out.endTag(null, TAG_SESSION_CHECKSUM);
|
||||
}
|
||||
}
|
||||
@@ -4467,7 +4411,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
int autoRevokePermissionsMode = MODE_DEFAULT;
|
||||
List<Integer> childSessionIds = new ArrayList<>();
|
||||
List<InstallationFile> files = new ArrayList<>();
|
||||
ArrayMap<String, List<CertifiedChecksum>> checksums = new ArrayMap<>();
|
||||
ArrayMap<String, List<Checksum>> checksums = new ArrayMap<>();
|
||||
int outerDepth = in.getDepth();
|
||||
int type;
|
||||
while ((type = in.next()) != XmlPullParser.END_DOCUMENT
|
||||
@@ -4499,18 +4443,16 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
}
|
||||
if (TAG_SESSION_CHECKSUM.equals(in.getName())) {
|
||||
final String fileName = readStringAttribute(in, ATTR_NAME);
|
||||
final CertifiedChecksum certifiedChecksum = new CertifiedChecksum(
|
||||
new Checksum(in.getAttributeInt(null, ATTR_CHECKSUM_KIND, 0),
|
||||
readByteArrayAttribute(in, ATTR_CHECKSUM_VALUE)),
|
||||
readStringAttribute(in, ATTR_CHECKSUM_PACKAGE),
|
||||
readByteArrayAttribute(in, ATTR_CHECKSUM_CERTIFICATE));
|
||||
final Checksum checksum = new Checksum(
|
||||
in.getAttributeInt(null, ATTR_CHECKSUM_KIND, 0),
|
||||
readByteArrayAttribute(in, ATTR_CHECKSUM_VALUE));
|
||||
|
||||
List<CertifiedChecksum> certifiedChecksums = checksums.get(fileName);
|
||||
if (certifiedChecksums == null) {
|
||||
certifiedChecksums = new ArrayList<>();
|
||||
checksums.put(fileName, certifiedChecksums);
|
||||
List<Checksum> fileChecksums = checksums.get(fileName);
|
||||
if (fileChecksums == null) {
|
||||
fileChecksums = new ArrayList<>();
|
||||
checksums.put(fileName, fileChecksums);
|
||||
}
|
||||
certifiedChecksums.add(certifiedChecksum);
|
||||
fileChecksums.add(checksum);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5584,6 +5584,9 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
if (applicationInfo == null) {
|
||||
throw new ParcelableException(new PackageManager.NameNotFoundException(packageName));
|
||||
}
|
||||
final InstallSourceInfo installSourceInfo = getInstallSourceInfo(packageName);
|
||||
final String installerPackageName =
|
||||
installSourceInfo != null ? installSourceInfo.getInitiatingPackageName() : null;
|
||||
|
||||
List<Pair<String, File>> filesToChecksum = new ArrayList<>();
|
||||
|
||||
@@ -5605,9 +5608,10 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
ApkChecksums.Injector injector = new ApkChecksums.Injector(
|
||||
() -> mContext,
|
||||
() -> handler,
|
||||
() -> mInjector.getIncrementalManager());
|
||||
ApkChecksums.getChecksums(filesToChecksum, optional, required, trustedCerts,
|
||||
statusReceiver, injector);
|
||||
() -> mInjector.getIncrementalManager(),
|
||||
() -> mPmInternal);
|
||||
ApkChecksums.getChecksums(filesToChecksum, optional, required, installerPackageName,
|
||||
trustedCerts, statusReceiver, injector);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user