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

Commit c15017f1 authored by Mohammad Samiul Islam's avatar Mohammad Samiul Islam
Browse files

Warn user when revoking split permissions unknown to app

Users did not get any warning message when revoking permission for
activity recognition. The issue can be generalized to any "install"
permission that has been split into a "runtime" permission at a
higher version than what the app is targeting.

Bug: 122468573
Test: manually tested
    - opened the permission settings of a test app on mobile
    - clicked on "deny" button for activity recognition permission
    - it showed old device warning
    - clicked on "deny" for access_background_location permission
    - it did not show old device warning

Change-Id: I4ced10b46d389d370ac5654999357a345c9ff2a0
parent 7c592e25
Loading
Loading
Loading
Loading
+62 −0
Original line number Diff line number Diff line
@@ -34,14 +34,17 @@ import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.UsesPermissionInfo;
import android.os.Build;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.permission.PermissionManager;
import android.provider.Settings;
import android.util.ArrayMap;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -69,6 +72,7 @@ import java.util.List;
 * #getBackgroundPermissions() background permissions group}.
 */
public final class AppPermissionGroup implements Comparable<AppPermissionGroup> {
    private static final String LOG_TAG = AppPermissionGroup.class.getSimpleName();
    private static final String PLATFORM_PACKAGE_NAME = "android";

    private static final String KILL_REASON_APP_OP_CHANGE = "Permission related app op changed";
@@ -1193,4 +1197,62 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
            mTriggerLocationAccessCheckOnPersist = false;
        }
    }

    /**
     * Check if permission group contains a runtime permission that split from an installed
     * permission and the split happened in an Android version higher than app's targetSdk.
     *
     * @return {@code true} if there is such permission, {@code false} otherwise
     */
    public boolean hasInstallToRuntimeSplit() {
        PermissionManager permissionManager =
                (PermissionManager) mContext.getSystemService(PermissionManager.class);

        int numSplitPerms = permissionManager.getSplitPermissions().size();
        for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
            PermissionManager.SplitPermissionInfo spi =
                    permissionManager.getSplitPermissions().get(splitPermNum);
            String splitPerm = spi.getSplitPermission();

            PermissionInfo pi;
            try {
                pi = mPackageManager.getPermissionInfo(splitPerm, 0);
            } catch (NameNotFoundException e) {
                Log.w(LOG_TAG, "No such permission: " + splitPerm, e);
                continue;
            }

            // Skip if split permission is not "install" permission.
            if (pi.getProtection() != pi.PROTECTION_NORMAL) {
                continue;
            }

            List<String> newPerms = spi.getNewPermissions();
            int numNewPerms = newPerms.size();
            for (int newPermNum = 0; newPermNum < numNewPerms; newPermNum++) {
                String newPerm = newPerms.get(newPermNum);

                if (!hasPermission(newPerm)) {
                    continue;
                }

                try {
                    pi = mPackageManager.getPermissionInfo(newPerm, 0);
                } catch (NameNotFoundException e) {
                    Log.w(LOG_TAG, "No such permission: " + newPerm, e);
                    continue;
                }

                // Skip if new permission is not "runtime" permission.
                if (pi.getProtection() != pi.PROTECTION_DANGEROUS) {
                    continue;
                }

                if (mPackageInfo.applicationInfo.targetSdkVersion < spi.getTargetSdk()) {
                    return true;
                }
            }
        }
        return false;
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -870,7 +870,8 @@ public class AppPermissionFragment extends SettingsWithButtonHeader {
                }
            }

            if ((requestToRevokeGrantedByDefault || !mGroup.doesSupportRuntimePermissions())
            if ((requestToRevokeGrantedByDefault || !mGroup.doesSupportRuntimePermissions()
                    || mGroup.hasInstallToRuntimeSplit())
                    && !mHasConfirmedRevoke) {
                showDefaultDenyDialog(changeTarget);
                updateButtons();