一、问题发生的现象及日志打印

1.1 问题发生现象

  开机向导中增加蓝牙、WIFI及设置时区的权限后,adb push到手机里面,重启手机无法开机,卡到开机动画界面,无法进入开机向导。

1.2 Log打印分析

​  从日志看应该是应用本身是priv级别的app,并且申请了BLUETOOTH_PRIVILEGE、WRITE_SECURE_SETTINGS、INTERACT_ACROSS_USERS和SET_TIME_ZONE,但是没有在权限白名单中添加,所以导致类似日志打印,最终会导致system server重启,系统无法开机。

11-10 07:03:49.084  2392  2392 W PackageManager: Privileged permission android.permission.BLUETOOTH_PRIVILEGED for package com.dten.setupwiard - not in privapp-permissions whitelist
11-10 07:03:49.085  2392  2392 W PackageManager: Privileged permission android.permission.WRITE_SECURE_SETTINGS for package com.dten.setupwiard - not in privapp-permissions whitelist
11-10 07:03:49.085  2392  2392 W PackageManager: Privileged permission android.permission.INTERACT_ACROSS_USERS for package com.dten.setupwiard - not in privapp-permissions whitelist
11-10 07:03:49.085  2392  2392 W PackageManager: Privileged permission android.permission.SET_TIME_ZONE for package com.dten.setupwiard - not in privapp-permissions whitelist//  进而会有如下日志打印,导致system server进程重启
10 06:13:08.174  2645  2645 E System  : ******************************************
11-10 06:13:08.177  2645  2645 E System  : ************ Failure starting system services
11-10 06:13:08.177  2645  2645 E System  : java.lang.IllegalStateException: Signature|privileged permissions not in privapp-permissions whitelist: {com.dten.setupwiard: android.permission.WRITE_SECURE_SETTINGS, com.dten.setupwiard: android.permission.INTERACT_ACROSS_USER
S, com.dten.setupwiard: android.permission.BLUETOOTH_PRIVILEGED, com.dten.setupwiard: android.permission.SET_TIME_ZONE}
11-10 06:13:08.177  2645  2645 E System  :      at com.android.server.pm.permission.PermissionManagerService.systemReady(PermissionManagerService.java:2956)
11-10 06:13:08.177  2645  2645 E System  :      at com.android.server.pm.permission.PermissionManagerService.access$100(PermissionManagerService.java:122)
11-10 06:13:08.177  2645  2645 E System  :      at com.android.server.pm.permission.PermissionManagerService$PermissionManagerServiceInternalImpl.systemReady(PermissionManagerService.java:3017)
11-10 06:13:08.177  2645  2645 E System  :      at com.android.server.pm.PackageManagerService.systemReady(PackageManagerService.java:21902)
11-10 06:13:08.177  2645  2645 E System  :      at com.android.server.SystemServer.startOtherServices(SystemServer.java:2096)
11-10 06:13:08.177  2645  2645 E System  :      at com.android.server.SystemServer.run(SystemServer.java:539)
11-10 06:13:08.177  2645  2645 E System  :      at com.android.server.SystemServer.main(SystemServer.java:367)
11-10 06:13:08.177  2645  2645 E System  :      at java.lang.reflect.Method.invoke(Native Method)
11-10 06:13:08.177  2645  2645 E System  :      at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
11-10 06:13:08.177  2645  2645 E System  :      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1050)

二、代码逻辑分析

​  根据报错日志定位到代码逻辑是PermissionManagerService.java(frameworks\base\services\core\java\com\android\server\pm\permission)中的grantSignaturePermission()方法

private boolean grantSignaturePermission(String perm, PackageParser.Package pkg,         BasePermission bp, PermissionsState origPermissions) {.....//可以看到,如果该pkg对应的perm不在白名单中,则会下面加入过denied的列表中,导致下面的not in priv的日志打印if (!hasPrivappWhitelistEntry(perm, pkg)) {                                       // Only report violations for apps on system image                           if (!mSystemReady && !pkg.isUpdatedSystemApp()) {                             // it's only a reportable violation if the permission isn't explicitly denied          ArraySet<String> deniedPermissions = null;                               if (pkg.isVendor()) {                                                     deniedPermissions = SystemConfig.getInstance()                       .getVendorPrivAppDenyPermissions(pkg.packageName);           } else if (pkg.isProduct()) {                                             deniedPermissions = SystemConfig.getInstance()                       .getProductPrivAppDenyPermissions(pkg.packageName);           } else if (pkg.isProductServices()) {                                     deniedPermissions = SystemConfig.getInstance()                       .getProductServicesPrivAppDenyPermissions(pkg.packageName);   } else {                                                                 deniedPermissions = SystemConfig.getInstance()                       .getPrivAppDenyPermissions(pkg.packageName);                 }                                                                         final boolean permissionViolation =                                       deniedPermissions == null || !deniedPermissions.contains(perm);                if (permissionViolation) {                                               Slog.w(TAG, "Privileged permission " + perm + " for package "         + pkg.packageName + " - not in privapp-permissions whitelist");                                                                                 if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {         if (mPrivappPermissionsViolations == null) {                     mPrivappPermissionsViolations = new ArraySet<>();             }                                                                 mPrivappPermissionsViolations.add(pkg.packageName + ": " + perm); }                                                                     } else {                                                                 return false;                                                         }                                                                         }                                                                             if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {                return false;                                                             }                                                                             }                                                                                 }                                                                                     ......       }

由于上面条件,如果对应应用的perm不再权限白名单中,则会增加到deniedPermission中,后面在systemready中会抛出异常,导致system server进程重启。

 private void systemReady() {      mSystemReady = true;                                                                 if (mPrivappPermissionsViolations != null) {                                        throw new IllegalStateException("Signature|privileged permissions not in "               + "privapp-permissions whitelist: " + mPrivappPermissionsViolations);            }                                                                                                                                                             mPermissionControllerManager = mContext.getSystemService(PermissionControllerManager.class); mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class);        }

