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

Commit a58ce39e authored by Chad Brubaker's avatar Chad Brubaker
Browse files

Add permission usage information

Applications will be able to add information to their uses-permission
elements about how the data protected by that permission is used.

Currently the system does not use this information, that will be done in
a follow up CL.

Test: atest PermissionUsageTest
Bug: 111207567
Change-Id: Ic168684cc800febc8fb3a3f807e1917f1f1585a4
parent 01ce8981
Loading
Loading
Loading
Loading
+31 −2
Original line number Diff line number Diff line
@@ -480,6 +480,10 @@ package android {
    field public static final int dashGap = 16843175; // 0x10101a7
    field public static final int dashWidth = 16843174; // 0x10101a6
    field public static final int data = 16842798; // 0x101002e
    field public static final int dataRetentionTime = 16844189; // 0x101059d
    field public static final int dataSentOffDevice = 16844186; // 0x101059a
    field public static final int dataSharedWithThirdParty = 16844187; // 0x101059b
    field public static final int dataUsedForMonetization = 16844188; // 0x101059c
    field public static final int datePickerDialogTheme = 16843948; // 0x10104ac
    field public static final int datePickerMode = 16843955; // 0x10104b3
    field public static final int datePickerStyle = 16843612; // 0x101035c
@@ -1496,6 +1500,7 @@ package android {
    field public static final deprecated int unfocusedMonthDateColor = 16843588; // 0x1010344
    field public static final int unselectedAlpha = 16843278; // 0x101020e
    field public static final int updatePeriodMillis = 16843344; // 0x1010250
    field public static final int usageInfoRequired = 16844185; // 0x1010599
    field public static final int use32bitAbi = 16844053; // 0x1010515
    field public static final int useAppZygote = 16844184; // 0x1010598
    field public static final int useDefaultMargins = 16843641; // 0x1010379
@@ -11168,8 +11173,8 @@ package android.content.pm {
    field public android.content.pm.ProviderInfo[] providers;
    field public android.content.pm.ActivityInfo[] receivers;
    field public android.content.pm.FeatureInfo[] reqFeatures;
    field public java.lang.String[] requestedPermissions;
    field public int[] requestedPermissionsFlags;
    field public deprecated java.lang.String[] requestedPermissions;
    field public deprecated int[] requestedPermissionsFlags;
    field public android.content.pm.ServiceInfo[] services;
    field public java.lang.String sharedUserId;
    field public int sharedUserLabel;
@@ -11177,6 +11182,7 @@ package android.content.pm {
    field public android.content.pm.SigningInfo signingInfo;
    field public java.lang.String[] splitNames;
    field public int[] splitRevisionCodes;
    field public android.content.pm.UsesPermissionInfo[] usesPermissions;
    field public deprecated int versionCode;
    field public java.lang.String versionName;
  }
@@ -11652,6 +11658,7 @@ package android.content.pm {
    field public java.lang.String group;
    field public java.lang.CharSequence nonLocalizedDescription;
    field public deprecated int protectionLevel;
    field public boolean usageInfoRequired;
  }
  public final class ProviderInfo extends android.content.pm.ComponentInfo implements android.os.Parcelable {
@@ -11831,6 +11838,28 @@ package android.content.pm {
    field public static final android.os.Parcelable.Creator<android.content.pm.SigningInfo> CREATOR;
  }
  public final class UsesPermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
    method public int describeContents();
    method public int getDataRetention();
    method public int getDataRetentionWeeks();
    method public int getDataSentOffDevice();
    method public int getDataSharedWithThirdParty();
    method public int getDataUsedForMonetization();
    method public int getFlags();
    method public java.lang.String getPermission();
    field public static final android.os.Parcelable.Creator<android.content.pm.UsesPermissionInfo> CREATOR;
    field public static final int FLAG_REQUESTED_PERMISSION_GRANTED = 2; // 0x2
    field public static final int RETENTION_NOT_RETAINED = 1; // 0x1
    field public static final int RETENTION_SPECIFIED = 4; // 0x4
    field public static final int RETENTION_UNDEFINED = 0; // 0x0
    field public static final int RETENTION_UNLIMITED = 3; // 0x3
    field public static final int RETENTION_USER_SELECTED = 2; // 0x2
    field public static final int USAGE_NO = 3; // 0x3
    field public static final int USAGE_UNDEFINED = 0; // 0x0
    field public static final int USAGE_USER_TRIGGERED = 2; // 0x2
    field public static final int USAGE_YES = 1; // 0x1
  }
  public final class VersionedPackage implements android.os.Parcelable {
    ctor public VersionedPackage(java.lang.String, int);
    ctor public VersionedPackage(java.lang.String, long);
+21 −0
Original line number Diff line number Diff line
@@ -22,6 +22,9 @@ import android.apex.ApexInfo;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.ArrayList;
import java.util.List;

/**
 * Overall information about the contents of a package.  This corresponds
 * to all of the information collected from AndroidManifest.xml.
@@ -204,7 +207,10 @@ public class PackageInfo implements Parcelable {
     * {@link PackageManager#GET_PERMISSIONS} was set.  This list includes
     * all permissions requested, even those that were not granted or known
     * by the system at install time.
     *
     * @deprecated Use {@link #usesPermissions}
     */
    @Deprecated
    public String[] requestedPermissions;

    /**
@@ -214,9 +220,22 @@ public class PackageInfo implements Parcelable {
     * {@link PackageManager#GET_PERMISSIONS} was set.  Each value matches
     * the corresponding entry in {@link #requestedPermissions}, and will have
     * the flag {@link #REQUESTED_PERMISSION_GRANTED} set as appropriate.
     *
     * @deprecated Use {@link #usesPermissions}
     */
    @Deprecated
    public int[] requestedPermissionsFlags;

    /**
     * Array of all {@link android.R.styleable#AndroidManifestUsesPermission
     * &lt;uses-permission&gt;} tags included under &lt;manifest&gt;,
     * or null if there were none.  This is only filled in if the flag
     * {@link PackageManager#GET_PERMISSIONS} was set.  This list includes
     * all permissions requested, even those that were not granted or known
     * by the system at install time.
     */
    public UsesPermissionInfo[] usesPermissions;

    /**
     * Flag for {@link #requestedPermissionsFlags}: the requested permission
     * is required for the application to run; the user can not optionally
@@ -456,6 +475,7 @@ public class PackageInfo implements Parcelable {
        dest.writeTypedArray(permissions, parcelableFlags);
        dest.writeStringArray(requestedPermissions);
        dest.writeIntArray(requestedPermissionsFlags);
        dest.writeTypedArray(usesPermissions, parcelableFlags);
        dest.writeTypedArray(signatures, parcelableFlags);
        dest.writeTypedArray(configPreferences, parcelableFlags);
        dest.writeTypedArray(reqFeatures, parcelableFlags);
@@ -520,6 +540,7 @@ public class PackageInfo implements Parcelable {
        permissions = source.createTypedArray(PermissionInfo.CREATOR);
        requestedPermissions = source.createStringArray();
        requestedPermissionsFlags = source.createIntArray();
        usesPermissions = source.createTypedArray(UsesPermissionInfo.CREATOR);
        signatures = source.createTypedArray(Signature.CREATOR);
        configPreferences = source.createTypedArray(ConfigurationInfo.CREATOR);
        reqFeatures = source.createTypedArray(FeatureInfo.CREATOR);
+77 −13
Original line number Diff line number Diff line
@@ -785,18 +785,23 @@ public class PackageParser {
                    pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
                }
            }
            N = p.requestedPermissions.size();
            N = p.usesPermissionInfos.size();
            if (N > 0) {
                pi.requestedPermissions = new String[N];
                pi.requestedPermissionsFlags = new int[N];
                pi.usesPermissions = new UsesPermissionInfo[N];
                for (int i=0; i<N; i++) {
                    final String perm = p.requestedPermissions.get(i);
                    UsesPermissionInfo info = p.usesPermissionInfos.get(i);
                    final String perm = info.getPermission();
                    pi.requestedPermissions[i] = perm;
                    int permissionFlags = 0;
                    // The notion of required permissions is deprecated but for compatibility.
                    pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
                    permissionFlags |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
                    if (grantedPermissions != null && grantedPermissions.contains(perm)) {
                        pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
                        permissionFlags |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
                    }
                    pi.requestedPermissionsFlags[i] = permissionFlags;
                    pi.usesPermissions[i] = new UsesPermissionInfo(info, permissionFlags);
                }
            }
        }
@@ -2114,12 +2119,12 @@ public class PackageParser {
                    return null;
                }
            } else if (tagName.equals(TAG_USES_PERMISSION)) {
                if (!parseUsesPermission(pkg, res, parser)) {
                if (!parseUsesPermission(pkg, res, parser, outError)) {
                    return null;
                }
            } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
                    || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
                if (!parseUsesPermission(pkg, res, parser)) {
                if (!parseUsesPermission(pkg, res, parser, outError)) {
                    return null;
                }
            } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
@@ -2442,7 +2447,7 @@ public class PackageParser {
                    newPermsMsg.append(' ');
                }
                newPermsMsg.append(npi.name);
                pkg.requestedPermissions.add(npi.name);
                addRequestedPermission(pkg, npi.name);
                pkg.implicitPermissions.add(npi.name);
            }
        }
@@ -2463,7 +2468,7 @@ public class PackageParser {
            for (int in = 0; in < newPerms.size(); in++) {
                final String perm = newPerms.get(in);
                if (!pkg.requestedPermissions.contains(perm)) {
                    pkg.requestedPermissions.add(perm);
                    addRequestedPermission(pkg, perm);
                    pkg.implicitPermissions.add(perm);
                }
            }
@@ -2543,13 +2548,13 @@ public class PackageParser {
            }
        } else {
            if (FORCE_AUDIO_PACKAGES.contains(pkg.packageName)) {
                pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_AUDIO);
                addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_AUDIO);
            }
            if (FORCE_VIDEO_PACKAGES.contains(pkg.packageName)) {
                pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_VIDEO);
                addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_VIDEO);
            }
            if (FORCE_IMAGES_PACKAGES.contains(pkg.packageName)) {
                pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_IMAGES);
                addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_IMAGES);
            }
        }

@@ -2588,6 +2593,14 @@ public class PackageParser {
        }
    }

    /**
     * Helper method for adding a requested permission to a package outside of a uses-permission.
     */
    private void addRequestedPermission(Package pkg, String permission) {
        pkg.requestedPermissions.add(permission);
        pkg.usesPermissionInfos.add(new UsesPermissionInfo(permission));
    }

    /**
     * Computes the targetSdkVersion to use at runtime. If the package is not
     * compatible with this platform, populates {@code outError[0]} with an
@@ -2845,8 +2858,8 @@ public class PackageParser {
        return certSha256Digests;
    }

    private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
            throws XmlPullParserException, IOException {
    private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser,
            String[] outError) throws XmlPullParserException, IOException {
        TypedArray sa = res.obtainAttributes(parser,
                com.android.internal.R.styleable.AndroidManifestUsesPermission);

@@ -2870,6 +2883,44 @@ public class PackageParser {
        final String requiredNotfeature = sa.getNonConfigurationString(
                com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);

        int dataSentOffDevice = sa.getInt(
                com.android.internal.R.styleable.AndroidManifestUsesPermission_dataSentOffDevice, 0);

        int dataSharedWithThirdParty = sa.getInt(
                com.android.internal.R.styleable.AndroidManifestUsesPermission_dataSharedWithThirdParty, 0);

        int dataUsedForMonetization = sa.getInt(
                com.android.internal.R.styleable.AndroidManifestUsesPermission_dataUsedForMonetization, 0);

        int retentionWeeks = -1;
        int retention;

        String rawRetention = sa.getString(
                com.android.internal.R.styleable.AndroidManifestUsesPermission_dataRetentionTime);

        if (rawRetention == null) {
            retention = UsesPermissionInfo.RETENTION_UNDEFINED;
        } else if ("notRetained".equals(rawRetention)) {
            retention = UsesPermissionInfo.RETENTION_NOT_RETAINED;
        } else if ("userSelected".equals(rawRetention)) {
            retention = UsesPermissionInfo.RETENTION_USER_SELECTED;
        } else if ("unlimited".equals(rawRetention)) {
            retention = UsesPermissionInfo.RETENTION_UNLIMITED;
        } else {
            // A number of weeks was specified
            retention = UsesPermissionInfo.RETENTION_SPECIFIED;
            retentionWeeks = sa.getInt(
                com.android.internal.R.styleable.AndroidManifestUsesPermission_dataRetentionTime,
                -1);

            if (retentionWeeks < 0) {
                outError[0] = "Bad value provided for dataRetentionTime.";
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                XmlUtils.skipCurrentTag(parser);
                sa.recycle();
                return false;
            }
        }
        sa.recycle();

        XmlUtils.skipCurrentTag(parser);
@@ -2902,6 +2953,10 @@ public class PackageParser {
                    + parser.getPositionDescription());
        }

        UsesPermissionInfo info = new UsesPermissionInfo(name, dataSentOffDevice,
                dataSharedWithThirdParty, dataUsedForMonetization, retention, retentionWeeks);
        pkg.usesPermissionInfos.add(info);

        return true;
    }

@@ -3236,6 +3291,10 @@ public class PackageParser {
        perm.info.flags = sa.getInt(
                com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);

        perm.info.usageInfoRequired = sa.getInt(
                com.android.internal.R.styleable.AndroidManifestPermission_usageInfoRequired, 0)
                != 0;

        sa.recycle();

        if (perm.info.protectionLevel == -1) {
@@ -6370,6 +6429,9 @@ public class PackageParser {
        @UnsupportedAppUsage
        public final ArrayList<String> requestedPermissions = new ArrayList<String>();

        public final ArrayList<UsesPermissionInfo> usesPermissionInfos =
                new ArrayList<>();

        /** Permissions requested but not in the manifest. */
        public final ArrayList<String> implicitPermissions = new ArrayList<>();

@@ -6900,6 +6962,7 @@ public class PackageParser {

            dest.readStringList(requestedPermissions);
            internStringArrayList(requestedPermissions);
            dest.readParcelableList(usesPermissionInfos, boot);
            dest.readStringList(implicitPermissions);
            internStringArrayList(implicitPermissions);
            protectedBroadcasts = dest.createStringArrayList();
@@ -7066,6 +7129,7 @@ public class PackageParser {
            dest.writeParcelableList(instrumentation, flags);

            dest.writeStringList(requestedPermissions);
            dest.writeParcelableList(usesPermissionInfos, flags);
            dest.writeStringList(implicitPermissions);
            dest.writeStringList(protectedBroadcasts);

+10 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -308,6 +309,12 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
     */
    public CharSequence nonLocalizedDescription;

    /**
     * If {@code true} an application targeting {@link Build.VERSION_CODES.Q} <em>must</em>
     * include permission data usage information in order to be able to be granted this permission.
     */
    public boolean usageInfoRequired;

    /** @hide */
    public static int fixProtectionLevel(int level) {
        if (level == PROTECTION_SIGNATURE_OR_SYSTEM) {
@@ -394,6 +401,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
        descriptionRes = orig.descriptionRes;
        requestRes = orig.requestRes;
        nonLocalizedDescription = orig.nonLocalizedDescription;
        usageInfoRequired = orig.usageInfoRequired;
    }

    /**
@@ -458,6 +466,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
        dest.writeInt(descriptionRes);
        dest.writeInt(requestRes);
        TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags);
        dest.writeInt(usageInfoRequired ? 1 : 0);
    }

    /** @hide */
@@ -498,5 +507,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
        descriptionRes = source.readInt();
        requestRes = source.readInt();
        nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
        usageInfoRequired = source.readInt() != 0;
    }
}
+274 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading