Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android checkCallingOrSelfPermission not returning properly

I am writing a service which needs to see if its caller holds a particular private permission. I do not want to prevent callers that lack this permission, I only want to know the status so that I can react accordingly. It would seem that the Context method checkCallingPermission() is perfect for what I need, returning 0 if the caller has the specified permission and -1 otherwise. I'm finding that -1 is returned in all cases though.

I wrote a test case (using the similar method checkCallingOrSelfPermission() where I pulled my package's PackageInfo from the system, enumerated each of my permissions (only one requested for the package), and display the result of checkCallingOrSelfPermission(). Since the permissions I'm checking against in this case are exactly the permissions I hold, I would expect checkCallingOrSelfPermission() to return 0 (PackageManager.PERMISSION_GRANTED) only... buy it only returns -1 (PackageManager.PERMISSION_DENIED).

I've checked this and received the same results on both a 4.0 emulator and a 2.3 device.

Any idea what I'm doing wrong to cause these calls to fail?

My test manifest includes:

<permission
    android:protectionLevel="signatureOrSystem"
    android:name="abcd" />
<uses-permission android:name="abcd" />

My test activity code is:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    PackageManager pm = getPackageManager();
    try {
        PackageInfo pi = pm.getPackageInfo("com.test.check", PackageManager.GET_PERMISSIONS);
        if ((null == pi.requestedPermissions) ||
            (pi.requestedPermissions.length == 0)) {
            Log.d("CHECK", "Package has NO permissions!");
            finish();
            return;
        }

        for (int i = 0; i < pi.requestedPermissions.length; ++i) {
            Log.d("CHECK", pi.requestedPermissions[i] + " " + checkCallingOrSelfPermission(pi.requestedPermissions[i]));
        }
    } catch (NameNotFoundException e) {
        Log.d("CHECK", "Package name is wrong!");
    }

    finish();
}

and my test results are:

D/CHECK   ( 3600): abcd -1
like image 892
mah Avatar asked Jul 10 '12 19:07

mah


1 Answers

I have not been able to resolve this within the scope of my service needing to check permissions, but I have found a work-around for the service (and a problem in my test case).

My test case failed because the permission I created and checked with, "abcd", was renamed by Android in the <permission> entry, however Android failed to equally rename it in the <uses-permission> entry. It was renamed to have my package name prepended to it (and this renaming does not occur if I provide a name including a period in it, such as "test.abcd").

Though changing the permission name fixed my test case, my actual case within a service was already using a fully qualified permission name and checkCallingPermission() continues to fail. I discovered, however, that the PackageManager's checkPermission() method does work as expected (at the expense of my needing to retrieve the name of the caller's package).

So to summarize, the following does not work correctly (though I do not know why):

boolean permission = (PackageManager.PERMISSION_GRANTED == checkCallingPermission(PERMISSION_NAME));

while this seems to work correctly:

PackageManager pm = getPackageManager();
boolean permission = (PackageManager.PERMISSION_GRANTED == pm.checkPermission(PERMISSION_NAME, pm.getNameForUid(getCallingUid())));
like image 57
mah Avatar answered Nov 15 '22 23:11

mah