从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 booleanisCallingPackageAllowedToDrawOverlays(Context context, intuid,
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 booleanisCallingPackageAllowedToPerformAppOpsProtectedOperation(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 intcheckCallingOrSelfPermission(Stringpermission) {
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) 方法可以说是埋了个坑,一般不会有这个问题,如果有问题,就用上面的方法去处理。

[Android]从canDrawOverlays权限获取错误说起相关推荐

  1. Android M 动态权限获取

    新的权限获取方式除了要求像之前版本一样在AndroidManifest文件中静态申请之外,应用还需根据需要请求权限,方式采用向用户显示一个请求权限的对话框.这些被动态申请的权限可以在系统设置中被手动关 ...

  2. android临时root权限获取失败,安卓手机为何获取Root权限失败?分析手机Root失败的原因是什么?...

    如今,手机预装的APP应用程序实在太多,对于有系统纯净强迫症的用户来说,拿到手机第一件事就是折腾,通过Root或者刷机解决问题,那么我们在获取ROOT权限的时候可能会遇到失败,那么安卓手机为何获取Ro ...

  3. android电视root权限获取,电视盒子/ 智能电视如何通过ADB获取ROOT权限?

    如何通过adb获取root权限(安卓电视盒和智能电视通用)? Android 系统rom里面最主要的就3个文件:boot.img.system.img.userdata.img 其中boot.img ...

  4. android 如何 root权限获取,如何获取android手机root权限获取

    安卓手机的卡与不卡,和是否root无关. 安卓的卡,是其开发时就注定的,其原因如下: 1.内存小/少 手机内存在手机出厂的时候就已经固定了,其总量无法调整,不能像电脑一样加内存条.所以想提升可用内存, ...

  5. android的ROOT权限获取

    关于安卓2.3.6 ROOT的方法在网上搜索了很久,发现很多自己都没有成功ROOT.在这里和大家分享下自己使用移动叔叔ROOT工具ROOT 2.3.6的方法. (本人是安卓新手,很多地方还不太懂,有些 ...

  6. 东芝AC100 Android上网本Root权限获取

    因为需要安装一个便携AP功能的软件,所以需要先获取ROOT权限! ROOTing方法参见:tosh-ac100.wetpaint.com/page/Rooting 1: Instal z4root. ...

  7. android临时root权限获取失败,获取ROOT权限失败怎么办?

    Android手机Root失败原 今Android平台便ROOT 式键ROOT用户通发 者提供ROOT工具简单快捷实现 ROOT包括腾讯手 机关机.360手机助 手.卓师.刷机精灵卓师甜椒及移叔叔 R ...

  8. 【转】Android权限获取机制与常见权限不足问题分析

    转自:http://blog.csdn.net/linweig/article/details/6127488# Android系统是运行在Linux内核上的,Android与Linux分别有自己的一 ...

  9. Android 9.0模拟器root权限获取

    Android 9.0在获取权限时报如下错误 remount of the / superblock failed: Permission denied remount failed 解决方法为: 1 ...

最新文章

  1. sql server 表索引碎片处理
  2. [BZOJ 2425] 计数
  3. centos c++ 找不到头文件mysql.h
  4. java方法体逻辑不会写怎么办,想自己写框架?不会写Java注解可不行
  5. delimiters 插值 选项
  6. Sqoop1使用手册
  7. RedHat7安装Tomcat
  8. [转]使用debugger调试JavaScript脚本
  9. mybatisplus service insert 空指针_c++ 图解层序遍历和逐层打印智能指针建造的二叉树...
  10. mysql错误1215hy000_MySQL:错误1215(HY000):无法添加外键约束
  11. RS232 DB9 公头 母头 串口引脚定义
  12. x80hd装linux,台电X80HD:双系统切换的方法演示_台电 X80HD_平板电脑评测-中关村在线...
  13. 职称计算机2015年,2015年职称计算机考试题库最新版.doc
  14. win10截图截屏快捷键 截图截屏工具
  15. 液晶显示器常见、尺寸、分辨率、点距
  16. 计算机教研组活动简讯,思中信息技术组教研活动简报
  17. 中国前十软件公司招聘官网聚合
  18. 烽火ExMobi引领企业移动应用平台浪潮
  19. 6个开源项目提高GIS编程技能
  20. PHP配置连接MSSql数据库

热门文章

  1. 通过扫描二维码进入下载APP的流程
  2. hexo next主题去掉码市的Coding Pages等待页
  3. 【胡侃系列】基于多元回归模型的双十一购物狂欢节天猫商城销售额预测
  4. 白岩松:不平静,就不会幸福 幸福在哪里(代序)
  5. ucos 学习:STM32F107 学习板 资料收集
  6. STM32常用的开发工具有哪些?
  7. mac 重启 ssh 服务
  8. 帝国Empire采集-帝国如何免费采集
  9. 关于Flutter空安全的一些使用经验和理解
  10. C语言if语句教学计划,c语言教学计划.doc