[Android]从canDrawOverlays权限获取错误说起

从Settings.canDrawOverlays到Binder.getCallingPid

在调试程序的时候,发现一个奇怪的问题,在主线程调用Settings.canDrawOverlays判断是否有悬浮权限的结果和在另外一个service线程中调用Settings.canDrawOverlays的结果不一样,奇怪。

事出反常必有妖,我们去看看谁在作怪。

查看其定义

frameworks/base/core/java/android/provider/Settings.java

2225    public static boolean canDrawOverlays(Context context) {

2226        return Settings.isCallingPackageAllowedToDrawOverlays(context, Process.myUid(),

2227                context.getOpPackageName(), false);

2228    }

再调用

13247    public static boolean isCallingPackageAllowedToDrawOverlays(Context context, int uid,
13248            String callingPackage, boolean throwException) {
13249        return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid,
13250                callingPackage, throwException, AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
13251                PM_SYSTEM_ALERT_WINDOW, false);
13252    }

13277    public static boolean isCallingPackageAllowedToPerformAppOpsProtectedOperation(Context context,
13278            int uid, String callingPackage, boolean throwException, int appOpsOpCode, String[]
13279            permissions, boolean makeNote) {
13280        if (callingPackage == null) {
13281            return false;
13282        }
13283
13284        AppOpsManager appOpsMgr = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
13285        int mode = AppOpsManager.MODE_DEFAULT;
13286        if (makeNote) {
13287            mode = appOpsMgr.noteOpNoThrow(appOpsOpCode, uid, callingPackage);
13288        } else {
13289            mode = appOpsMgr.checkOpNoThrow(appOpsOpCode, uid, callingPackage);
13290        }
13291
13292        switch (mode) {
13293            case AppOpsManager.MODE_ALLOWED:
13294                return true;
13295
13296            case AppOpsManager.MODE_DEFAULT:
13297                // this is the default operating mode after an app's installation
13298                // In this case we will check all associated static permission to see
13299                // if it is granted during install time.
13300                for (String permission : permissions) {
13301                    if (context.checkCallingOrSelfPermission(permission) == PackageManager
13302                            .PERMISSION_GRANTED) {
13303                        // if either of the permissions are granted, we will allow it
13304                        return true;
13305                    }
13306                }
13307
13308            default:
13309                // this is for all other cases trickled down here...
13310                if (!throwException) {
13311                    return false;
13312                }
13313        }

添加log,发现是context.checkCallingOrSelfPermission(permission)

的结果在不同线程里不一样,

753    public int checkCallingOrSelfPermission(String permission) {
754        return mBase.checkCallingOrSelfPermission(permission);
755    }

1786    public int checkCallingOrSelfPermission(String permission) {
1787        if (permission == null) {
1788            throw new IllegalArgumentException("permission is null");
1789        }
1790
1791        return checkPermission(permission, Binder.getCallingPid(),
1792                Binder.getCallingUid());
1793    }

这里可以看到,使用了Binder.getCallingPid()Binder.getCallingUid()作为参数,在碰到的问题中,次线程是通过Binder调起的服务,所以其Binder.getCallingPid()和主线程不一样,是调用者进程的PID,就是这里的差异,导致了在同一个进程中,不同线程的调用结果不一样,

我们可以使用checkSelfPermission(“android.permission.SYSTEM_ALERT_WINDOW”)去判断权限,

或者使用Binder. clearCallingIdentity(); 把调用信息设置为当前进程后再调用Settings.canDrawOverlays方法。

回过头来看,不同线程的执行结果不一样,肯定是有线程差异在影响,我们应当对Binder的线程情况及Binder.getCallingPid有意识。对于Binder线程中权限的获取,我们都应当格外注意。

Settings.canDrawOverlays(context) 方法可以说是埋了个坑,一般不会有这个问题,如果有问题,就用上面的方法去处理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值