Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Do Ordinary Developers Try Out isPermissionRevokedByPolicy()?

API Level 23 added isPermissionRevokedByPolicy() on PackageManager. It is supposed to return false if a requested permission is blocked for a certain package "by policy":

Typically the device owner or the profile owner may apply such a policy.

Is there anything that a developer can do to cause isPermissionRevokedByPolicy() to return false for some package/permission combination, short of going through the whole Android for Work set of shenanigans?

like image 395
CommonsWare Avatar asked Dec 03 '15 22:12

CommonsWare


People also ask

What does revoke permissions mean?

Android 11 (and newer) can automatically remove permissions from “unused apps” to limit access to sensitive personal data, including location, camera, contacts, files, microphone, and phone.

What does Read_phone_state permission do?

Allows read only access to phone state, including the phone number of the device, current cellular network information, the status of any ongoing calls, and a list of any PhoneAccounts registered on the device. Used to determine the state of the mobile app. Jacob to provide additional details on exact functions.

How to check if permission is granted or not in Android?

checkSelfPermission(activity, Manifest. permission. X) checks if any permission is already granted, if you check out other answers they do the same, and rest of the code asks for the permissions not granted.


1 Answers

Of course, I might be wrong, but it looks like the short answer is "no, there's not", unfortunately.

A bit more extended answer: Here's the code of ApplicationPackageManager:

@Override
public boolean isPermissionRevokedByPolicy(String permName, String pkgName) {
    try {
        return mPM.isPermissionRevokedByPolicy(permName, pkgName, mContext.getUserId());
    } catch (RemoteException e) {
        throw new RuntimeException("Package manager has died", e);
    }
}

where mPM -

private final IPackageManager mPM;

It's being initialized in the constructor, which is called by ContextImpl.getPackageManager():

@Override
public PackageManager getPackageManager() {
    if (mPackageManager != null) {
        return mPackageManager;
    }

    IPackageManager pm = ActivityThread.getPackageManager();
    if (pm != null) {
        // Doesn't matter if we make more than one instance.
        return (mPackageManager = new ApplicationPackageManager(this, pm));
    }

    return null;
}

(source code)

Going deeper and looking into ActivityThread.getPackageManager():

public static IPackageManager getPackageManager() {
    if (sPackageManager != null) {
        //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
        return sPackageManager;
    }
    IBinder b = ServiceManager.getService("package");
    //Slog.v("PackageManager", "default service binder = " + b);
    sPackageManager = IPackageManager.Stub.asInterface(b);
    //Slog.v("PackageManager", "default service = " + sPackageManager);
    return sPackageManager;
}

(source code)

All these steps I was doing to find the actual implementation of isPermissionRevokedByPolicy btw. Then I had to find who extends IPackageManager.Stub - it's PackageManagerService (source code).

So here is the actual implementation:

@Override
public boolean isPermissionRevokedByPolicy(String permission, String packageName, int userId) {
    if (UserHandle.getCallingUserId() != userId) {
        mContext.enforceCallingPermission(
                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
                "isPermissionRevokedByPolicy for user " + userId);
    }
    if (checkPermission(permission, packageName, userId)
            == PackageManager.PERMISSION_GRANTED) {
        return false;
    }
    final long identity = Binder.clearCallingIdentity();
    try {
        final int flags = getPermissionFlags(permission, packageName, userId);
        return (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0;
    } finally {
        Binder.restoreCallingIdentity(identity);
    }
}

Potentially to "fake" the status of particular permission, you'd need to hack checkPermission and getPermissionFlags methods. The problem, I'm afraid, that there's no obvious way how to feed ApplicationPackageManager with overriden PackageManagerService, at least, without reflection.

like image 195
Konstantin Loginov Avatar answered Nov 14 '22 02:11

Konstantin Loginov