2

I'm trying to adapt my code for Android Marshmallow.

I wrote a function to check if a permission is revocable or not (PROTECTION_NORMAL and PROTECTION_SIGNATURE are granted upon install).

Running on API-22, Manifest.permission.READ_PHONE_STATE returns protectionLevel=PermissionInfo.PROTECTION_DANGEROUS, which is what I expected.

But on API-22, Manifest.permission.INSTALL_SHORTCUT also returns protectionLevel=PermissionInfo.PROTECTION_DANGEROUS, which is wrong from the documentation.

How does that happen? What's wrong with my code:

final PermissionInfo permissionInfo = packageManager.getPermissionInfo(permission, 0);
switch (permissionInfo.protectionLevel) {
    case PermissionInfo.PROTECTION_NORMAL:
    case PermissionInfo.PROTECTION_SIGNATURE:
        return false;
    default:
        return true;
}
shkschneider
  • 17,833
  • 13
  • 59
  • 112

1 Answers1

4

Manifest.permission.INSTALL_SHORTCUT also returns protectionLevel=PermissionInfo.PROTECTION_DANGEROUS

Not if you are using the code you show in your question. At best, your code is indicating if the protectionLevel is normal or signature and has no other bits set.

How does that happen?

protectionLevel is a bitmask. You are not comparing the bitmask properly.

int coreBits=info.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;

coreBits will be one of the core PROTECTION_ values. protectionLevel may not, as there may be higher-order bits set (e.g., PROTECTION_FLAG_PRE23). And, on Android 6.0, coreBits reports that INSTALL_SHORTCUT is a normal permission.

See this sample project for a demonstration of using PermissionInfo.PROTECTION_MASK_BASE.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Awesome answer. Did not catch that `protectionLevel` was a bitmask. Thanks for the reference code too https://github.com/commonsguy/cw-omnibus/blob/master/Permissions/PermissionReporter/app/src/main/java/com/commonsware/android/permreporter/MainActivity.java – shkschneider Aug 25 '15 at 12:18