​ 所以问题的关键是hasPrivappWhitelistEntry方法,我们重点看下这个方法,该方法中如果是product下则权限白名单是从通过SystemConfig类中getProductPrivAppPermissions方法。

 private boolean hasPrivappWhitelistEntry(String perm, PackageParser.Package pkg) {       ArraySet<String> wlPermissions = null;....if (pkg.isProduct()) {                                                          wlPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg.packageName);  } ....// Let's check if this package is whitelisted...                                     boolean whitelisted = wlPermissions != null && wlPermissions.contains(perm);      // If it's not, we'll also tail-recurse to the parent.                               return whitelisted ||                                                               pkg.parentPackage != null && hasPrivappWhitelistEntry(perm, pkg.parentPackage);}

SystemConfig的getProductPrivAppPermissions方法很简单,只是返回mProductPrivAppPermissions 数据类型,是一个ArrayMap的数据结构,以应用包名为key,存储应用的priv-app 的权限白名单。

final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();

​ 到目前为止,逻辑就很简单了,重点看下mProductPrivAppPermissions是如何添加元素即可,根据代码逻辑,mProductPrivAppPermissions是通过系统在开机过程中读取/product/etc/permissions/ 、/vendor/etc/permissions/ 、/system/etc/permissions/ 下的xml文件所得。因此我们需要给开机向导应用增加对应的权限白名单。

三、解决方案思路

  根据第二块的代码分析,解决思路就比较清楚了,关键是给开机向导app增加权限白名单。

3.1 第一种尝试

  在privapp-permissions-platform.xml(frameworks/base/data/etc/)中增加如下代码,进行验证,adb push 到手机中进行验证,发现问题并没没有解决。

<permissions><privapp-permissions package="com.dten.setupwiard"><permission name="android.permission.SET_TIME_ZONE"/><permission name="android.permission.WRITE_SECURE_SETTINGS"/><permission name="android.permission.BLUETOOTH_PRIVILEGED"/><permission name="android.permission.INTERACT_ACROSS_USERS"/></privapp-permissions>
</permissions>

进一步分析代码,可以看到,不同目录下的应用对应的权限文件路径是不一样的,privapp-permissions-platform.xml文件被编译到/system/etc/permissions/下,所以只对/system/priv-app/下的应用有效果。而决定xml文件编译到那个路径下,是在frameworks/base/data/etc/Andoid.bp来决定的。

prebuilt_etc {                               name: "privapp-permissions-platform.xml",sub_dir: "permissions",                  src: "privapp-permissions-platform.xml",
}                                            prebuilt_etc {                                      name: "privapp_whitelist_com.android.settings", product_specific: true,                         sub_dir: "permissions",                         src: "com.android.settings.xml",                filename_from_src: true,
}

3.2 第二种尝试

  根据第一种尝试的分析,可以仿照com.dten.setting,我们创建一个com.dten.setupwiard.xml,并且在Android.bp中增加如下内容。

prebuilt_etc {                                     name: "privapp_whitelist_com.dten.setupwiard", product_specific: true,                        sub_dir: "permissions",                        src: "com.dten.setupwiard.xml",                filename_from_src: true,
}

如果觉得现在就ok了,可能会空欢喜一场,因为编译完,/product/etc/permissions/下面并没有生产com.dten.setupwiard.xml文件,根据android的编译规则,以及参考com.android.settings,应该是没有将其拷贝到out目录,所以需要在编译对应模块,比如编译com.dten.setupwiard的Android.mk文件中增加如下编译选项。

LOCAL_REQUIRED_MODULES := privapp_whitelist_com.dten.setupwiard

LOCAL_REQUIRED_MODULES的作用是当编译整个android 源码时,会将Mms模块在编译路径中依赖的module编译到out目录,并且打包,但是单独编译模块不会拷贝打包。

最后,编译完,烧录到设备中,可以成功开机。问题得到解决。

