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

Commit ec6f3e18 authored by Alex Buynytskyy's avatar Alex Buynytskyy
Browse files

APK digest API and initial implementation.

Bug: 160605420
Test: atest ChecksumsTest

Change-Id: I08ef0b131c44313f2c6acddad00dfa03598cc1ff
parent 5be7e288
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -11617,6 +11617,16 @@ package android.content.pm {
    field public int version;
  }
  public final class FileChecksum implements android.os.Parcelable {
    method public int describeContents();
    method public int getKind();
    method @Nullable public java.security.cert.Certificate getSourceCertificate() throws java.security.cert.CertificateException;
    method @Nullable public String getSplitName();
    method @NonNull public byte[] getValue();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.FileChecksum> CREATOR;
  }
  public final class InstallSourceInfo implements android.os.Parcelable {
    method public int describeContents();
    method @Nullable public String getInitiatingPackageName();
@@ -11992,6 +12002,7 @@ package android.content.pm {
    method @Nullable public abstract android.graphics.drawable.Drawable getApplicationLogo(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
    method @NonNull public CharSequence getBackgroundPermissionOptionLabel();
    method @Nullable public abstract android.content.pm.ChangedPackages getChangedPackages(@IntRange(from=0) int);
    method public void getChecksums(@NonNull String, boolean, int, @Nullable java.util.List<java.security.cert.Certificate>, @NonNull android.content.IntentSender) throws java.security.cert.CertificateEncodingException, java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
    method public abstract int getComponentEnabledSetting(@NonNull android.content.ComponentName);
    method @NonNull public abstract android.graphics.drawable.Drawable getDefaultActivityIcon();
    method @Nullable public abstract android.graphics.drawable.Drawable getDrawable(@NonNull String, @DrawableRes int, @Nullable android.content.pm.ApplicationInfo);
@@ -12082,6 +12093,7 @@ 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";
@@ -12236,6 +12248,8 @@ package android.content.pm {
    field public static final int MATCH_SYSTEM_ONLY = 1048576; // 0x100000
    field public static final int MATCH_UNINSTALLED_PACKAGES = 8192; // 0x2000
    field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L
    field public static final int PARTIAL_MERKLE_ROOT_1M_SHA256 = 32; // 0x20
    field public static final int PARTIAL_MERKLE_ROOT_1M_SHA512 = 64; // 0x40
    field public static final int PERMISSION_DENIED = -1; // 0xffffffff
    field public static final int PERMISSION_GRANTED = 0; // 0x0
    field public static final int SIGNATURE_FIRST_NOT_SIGNED = -1; // 0xffffffff
@@ -12245,9 +12259,16 @@ package android.content.pm {
    field public static final int SIGNATURE_SECOND_NOT_SIGNED = -2; // 0xfffffffe
    field public static final int SIGNATURE_UNKNOWN_PACKAGE = -4; // 0xfffffffc
    field public static final int SYNCHRONOUS = 2; // 0x2
    field @Nullable public static final java.util.List<java.security.cert.Certificate> TRUST_ALL;
    field @NonNull public static final java.util.List<java.security.cert.Certificate> TRUST_NONE;
    field public static final int VERIFICATION_ALLOW = 1; // 0x1
    field public static final int VERIFICATION_REJECT = -1; // 0xffffffff
    field public static final int VERSION_CODE_HIGHEST = -1; // 0xffffffff
    field public static final int WHOLE_MD5 = 2; // 0x2
    field public static final int WHOLE_MERKLE_ROOT_4K_SHA256 = 1; // 0x1
    field public static final int WHOLE_SHA1 = 4; // 0x4
    field public static final int WHOLE_SHA256 = 8; // 0x8
    field public static final int WHOLE_SHA512 = 16; // 0x10
  }
  public static class PackageManager.NameNotFoundException extends android.util.AndroidException {
+44 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelableException;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
@@ -107,7 +108,11 @@ import dalvik.system.VMRuntime;

import libcore.util.EmptyArray;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -135,6 +140,12 @@ public class ApplicationPackageManager extends PackageManager {
    // Default flags to use with PackageManager when no flags are given.
    private static final int sDefaultFlags = GET_SHARED_LIBRARY_FILES;

    /** Default set of checksums - includes all available checksums.
     * @see PackageManager#getChecksums  */
    private static final int DEFAULT_CHECKSUMS =
            WHOLE_MERKLE_ROOT_4K_SHA256 | WHOLE_MD5 | WHOLE_SHA1 | WHOLE_SHA256 | WHOLE_SHA512
                    | PARTIAL_MERKLE_ROOT_1M_SHA256 | PARTIAL_MERKLE_ROOT_1M_SHA512;

    // Name of the resource which provides background permission button string
    public static final String APP_PERMISSION_BUTTON_ALLOW_ALWAYS =
            "app_permission_button_allow_always";
@@ -945,6 +956,39 @@ public class ApplicationPackageManager extends PackageManager {
        }
    }

    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;
    }

    @Override
    public void getChecksums(@NonNull String packageName, boolean includeSplits,
            @FileChecksumKind int required, @Nullable List<Certificate> trustedInstallers,
            @NonNull IntentSender statusReceiver)
            throws CertificateEncodingException, IOException, NameNotFoundException {
        Objects.requireNonNull(packageName);
        Objects.requireNonNull(statusReceiver);
        try {
            mPM.getChecksums(packageName, includeSplits, DEFAULT_CHECKSUMS, required,
                    encodeCertificates(trustedInstallers), statusReceiver, getUserId());
        } catch (ParcelableException e) {
            e.maybeRethrow(PackageManager.NameNotFoundException.class);
            throw new RuntimeException(e);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Wrap the cached value in a class that does deep compares on string
     * arrays.  The comparison is needed only for the verification mode of
+20 −0
Original line number Diff line number Diff line
/*
 * 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;

parcelable FileChecksum;
+238 −0
Original line number Diff line number Diff line
/*
 * 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.annotation.NonNull;
import android.annotation.Nullable;
import android.content.IntentSender;
import android.os.Parcel;
import android.os.Parcelable;

import com.android.internal.util.DataClass;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.List;

/**
 * A typed checksum.
 *
 * @see PackageManager#getChecksums(String, boolean, int, List, IntentSender)
 */
@DataClass(genHiddenConstructor = true)
public final class FileChecksum implements Parcelable {
    /**
     * Checksum for which split. Null indicates base.apk.
     */
    private final @Nullable String mSplitName;
    /**
     * Checksum kind.
     */
    private final @PackageManager.FileChecksumKind int mKind;
    /**
     * Checksum value.
     */
    private final @NonNull byte[] mValue;
    /**
     * For Installer-provided checksums, certificate of the Installer/AppStore.
     */
    private final @Nullable byte[] mSourceCertificate;

    /**
     * Constructor, internal use only
     *
     * @hide
     */
    public FileChecksum(@Nullable String splitName, @PackageManager.FileChecksumKind int kind,
            @NonNull byte[] value) {
        this(splitName, kind, value, (byte[]) null);
    }

    /**
     * Constructor, internal use only
     *
     * @hide
     */
    public FileChecksum(@Nullable String splitName, @PackageManager.FileChecksumKind int kind,
            @NonNull byte[] value, @Nullable Certificate sourceCertificate)
            throws CertificateEncodingException {
        this(splitName, kind, value,
                (sourceCertificate != null) ? sourceCertificate.getEncoded() : null);
    }

    /**
     * Certificate of the source of this checksum.
     * @throws CertificateException in case when certificate can't be re-created from serialized
     * data.
     */
    public @Nullable Certificate getSourceCertificate() throws CertificateException {
        if (mSourceCertificate == null) {
            return null;
        }
        final CertificateFactory cf = CertificateFactory.getInstance("X.509");
        final InputStream is = new ByteArrayInputStream(mSourceCertificate);
        final X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
        return cert;
    }



    // Code below generated by codegen v1.0.15.
    //
    // DO NOT MODIFY!
    // CHECKSTYLE:OFF Generated code
    //
    // To regenerate run:
    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/FileChecksum.java
    //
    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
    //   Settings > Editor > Code Style > Formatter Control
    //@formatter:off


    /**
     * Creates a new FileChecksum.
     *
     * @param splitName
     *   Checksum for which split. Null indicates base.apk.
     * @param kind
     *   Checksum kind.
     * @param value
     *   Checksum value.
     * @param sourceCertificate
     *   For Installer-provided checksums, certificate of the Installer/AppStore.
     * @hide
     */
    @DataClass.Generated.Member
    public FileChecksum(
            @Nullable String splitName,
            @PackageManager.FileChecksumKind int kind,
            @NonNull byte[] value,
            @Nullable byte[] sourceCertificate) {
        this.mSplitName = splitName;
        this.mKind = kind;
        com.android.internal.util.AnnotationValidations.validate(
                PackageManager.FileChecksumKind.class, null, mKind);
        this.mValue = value;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, mValue);
        this.mSourceCertificate = sourceCertificate;

        // onConstructed(); // You can define this method to get a callback
    }

    /**
     * Checksum for which split. Null indicates base.apk.
     */
    @DataClass.Generated.Member
    public @Nullable String getSplitName() {
        return mSplitName;
    }

    /**
     * Checksum kind.
     */
    @DataClass.Generated.Member
    public @PackageManager.FileChecksumKind int getKind() {
        return mKind;
    }

    /**
     * Checksum value.
     */
    @DataClass.Generated.Member
    public @NonNull byte[] getValue() {
        return mValue;
    }

    @Override
    @DataClass.Generated.Member
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        // You can override field parcelling by defining methods like:
        // void parcelFieldName(Parcel dest, int flags) { ... }

        byte flg = 0;
        if (mSplitName != null) flg |= 0x1;
        if (mSourceCertificate != null) flg |= 0x8;
        dest.writeByte(flg);
        if (mSplitName != null) dest.writeString(mSplitName);
        dest.writeInt(mKind);
        dest.writeByteArray(mValue);
        if (mSourceCertificate != null) dest.writeByteArray(mSourceCertificate);
    }

    @Override
    @DataClass.Generated.Member
    public int describeContents() { return 0; }

    /** @hide */
    @SuppressWarnings({"unchecked", "RedundantCast"})
    @DataClass.Generated.Member
    /* package-private */ FileChecksum(@NonNull Parcel in) {
        // You can override field unparcelling by defining methods like:
        // static FieldType unparcelFieldName(Parcel in) { ... }

        byte flg = in.readByte();
        String splitName = (flg & 0x1) == 0 ? null : in.readString();
        int kind = in.readInt();
        byte[] value = in.createByteArray();
        byte[] sourceCertificate = (flg & 0x8) == 0 ? null : in.createByteArray();

        this.mSplitName = splitName;
        this.mKind = kind;
        com.android.internal.util.AnnotationValidations.validate(
                PackageManager.FileChecksumKind.class, null, mKind);
        this.mValue = value;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, mValue);
        this.mSourceCertificate = sourceCertificate;

        // onConstructed(); // You can define this method to get a callback
    }

    @DataClass.Generated.Member
    public static final @NonNull Parcelable.Creator<FileChecksum> CREATOR
            = new Parcelable.Creator<FileChecksum>() {
        @Override
        public FileChecksum[] newArray(int size) {
            return new FileChecksum[size];
        }

        @Override
        public FileChecksum createFromParcel(@NonNull Parcel in) {
            return new FileChecksum(in);
        }
    };

    @DataClass.Generated(
            time = 1598322801861L,
            codegenVersion = "1.0.15",
            sourceFile = "frameworks/base/core/java/android/content/pm/FileChecksum.java",
            inputSignatures = "private final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.content.pm.PackageManager.FileChecksumKind int mKind\nprivate final @android.annotation.NonNull byte[] mValue\nprivate final @android.annotation.Nullable byte[] mSourceCertificate\npublic @android.annotation.Nullable java.security.cert.Certificate getSourceCertificate()\nclass FileChecksum extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
    @Deprecated
    private void __metadata() {}


    //@formatter:on
    // End of generated code

}
+2 −0
Original line number Diff line number Diff line
@@ -743,6 +743,8 @@ interface IPackageManager {

    void notifyPackagesReplacedReceived(in String[] packages);

    void getChecksums(in String packageName, boolean includeSplits, int optional, int required, in List trustedInstallers, in IntentSender statusReceiver, int userId);

    //------------------------------------------------------------------------
    //
    // The following binder interfaces have been moved to IPermissionManager
Loading