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

Commit 102d3d86 authored by Evgenii Stepanov's avatar Evgenii Stepanov
Browse files

Add "enableGwpAsan" tag to android manifest.

This tag can be used to enable and disable gwp-asan on applications and
their components. The default setting is disabled, except for the system
applications which are enabled with a small probability (approx. 1% of
processes).

Enabling gwp-asan can be used to crowd test an app.

This change includes a compat feature that overrides the default value
of enableGwpAsan for an app.

Bug: 149991821
Test: atest CtsGwpAsanTestCases
Exempt-From-Owner-Approval: cherrypick
Merged-In: I5eb647c517e5487b1d1eed6b9a43242490f19289
Change-Id: I5b4db666f38af846927f88702cc690f0916cadb1
parent 3c706cfc
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -572,6 +572,7 @@ package android {
    field public static final int elevation = 16843840; // 0x1010440
    field public static final int ellipsize = 16842923; // 0x10100ab
    field public static final int ems = 16843096; // 0x1010158
    field public static final int enableGwpAsan = 16844310; // 0x1010616
    field public static final int enableVrMode = 16844069; // 0x1010525
    field public static final int enabled = 16842766; // 0x101000e
    field public static final int end = 16843996; // 0x10104dc
@@ -11439,6 +11440,7 @@ package android.content.pm {
    method public int describeContents();
    method public void dump(android.util.Printer, String);
    method public static CharSequence getCategoryTitle(android.content.Context, int);
    method @Nullable public Boolean isGwpAsanEnabled();
    method public boolean isProfileableByShell();
    method public boolean isResourceOverlay();
    method public boolean isVirtualPreload();
+25 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ProcessInfo;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Build;
@@ -38,6 +39,8 @@ import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;

import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Parcelling;
import com.android.internal.util.Parcelling.BuiltIn.ForBoolean;
import com.android.server.SystemConfig;

import java.lang.annotation.Retention;
@@ -56,6 +59,7 @@ import java.util.UUID;
 * <application> tag.
 */
public class ApplicationInfo extends PackageItemInfo implements Parcelable {
    private static ForBoolean sForBoolean = Parcelling.Cache.getOrCreate(ForBoolean.class);

    /**
     * Default task affinity of all activities in this application. See 
@@ -1272,6 +1276,14 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
    /** @hide */
    public String zygotePreloadName;

    /**
     * Indicates if the application has requested GWP-ASan to be enabled, disabled, or left
     * unspecified. Processes can override this setting.
     * @hide
     */
    @Nullable
    public Boolean enableGwpAsan;

    /**
     * Represents the default policy. The actual policy used will depend on other properties of
     * the application, e.g. the target SDK version.
@@ -1413,6 +1425,9 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
            pw.println(prefix + "usesNonSdkApi=" + usesNonSdkApi());
            pw.println(prefix + "allowsPlaybackCapture="
                        + (isAudioPlaybackCaptureAllowed() ? "true" : "false"));
            if (enableGwpAsan != null) {
                pw.println(prefix + "enableGwpAsan=" + enableGwpAsan);
            }
        }
        super.dumpBack(pw, prefix);
    }
@@ -1511,6 +1526,9 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
            if (category != CATEGORY_UNDEFINED) {
                proto.write(ApplicationInfoProto.Detail.CATEGORY, category);
            }
            if (enableGwpAsan != null) {
                proto.write(ApplicationInfoProto.Detail.ENABLE_GWP_ASAN, enableGwpAsan);
            }
            proto.end(detailToken);
        }
        proto.end(token);
@@ -1620,6 +1638,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
        mHiddenApiPolicy = orig.mHiddenApiPolicy;
        hiddenUntilInstalled = orig.hiddenUntilInstalled;
        zygotePreloadName = orig.zygotePreloadName;
        enableGwpAsan = orig.enableGwpAsan;
    }

    public String toString() {
@@ -1703,6 +1722,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
        dest.writeInt(mHiddenApiPolicy);
        dest.writeInt(hiddenUntilInstalled ? 1 : 0);
        dest.writeString(zygotePreloadName);
        sForBoolean.parcel(enableGwpAsan, dest, parcelableFlags);
    }

    public static final @android.annotation.NonNull Parcelable.Creator<ApplicationInfo> CREATOR
@@ -1783,6 +1803,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
        mHiddenApiPolicy = source.readInt();
        hiddenUntilInstalled = source.readInt() != 0;
        zygotePreloadName = source.readString();
        enableGwpAsan = sForBoolean.unparcel(source);
    }

    /**
@@ -2161,6 +2182,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
    /** {@hide} */ public void setResourcePath(String resourcePath) { scanPublicSourceDir = resourcePath; }
    /** {@hide} */ public void setBaseResourcePath(String baseResourcePath) { publicSourceDir = baseResourcePath; }
    /** {@hide} */ public void setSplitResourcePaths(String[] splitResourcePaths) { splitPublicSourceDirs = splitResourcePaths; }
    /** {@hide} */ public void setGwpAsanEnabled(@Nullable Boolean value) { enableGwpAsan = value; }

    /** {@hide} */
    @UnsupportedAppUsage
@@ -2172,4 +2194,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
    @UnsupportedAppUsage
    public String getBaseResourcePath() { return publicSourceDir; }
    /** {@hide} */ public String[] getSplitResourcePaths() { return splitPublicSourceDirs; }
    @Nullable
    public Boolean isGwpAsanEnabled() { return enableGwpAsan; }
}
+123 −32
Original line number Diff line number Diff line
@@ -23,66 +23,157 @@ import android.os.Parcelable;
import android.text.TextUtils;
import android.util.ArraySet;

import com.android.internal.util.DataClass;
import com.android.internal.util.Parcelling;

/**
 * Information about a process an app may run.  This corresponds to information collected from the
 * AndroidManifest.xml's &lt;permission-group&gt; tags.
 * @hide
 */
@DataClass(genGetters = true, genSetters = false, genParcelable = true, genAidl = false,
        genBuilder = false)
public class ProcessInfo implements Parcelable {
    /**
     * The name of the process, fully-qualified based on the app's package name.
     */
    @NonNull
    public String name;

    /**
     * If non-null, these are permissions that are not allowed in this process.
     */
    @Nullable
    @DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedStringArraySet.class)
    public ArraySet<String> deniedPermissions;

    public ProcessInfo(String name, ArraySet<String> deniedPermissions) {
        this.name = name;
        this.deniedPermissions = deniedPermissions;
    }
    /**
     * Indicates if the process has requested GWP-ASan to be enabled, disabled, or left unspecified.
     */
    @Nullable
    public Boolean enableGwpAsan;

    @Deprecated
    public ProcessInfo(@NonNull ProcessInfo orig) {
        this.name = orig.name;
        this.deniedPermissions = orig.deniedPermissions;
        this.enableGwpAsan = orig.enableGwpAsan;
    }

    public int describeContents() {
        return 0;


    // 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/ProcessInfo.java
    //
    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
    //   Settings > Editor > Code Style > Formatter Control
    //@formatter:off


    /**
     * Creates a new ProcessInfo.
     *
     * @param name
     *   The name of the process, fully-qualified based on the app's package name.
     * @param deniedPermissions
     *   If non-null, these are permissions that are not allowed in this process.
     * @param enableGwpAsan
     *   Indicates if the process has requested GWP-ASan to be enabled, disabled, or left unspecified.
     */
    @DataClass.Generated.Member
    public ProcessInfo(
            @NonNull String name,
            @Nullable ArraySet<String> deniedPermissions,
            @Nullable Boolean enableGwpAsan) {
        this.name = name;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, name);
        this.deniedPermissions = deniedPermissions;
        this.enableGwpAsan = enableGwpAsan;

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

    public void writeToParcel(Parcel dest, int parcelableFlags) {
        dest.writeString(this.name);
        final int numDenied = this.deniedPermissions != null
                ? this.deniedPermissions.size() : 0;
        dest.writeInt(numDenied);
        for (int i = 0; i < numDenied; i++) {
            dest.writeString(this.deniedPermissions.valueAt(i));
    @DataClass.Generated.Member
    static Parcelling<ArraySet<String>> sParcellingForDeniedPermissions =
            Parcelling.Cache.get(
                    Parcelling.BuiltIn.ForInternedStringArraySet.class);
    static {
        if (sParcellingForDeniedPermissions == null) {
            sParcellingForDeniedPermissions = Parcelling.Cache.put(
                    new Parcelling.BuiltIn.ForInternedStringArraySet());
        }
    }

    public static final @NonNull Creator<ProcessInfo> CREATOR =
            new Creator<ProcessInfo>() {
                public ProcessInfo createFromParcel(Parcel source) {
                    return new ProcessInfo(source);
    @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 (deniedPermissions != null) flg |= 0x2;
        if (enableGwpAsan != null) flg |= 0x4;
        dest.writeByte(flg);
        dest.writeString(name);
        sParcellingForDeniedPermissions.parcel(deniedPermissions, dest, flags);
        if (enableGwpAsan != null) dest.writeBoolean(enableGwpAsan);
    }

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

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

        byte flg = in.readByte();
        String _name = in.readString();
        ArraySet<String> _deniedPermissions = sParcellingForDeniedPermissions.unparcel(in);
        Boolean _enableGwpAsan = (flg & 0x4) == 0 ? null : (Boolean) in.readBoolean();

        this.name = _name;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, name);
        this.deniedPermissions = _deniedPermissions;
        this.enableGwpAsan = _enableGwpAsan;

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

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

    private ProcessInfo(Parcel source) {
        this.name = source.readString();
        final int numDenied = source.readInt();
        if (numDenied > 0) {
            this.deniedPermissions = new ArraySet<>(numDenied);
            for (int i = numDenied - 1; i >= 0; i--) {
                this.deniedPermissions.add(TextUtils.safeIntern(source.readString()));
            }
        }
        @Override
        public ProcessInfo createFromParcel(@NonNull Parcel in) {
            return new ProcessInfo(in);
        }
    };

    @DataClass.Generated(
            time = 1582840056156L,
            codegenVersion = "1.0.15",
            sourceFile = "frameworks/base/core/java/android/content/pm/ProcessInfo.java",
            inputSignatures = "public @android.annotation.NonNull java.lang.String name\npublic @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedStringArraySet.class) android.util.ArraySet<java.lang.String> deniedPermissions\npublic @android.annotation.Nullable java.lang.Boolean enableGwpAsan\nclass ProcessInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=false, genParcelable=true, genAidl=false, genBuilder=false)")
    @Deprecated
    private void __metadata() {}


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

}
+2 −0
Original line number Diff line number Diff line
@@ -236,6 +236,8 @@ public interface ParsingPackage extends ParsingPackageRead {

    ParsingPackage setEnabled(boolean enabled);

    ParsingPackage setGwpAsanEnabled(Boolean enableGwpAsan);

    ParsingPackage setCrossProfile(boolean crossProfile);

    ParsingPackage setFullBackupContent(int fullBackupContent);
+20 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.content.pm.FeatureGroupInfo;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageParser;
import android.content.pm.ProcessInfo;
import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.parsing.component.ParsedComponent;
import android.content.pm.parsing.component.ParsedFeature;
@@ -406,6 +407,10 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
    private boolean allowNativeHeapPointerTagging;
    private boolean preserveLegacyExternalStorage;

    @Nullable
    @DataClass.ParcelWith(ForBoolean.class)
    protected Boolean enableGwpAsan = null;

    // TODO(chiuwinson): Non-null
    @Nullable
    private ArraySet<String> mimeGroups;
@@ -904,7 +909,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
        appInfo.volumeUuid = volumeUuid;
        appInfo.zygotePreloadName = zygotePreloadName;
        appInfo.crossProfile = isCrossProfile();

        appInfo.setGwpAsanEnabled(enableGwpAsan);
        appInfo.setBaseCodePath(baseCodePath);
        appInfo.setBaseResourcePath(baseCodePath);
        appInfo.setCodePath(codePath);
@@ -1086,6 +1091,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
        dest.writeBoolean(this.allowNativeHeapPointerTagging);
        dest.writeBoolean(this.preserveLegacyExternalStorage);
        dest.writeArraySet(this.mimeGroups);
        sForBoolean.parcel(this.enableGwpAsan, dest, flags);
    }

    public ParsingPackageImpl(Parcel in) {
@@ -1243,6 +1249,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
        this.allowNativeHeapPointerTagging = in.readBoolean();
        this.preserveLegacyExternalStorage = in.readBoolean();
        this.mimeGroups = (ArraySet<String>) in.readArraySet(boot);
        this.enableGwpAsan = sForBoolean.unparcel(in);
    }

    public static final Parcelable.Creator<ParsingPackageImpl> CREATOR =
@@ -1964,6 +1971,12 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
        return directBootAware;
    }

    @Override
    @Nullable
    public Boolean isGwpAsanEnabled() {
        return enableGwpAsan;
    }

    @Override
    public boolean isPartiallyDirectBootAware() {
        return partiallyDirectBootAware;
@@ -2419,6 +2432,12 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
        return this;
    }

    @Override
    public ParsingPackageImpl setGwpAsanEnabled(@Nullable Boolean value) {
        enableGwpAsan = value;
        return this;
    }

    @Override
    public ParsingPackageImpl setPartiallyDirectBootAware(boolean value) {
        partiallyDirectBootAware = value;
Loading