普通开发者如何试用isPermissionRevokedByPolicy()?

How Do Ordinary Developers Try Out isPermissionRevokedByPolicy()?

API 已添加 23 级 isPermissionRevokedByPolicy() on PackageManager。它应该 return false 如果某个包的请求权限被阻止 "by policy":

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

对于某些 package/permission 组合,开发人员可以做些什么来使 isPermissionRevokedByPolicy() 到 return false,而不是遍历整个 Android 对于恶作剧的工作集?

当然,我可能是错的,但不幸的是,看起来简短的答案是 "no, there's not"。

更详细的回答: 这是 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);
    }
}

其中 mPM -

private final IPackageManager mPM;

它正在构造函数中初始化,由 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)

深入研究 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)

我所做的所有这些步骤都是为了找到 isPermissionRevokedByPolicy 顺便说一句的实际实现。然后我必须找到谁扩展了 IPackageManager.Stub - 它是 PackageManagerService (source code).

所以这里是实际的实现:

@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);
    }
}

可能 "fake" 特定权限的状态,您需要修改 checkPermission 和 getPermissionFlags 方法。恐怕问题是,没有明显的方法可以为 ApplicationPackageManager 提供覆盖的 PackageManagerService,至少,没有反射。

我认为没有直接的方法。但是如果调用包的运行时 permissionstate 可以更改,那么 ispermissionrevokedbypolicy() 将 return 为 false。但我觉得这也是一个棘手的部分。