diff options
9 files changed, 105 insertions, 71 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 10801b07c5ee..5679a3dbcd6a 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -12298,7 +12298,7 @@ package android.content.pm { method @Deprecated public abstract void removePackageFromPreferred(@NonNull String); method public abstract void removePermission(@NonNull String); method @RequiresPermission(value="android.permission.WHITELIST_RESTRICTED_PERMISSIONS", conditional=true) public boolean removeWhitelistedRestrictedPermission(@NonNull String, @NonNull String, int); - method public void requestChecksums(@NonNull String, boolean, int, @NonNull java.util.List<java.security.cert.Certificate>, @NonNull android.content.IntentSender) throws java.security.cert.CertificateEncodingException, android.content.pm.PackageManager.NameNotFoundException; + method public void requestChecksums(@NonNull String, boolean, int, @NonNull java.util.List<java.security.cert.Certificate>, @NonNull android.content.pm.PackageManager.OnChecksumsReadyListener) throws java.security.cert.CertificateEncodingException, android.content.pm.PackageManager.NameNotFoundException; method @Nullable public abstract android.content.pm.ResolveInfo resolveActivity(@NonNull android.content.Intent, int); method @Nullable public abstract android.content.pm.ProviderInfo resolveContentProvider(@NonNull String, int); method @Nullable public abstract android.content.pm.ResolveInfo resolveService(@NonNull android.content.Intent, int); @@ -12318,7 +12318,6 @@ package android.content.pm { field public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3; // 0x3 field public static final int COMPONENT_ENABLED_STATE_ENABLED = 1; // 0x1 field public static final int DONT_KILL_APP = 1; // 0x1 - field public static final String EXTRA_CHECKSUMS = "android.content.pm.extra.CHECKSUMS"; field public static final String EXTRA_VERIFICATION_ID = "android.content.pm.extra.VERIFICATION_ID"; field public static final String EXTRA_VERIFICATION_RESULT = "android.content.pm.extra.VERIFICATION_RESULT"; field public static final String FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS = "android.software.activities_on_secondary_displays"; @@ -12504,6 +12503,10 @@ package android.content.pm { ctor public PackageManager.NameNotFoundException(String); } + @java.lang.FunctionalInterface public static interface PackageManager.OnChecksumsReadyListener { + method public void onChecksumsReady(@NonNull java.util.List<android.content.pm.ApkChecksum>); + } + public static final class PackageManager.Property implements android.os.Parcelable { method public int describeContents(); method public boolean getBoolean(); diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index b51d4ac8c988..8ac91396a6b0 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -39,11 +39,13 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; import android.content.pm.ActivityInfo; +import android.content.pm.ApkChecksum; import android.content.pm.ApplicationInfo; import android.content.pm.ChangedPackages; import android.content.pm.Checksum; import android.content.pm.ComponentInfo; import android.content.pm.FeatureInfo; +import android.content.pm.IOnChecksumsReadyListener; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageDeleteObserver; import android.content.pm.IPackageManager; @@ -880,10 +882,10 @@ public class ApplicationPackageManager extends PackageManager { @Override public void requestChecksums(@NonNull String packageName, boolean includeSplits, @Checksum.Type int required, @NonNull List<Certificate> trustedInstallers, - @NonNull IntentSender statusReceiver) + @NonNull OnChecksumsReadyListener onChecksumsReadyListener) throws CertificateEncodingException, NameNotFoundException { Objects.requireNonNull(packageName); - Objects.requireNonNull(statusReceiver); + Objects.requireNonNull(onChecksumsReadyListener); Objects.requireNonNull(trustedInstallers); try { if (trustedInstallers == TRUST_ALL) { @@ -895,8 +897,17 @@ public class ApplicationPackageManager extends PackageManager { "trustedInstallers has to be one of TRUST_ALL/TRUST_NONE or a non-empty " + "list of certificates."); } + IOnChecksumsReadyListener onChecksumsReadyListenerDelegate = + new IOnChecksumsReadyListener.Stub() { + @Override + public void onChecksumsReady(List<ApkChecksum> checksums) + throws RemoteException { + onChecksumsReadyListener.onChecksumsReady(checksums); + } + }; mPM.requestChecksums(packageName, includeSplits, DEFAULT_CHECKSUMS, required, - encodeCertificates(trustedInstallers), statusReceiver, getUserId()); + encodeCertificates(trustedInstallers), onChecksumsReadyListenerDelegate, + getUserId()); } catch (ParcelableException e) { e.maybeRethrow(PackageManager.NameNotFoundException.class); throw new RuntimeException(e); diff --git a/core/java/android/content/pm/IOnChecksumsReadyListener.aidl b/core/java/android/content/pm/IOnChecksumsReadyListener.aidl new file mode 100644 index 000000000000..7963ce19956a --- /dev/null +++ b/core/java/android/content/pm/IOnChecksumsReadyListener.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 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.ApkChecksum; + +/** + * Listener that gets notified when checksums are available. + * {@hide} + */ +oneway interface IOnChecksumsReadyListener { + void onChecksumsReady(in List<ApkChecksum> checksums); +} diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index b8829bbf1ca5..a46876ec53c4 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -27,6 +27,7 @@ import android.content.pm.InstantAppInfo; import android.content.pm.FeatureInfo; import android.content.pm.IDexModuleRegisterCallback; import android.content.pm.InstallSourceInfo; +import android.content.pm.IOnChecksumsReadyListener; import android.content.pm.IPackageInstaller; import android.content.pm.IPackageDeleteObserver; import android.content.pm.IPackageDeleteObserver2; @@ -754,7 +755,7 @@ interface IPackageManager { void notifyPackagesReplacedReceived(in String[] packages); - void requestChecksums(in String packageName, boolean includeSplits, int optional, int required, in List trustedInstallers, in IntentSender statusReceiver, int userId); + void requestChecksums(in String packageName, boolean includeSplits, int optional, int required, in List trustedInstallers, in IOnChecksumsReadyListener onChecksumsReadyListener, int userId); //------------------------------------------------------------------------ // diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index d09d83f0cd1d..b95b991b095c 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3858,13 +3858,6 @@ public abstract class PackageManager { public static final String EXTRA_FAILURE_EXISTING_PERMISSION = "android.content.pm.extra.FAILURE_EXISTING_PERMISSION"; - /** - * Extra field name for the ID of a package pending verification. Passed to - * a package verifier and is used to call back to - * @see #requestChecksums - */ - public static final String EXTRA_CHECKSUMS = "android.content.pm.extra.CHECKSUMS"; - /** * Permission flag: The permission is set in its current state * by the user and apps can still request it at runtime. @@ -8709,9 +8702,20 @@ public abstract class PackageManager { */ public static final @NonNull List<Certificate> TRUST_NONE = Collections.singletonList(null); + /** Listener that gets notified when checksums are available. */ + @FunctionalInterface + public interface OnChecksumsReadyListener { + /** + * Called when the checksums are available. + * + * @param checksums array of checksums. + */ + void onChecksumsReady(@NonNull List<ApkChecksum> checksums); + } + /** * Requesting the checksums for APKs within a package. - * The checksums will be returned asynchronously via statusReceiver. + * The checksums will be returned asynchronously via onChecksumsReadyListener. * * By default returns all readily available checksums: * - enforced by platform, @@ -8730,15 +8734,14 @@ public abstract class PackageManager { * {@link #TRUST_ALL} will return checksums from any installer, * {@link #TRUST_NONE} disables optimized installer-enforced checksums, * otherwise the list has to be non-empty list of certificates. - * @param statusReceiver called once when the results are available as - * {@link #EXTRA_CHECKSUMS} of type {@link ApkChecksum}[]. + * @param onChecksumsReadyListener called once when the results are available. * @throws CertificateEncodingException if an encoding error occurs for trustedInstallers. * @throws IllegalArgumentException if the list of trusted installer certificates is empty. * @throws NameNotFoundException if a package with the given name cannot be found on the system. */ public void requestChecksums(@NonNull String packageName, boolean includeSplits, @Checksum.Type int required, @NonNull List<Certificate> trustedInstallers, - @NonNull IntentSender statusReceiver) + @NonNull OnChecksumsReadyListener onChecksumsReadyListener) throws CertificateEncodingException, NameNotFoundException { throw new UnsupportedOperationException("requestChecksums not implemented in subclass"); } diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java index dad8bd826e3d..9ccb0c786ebe 100644 --- a/services/core/java/android/content/pm/PackageManagerInternal.java +++ b/services/core/java/android/content/pm/PackageManagerInternal.java @@ -1137,7 +1137,8 @@ public abstract class PackageManagerInternal { */ public abstract void requestChecksums(@NonNull String packageName, boolean includeSplits, @Checksum.Type int optional, @Checksum.Type int required, - @Nullable List trustedInstallers, @NonNull IntentSender statusReceiver, int userId, + @Nullable List trustedInstallers, + @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, int userId, @NonNull Executor executor, @NonNull Handler handler); /** diff --git a/services/core/java/com/android/server/pm/ApkChecksums.java b/services/core/java/com/android/server/pm/ApkChecksums.java index 5373f996d7f8..66ea55401cef 100644 --- a/services/core/java/com/android/server/pm/ApkChecksums.java +++ b/services/core/java/com/android/server/pm/ApkChecksums.java @@ -23,7 +23,6 @@ import static android.content.pm.Checksum.TYPE_WHOLE_MERKLE_ROOT_4K_SHA256; import static android.content.pm.Checksum.TYPE_WHOLE_SHA1; import static android.content.pm.Checksum.TYPE_WHOLE_SHA256; import static android.content.pm.Checksum.TYPE_WHOLE_SHA512; -import static android.content.pm.PackageManager.EXTRA_CHECKSUMS; import static android.content.pm.parsing.ApkLiteParseUtils.APK_FILE_EXTENSION; import static android.util.apk.ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256; import static android.util.apk.ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512; @@ -32,15 +31,15 @@ import static android.util.apk.ApkSigningBlockUtils.CONTENT_DIGEST_VERITY_CHUNKE import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; -import android.content.Intent; -import android.content.IntentSender; import android.content.pm.ApkChecksum; import android.content.pm.Checksum; +import android.content.pm.IOnChecksumsReadyListener; import android.content.pm.PackageManagerInternal; import android.content.pm.PackageParser; import android.content.pm.Signature; import android.content.pm.parsing.ApkLiteParseUtils; import android.os.Handler; +import android.os.RemoteException; import android.os.SystemClock; import android.os.incremental.IncrementalManager; import android.os.incremental.IncrementalStorage; @@ -294,21 +293,21 @@ public class ApkChecksums { /** * 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 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 + * @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 onChecksumsReadyListener 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 IOnChecksumsReadyListener onChecksumsReadyListener, @NonNull Injector injector) { List<Map<Integer, ApkChecksum>> result = new ArrayList<>(filesToChecksum.size()); for (int i = 0, size = filesToChecksum.size(); i < size; ++i) { @@ -326,14 +325,14 @@ public class ApkChecksums { } long startTime = SystemClock.uptimeMillis(); - processRequiredChecksums(filesToChecksum, result, required, statusReceiver, injector, - startTime); + processRequiredChecksums(filesToChecksum, result, required, onChecksumsReadyListener, + injector, startTime); } private static void processRequiredChecksums(List<Pair<String, File>> filesToChecksum, List<Map<Integer, ApkChecksum>> result, @Checksum.Type int required, - @NonNull IntentSender statusReceiver, + @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, @NonNull Injector injector, long startTime) { final boolean timeout = @@ -350,7 +349,7 @@ public class ApkChecksums { // Not ready, come back later. injector.getHandler().postDelayed(() -> { processRequiredChecksums(filesToChecksum, result, required, - statusReceiver, injector, startTime); + onChecksumsReadyListener, injector, startTime); }, PROCESS_REQUIRED_CHECKSUMS_DELAY_MILLIS); return; } @@ -363,13 +362,9 @@ public class ApkChecksums { } } - final Intent intent = new Intent(); - intent.putExtra(EXTRA_CHECKSUMS, - allChecksums.toArray(new ApkChecksum[allChecksums.size()])); - try { - statusReceiver.sendIntent(injector.getContext(), 1, intent, null, null); - } catch (IntentSender.SendIntentException e) { + onChecksumsReadyListener.onChecksumsReady(allChecksums); + } catch (RemoteException e) { Slog.w(TAG, e); } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index f444ed6df2a3..498c314cbc68 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -177,6 +177,7 @@ import android.content.pm.DataLoaderType; import android.content.pm.FallbackCategoryProvider; import android.content.pm.FeatureInfo; import android.content.pm.IDexModuleRegisterCallback; +import android.content.pm.IOnChecksumsReadyListener; import android.content.pm.IPackageChangeObserver; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageDeleteObserver; @@ -5523,19 +5524,19 @@ public class PackageManagerService extends IPackageManager.Stub public void requestChecksums(@NonNull String packageName, boolean includeSplits, @Checksum.Type int optional, @Checksum.Type int required, @Nullable List trustedInstallers, - @NonNull IntentSender statusReceiver, int userId) { + @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, int userId) { requestChecksumsInternal(packageName, includeSplits, optional, required, trustedInstallers, - statusReceiver, userId, mInjector.getBackgroundExecutor(), + onChecksumsReadyListener, userId, mInjector.getBackgroundExecutor(), mInjector.getBackgroundHandler()); } private void requestChecksumsInternal(@NonNull String packageName, boolean includeSplits, - @Checksum.Type int optional, - @Checksum.Type int required, @Nullable List trustedInstallers, - @NonNull IntentSender statusReceiver, int userId, @NonNull Executor executor, - @NonNull Handler handler) { + @Checksum.Type int optional, @Checksum.Type int required, + @Nullable List trustedInstallers, + @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, int userId, + @NonNull Executor executor, @NonNull Handler handler) { Objects.requireNonNull(packageName); - Objects.requireNonNull(statusReceiver); + Objects.requireNonNull(onChecksumsReadyListener); Objects.requireNonNull(executor); Objects.requireNonNull(handler); @@ -5571,7 +5572,7 @@ public class PackageManagerService extends IPackageManager.Stub () -> mInjector.getIncrementalManager(), () -> mPmInternal); ApkChecksums.getChecksums(filesToChecksum, optional, required, installerPackageName, - trustedCerts, statusReceiver, injector); + trustedCerts, onChecksumsReadyListener, injector); }); } @@ -27110,12 +27111,14 @@ public class PackageManagerService extends IPackageManager.Stub ps.setStatesOnCrashOrAnr(); } + @Override public void requestChecksums(@NonNull String packageName, boolean includeSplits, @Checksum.Type int optional, @Checksum.Type int required, - @Nullable List trustedInstallers, @NonNull IntentSender statusReceiver, int userId, + @Nullable List trustedInstallers, + @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, int userId, @NonNull Executor executor, @NonNull Handler handler) { requestChecksumsInternal(packageName, includeSplits, optional, required, - trustedInstallers, statusReceiver, userId, executor, handler); + trustedInstallers, onChecksumsReadyListener, userId, executor, handler); } @Override diff --git a/services/core/java/com/android/server/pm/ProcessLoggingHandler.java b/services/core/java/com/android/server/pm/ProcessLoggingHandler.java index ce77c9163843..8c5084afcdf9 100644 --- a/services/core/java/com/android/server/pm/ProcessLoggingHandler.java +++ b/services/core/java/com/android/server/pm/ProcessLoggingHandler.java @@ -16,22 +16,16 @@ package com.android.server.pm; -import static android.content.pm.PackageManager.EXTRA_CHECKSUMS; - import android.app.admin.SecurityLog; import android.content.Context; -import android.content.IIntentReceiver; -import android.content.IIntentSender; -import android.content.Intent; -import android.content.IntentSender; import android.content.pm.ApkChecksum; import android.content.pm.Checksum; +import android.content.pm.IOnChecksumsReadyListener; import android.content.pm.PackageManagerInternal; import android.os.Bundle; import android.os.Handler; import android.os.HandlerExecutor; -import android.os.IBinder; -import android.os.Parcelable; +import android.os.RemoteException; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Slog; @@ -39,7 +33,6 @@ import android.util.Slog; import com.android.internal.os.BackgroundThread; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.concurrent.Executor; @@ -109,26 +102,23 @@ public final class ProcessLoggingHandler extends Handler { // Capturing local loggingInfo to still log even if hash was invalidated. try { pmi.requestChecksums(packageName, false, 0, CHECKSUM_TYPE, null, - new IntentSender((IIntentSender) new IIntentSender.Stub() { + new IOnChecksumsReadyListener.Stub() { @Override - public void send(int code, Intent intent, String resolvedType, - IBinder allowlistToken, IIntentReceiver finishedReceiver, - String requiredPermission, Bundle options) { - processChecksums(loggingInfo, intent); + public void onChecksumsReady(List<ApkChecksum> checksums) + throws RemoteException { + processChecksums(loggingInfo, checksums); } - }), context.getUserId(), mExecutor, this); + }, context.getUserId(), + mExecutor, this); } catch (Throwable t) { Slog.e(TAG, "requestChecksums() failed", t); enqueueProcessChecksum(loggingInfo, null); } } - void processChecksums(final LoggingInfo loggingInfo, Intent intent) { - Parcelable[] parcelables = intent.getParcelableArrayExtra(EXTRA_CHECKSUMS); - ApkChecksum[] checksums = Arrays.copyOf(parcelables, parcelables.length, - ApkChecksum[].class); - - for (ApkChecksum checksum : checksums) { + void processChecksums(final LoggingInfo loggingInfo, List<ApkChecksum> checksums) { + for (int i = 0, size = checksums.size(); i < size; ++i) { + ApkChecksum checksum = checksums.get(i); if (checksum.getType() == CHECKSUM_TYPE) { processChecksum(loggingInfo, checksum.getValue()); return; |