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

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

Support ephemeral permissions

Ephemeral permissions may be mixed in permission groups, avoid trying to
grant non-ephemeral group members and avoid showing a group for an
ephemeral app if all permissions of that group are not ephemeral

Test: Verified that runtime permissions work for ephemeral and that
groups which contain no ephemeral permissions are auto-rejected/not
displayed in settings.
Test: cts-tradefed run cts -m CtsPermission2TestCases
Test: Verified that permissions that cannot be granted are not shown in
the all permissions fragment.
Change-Id: I511689bc540a025e0e3ebdaf9c62e01764028a9f
parent adf735f3
Loading
Loading
Loading
Loading
+20 −3
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
    private final int mIconResId;

    private final boolean mAppSupportsRuntimePermissions;
    private final boolean mIsEphemeralApp;
    private boolean mContainsEphemeralPermission;

    public static AppPermissionGroup create(Context context, PackageInfo packageInfo,
            String permissionName) {
@@ -67,7 +69,8 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
            return null;
        }

        if (permissionInfo.protectionLevel != PermissionInfo.PROTECTION_DANGEROUS
        if ((permissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
                != PermissionInfo.PROTECTION_DANGEROUS
                || (permissionInfo.flags & PermissionInfo.FLAG_INSTALLED) == 0
                || (permissionInfo.flags & PermissionInfo.FLAG_REMOVED) != 0) {
            return null;
@@ -133,7 +136,8 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
            }

            // Collect only runtime permissions.
            if (requestedPermissionInfo.protectionLevel != PermissionInfo.PROTECTION_DANGEROUS) {
            if ((requestedPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
                    != PermissionInfo.PROTECTION_DANGEROUS) {
                continue;
            }

@@ -158,7 +162,7 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
                    requestedPermission, packageInfo.packageName, userHandle);

            Permission permission = new Permission(requestedPermission, granted,
                    appOp, appOpAllowed, flags);
                    appOp, appOpAllowed, flags, requestedPermissionInfo.protectionLevel);
            group.addPermission(permission);
        }

@@ -191,6 +195,7 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
        mPackageInfo = packageInfo;
        mAppSupportsRuntimePermissions = packageInfo.applicationInfo
                .targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1;
        mIsEphemeralApp = packageInfo.applicationInfo.isEphemeralApp();
        mAppOps = context.getSystemService(AppOpsManager.class);
        mActivityManager = context.getSystemService(ActivityManager.class);
        mDeclaringPackage = declaringPackage;
@@ -210,6 +215,10 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
        return mAppSupportsRuntimePermissions;
    }

    public boolean isGrantingAllowed() {
        return !mIsEphemeralApp || mContainsEphemeralPermission;
    }

    public boolean isReviewRequired() {
        if (mAppSupportsRuntimePermissions) {
            return false;
@@ -328,6 +337,11 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
                continue;
            }

            if (!permission.isGrantingAllowed(mIsEphemeralApp)) {
                // Skip unallowed permissions.
                continue;
            }

            if (mAppSupportsRuntimePermissions) {
                // Do not touch permissions fixed by the system.
                if (permission.isSystemFixed()) {
@@ -636,5 +650,8 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>

    private void addPermission(Permission permission) {
        mPermissions.put(permission.getName(), permission);
        if (permission.isEphemeral()) {
            mContainsEphemeralPermission = true;
        }
    }
}
+13 −2
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.packageinstaller.permission.model;

import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;

public final class Permission {
    private final String mName;
@@ -25,14 +26,16 @@ public final class Permission {
    private boolean mGranted;
    private boolean mAppOpAllowed;
    private int mFlags;
    private boolean mIsEphemeral;

    public Permission(String name, boolean granted,
            String appOp, boolean appOpAllowed, int flags) {
            String appOp, boolean appOpAllowed, int flags, int protectionLevel) {
        mName = name;
        mGranted = granted;
        mAppOp = appOp;
        mAppOpAllowed = appOpAllowed;
        mFlags = flags;
        mIsEphemeral = (protectionLevel & PermissionInfo.PROTECTION_FLAG_EPHEMERAL) != 0;
    }

    public String getName() {
@@ -130,4 +133,12 @@ public final class Permission {
    public void setAppOpAllowed(boolean mAppOpAllowed) {
        this.mAppOpAllowed = mAppOpAllowed;
    }

    public boolean isEphemeral() {
        return mIsEphemeral;
    }

    public boolean isGrantingAllowed(boolean isEphemeralApp) {
        return !isEphemeralApp || isEphemeral();
    }
}
+5 −3
Original line number Diff line number Diff line
@@ -177,7 +177,8 @@ public class PermissionApps {
                        continue;
                    }

                    if (requestedPermissionInfo.protectionLevel
                    if ((requestedPermissionInfo.protectionLevel
                                & PermissionInfo.PROTECTION_MASK_BASE)
                                    != PermissionInfo.PROTECTION_DANGEROUS
                            || (requestedPermissionInfo.flags
                                & PermissionInfo.FLAG_INSTALLED) == 0
@@ -267,7 +268,8 @@ public class PermissionApps {
        } catch (PackageManager.NameNotFoundException e) {
            try {
                PermissionInfo permInfo = mPm.getPermissionInfo(mGroupName, 0);
                if (permInfo.protectionLevel != PermissionInfo.PROTECTION_DANGEROUS) {
                if ((permInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
                        != PermissionInfo.PROTECTION_DANGEROUS) {
                    Log.w(LOG_TAG, mGroupName + " is not a runtime permission");
                    return;
                }
+4 −2
Original line number Diff line number Diff line
@@ -128,7 +128,8 @@ public final class PermissionGroups implements LoaderCallbacks<List<PermissionGr
                // Cache seen permissions and see if group has runtime permissions.
                for (PermissionInfo groupPermission : groupPermissions) {
                    seenPermissions.add(groupPermission.name);
                    if (groupPermission.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS
                    if ((groupPermission.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
                            == PermissionInfo.PROTECTION_DANGEROUS
                            && (groupPermission.flags & PermissionInfo.FLAG_INSTALLED) != 0
                            && (groupPermission.flags & PermissionInfo.FLAG_REMOVED) == 0) {
                        hasRuntimePermissions = true;
@@ -178,7 +179,8 @@ public final class PermissionGroups implements LoaderCallbacks<List<PermissionGr
                    }

                    // We care only about installed runtime permissions.
                    if (permissionInfo.protectionLevel != PermissionInfo.PROTECTION_DANGEROUS
                    if ((permissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
                            != PermissionInfo.PROTECTION_DANGEROUS
                            || (permissionInfo.flags & PermissionInfo.FLAG_INSTALLED) == 0) {
                        continue;
                    }
+8 −0
Original line number Diff line number Diff line
@@ -150,6 +150,10 @@ public class GrantPermissionsActivity extends OverlayTouchActivity
            if (group == null) {
                continue;
            }
            if (!group.isGrantingAllowed()) {
                // Skip showing groups that we know cannot be granted.
                continue;
            }
            // We allow the user to choose only non-fixed permissions. A permission
            // is fixed either by device policy or the user denying with prejudice.
            if (!group.isUserFixed() && !group.isPolicyFixed()) {
@@ -359,6 +363,10 @@ public class GrantPermissionsActivity extends OverlayTouchActivity
                    != PermissionInfo.PROTECTION_DANGEROUS) {
                return PERMISSION_DENIED;
            }
            if ((pInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_EPHEMERAL) == 0
                    && callingPackageInfo.applicationInfo.isEphemeralApp()) {
                return PERMISSION_DENIED;
            }
        } catch (NameNotFoundException e) {
            return PERMISSION_DENIED;
        }
Loading