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?
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With