Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 36837c89 authored by Alex Buynytskyy's avatar Alex Buynytskyy Committed by Android (Google) Code Review
Browse files

Merge "Add public API to obtain digests of a file."

parents 6d8c7631 578ac902
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -12555,6 +12555,7 @@ package android.content.pm {
    method @NonNull public java.io.OutputStream openWrite(@NonNull String, long, long) throws java.io.IOException;
    method public void removeChildSessionId(int);
    method public void removeSplit(@NonNull String) throws java.io.IOException;
    method public void requestChecksums(@NonNull String, int, @NonNull java.util.List<java.security.cert.Certificate>, @NonNull android.content.pm.PackageManager.OnChecksumsReadyListener) throws java.security.cert.CertificateEncodingException, java.io.FileNotFoundException;
    method @Deprecated public void setChecksums(@NonNull String, @NonNull java.util.List<android.content.pm.Checksum>, @Nullable byte[]) throws java.io.IOException;
    method public void setStagingProgress(float);
    method public void transfer(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
+10 −10
Original line number Diff line number Diff line
@@ -920,7 +920,6 @@ public class ApplicationPackageManager extends PackageManager {
        Objects.requireNonNull(packageName);
        Objects.requireNonNull(onChecksumsReadyListener);
        Objects.requireNonNull(trustedInstallers);
        try {
        if (trustedInstallers == TRUST_ALL) {
            trustedInstallers = null;
        } else if (trustedInstallers == TRUST_NONE) {
@@ -930,6 +929,7 @@ public class ApplicationPackageManager extends PackageManager {
                    "trustedInstallers has to be one of TRUST_ALL/TRUST_NONE or a non-empty "
                            + "list of certificates.");
        }
        try {
            IOnChecksumsReadyListener onChecksumsReadyListenerDelegate =
                    new IOnChecksumsReadyListener.Stub() {
                        @Override
@@ -938,7 +938,7 @@ public class ApplicationPackageManager extends PackageManager {
                            onChecksumsReadyListener.onChecksumsReady(checksums);
                        }
                    };
            mPM.requestChecksums(packageName, includeSplits, DEFAULT_CHECKSUMS, required,
            mPM.requestPackageChecksums(packageName, includeSplits, DEFAULT_CHECKSUMS, required,
                    encodeCertificates(trustedInstallers), onChecksumsReadyListenerDelegate,
                    getUserId());
        } catch (ParcelableException e) {
+2 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.content.pm;

import android.content.pm.Checksum;
import android.content.pm.DataLoaderParamsParcel;
import android.content.pm.IOnChecksumsReadyListener;
import android.content.pm.IPackageInstallObserver2;
import android.content.IntentSender;
import android.os.ParcelFileDescriptor;
@@ -36,6 +37,7 @@ interface IPackageInstallerSession {
    void stageViaHardLink(String target);

    void setChecksums(String name, in Checksum[] checksums, in byte[] signature);
    void requestChecksums(in String name, int optional, int required, in List trustedInstallers, in IOnChecksumsReadyListener onChecksumsReadyListener);

    void removeSplit(String splitName);

+1 −1
Original line number Diff line number Diff line
@@ -750,7 +750,7 @@ interface IPackageManager {

    void notifyPackagesReplacedReceived(in String[] packages);

    void requestChecksums(in String packageName, boolean includeSplits, int optional, int required, in List trustedInstallers, in IOnChecksumsReadyListener onChecksumsReadyListener, int userId);
    void requestPackageChecksums(in String packageName, boolean includeSplits, int optional, int required, in List trustedInstallers, in IOnChecksumsReadyListener onChecksumsReadyListener, int userId);

    IntentSender getLaunchIntentSenderForPackage(String packageName, String callingPackage,
                String featureId, int userId);
+102 −1
Original line number Diff line number Diff line
@@ -19,6 +19,13 @@ package android.content.pm;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.MODE_IGNORED;
import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256;
import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512;
import static android.content.pm.Checksum.TYPE_WHOLE_MD5;
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 android.Manifest;
import android.annotation.CurrentTimeMillisLong;
@@ -62,12 +69,16 @@ import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;

import java.io.Closeable;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.security.MessageDigest;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
@@ -406,6 +417,13 @@ public class PackageInstaller {
    @Retention(RetentionPolicy.SOURCE)
    public @interface FileLocation{}

    /** Default set of checksums - includes all available checksums.
     * @see Session#requestChecksums  */
    private static final int DEFAULT_CHECKSUMS =
            TYPE_WHOLE_MERKLE_ROOT_4K_SHA256 | TYPE_WHOLE_MD5 | TYPE_WHOLE_SHA1 | TYPE_WHOLE_SHA256
                    | TYPE_WHOLE_SHA512 | TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256
                    | TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512;

    private final IPackageInstaller mInstaller;
    private final int mUserId;
    private final String mInstallerPackageName;
@@ -1256,7 +1274,7 @@ public class PackageInstaller {
         * @param name      previously written as part of this session.
         *                  {@link #openWrite}
         * @param checksums installer intends to make available via
         *                  {@link PackageManager#requestChecksums}.
         *                  {@link PackageManager#requestChecksums} or {@link #requestChecksums}.
         * @param signature DER PKCS#7 detached signature bytes over binary serialized checksums
         *                  to enable integrity checking for the checksums or null for no integrity
         *                  checking. {@link PackageManager#requestChecksums} will return
@@ -1293,6 +1311,89 @@ public class PackageInstaller {
            }
        }

        private static List<byte[]> encodeCertificates(List<Certificate> certs) throws
                CertificateEncodingException {
            if (certs == null) {
                return null;
            }
            List<byte[]> result = new ArrayList<>(certs.size());
            for (Certificate cert : certs) {
                if (!(cert instanceof X509Certificate)) {
                    throw new CertificateEncodingException("Only X509 certificates supported.");
                }
                result.add(cert.getEncoded());
            }
            return result;
        }

        /**
         * Requests checksums for the APK file in session.
         * <p>
         * A possible use case is replying to {@link Intent#ACTION_PACKAGE_NEEDS_VERIFICATION}
         * broadcast.
         * The checksums will be returned asynchronously via onChecksumsReadyListener.
         * <p>
         * By default returns all readily available checksums:
         * <ul>
         * <li>enforced by platform,
         * <li>enforced by the installer.
         * </ul>
         * If the caller needs a specific checksum type, they can specify it as required.
         * <p>
         * <b>Caution: Android can not verify installer-provided checksums. Make sure you specify
         * trusted installers.</b>
         * <p>
         * @param name      previously written as part of this session.
         *                  {@link #openWrite}
         * @param required to explicitly request the checksum types. Will incur significant
         *                 CPU/memory/disk usage.
         * @param trustedInstallers for checksums enforced by installer, which installers are to be
         *                          trusted.
         *                          {@link PackageManager#TRUST_ALL} will return checksums from any
         *                          installer,
         *                          {@link PackageManager#TRUST_NONE} disables optimized
         *                          installer-enforced checksums, otherwise the list has to be
         *                          a non-empty list of certificates.
         * @param onChecksumsReadyListener called once when the results are available.
         * @throws CertificateEncodingException if an encoding error occurs for trustedInstallers.
         * @throws FileNotFoundException if the file does not exist.
         * @throws IllegalArgumentException if the list of trusted installer certificates is empty.
         */
        public void requestChecksums(@NonNull String name, @Checksum.TypeMask int required,
                @NonNull List<Certificate> trustedInstallers,
                @NonNull PackageManager.OnChecksumsReadyListener onChecksumsReadyListener)
                throws CertificateEncodingException, FileNotFoundException {
            Objects.requireNonNull(name);
            Objects.requireNonNull(onChecksumsReadyListener);
            Objects.requireNonNull(trustedInstallers);
            if (trustedInstallers == PackageManager.TRUST_ALL) {
                trustedInstallers = null;
            } else if (trustedInstallers == PackageManager.TRUST_NONE) {
                trustedInstallers = Collections.emptyList();
            } else if (trustedInstallers.isEmpty()) {
                throw new IllegalArgumentException(
                        "trustedInstallers has to be one of TRUST_ALL/TRUST_NONE or a non-empty "
                                + "list of certificates.");
            }
            try {
                IOnChecksumsReadyListener onChecksumsReadyListenerDelegate =
                        new IOnChecksumsReadyListener.Stub() {
                            @Override
                            public void onChecksumsReady(List<ApkChecksum> checksums)
                                    throws RemoteException {
                                onChecksumsReadyListener.onChecksumsReady(checksums);
                            }
                        };
                mSession.requestChecksums(name, DEFAULT_CHECKSUMS, required,
                        encodeCertificates(trustedInstallers), onChecksumsReadyListenerDelegate);
            } catch (ParcelableException e) {
                e.maybeRethrow(FileNotFoundException.class);
                throw new RuntimeException(e);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        /**
         * Attempt to commit everything staged in this session. This may require
         * user intervention, and so it may not happen immediately. The final
Loading