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

Commit ce4afafc authored by Winson's avatar Winson
Browse files

Split ParsedPermissionImpl

Bug: 178218967

Change-Id: I7520f4cbe0af1ea430b95fead961b6f09419655e
parent 948f7bf3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.content.pm.parsing.component.ParsedIntentInfo;
import android.content.pm.parsing.component.ParsedMainComponent;
import android.content.pm.parsing.component.ParsedPermission;
import android.content.pm.parsing.component.ParsedPermissionGroup;
import android.content.pm.parsing.component.ParsedPermissionImpl;
import android.content.pm.parsing.component.ParsedProcess;
import android.content.pm.parsing.component.ParsedProvider;
import android.content.pm.parsing.component.ParsedProviderImpl;
@@ -1294,7 +1295,7 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
        this.providers = ParsingUtils.createTypedInterfaceList(in, ParsedProviderImpl.CREATOR);
        this.attributions = ParsingUtils.createTypedInterfaceList(in,
                ParsedAttributionImpl.CREATOR);
        this.permissions = in.createTypedArrayList(ParsedPermission.CREATOR);
        this.permissions = ParsingUtils.createTypedInterfaceList(in, ParsedPermissionImpl.CREATOR);
        this.permissionGroups = in.createTypedArrayList(ParsedPermissionGroup.CREATOR);
        this.instrumentations = ParsingUtils.createTypedInterfaceList(in,
                ParsedInstrumentationImpl.CREATOR);