四、验证问题

​ 验证问题主要有两种方式:

  • 编译烧录版本进行验证,该方法比较耗时,但是相对准确,因为最终的方案还是需要编译到版本中验证
  • 快速替换验证,使用adb 命令进行快速验证,前提是userdebug版本,并且Android 10.0以后,必须是非system目录下的文件,因为system目录,没法remount

五、参考文献

  • https://zhuanlan.zhihu.com/p/147668734

Android 应用权限导致系统无法开机相关推荐

  1. 关于Android外设键盘导致系统输入法隐藏的解决方案

     关于Android外设键盘导致系统输入法隐藏的解决方案 Android系统发展到今天,如果你还认为它只是应用于手机的话,那你就out了.现在很多企业在通过Android系统来定制他们的相应的设备 ...

  2. Android系统的开机画面显示过程分析(13)

          WindowManagerService类的成员函数performEnableScreen的实现如下所示: public class WindowManagerService extend ...

  3. 【Android 逆向】Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )

    文章目录 一.Android 逆向中使用的 android.permission 权限 二.Android 系统中的 Linux 用户权限 一.Android 逆向中使用的 android.permi ...

  4. Android9获取权限闪退,Android 9.0 关于ACTION_CALL无权限导致闪退的问题

    Android 9.0 关于ACTION_CALL无权限导致闪退的问题 18年年底毕业,开始从事android研发,对application层有兴趣,于是自学使用Android studio对app的 ...

  5. android 9.0 系统添加开机铃声

    1.概述 在9.0的系统rom定制化开发中,在做一些项目中,有些产品需求要求添加开机铃声,就是在播放开机动画的过程中,播放开机音乐, 在原生系统中,是默认可以播放开机铃声的,接下来来分析下系统关于播放 ...

  6. 电脑计算机无法启动有还原和取消,win7系统提示配置windwos update失败还原更改导致电脑无法开机的三种解决方法...

    win7系统每个一段时间都需要更新,有时候win7旗舰版系统遇到更新失败无法开机进入系统,怎么办呢?而且弹出提示"配置windwos update 失败还原更改,请勿关闭计算机", ...

  7. 黑鲨android的开机密码,黑鲨研习win10系统删除开机密码的处理步骤

    随着电脑的使用率越来越高,我们有时候可能会遇到对win10系统删除开机密码的设置方法,想必大家都遇到过需要对win10系统删除开机密码进行设置的情况吧,那么应该怎么设置win10系统删除开机密码呢?我 ...

  8. AndroidUSB热敏打印机使用动态申请权限绕过系统权限对话框

    AndroidUSB热敏打印机使用动态申请权限绕过系统权限对话框 最近在做超市收银系统,需要使用热敏打印机打印小票,记录一下踩过的坑.公司使用的是佳维视智能收银机与芯烨XP-D610L热敏打印机. 在 ...

  9. android应用权限杂谈

    1 为什么Android总是事无巨细地告诉你应用索取的每一项权限? 相比Apple,Microsoft严格控制生态系统(从苹果给开发者的"App Store Guideline"可 ...

最新文章

  1. 使用合成数据集来做目标检测:目标检测的介绍
  2. python哪本好-在众多小说中,Python告诉你哪本小说好看
  3. Android开发之在Fragment和Activity页面拍照需要注意的地方
  4. 从零学web前端_从零到前端英雄(第1部分)
  5. oracle中sequence详解
  6. 『ORACLE』SPM(下)-baseline实验(11g)
  7. jeecg导出Excel
  8. 学习ubuntu之wget命令
  9. 1.3-----Simplify 3D切片软件简单设置
  10. 深度学习 简介 综述
  11. canvas画钟表demo
  12. 常用的做外链方法总结
  13. 海通股票交易接口查询当日成交c++源码分享
  14. 微信小程序用vant自定义tabbar页面并跳转相应页面
  15. 点击网页弹出窗口的js代码
  16. 千呼万唤始出来——uFUN开发板2.0开箱评测
  17. win10计算机睡眠 隔几分钟就唤醒,win10睡眠2秒后自动唤醒
  18. 雅思听力常见人名及地名(常考,必备)
  19. CSAPP Lab:attacklab
  20. Ali,Tencent遭反垄断罚款!巨头们的蛮长时代要结束了?

热门文章

  1. 用Python获取英雄联盟皮肤原画?走过路过不要错过
  2. python 九九乘法表 和 两种方法打印闪电标志
  3. faster rcnn接口_源码解析faster rcnn (mask rcnn)全过程
  4. 超市微信小程序怎么做_新手如何制作一个超市小程序?能发挥什么作用?
  5. YOLOv7自适应锚框计算
  6. android qq密码,怎么用手机改qq密码
  7. Oracle 9i迁移升级到Oracle 10g过程
  8. 比心APP的强势入场,游戏陪玩市场的风口到了?
  9. NCC restful接口笔记
  10. 关闭Win10自动更新工具