+12 −2
Original line number Diff line number Diff line
@@ -46,8 +46,8 @@ public class ComponentMutateUtils {
        ((ParsedActivityImpl) activity).setResizeMode(resizeMode);
    }

    public static void setExactFlags(ParsedActivity activity, int exactFlags) {
        ((ParsedActivityImpl) activity).setFlags(exactFlags);
    public static void setExactFlags(ParsedComponent component, int exactFlags) {
        ((ParsedComponentImpl) component).setFlags(exactFlags);
    }

    public static void setEnabled(@NonNull ParsedMainComponent component, boolean enabled) {
@@ -75,4 +75,14 @@ public class ComponentMutateUtils {
    public static void setSyncable(@NonNull ParsedProvider provider, boolean syncable) {
        ((ParsedProviderImpl) provider).setSyncable(syncable);
    }

    public static void setProtectionLevel(@NonNull ParsedPermission permission,
            int protectionLevel) {
        ((ParsedPermissionImpl) permission).setProtectionLevel(protectionLevel);
    }

    public static void setParsedPermissionGroup(@NonNull ParsedPermission permission,
            @NonNull ParsedPermissionGroup permissionGroup) {
        ((ParsedPermissionImpl) permission).setParsedPermissionGroup(permissionGroup);
    }
}
+9 −187
Original line number Diff line number Diff line
@@ -16,206 +16,28 @@

package android.content.pm.parsing.component;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.PermissionInfo;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.ArraySet;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DataClass;
import com.android.internal.util.Parcelling;
import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
import com.android.internal.util.Parcelling.BuiltIn.ForStringSet;

import java.util.Locale;
import java.util.Set;

/** @hide */
public class ParsedPermission extends ParsedComponentImpl {

    private static ForStringSet sForStringSet = Parcelling.Cache.getOrCreate(ForStringSet.class);
public interface ParsedPermission extends ParsedComponent {

    @Nullable
    private String backgroundPermission;
    @Nullable
    @DataClass.ParcelWith(ForInternedString.class)
    private String group;
    private int requestRes;
    private int protectionLevel;
    private boolean tree;
    @Nullable
    private ParsedPermissionGroup parsedPermissionGroup;
    @Nullable
    private Set<String> knownCerts;

    @VisibleForTesting
    public ParsedPermission() {
    }

    public ParsedPermission(ParsedPermission other) {
        super(other);
        this.backgroundPermission = other.backgroundPermission;
        this.group = other.group;
        this.requestRes = other.requestRes;
        this.protectionLevel = other.protectionLevel;
        this.tree = other.tree;
        this.parsedPermissionGroup = other.parsedPermissionGroup;
    }

    public ParsedPermission setBackgroundPermission(String backgroundPermission) {
        this.backgroundPermission = backgroundPermission;
        return this;
    }

    public ParsedPermission setGroup(String group) {
        this.group = TextUtils.safeIntern(group);
        return this;
    }

    public boolean isRuntime() {
        return getProtection() == PermissionInfo.PROTECTION_DANGEROUS;
    }

    public boolean isAppOp() {
        return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0;
    }

    @PermissionInfo.Protection
    public int getProtection() {
        return protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
    }

    public int getProtectionFlags() {
        return protectionLevel & ~PermissionInfo.PROTECTION_MASK_BASE;
    }

    public @Nullable Set<String> getKnownCerts() {
        return knownCerts;
    }

    protected void setKnownCert(String knownCert) {
        // Convert the provided digest to upper case for consistent Set membership
        // checks when verifying the signing certificate digests of requesting apps.
        this.knownCerts = Set.of(knownCert.toUpperCase(Locale.US));
    }

    protected void setKnownCerts(String[] knownCerts) {
        this.knownCerts = new ArraySet<>();
        for (String knownCert : knownCerts) {
            this.knownCerts.add(knownCert.toUpperCase(Locale.US));
        }
    }

    public int calculateFootprint() {
        int size = getName().length();
        if (getNonLocalizedLabel() != null) {
            size += getNonLocalizedLabel().length();
        }
        return size;
    }

    public ParsedPermission setKnownCerts(Set<String> knownCerts) {
        this.knownCerts = knownCerts;
        return this;
    }

    public ParsedPermission setRequestRes(int requestRes) {
        this.requestRes = requestRes;
        return this;
    }

    public ParsedPermission setTree(boolean tree) {
        this.tree = tree;
        return this;
    }

    public String toString() {
        return "Permission{"
                + Integer.toHexString(System.identityHashCode(this))
                + " " + getName() + "}";
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeString(this.backgroundPermission);
        dest.writeString(this.group);
        dest.writeInt(this.requestRes);
        dest.writeInt(this.protectionLevel);
        dest.writeBoolean(this.tree);
        dest.writeParcelable(this.parsedPermissionGroup, flags);
        sForStringSet.parcel(knownCerts, dest, flags);
    }

    protected ParsedPermission(Parcel in) {
        super(in);
        // We use the boot classloader for all classes that we load.
        final ClassLoader boot = Object.class.getClassLoader();
        this.backgroundPermission = in.readString();
        this.group = in.readString();
        this.requestRes = in.readInt();
        this.protectionLevel = in.readInt();
        this.tree = in.readBoolean();
        this.parsedPermissionGroup = in.readParcelable(boot);
        this.knownCerts = sForStringSet.unparcel(in);
    }

    @NonNull
    public static final Parcelable.Creator<ParsedPermission> CREATOR =
            new Parcelable.Creator<ParsedPermission>() {
                @Override
                public ParsedPermission createFromParcel(Parcel source) {
                    return new ParsedPermission(source);
                }

                @Override
                public ParsedPermission[] newArray(int size) {
                    return new ParsedPermission[size];
                }
            };
    String getBackgroundPermission();

    @Nullable
    public String getBackgroundPermission() {
        return backgroundPermission;
    }
    String getGroup();

    @Nullable
    public String getGroup() {
        return group;
    }

    public int getRequestRes() {
        return requestRes;
    }

    public int getProtectionLevel() {
        return protectionLevel;
    }

    public boolean isTree() {
        return tree;
    }
    Set<String> getKnownCerts();

    @Nullable
    public ParsedPermissionGroup getParsedPermissionGroup() {
        return parsedPermissionGroup;
    }
    ParsedPermissionGroup getParsedPermissionGroup();

    public ParsedPermission setProtectionLevel(int value) {
        protectionLevel = value;
        return this;
    }
    int getProtectionLevel();

    public ParsedPermission setParsedPermissionGroup(@Nullable ParsedPermissionGroup value) {
        parsedPermissionGroup = value;
        return this;
    }
    int getRequestRes();

    boolean isTree();
}
+255 −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.parsing.component;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.ArraySet;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DataClass;
import com.android.internal.util.Parcelling;
import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
import com.android.internal.util.Parcelling.BuiltIn.ForStringSet;

import java.util.Locale;
import java.util.Set;

/** @hide */
@DataClass(genGetters = true, genSetters = true, genBuilder = false, genParcelable = false)
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public class ParsedPermissionImpl extends ParsedComponentImpl implements ParsedPermission {

    private static ForStringSet sForStringSet = Parcelling.Cache.getOrCreate(ForStringSet.class);

    @Nullable
    private String backgroundPermission;
    @Nullable
    @DataClass.ParcelWith(ForInternedString.class)
    private String group;
    private int requestRes;
    private int protectionLevel;
    private boolean tree;
    @Nullable
    private ParsedPermissionGroup parsedPermissionGroup;
    @Nullable
    private Set<String> knownCerts;

    @VisibleForTesting
    public ParsedPermissionImpl() {
    }

    public ParsedPermissionImpl(ParsedPermission other) {
        super(other);
        this.backgroundPermission = other.getBackgroundPermission();
        this.group = other.getGroup();
        this.requestRes = other.getRequestRes();
        this.protectionLevel = other.getProtectionLevel();
        this.tree = other.isTree();
        this.parsedPermissionGroup = other.getParsedPermissionGroup();
    }

    public ParsedPermissionImpl setGroup(String group) {
        this.group = TextUtils.safeIntern(group);
        return this;
    }

    protected void setKnownCert(String knownCert) {
        // Convert the provided digest to upper case for consistent Set membership
        // checks when verifying the signing certificate digests of requesting apps.
        this.knownCerts = Set.of(knownCert.toUpperCase(Locale.US));
    }

    protected void setKnownCerts(String[] knownCerts) {
        this.knownCerts = new ArraySet<>();
        for (String knownCert : knownCerts) {
            this.knownCerts.add(knownCert.toUpperCase(Locale.US));
        }
    }

    public String toString() {
        return "Permission{"
                + Integer.toHexString(System.identityHashCode(this))
                + " " + getName() + "}";
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeString(this.backgroundPermission);
        dest.writeString(this.group);
        dest.writeInt(this.requestRes);
        dest.writeInt(this.protectionLevel);
        dest.writeBoolean(this.tree);
        dest.writeParcelable(this.parsedPermissionGroup, flags);
        sForStringSet.parcel(knownCerts, dest, flags);
    }

    protected ParsedPermissionImpl(Parcel in) {
        super(in);
        // We use the boot classloader for all classes that we load.
        final ClassLoader boot = Object.class.getClassLoader();
        this.backgroundPermission = in.readString();
        this.group = TextUtils.safeIntern(in.readString());
        this.requestRes = in.readInt();
        this.protectionLevel = in.readInt();
        this.tree = in.readBoolean();
        this.parsedPermissionGroup = in.readParcelable(boot);
        this.knownCerts = sForStringSet.unparcel(in);
    }

    @NonNull
    public static final Parcelable.Creator<ParsedPermissionImpl> CREATOR =
            new Parcelable.Creator<ParsedPermissionImpl>() {
                @Override
                public ParsedPermissionImpl createFromParcel(Parcel source) {
                    return new ParsedPermissionImpl(source);
                }

                @Override
                public ParsedPermissionImpl[] newArray(int size) {
                    return new ParsedPermissionImpl[size];
                }
            };



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


    @DataClass.Generated.Member
    public ParsedPermissionImpl(
            @Nullable String backgroundPermission,
            @Nullable String group,
            int requestRes,
            int protectionLevel,
            boolean tree,
            @Nullable ParsedPermissionGroup parsedPermissionGroup,
            @Nullable Set<String> knownCerts) {
        this.backgroundPermission = backgroundPermission;
        this.group = group;
        this.requestRes = requestRes;
        this.protectionLevel = protectionLevel;
        this.tree = tree;
        this.parsedPermissionGroup = parsedPermissionGroup;
        this.knownCerts = knownCerts;

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

    @DataClass.Generated.Member
    public @Nullable String getBackgroundPermission() {
        return backgroundPermission;
    }

    @DataClass.Generated.Member
    public @Nullable String getGroup() {
        return group;
    }

    @DataClass.Generated.Member
    public int getRequestRes() {
        return requestRes;
    }

    @DataClass.Generated.Member
    public int getProtectionLevel() {
        return protectionLevel;
    }

    @DataClass.Generated.Member
    public boolean isTree() {
        return tree;
    }

    @DataClass.Generated.Member
    public @Nullable ParsedPermissionGroup getParsedPermissionGroup() {
        return parsedPermissionGroup;
    }

    @DataClass.Generated.Member
    public @Nullable Set<String> getKnownCerts() {
        return knownCerts;
    }

    @DataClass.Generated.Member
    public @NonNull ParsedPermissionImpl setBackgroundPermission(@NonNull String value) {
        backgroundPermission = value;
        return this;
    }

    @DataClass.Generated.Member
    public @NonNull ParsedPermissionImpl setRequestRes( int value) {
        requestRes = value;
        return this;
    }

    @DataClass.Generated.Member
    public @NonNull ParsedPermissionImpl setProtectionLevel( int value) {
        protectionLevel = value;
        return this;
    }

    @DataClass.Generated.Member
    public @NonNull ParsedPermissionImpl setTree( boolean value) {
        tree = value;
        return this;
    }

    @DataClass.Generated.Member
    public @NonNull ParsedPermissionImpl setParsedPermissionGroup(@NonNull ParsedPermissionGroup value) {
        parsedPermissionGroup = value;
        return this;
    }

    @DataClass.Generated.Member
    public @NonNull ParsedPermissionImpl setKnownCerts(@NonNull Set<String> value) {
        knownCerts = value;
        return this;
    }

    @DataClass.Generated(
            time = 1627598236506L,
            codegenVersion = "1.0.23",
            sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedPermissionImpl.java",
            inputSignatures = "private static  com.android.internal.util.Parcelling.BuiltIn.ForStringSet sForStringSet\nprivate @android.annotation.Nullable java.lang.String backgroundPermission\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String group\nprivate  int requestRes\nprivate  int protectionLevel\nprivate  boolean tree\nprivate @android.annotation.Nullable android.content.pm.parsing.component.ParsedPermissionGroup parsedPermissionGroup\nprivate @android.annotation.Nullable java.util.Set<java.lang.String> knownCerts\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<android.content.pm.parsing.component.ParsedPermissionImpl> CREATOR\npublic  android.content.pm.parsing.component.ParsedPermissionImpl setGroup(java.lang.String)\nprotected  void setKnownCert(java.lang.String)\nprotected  void setKnownCerts(java.lang.String[])\npublic  java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedPermissionImpl extends android.content.pm.parsing.component.ParsedComponentImpl implements [android.content.pm.parsing.component.ParsedPermission]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=false)")
    @Deprecated
    private void __metadata() {}


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

}
+48 −14
Original line number Diff line number Diff line
@@ -45,10 +45,9 @@ public class ParsedPermissionUtils {
            XmlResourceParser parser, boolean useRoundIcon, ParseInput input)
            throws IOException, XmlPullParserException {
        String packageName = pkg.getPackageName();
        ParsedPermission
                permission = new ParsedPermission();
        ParsedPermissionImpl permission = new ParsedPermissionImpl();
        String tag = "<" + parser.getName() + ">";
        final ParseResult<ParsedPermission> result;
        ParseResult<ParsedPermissionImpl> result;

        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestPermission);
        try {
@@ -62,7 +61,7 @@ public class ParsedPermissionUtils {
                    R.styleable.AndroidManifestPermission_name,
                    R.styleable.AndroidManifestPermission_roundIcon);
            if (result.isError()) {
                return result;
                return input.error(result);
            }

            if (sa.hasValue(
@@ -121,7 +120,7 @@ public class ParsedPermissionUtils {
            }

            // For now only platform runtime permissions can be restricted
            if (!permission.isRuntime() || !"android".equals(permission.getPackageName())) {
            if (!isRuntime(permission) || !"android".equals(permission.getPackageName())) {
                permission.setFlags(permission.getFlags() & ~PermissionInfo.FLAG_HARD_RESTRICTED);
                permission.setFlags(permission.getFlags() & ~PermissionInfo.FLAG_SOFT_RESTRICTED);
            } else {
@@ -139,26 +138,31 @@ public class ParsedPermissionUtils {
        permission.setProtectionLevel(
                PermissionInfo.fixProtectionLevel(permission.getProtectionLevel()));

        final int otherProtectionFlags = permission.getProtectionFlags()
        final int otherProtectionFlags = getProtectionFlags(permission)
                & ~(PermissionInfo.PROTECTION_FLAG_APPOP | PermissionInfo.PROTECTION_FLAG_INSTANT
                | PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY);
        if (otherProtectionFlags != 0
                && permission.getProtection() != PermissionInfo.PROTECTION_SIGNATURE
                && permission.getProtection() != PermissionInfo.PROTECTION_INTERNAL) {
                && getProtection(permission) != PermissionInfo.PROTECTION_SIGNATURE
                && getProtection(permission) != PermissionInfo.PROTECTION_INTERNAL) {
            return input.error("<permission> protectionLevel specifies a non-instant, non-appop,"
                    + " non-runtimeOnly flag but is not based on signature or internal type");
        }

        return ComponentParseUtils.parseAllMetaData(pkg, res, parser, tag, permission, input);
        result = ComponentParseUtils.parseAllMetaData(pkg, res, parser, tag, permission, input);
        if (result.isError()) {
            return input.error(result);
        }

        return input.success(result.getResult());
    }

    @NonNull
    public static ParseResult<ParsedPermission> parsePermissionTree(ParsingPackage pkg, Resources res,
            XmlResourceParser parser, boolean useRoundIcon, ParseInput input)
            throws IOException, XmlPullParserException {
        ParsedPermission permission = new ParsedPermission();
        ParsedPermissionImpl permission = new ParsedPermissionImpl();
        String tag = "<" + parser.getName() + ">";
        final ParseResult<ParsedPermission> result;
        ParseResult<ParsedPermissionImpl> result;

        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestPermissionTree);
        try {
@@ -172,7 +176,7 @@ public class ParsedPermissionUtils {
                    R.styleable.AndroidManifestPermissionTree_name,
                    R.styleable.AndroidManifestPermissionTree_roundIcon);
            if (result.isError()) {
                return result;
                return input.error(result);
            }
        } finally {
            sa.recycle();
@@ -190,8 +194,12 @@ public class ParsedPermissionUtils {
        permission.setProtectionLevel(PermissionInfo.PROTECTION_NORMAL)
                .setTree(true);

        return ComponentParseUtils.parseAllMetaData(pkg, res, parser, tag, permission,
                input);
        result = ComponentParseUtils.parseAllMetaData(pkg, res, parser, tag, permission, input);
        if (result.isError()) {
            return input.error(result);
        }

        return input.success(result.getResult());
    }

    @NonNull
@@ -232,4 +240,30 @@ public class ParsedPermissionUtils {
        return ComponentParseUtils.parseAllMetaData(pkg, res, parser, tag, permissionGroup,
                input);
    }

    public static boolean isRuntime(@NonNull ParsedPermission permission) {
        return getProtection(permission) == PermissionInfo.PROTECTION_DANGEROUS;
    }

    public static boolean isAppOp(@NonNull ParsedPermission permission) {
        return (permission.getProtectionLevel() & PermissionInfo.PROTECTION_FLAG_APPOP) != 0;
    }

    @PermissionInfo.Protection
    public static int getProtection(@NonNull ParsedPermission permission) {
        return permission.getProtectionLevel() & PermissionInfo.PROTECTION_MASK_BASE;
    }

    public static int getProtectionFlags(@NonNull ParsedPermission permission) {
        return permission.getProtectionLevel() & ~PermissionInfo.PROTECTION_MASK_BASE;
    }

    public static int calculateFootprint(@NonNull ParsedPermission permission) {
        int size = permission.getName().length();
        CharSequence nonLocalizedLabel = permission.getNonLocalizedLabel();
        if (nonLocalizedLabel != null) {
            size += nonLocalizedLabel.length();
        }
        return size;
    }
}
Loading