赞
踩
##################################################
目录
外部存储器 /storage/emulated/用户_UID 家目录
利用 dumpsys package 从指定应用信息中获取 userid 和 gids
CM311-1A 盒子 Android 9 所有已知的权限组
联系人权限组 android.permission-group.CONTACTS
电话权限组 android.permission-group.PHONE
日历权限组 android.permission-group.CALENDAR
通话记录权限组 android.permission-group.CALL_LOG
相机权限组 android.permission-group.CAMERA
身体传感器权限组 android.permission-group.SENSORS
位置信息权限组 android.permission-group.LOCATION
存储空间权限组 android.permission-group.STORAGE
系统控制权限组 androidlogic.permission-group.SYSTEM_CONTROL
麦克风权限组 android.permission-group.MICROPHONE
短信权限组 android.permission-group.SMS
CM311-1A 盒子和手机设备都没有看到 WIFI 网络相关的权限
第一层 —— 开发层 AndroidManifest.xml
CM311-1A 的 platform.xml 配置文件详解
##################################################
——————————
%%%%%
- cmcc_jiangsu:/ # pm list users
- Users:
- UserInfo{0:机主:13} running
- cmcc_jiangsu:/ #
%%%%%
- cmcc_jiangsu:/ # whoami
- root
- cmcc_jiangsu:/ #
——————————
非常注意:
多用户的创建、启动、停止等行为是系统级的
因此只有具有 root、system 权限的进程才能操作
%%%%%
语法如下:
pm create-user 用户名
然后发现盒子竟然也不能创建用户!!!
- cmcc_jiangsu:/ # pm create-user "user_1"
- Error: couldn't create User.
- 1|cmcc_jiangsu:/ #
无奈只好换上旧手机:
- C:\Users\byme>adb devices /* USB 插上之后查看连接状态 */
- List of devices attached
- 8OOXXOOXXxxooxxF device
-
-
- C:\Users\byme>adb root /* 看来无法获得 root 权限 */
- adbd cannot run as root in production builds
-
- C:\Users\byme>adb shell
- shell@GIONEE_G1605A:/ $ pm list users /* 查看用户列表 */
- Users:
- UserInfo{0:机主:13} running
- shell@GIONEE_G1605A:/ $ whoami /* 查看登陆账户 */
- shell
- shell@GIONEE_G1605A:/ $ pm create-user "ranchui" /* 创建用户燃吹 */
- Success: created user id 10
- 1|shell@GIONEE_G1605A:/ $ pm list users /* 用户 UID 是 10 */
- Users:
- UserInfo{0:机主:13} running
- UserInfo{10:ranchui:0}
- shell@GIONEE_G1605A:/ $
如果之前创建多了也没关系 删除多余的用户之后重启手机 UID 就会重新计算:
- shell@GIONEE_G1605A:/ $ pm create-user "user"
- Success: created user id 10
- 1|shell@GIONEE_G1605A:/ $ pm list users
- Users:
- UserInfo{0:机主:13} running
- UserInfo{10:user:0}
- shell@GIONEE_G1605A:/ $
——————————
%%%%%
启动和切换用户语法如下:
- am start-user USER_ID /* 启用一个账户 */
- am switch-user USER_ID /* 切换到指定账户 */
启动指定用户:
- shell@GIONEE_G1605A:/ $ pm list users /* 当前 ranchui 未上线 */
- Users:
- UserInfo{0:机主:13} running
- UserInfo{10:ranchui:0}
- shell@GIONEE_G1605A:/ $ am start-user 10 /* 根据 UID 启用用户 ranchui */
- Success: user started
- shell@GIONEE_G1605A:/ $ pm list users /* 用户 ranchui 已经在线 */
- Users:
- UserInfo{0:机主:13} running
- UserInfo{10:ranchui:10} running
- shell@GIONEE_G1605A:/ $
切换成指定用户:
- shell@GIONEE_G1605A:/ $ am switch-user 10 /* 切换成 ranchui 用户 */
- shell@GIONEE_G1605A:/ $
正在切换用户:
然后就发现无法调试了:
- shell@GIONEE_G1605A:/ $ /* 这边莫名退出去了 */
- C:\Users\byme>adb shell /* 查看连接还在 但是不支持调试 */
- adb.exe: device unauthorized.
- This adb server's $ADB_VENDOR_KEYS is not set
- Try 'adb kill-server' if that seems wrong.
- Otherwise check for a confirmation dialog on your device.
- C:\Users\byme>adb kill-server /* 关掉一次 adb */
- C:\Users\byme>adb devices /* 发现不是 device 是个未经授权的 unauthorized */
- * daemon not running; starting now at tcp:5037
- * daemon started successfully
- List of devices attached
- 8ooxxOOOXXXooxxF unauthorized
- C:\Users\byme>
然后手机竟然开始首次登陆配置:
这个新建立的用户确确实实不允许 USB 调试:
无奈 只好重启手机之后默认登陆主账户再次开启调试功能:
- C:\Users\byme>adb devices /* 此时还未授权 */
- List of devices attached
- 8ooxxOOOXXXooxxF unauthorized
-
-
- C:\Users\byme>adb devices /* 授权过后 */
- List of devices attached
- 8ooxxOOOXXXooxxF device
-
-
- C:\Users\byme>
——————————
%%%%%
语法如下:
pm remove-user USER_ID
示例删除刚刚创建的 ranchui 用户:
- C:\Users\byme>adb shell
- shell@GIONEE_G1605A:/ $ pm list users /* 查看用户列表 */
- Users:
- UserInfo{0:机主:13} running
- UserInfo{10:ranchui:10}
- shell@GIONEE_G1605A:/ $ pm remove-user 10 /* 根据 UID 删除用户 */
- Success: removed user
- shell@GIONEE_G1605A:/ $ pm list users /* 再次查看用户列表 */
- Users:
- UserInfo{0:机主:13} running
- shell@GIONEE_G1605A:/ $ am start-user 10 /* 因为没有该账户所以报错 */
- Error: could not start user
- shell@GIONEE_G1605A:/ $ am switch-user 10 /* 没有该账户所以屏幕也没切换过去 */
- shell@GIONEE_G1605A:/ $
##################################################
——————————
Android 4.0 开始 Google 就开始在 Android 上布局多用户
UserManager 由此诞生 然而此时尚未对应的 Binder 服务 真正支持多用户是从 Android 4.2 开始
即使如此系统中也依然存在各类 Bug 和兼容性问题
直到 Android 6.0 多用户才比较完善
国内外的厂家也纷纷开始针对多用户这个噱头来作各类 花里胡哨 的操作
手机分身
分身应用
应用双开
等等等等 不得不说 国内的厂家在多用户这方面定制化到现在已经很是稳定和完善了
——————————
对于 Android 中的每一个进程都有一个单独的 uid、gid 以及 gids 集合
经过这三者 Android 系统实现了一套文件和数据访问权限规则系统
例如 访问某个文件 文件系统规定了该文件在磁盘中的 rwx 权限
%%%%%
UID 是用户 id
在 Linux 上一个用户 uid 标识着一个给定的用户 而 Android 上也沿用了 Linux 用户的概念
root 用户 uid 为 0
system Uid 为 1000
- Android 在创建每个用户时 都会分配一个整型的 userId
- 对于主用户 就是正常下的默认用户 来说 userId 为 0
- 之后创建的 userId 将从 10 开始计算 每增加一个用户 userId 就会加 1
而且每一个应用程序在安装时也被赋予了单独的 uid
这个 uid 将伴随着应用从安装到卸载包括缓存
%%%%%
GID 是用户组 id
Linux 上规定每一个应用都应该有一个用户组
对于 Android 应用程序来讲每一个应用的所属用户组与 uid 相同
%%%%%
GIDS 是应用在安装后所得到权限的 id 集合
在 Android 上每一个权限均可能对应一个或多个 group 而每一个 group 都有一个 gid name
所以 gids 就是经过对每一个 gid name 计算得出的 id 集合
一个 uid 能够关联 gids 代表该 uid 拥有多种权限
%%%%%
获取 system_server 的 PID 然后根据这个 PID 查看 UID/GID/Groups :
- cmcc_jiangsu:/ # ps -A | grep system_server /* 得到 PID 为 3620 */
- system 3620 2604 1386312 181192 SyS_epoll_wait 0 S system_server
- cmcc_jiangsu:/ # cat /proc/3620/status /* 查看该进程的 status */
- Name: system_server
- Umask: 0077
- State: S (sleeping)
- Tgid: 3620
- Ngid: 0
- Pid: 3620
- PPid: 2604
- TracerPid: 0
- Uid: 1000 1000 1000 1000
- Gid: 1000 1000 1000 1000
- FDSize: 512
- Groups: 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1018 1021 1023 1024 10
- 32 1065 3001 3002 3003 3006 3007 3009 3010
- VmPeak: 1419816 kB
- VmSize: 1386312 kB
- VmLck: 0 kB
- VmPin: 0 kB
- VmHWM: 206464 kB
- VmRSS: 181088 kB
- RssAnon: 15028 kB
- RssFile: 165708 kB
- RssShmem: 352 kB
- VmData: 1018244 kB
- VmStk: 8192 kB
- VmExe: 24 kB
- VmLib: 80572 kB
- VmPTE: 524 kB
- VmPMD: 0 kB
- VmSwap: 0 kB
- Threads: 97
- SigQ: 0/10948
- SigPnd: 0000000000000000
- ShdPnd: 0000000000000000
- SigBlk: 0000000000001204
- SigIgn: 0000000000000001
- SigCgt: 00000006400084f8
- CapInh: 0000001806897c20
- CapPrm: 0000001806897c20
- CapEff: 0000001806897c20
- CapBnd: 0000000000000000
- CapAmb: 0000000000000000
- Seccomp: 0
- Speculation_Store_Bypass: unknown
- Cpus_allowed: f
- Cpus_allowed_list: 0-3
- Mems_allowed: 1
- Mems_allowed_list: 0
- voluntary_ctxt_switches: 2526
- nonvoluntary_ctxt_switches: 1818
- cmcc_jiangsu:/ #
——————————
在 Android 中应用的 uid 是和当前的用户有关的
同一个应用具有相同的 appId
其 uid 的计算方式为:
appUid = userId * 1000000 + appId
在主用户中 uid 就等于 appId
——————————
为了多用户下的数据安全性
在每个新用户创建之初不管是 外部存储器/External Storage 还是 app data 目录
Android 都为其准备了独立的文件存储
新用户创建时 Android 在
/storage/emulated
/data/user
目录下为每个用户都创建了名为用户 id 的家目录
%%%%%
目录 /storage/emulated/ 下拥有不同的用户分区
当我们在代码中使用
Environment.getExternalStorageDirectory().absolutePath
获取外部存储路径时返回的就是当前用户下的对应目录
例如 userId = 11 则返回为
/storage/emulated/11
多用户下的 /storage 分区有不同的用户家目录
可以看出常用的 /sdcard 目录其实最终也是软链到了 /storage/emulated/0 目录:
- cmcc_jiangsu:/ # ls -l /storage/emulated/
- total 8
- drwxrwx--x 32 root sdcard_rw 4096 2022-07-25 11:35 0
- drwxrwx--x 2 root sdcard_rw 4096 2015-01-01 08:00 obb
- cmcc_jiangsu:/ # ls -l /sdcard
- lrwxrwxrwx 1 root root 21 1970-01-01 08:00 /sdcard -> /storage/self/primary
- cmcc_jiangsu:/ # ls -l /storage/self/primary
- lrwxrwxrwx 1 root root 19 2015-01-01 08:00 /storage/self/primary -> /mnt/user/0/primary
- cmcc_jiangsu:/ # ls -l /mnt/user/0/primary
- lrwxrwxrwx 1 root reserved_disk 19 2015-01-01 08:00 /mnt/user/0/primary -> /storage/emulated/0
- cmcc_jiangsu:/ #
%%%%%
多用户下的 /data 分区也有不同用户的家目录
也是以用户 UID 命名
与 External Storage/外部存储器 相同
新用户创建时 Android 也会在 /data/user 目录下创建名为 userId 的目录
用于存储该用户中所有 App 的隐私数据
如果在代码中使用 Context.getFilesDir() 来获取应用的 data 目录不同 User 下也会有不同
也可以看出来平常说到的 /data/data 目录其实也是软链到了 /data/user/0
- cmcc_jiangsu:/ # ls /data/user -alh
- total 6.0K
- drwx--x--x 2 system system 4.0K 2015-01-01 08:00 .
- drwxrwx--x 40 system system 4.0K 2015-01-01 08:00 ..
- lrwxrwxrwx 1 root root 10 2015-01-01 08:00 0 -> /data/data
- cmcc_jiangsu:/ # ls -l /data/user/0/
- android.ext.services/ com.android.sharedstoragebackup/
- android.ext.shared/ com.android.shell/
- android/ com.android.statementservice/
- com.android.backupconfirm/ com.android.superuser/
- com.android.bluetooth/ com.android.systemui/
- com.android.certinstaller/ com.android.vpndialogs/
- com.android.companiondevicemanager/ com.android.webview/
- com.android.defcontainer/ com.cmcc.mid.softdetector/
- com.android.externalstorage/ com.dangbei.tvlauncher/
- com.android.inputdevices/ com.dangbeimarket/
- com.android.inputmethod.latin/ com.droidlogic.BluetoothRemote/
- com.android.keychain/ com.droidlogic.inputmethod.remote/
- com.android.location.fused/ com.droidlogic/
- com.android.managedprovisioning/ com.fengyun.live/
- com.android.packageinstaller/ com.iflytek.bt.auto/
- com.android.pacprocessor/ com.iflytek.xiri/
- com.android.providers.downloads/ com.iflytek.xiri2.system/
- com.android.providers.media/ com.mylejia.store/
- com.android.providers.settings/ com.tv.kuaisou/
- com.android.proxyhandler/ com.xiaodianshi.tv.yst/
- com.android.se/ jackpal.androidterm/
- com.android.settings/ me.thomastv.rebootupdate/
- cmcc_jiangsu:/ # ls -lh /data/user/0/com.android.shell/
- total 4.0K
- drwxrws--x 2 shell shell 4.0K 2015-01-01 08:00 cache
- drwxrws--x 2 shell shell 4.0K 2015-01-01 08:00 code_cache
- cmcc_jiangsu:/ #
——————————
%%%%%
多用户其实是系统为应用的 data 目录和 storage 目录分配了一份不同且独立的存储空间
不同用户下的存储空间互不影响且没有权限访问
/storage 目录不可以跨用户访问
例如用户 10 的 app 是无法访问 /storage/emulated/0 下的文件的
是不可以互相访问的
同时系统中的 AMS、PMS、WMS 等各大服务都会针对 userId/UserHandle 进行多用户适配
并在用户启动、切换、停止、删除等生命周期时做出相应策略的改变
%%%%%
多用户的创建流程主要在
UserManagerService.createUserInternalUnchecked()
函数中完成
用户创建的过程主要是应用运行环境例如文件系统、权限等的准备过程
主要可以分为六个步骤
第一步 为新用户创建一个新的 userId
新用户的 userId 从 10 开始递增
第二步 固化新用户信息和创建状态
构造包含新用户信息的 UserData 并固化到 /data/system/users/${userId}.xml 中:
- cmcc_jiangsu:/ # cat /data/system/users/0.xml
- <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
- <user id="0" serialNumber="0" flags="19" created="0" lastLoggedIn="1420070414617
- " lastLoggedInFingerprint="CM311-1a-YST/CM311-1a-YST/CM311-1a-YST:9/PPR1.180610.
- 011/V.955.05:userdebug/test-keys" profileBadge="0">
- <restrictions />
- </user>
- cmcc_jiangsu:/ #
将新创建新 userId 固化到 /data/system/users/userlist.xml 中:
- cmcc_jiangsu:/ # cat /data/system/users/userlist.xml
- <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
- <users nextSerialNumber="10" version="7">
- <guestRestrictions>
- <restrictions no_sms="true" no_install_unknown_sources="true" no_config_
- wifi="true" no_outgoing_calls="true" />
- </guestRestrictions>
- <deviceOwnerUserId id="-10000" />
- <user id="0" />
- </users>
- cmcc_jiangsu:/ #
第三步 准备文件系统
通过 vold 这个 Android 存储守护进程为新用户进行文件系统加密
创建 /data/system/users/${userId} 并设置 0700 权限
- cmcc_jiangsu:/ # ls -alh /data/system/users/
- total 10K
- drwxrwxr-x 3 system system 4.0K 2015-01-01 08:00 .
- drwxrwxr-x 19 system system 4.0K 2022-07-27 19:29 ..
- drwx------ 2 system system 4.0K 2022-07-27 19:20 0
- -rw------- 1 system system 298 2015-01-01 08:00 0.xml
- -rw------- 1 system system 335 2015-01-01 08:00 userlist.xml
- cmcc_jiangsu:/ #
创建 /data/misc/users/${userId} 并设置 0750 权限
- cmcc_jiangsu:/ # ls /data/misc/user/ -alh
- total 6.0K
- drwxrwx--x 3 root root 4.0K 2015-01-01 08:00 .
- drwxrwx--t 43 system misc 4.0K 2015-01-01 08:00 ..
- drwxr-x--- 2 system everybody 4.0K 2015-01-01 08:00 0
- cmcc_jiangsu:/ #
第四步 为已安装应用准备数据目录并记录其组件和默认权限配置
在 /data/user/${userId}/ 下创建各个已安装应用的 package 目录
- cmcc_jiangsu:/ # ls /data/user/0/
- android com.android.sharedstoragebackup
- android.ext.services com.android.shell
- android.ext.shared com.android.statementservice
- com.android.backupconfirm com.android.superuser
- com.android.bluetooth com.android.systemui
- com.android.certinstaller com.android.vpndialogs
- com.android.companiondevicemanager com.android.webview
- com.android.defcontainer com.cmcc.mid.softdetector
- com.android.externalstorage com.dangbei.tvlauncher
- com.android.inputdevices com.dangbeimarket
- com.android.inputmethod.latin com.droidlogic
- com.android.keychain com.droidlogic.BluetoothRemote
- com.android.location.fused com.droidlogic.inputmethod.remote
- com.android.managedprovisioning com.fengyun.live
- com.android.packageinstaller com.iflytek.bt.auto
- com.android.pacprocessor com.iflytek.xiri
- com.android.providers.downloads com.iflytek.xiri2.system
- com.android.providers.media com.mylejia.store
- com.android.providers.settings com.tv.kuaisou
- com.android.proxyhandler com.xiaodianshi.tv.yst
- com.android.se jackpal.androidterm
- com.android.settings me.thomastv.rebootupdate
- cmcc_jiangsu:/ #
在 /data/system/users/${userId}/package-restrictions.xml 中写入非默认启动组件的信息
- cmcc_jiangsu:/ # cat /data/system/users/0/package-restrictions.xml
- <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
- <package-restrictions>
- <pkg name="com.iflytek.xiri" ceDataInode="-4294967186" />
- <pkg name="com.droidlogic.inputmethod.remote" ceDataInode="-4294967182" />
- <pkg name="com.xiaodianshi.tv.yst" ceDataInode="-4294966764" />
- <pkg name="com.android.providers.media" ceDataInode="-4294967179" />
- <pkg name="com.mylejia.store" ceDataInode="-4294966914" stopped="true" nl="t
- rue" />
- <pkg name="com.android.externalstorage" ceDataInode="-4294967176" />
- <pkg name="com.android.companiondevicemanager" ceDataInode="-4294967173" />
- <pkg name="com.android.providers.downloads" ceDataInode="-4294967170" />
- <pkg name="com.fengyun.live" ceDataInode="-4294966943" stopped="true" nl="tr
- ue" />
- <pkg name="com.droidlogic" ceDataInode="-4294967167" />
- <pkg name="com.dangbei.tvlauncher" ceDataInode="-4294967163" />
- <pkg name="com.android.defcontainer" ceDataInode="-4294967266" />
- <pkg name="com.android.pacprocessor" ceDataInode="-4294967160" />
- <pkg name="com.android.certinstaller" ceDataInode="-4294967156" />
- <pkg name="me.thomastv.rebootupdate" ceDataInode="-4294966923" />
- <pkg name="android" ceDataInode="-4294967258" />
- <pkg name="com.android.backupconfirm" ceDataInode="-4294967153" />
- <pkg name="com.android.statementservice" ceDataInode="-4294967150" />
- <pkg name="com.android.superuser" ceDataInode="-4294967147" />
- <pkg name="com.android.providers.settings" ceDataInode="-4294967250" />
- <pkg name="com.android.sharedstoragebackup" ceDataInode="-4294967144" />
- <pkg name="com.iflytek.xiri2.system" ceDataInode="-4294967141" />
- <pkg name="com.android.webview" ceDataInode="-4294967137" enabled="1" />
- <pkg name="com.android.se" ceDataInode="-4294967133" />
- <pkg name="com.android.inputdevices" ceDataInode="-4294967242" />
- <pkg name="com.droidlogic.BluetoothRemote" ceDataInode="-4294967128" />
- <pkg name="android.ext.shared" ceDataInode="-4294967235" />
- <pkg name="com.android.keychain" ceDataInode="-4294967123" />
- <pkg name="android.ext.services" ceDataInode="-4294967229" />
- <pkg name="com.android.packageinstaller" ceDataInode="-4294967223" />
- <pkg name="com.android.proxyhandler" ceDataInode="-4294967217" />
- <pkg name="com.android.inputmethod.latin" ceDataInode="-4294967210">
- <disabled-components>
- <item name="com.android.inputmethod.latin.setup.SetupActivity" />
- </disabled-components>
- </pkg>
- <pkg name="com.android.managedprovisioning" ceDataInode="-4294967118" />
- <pkg name="jackpal.androidterm" ceDataInode="-4294966708" />
- <pkg name="com.iflytek.bt.auto" ceDataInode="-4294967115" />
- <pkg name="com.android.settings" ceDataInode="-4294967112" />
- <pkg name="com.android.vpndialogs" ceDataInode="-4294967108" />
- <pkg name="com.android.shell" ceDataInode="-4294967203" />
- <pkg name="com.dangbeimarket" ceDataInode="-4294966928" />
- <pkg name="com.android.location.fused" ceDataInode="-4294967196" />
- <pkg name="com.android.systemui" ceDataInode="-4294967189">
- <disabled-components>
- <item name="com.android.systemui.tuner.TunerActivity" />
- </disabled-components>
- </pkg>
- <pkg name="com.tv.kuaisou" ceDataInode="-4294966800" stopped="true" nl="true
- " />
- <pkg name="com.android.bluetooth" ceDataInode="-4294967104" enabled="1" />
- <pkg name="com.cmcc.mid.softdetector" ceDataInode="-4294967100" />
- <preferred-activities />
- <persistent-preferred-activities />
- <crossProfile-intent-filters />
- <default-apps />
- </package-restrictions>
- cmcc_jiangsu:/ #
更新 /data/system/packages.list 文件主要是最后一串 gids 可能会改变
- cmcc_jiangsu:/ # cat /data/system/packages.list
- com.iflytek.xiri 10021 0 /data/user/0/com.iflytek.xiri default:targetSdkVersion=19 3002,3003,3001
- com.droidlogic.inputmethod.remote 10022 0 /data/user/0/com.droidlogic.inputmethod.remote default:targetSdkVersion=28 none
- com.xiaodianshi.tv.yst 10032 0 /data/user_de/0/com.xiaodianshi.tv.yst default:targetSdkVersion=26 3003
- com.android.providers.media 10002 0 /data/user/0/com.android.providers.media media:privapp:targetSdkVersion=28 2001,1065,1023,1015,3003,3007,1024
- com.mylejia.store 10026 0 /data/user_de/0/com.mylejia.store default:targetSdkVersion=24 3003,1007
- com.android.externalstorage 10004 0 /data/user/0/com.android.externalstorage platform:privapp:targetSdkVersion=28 1023,1015
- com.android.companiondevicemanager 10012 0 /data/user/0/com.android.companiondevicemanager default:targetSdkVersion=28 3002,3001
- com.android.providers.downloads 10002 0 /data/user/0/com.android.providers.downloads media:privapp:targetSdkVersion=28 2001,1065,1023,1015,3003,3007,1024
- com.fengyun.live 10027 0 /data/user_de/0/com.fengyun.live default:targetSdkVersion=24 3003
- com.droidlogic 1000 0 /data/user/0/com.droidlogic platform:privapp:targetSdkVersion=28 1065,3002,1023,1015,3003,3001,1007
- com.dangbei.tvlauncher 10016 0 /data/user/0/com.dangbei.tvlauncher default:targetSdkVersion=22 3002,3003,3001
- com.android.defcontainer 10000 0 /data/user_de/0/com.android.defcontainer platform:privapp:targetSdkVersion=28 2001
- com.android.pacprocessor 10017 0 /data/user/0/com.android.pacprocessor platform:targetSdkVersion=28 3003
- com.android.certinstaller 10013 0 /data/user/0/com.android.certinstaller platform:targetSdkVersion=28 none
- me.thomastv.rebootupdate 10024 0 /data/user_de/0/me.thomastv.rebootupdate default:targetSdkVersion=25 none
- android 1000 0 /data/system platform:privapp:targetSdkVersion=28 1065,3002,1023,1015,3003,3001,1007
- com.android.backupconfirm 10001 0 /data/user/0/com.android.backupconfirm platform:privapp:targetSdkVersion=28 none
- com.android.statementservice 10009 0 /data/user/0/com.android.statementservice default:privapp:targetSdkVersion=28 3003
- com.android.superuser 10019 1 /data/user/0/com.android.superuser default:targetSdkVersion=22 none
- com.android.providers.settings 1000 0 /data/user_de/0/com.android.providers.settings platform:privapp:targetSdkVersion=28 1065,3002,1023,1015,3003,3001,1007
- com.android.sharedstoragebackup 10007 0 /data/user/0/com.android.sharedstoragebackup platform:privapp:targetSdkVersion=28 1023,1015
- com.iflytek.xiri2.system 1000 0 /data/user/0/com.iflytek.xiri2.system platform:privapp:targetSdkVersion=28 1065,3002,1023,1015,3003,3001,1007
- com.android.webview 10023 0 /data/user/0/com.android.webview default:targetSdkVersion=28 3003
- com.android.se 1068 0 /data/user/0/com.android.se platform:privapp:targetSdkVersion=28 none
- com.android.inputdevices 1000 0 /data/user_de/0/com.android.inputdevices platform:privapp:targetSdkVersion=28 1065,3002,1023,1015,3003,3001,1007
- com.droidlogic.BluetoothRemote 1000 0 /data/user/0/com.droidlogic.BluetoothRemote platform:privapp:targetSdkVersion=28 1065,3002,1023,1015,3003,3001,1007
- android.ext.shared 10015 0 /data/user_de/0/android.ext.shared platform:targetSdkVersion=28 none
- com.android.keychain 1000 0 /data/user/0/com.android.keychain platform:privapp:targetSdkVersion=28 1065,3002,1023,1015,3003,3001,1007
- android.ext.services 10003 0 /data/user_de/0/android.ext.services platform:privapp:targetSdkVersion=28 none
- com.android.packageinstaller 10008 0 /data/user_de/0/com.android.packageinstaller platform:privapp:targetSdkVersion=28 1065
- com.android.proxyhandler 10006 0 /data/user_de/0/com.android.proxyhandler platform:privapp:targetSdkVersion=28 3003
- com.android.inputmethod.latin 10020 0 /data/user_de/0/com.android.inputmethod.latin default:targetSdkVersion=23 none
- com.android.managedprovisioning 10005 0 /data/user/0/com.android.managedprovisioning platform:privapp:targetSdkVersion=28 3003
- jackpal.androidterm 10031 0 /data/user_de/0/jackpal.androidterm default:targetSdkVersion=22 3003
- com.iflytek.bt.auto 10014 0 /data/user/0/com.iflytek.bt.auto default:targetSdkVersion=28 3002,3001
- com.android.settings 1000 1 /data/user/0/com.android.settings platform:privapp:targetSdkVersion=28 1065,3002,1023,1015,3003,3001,1007
- com.android.vpndialogs 10010 0 /data/user/0/com.android.vpndialogs platform:privapp:targetSdkVersion=28 none
- com.android.shell 2000 0 /data/user_de/0/com.android.shell platform:privapp:targetSdkVersion=28 1065,3002,1023,1015,1002,3010,3011
- com.dangbeimarket 10025 0 /data/user_de/0/com.dangbeimarket default:targetSdkVersion=19 3002,3003,3001
- com.android.location.fused 1000 0 /data/user_de/0/com.android.location.fused platform:privapp:targetSdkVersion=28 1065,3002,1023,1015,3003,3001,1007
- com.android.systemui 10011 0 /data/user_de/0/com.android.systemui platform:privapp:targetSdkVersion=28 1065,3002,1023,1015,3001,3006
- com.tv.kuaisou 10028 0 /data/user_de/0/com.tv.kuaisou default:targetSdkVersion=22 3002,3003,3001
- com.android.bluetooth 1002 0 /data/user_de/0/com.android.bluetooth platform:privapp:targetSdkVersion=28 3002,3003,3001,3007,1002,3010,3011,3005,1016
- com.cmcc.mid.softdetector 10018 0 /data/user/0/com.cmcc.mid.softdetector default:targetSdkVersion=17 3003
- cmcc_jiangsu:/ #
这个改变的可能性是根据 permUser 的配置来决定
第五步 固化新用户创建完成的状态、通知 PMS 为新用户和应用赋予默认的权限
第六步 发送 ACTION_USER_ADDED 广播 新用户创建完成
%%%%%
Android 多用户的切换函数入口是
ActivityManagerService.switchUser()
AMS 的 startUser 方法只是判断了是否展示切换用户的 Dialog
最终都会调用到 UserController.startUser 这个函数中
方法很长 涉及到 AMS 和 WMS 的方法分支也很多
切换分为前台切换和后台切换 这里从前台切换 并且对用户未启动的情况总结下关键的切换过程
第一步 切换前冻结屏幕 禁止一切输入操作
这个过程在屏幕旋转的过程中也会执行 因此截取屏幕并展示也是采用和横竖屏切换一样的方式
冻结输入事件
强制结束 App 动画
截取当前屏幕并显示
如果是待启动用户 则初始化待启动用户的状态为 STATE_BOOTING
第二步 为待切换用户更改系统配置 设置 Keyguard
从 SettingsProvider 读取待切换用户的字体、语言、地区等配置并更新到系统
如果是初创用户 则字体使用默认配置 语言和地区使用当前用户的配置
为待切换用户更新资源 如 Attributes、Drawable、Color、Animator、StateList 等
有兴趣可以重点看下 AMS 的 updateGlobalConfiguration()
修改当前用户下所有 Window 的可见性 启动 Keyguard 切换过程中关闭 Keyguard 的指纹监听 并设置锁屏
在 Android 8.0 以前 Keyguard 是一个单独的 System App
8.0 后将其移至 SystemUI 中 该模块的功能主要有 展示和隐藏锁屏界面 认证和校验锁屏密码、指纹密码 等
如果是待启动用户 为待启动用户设置权限 校验或准备待启动用户的 App 存储目录
通知系统所有服务新用户正在启动 如 JobSchedulerService 会根据 Job 对应的用户是否启动来决定 Job 的维护
第三步 并行通知系统所有服务用户开始切换
系统所有服务及相关监听者在收到开始切换的消息后进行一系列的操作
也是用户切换所要完成的核心任务
所有系统服务及相关监听者完成切换任务后 执行 UserController.continueUserSwitch()
第四步 设置切换超时定时器
设置 3s 的延迟消息
如果 3s 内没有完成用户切换 则取消该消息 终止切换过程并执行 UserController.continueUserSwitch()
第五步 将待切换用户拉到前台
stop 当前用户下所有的 Activity
修改所有 ActivityStack 中 TaskRecord 的顺序 将切换用户或者在两个用户中都能运行的 Task 移动到栈顶
将最顶端 Task 对应的 Window 移动到最顶端
取出切换应用之前存在的前台 Activity 置于前台并 resume 如果没有前台应用 则启动 HomeActivity
发送用户切换广播
如果是后台切换 则发送 ACTION_USER_BACKGROUND
如果是前台切换 则发送 ACTION_USER_FOREGROUND 和 ACTION_USER_SWITCHED
第六步 切换超时消息到达时需要继续进行的切换操作
- 在
- 设置切换超时定时器
- 和
- 将待切换用户拉到前台
- 中切换超时消息到达时需要继续进行的切换操作 continueUserSwitch
解冻屏幕和输入
设置 Keyguard 如果切换用户设置了指纹 则需要开始监听指纹信息通知监听者用户已经完成了切换
第七步 完成切换用户
如果是后台切换
则直接调用 UserController.finishUserBoot()
如果是前台切换
ActivityThread 会在 handleResumeActivity 时设置 Main 线程 MessageQueue 的 mIdleHandlers
在 MessageQueue 执行 next() 会检查该列表并最终调用到 AMS 的 activityIdle() 中
此时会检查正在切换的用户列表并调用最终调用到 UserController.finishUserBoot()
设置切换用户的状态为 STATE_RUNNING_LOCKED
- 如果是新启动的用户,则通知系统所有用户监听者用户已经启动
- 并发送 ACTION_LOCKED_BOOT_COMPLETED 广播
- 在 Keyguard 第一次解锁时 会发送 ACTION_BOOT_COMPLETED 广播
——————————
%%%%%
安装 APP 时权限的获取记录存储在
/data/system/packages.xml
- cmcc_jiangsu:/ # cat /data/system/packages.xml | grep xiaodianshi /* 查看关于 bilibili tv 的权限 */
- <item name="com.xiaodianshi.tv.yst.permission.BLKV" package="com.xiaodia
- nshi.tv.yst" protection="2" />
- <package name="com.xiaodianshi.tv.yst" codePath="/data/app/com.xiaodianshi.t
- v.yst-Gq1cdiX3Aho20N4EPrC5gw==" nativeLibraryPath="/data/app/com.xiaodianshi.tv.
- yst-Gq1cdiX3Aho20N4EPrC5gw==/lib" primaryCpuAbi="armeabi-v7a" publicFlags="94530
- 7204" privateFlags="0" ft="1822bb3ec60" it="1822bb3f274" ut="1822bb3f274" versio
- n="105100" userId="10030">
- <item name="com.xiaodianshi.tv.yst.permission.BLKV" granted="true" f
- lags="0" />
- cmcc_jiangsu:/ # cat /data/system/packages.xml | grep jackpal.androidterm
- <item name="jackpal.androidterm.permission.PREPEND_TO_PATH" package="jac
- kpal.androidterm" protection="1" />
- <item name="jackpal.androidterm.permission.RUN_SCRIPT" package="jackpal.
- androidterm" protection="1" />
- <item name="jackpal.androidterm.permission.APPEND_TO_PATH" package="jack
- pal.androidterm" protection="1" />
- <package name="jackpal.androidterm" codePath="/data/app/jackpal.androidterm-
- sAgHElvcbHuZtUuQdCSIdQ==" nativeLibraryPath="/data/app/jackpal.androidterm-sAgHE
- lvcbHuZtUuQdCSIdQ==/lib" primaryCpuAbi="armeabi" publicFlags="940097092" private
- Flags="0" ft="1822bc31730" it="1822bc31983" ut="1822bc31983" version="71" userId
- ="10031">
- cmcc_jiangsu:/ # pm list packages -3 /* 查看第三方应用 */
- package:com.xiaodianshi.tv.yst
- package:com.mylejia.store
- package:com.fengyun.live
- package:me.thomastv.rebootupdate
- package:jackpal.androidterm
- package:com.dangbeimarket
- package:com.tv.kuaisou
- cmcc_jiangsu:/ # cat /data/system/packages.xml | grep com.dangbeimarket /* 查看当贝市场权限 */
- <item name="baidu.push.permission.WRITE_PUSHINFOPROVIDER.com.dangbeimark
- et" package="com.dangbeimarket" protection="2" />
- <item name="com.dangbeimarket.permission.JPUSH_MESSAGE" package="com.dan
- gbeimarket" protection="2" />
- <item name="com.dangbeimarket.permission.MIPUSH_RECEIVE" package="com.da
- ngbeimarket" protection="2" />
- <package name="com.dangbeimarket" codePath="/data/app/com.dangbeimarket-Gvch
- ZCDlwKegHBtoXBQhwg==" nativeLibraryPath="/data/app/com.dangbeimarket-GvchZCDlwKe
- gHBtoXBQhwg==/lib" primaryCpuAbi="armeabi-v7a" publicFlags="945307204" privateFl
- ags="0" ft="14aa2cb6b80" it="14aa2cb6f96" ut="14aa2cb6f96" version="286" userId=
- "10025">
- <item name="baidu.push.permission.WRITE_PUSHINFOPROVIDER.com.dangbei
- market" granted="true" flags="0" />
- <item name="com.dangbeimarket.permission.JPUSH_MESSAGE" granted="tru
- e" flags="0" />
- <item name="com.dangbeimarket.permission.MIPUSH_RECEIVE" granted="tr
- ue" flags="0" />
- cmcc_jiangsu:/ #
%%%%%
运行时权限的获取记录存储在
/data/system/users/$userId/runtime-permissions.xml
- cmcc_jiangsu:/ # cat /data/system/users/0/runtime-permissions.xml
- <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
- <runtime-permissions fingerprint="CM311-1a-YST/CM311-1a-YST/CM311-1a-YST:9/PPR1.180610.011/V.955.05:userdebug/test-keys" />
- cmcc_jiangsu:/ #
%%%%%
Android 系统和应用安装后的权限声明保存在
/etc/permissions/
目录下:
- cmcc_jiangsu:/ # ls /etc/permissions/
- android.hardware.bluetooth.xml com.android.media.remotedisplay.xml
- android.hardware.bluetooth_le.xml com.android.mediadrm.signer.xml
- android.hardware.hdmi.cec.xml platform.xml
- android.software.webview.xml privapp-permissions-platform.xml
- com.android.location.provider.xml
- cmcc_jiangsu:/ #
如果要查看最常使用的 platform 权限可以:
cat /etc/permissions/platform.xml | more
可以简单看一下这个配置文件 每个我们常见的权限都可能对应一个或多个 group gid
而我们上面说的 gids 就是由这个 group gid 生成的集合
——————————
%%%%%
语法如下:
- pm grant 包名 权限 /* 授予权限 */
- pm revoke 包名 权限 /* 移除权限*/
示例为终端模拟器添加删除写文件权限:
- cmcc_jiangsu:/ # pm grant jackpal.androidterm android.permission.WRITE_EXTERNAL_STORAGE
- cmcc_jiangsu:/ # pm revoke jackpal.androidterm android.permission.WRITE_EXTERNAL_STORAGE
- cmcc_jiangsu:/ #
其她常用权限:
- android.permission.CAMERA /* 相机权限 */
- android.permission.READ_EXTERNAL_STORAGE /* 读文件权限 */
- android.permission.WRITE_EXTERNAL_STORAGE /* 写文件权限 */
%%%%%
Android 系统上每一个独立的应用运行在不同的系统空间
以 User ID 和 Group ID 来标识
不同应用之间互相访问数据接口资源就牵涉到权限问题
关于用户 ID
- 我们在安装一个应用的时候系统就会为这个应用分配一个 userid
- 这个 userid 是全局唯一的
- 在同一 Android 系统的机器上不可能存在两个相同 userid 的应用
- 也就是说 userid 对于一个应用来说是唯一不变的 除非你卸载重新安装了该应用
- 但是 userid 并不像 MAC 地址一样是全球唯一的 同一个应用在不同的设备上 userid 可能会不同
- 这里所说的唯一是指在同一个 Android 设备上
-
- Android 的安全机制是进程级别的
- 通常情况下一个应用就是一个进程
- 并且一个应用也只有一个进程
- 当然应用内实现多进程这个是没有任何问题的
- 这里是说一般情况下
- 应用 A 是无法直接运行在应用 B 的进程当中的
-
- 但是有一点就是除非应用 A 和应用 B 使用了相同的 shareduserid
- 配置了相同的 shareduserid 的应用被系统视作同一个应用 对应的 userid 和权限都是相同的
- 但是如果仅仅是配置了相同的 shareduserid 就能够到达目的 显然这是一个很大的漏洞
- 为此谷歌做了另外一个限制 就是必须保证签名一致
- 一般的 A 公司的签名肯定是跟 B 公司的签名是不一样的
- 也就是说想要应用 A 和应用 B 运行在同一个进程当中那么肯定得保证签名和 shareduserid 是一致的
- shareduserid 保持一致这个很容易满足 但是签名一致恐怕只能是同一个公司
-
- 应用的数据和 user id 是相对应的 默认情况下其她应用是无法访问的
- 但是如果我们设置了 MODE_WORLD_READABLE 或者 MODE_WORLD_WRITEABLE 的 flag
- 那么其她应用就可以变得可读可写了 也就是说这些数据就变成了全局的数据
-
- 我们知道 Android 系统从 4.2 版本开始支持多用户
- 也就产生了用户 id 的概念 uid
- 在这里 uid 和 userid 是两个完全不同的概念
- android 中的用户是存在物理文件级数据差异的
- 例如有两个用户 用户 id 分别是 0 和 10
- 用户 10 安装了应用 A 此时对于用户 0 来说是完全不可见的
- 不像两个应用 A 和 B 两者的数据虽然默认情况下是不能互相访问的 但是我们有办法能够实现
那么用户 id 到底是什么:
简单的说用户 id 就是当前用户下为了各个应用之间数据共享和访问的
在 Android 系统中有些常用的 userid 是提前定义好的
例如 system 的用户 id 就是 1000 这个是在代码中提前定义好的
%%%%%
示例使用 dumpsys package 命令获取 终端模拟器 这个应用的所有信息:
- cmcc_jiangsu:/ # dumpsys package jackpal.androidterm
- Activity Resolver Table:
- Full MIME Types:
- */*:
- 6eb5070 jackpal.androidterm/.TermHere filter 85f0431
- Action: "android.intent.action.SEND"
- Category: "android.intent.category.DEFAULT"
- Type: "*"
- mPriority=0, mOrder=0, mHasPartialTypes=true
- b538fe9 jackpal.androidterm/.shortcuts.FSNavigator filter e12d733
- Action: "android.intent.action.GET_CONTENT"
- Category: "android.intent.category.DEFAULT"
- Category: "android.intent.category.OPENABLE"
- Type: "*"
- mPriority=0, mOrder=0, mHasPartialTypes=true
-
- Wild MIME Types:
- *:
- 6eb5070 jackpal.androidterm/.TermHere filter 85f0431
- Action: "android.intent.action.SEND"
- Category: "android.intent.category.DEFAULT"
- Type: "*"
- mPriority=0, mOrder=0, mHasPartialTypes=true
- b538fe9 jackpal.androidterm/.shortcuts.FSNavigator filter e12d733
- Action: "android.intent.action.GET_CONTENT"
- Category: "android.intent.category.DEFAULT"
- Category: "android.intent.category.OPENABLE"
- Type: "*"
- mPriority=0, mOrder=0, mHasPartialTypes=true
-
- Non-Data Actions:
- jackpal.androidterm.RUN_SHORTCUT:
- 3602f82 jackpal.androidterm/.RunShortcut filter 45c4897
- Action: "jackpal.androidterm.RUN_SHORTCUT"
- Category: "android.intent.category.DEFAULT"
- jackpal.androidterm.private.SWITCH_WINDOW:
- 65c1ce jackpal.androidterm/.TermInternal filter 2d8abbb
- Action: "jackpal.androidterm.private.SWITCH_WINDOW"
- Category: "android.intent.category.DEFAULT"
- jackpal.androidterm.OPEN_NEW_WINDOW:
- d877d32 jackpal.androidterm/.RemoteInterface filter 83648d8
- Action: "jackpal.androidterm.OPEN_NEW_WINDOW"
- Category: "android.intent.category.DEFAULT"
- android.intent.action.MAIN:
- 6ee9b65 jackpal.androidterm/.Term filter 8b301b5
- Action: "android.intent.action.MAIN"
- Category: "android.intent.category.LAUNCHER"
- Category: "android.intent.category.MULTIWINDOW_LAUNCHER"
- c0f203a jackpal.androidterm/.shortcuts.AddShortcut filter 5331a84
- Action: "android.intent.action.MAIN"
- android.intent.action.PICK:
- b538fe9 jackpal.androidterm/.shortcuts.FSNavigator filter 34d5ea2
- Action: "android.intent.action.PICK"
- Category: "android.intent.category.DEFAULT"
- jackpal.androidterm.RUN_SCRIPT:
- c6dd21d jackpal.androidterm/.RunScript filter 2a1e716
- Action: "jackpal.androidterm.RUN_SCRIPT"
- Category: "android.intent.category.DEFAULT"
- jackpal.androidterm.private.OPEN_NEW_WINDOW:
- 65c1ce jackpal.androidterm/.TermInternal filter 5bb104a
- Action: "jackpal.androidterm.private.OPEN_NEW_WINDOW"
- Category: "android.intent.category.DEFAULT"
- android.intent.action.CREATE_SHORTCUT:
- c0f203a jackpal.androidterm/.shortcuts.AddShortcut filter eeeb26d
- Action: "android.intent.action.CREATE_SHORTCUT"
-
- MIME Typed Actions:
- android.intent.action.SEND:
- 6eb5070 jackpal.androidterm/.TermHere filter 85f0431
- Action: "android.intent.action.SEND"
- Category: "android.intent.category.DEFAULT"
- Type: "*"
- mPriority=0, mOrder=0, mHasPartialTypes=true
- android.intent.action.GET_CONTENT:
- b538fe9 jackpal.androidterm/.shortcuts.FSNavigator filter e12d733
- Action: "android.intent.action.GET_CONTENT"
- Category: "android.intent.category.DEFAULT"
- Category: "android.intent.category.OPENABLE"
- Type: "*"
- mPriority=0, mOrder=0, mHasPartialTypes=true
-
- Service Resolver Table:
- Non-Data Actions:
- jackpal.androidterm.action.START_TERM.v1:
- 3f40e99 jackpal.androidterm/.TermService filter f7579ec
- Action: "jackpal.androidterm.action.START_TERM.v1"
- Category: "android.intent.category.DEFAULT"
-
- Permissions:
- Permission [jackpal.androidterm.permission.PREPEND_TO_PATH] (40775e5):
- sourcePackage=jackpal.androidterm
- uid=10031 gids=null type=0 prot=dangerous
- perm=Permission{13728ba jackpal.androidterm.permission.PREPEND_TO_PATH}
- packageSetting=PackageSetting{cc1336b jackpal.androidterm/10031}
-
- Permissions:
- Permission [jackpal.androidterm.permission.RUN_SCRIPT] (9ec705e):
- sourcePackage=jackpal.androidterm
- uid=10031 gids=null type=0 prot=dangerous
- perm=Permission{a9cac3f jackpal.androidterm.permission.RUN_SCRIPT}
- packageSetting=PackageSetting{cc1336b jackpal.androidterm/10031}
-
- Permissions:
- Permission [jackpal.androidterm.permission.APPEND_TO_PATH] (13fd63a):
- sourcePackage=jackpal.androidterm
- uid=10031 gids=null type=0 prot=dangerous
- perm=Permission{65012eb jackpal.androidterm.permission.APPEND_TO_PATH}
- packageSetting=PackageSetting{cc1336b jackpal.androidterm/10031}
-
- Key Set Manager:
- [jackpal.androidterm]
- Signing KeySets: 17
-
- Packages:
- Package [jackpal.androidterm] (cc1336b):
- userId=10031
- pkg=Package{ab23cd9 jackpal.androidterm}
- codePath=/data/app/jackpal.androidterm-sAgHElvcbHuZtUuQdCSIdQ==
- resourcePath=/data/app/jackpal.androidterm-sAgHElvcbHuZtUuQdCSIdQ==
- legacyNativeLibraryDir=/data/app/jackpal.androidterm-sAgHElvcbHuZtUuQdCSIdQ=
- =/lib
- primaryCpuAbi=armeabi
- secondaryCpuAbi=null
- versionCode=71 minSdk=4 targetSdk=22
- versionName=1.0.70
- splits=[base]
- apkSigningVersion=1
- applicationInfo=ApplicationInfo{544369e jackpal.androidterm}
- flags=[ HAS_CODE ALLOW_CLEAR_USER_DATA ALLOW_BACKUP ]
- privateFlags=[ DEFAULT_TO_DEVICE_PROTECTED_STORAGE DIRECT_BOOT_AWARE ]
- dataDir=/data/user_de/0/jackpal.androidterm
- supportsScreens=[small, medium, large, xlarge, resizeable, anyDensity]
- usesLibraries:
- org.apache.http.legacy
- usesLibraryFiles:
- /system/framework/org.apache.http.legacy.boot.jar
- timeStamp=2022-07-23 23:53:02
- firstInstallTime=2022-07-23 23:53:02
- lastUpdateTime=2022-07-23 23:53:02
- signatures=PackageSignatures{2e3957f version:1, signatures:[e7b54ff0], past
- signatures:[]}
- installPermissionsFixed=true
- pkgFlags=[ HAS_CODE ALLOW_CLEAR_USER_DATA ALLOW_BACKUP ]
- declared permissions:
- jackpal.androidterm.permission.RUN_SCRIPT: prot=dangerous, INSTALLED
- jackpal.androidterm.permission.APPEND_TO_PATH: prot=dangerous, INSTALLED
- jackpal.androidterm.permission.PREPEND_TO_PATH: prot=dangerous, INSTALLED
- requested permissions:
- android.permission.INTERNET
- android.permission.READ_EXTERNAL_STORAGE
- android.permission.WRITE_EXTERNAL_STORAGE
- android.permission.ACCESS_SUPERUSER
- android.permission.WAKE_LOCK
- install permissions:
- android.permission.INTERNET: granted=true
- android.permission.READ_EXTERNAL_STORAGE: granted=true
- android.permission.WRITE_EXTERNAL_STORAGE: granted=true
- android.permission.WAKE_LOCK: granted=true
- User 0: ceDataInode=-4294966708 installed=true hidden=false suspended=false
- stopped=false notLaunched=false enabled=0 instant=false virtual=false
- gids=[3003]
- runtime permissions:
-
- Package Changes:
- Sequence number=0
-
-
- Dexopt state:
- [jackpal.androidterm]
- path: /data/app/jackpal.androidterm-sAgHElvcbHuZtUuQdCSIdQ==/base.apk
- arm: [status=speed-profile] [reason=install]
-
-
- Compiler stats:
- [jackpal.androidterm]
- (No recorded stats)
- cmcc_jiangsu:/ #
获取 userid 可以使用 dumpsys package 搭配 grep 筛选 userId 和 gids:
- cmcc_jiangsu:/ # dumpsys package jackpal.androidterm | grep userId
- userId=10031
- cmcc_jiangsu:/ # dumpsys package jackpal.androidterm | grep gids
- uid=10031 gids=null type=0 prot=dangerous
- uid=10031 gids=null type=0 prot=dangerous
- uid=10031 gids=null type=0 prot=dangerous
- gids=[3003]
- cmcc_jiangsu:/ #
%%%%%
不同用户具有的权限不同
使用 dumpsys user 命令可以查看所有的用户信息 例如 userId、name、restrictions 等等:
- cmcc_jiangsu:/ # dumpsys user
- Users:
- UserInfo{0:null:13} serialNo=0
- State: RUNNING_UNLOCKED
- Created: <unknown>
- Last logged in: +2762d4h27m19s3ms ago
- Last logged in fingerprint: CM311-1a-YST/CM311-1a-YST/CM311-1a-YST:9/PPR1.18
- 0610.011/V.955.05:userdebug/test-keys
- Start time: +1h8m33s992ms ago
- Unlock time: +1h8m33s812ms ago
- Has profile owner: false
- Restrictions:
- none
- Device policy global restrictions:
- null
- Device policy local restrictions:
- null
- Effective restrictions:
- none
-
- Device owner id:-10000
-
- Guest restrictions:
- no_sms
- no_install_unknown_sources
- no_config_wifi
- no_outgoing_calls
-
- Device managed: false
- Started users state: {0=3}
-
- Max users: 1
- Supports switchable users: false
- All guests ephemeral: false
- cmcc_jiangsu:/ #
解释一下 访客用户/Guest 的默认权限限制:
- Guest restrictions: /* 来宾账户限制 */
- no_sms /* 限制发送短信 */
- no_install_unknown_sources /* 限制安装软件 */
- no_config_wifi /* 限制配置 WiFi */
- no_outgoing_calls /* 限制拨打电话 */
这些权限可以在创建用户时规定也可以后期由系统动态设置
特殊权限的用户:
- 用户 uid
- system 1000
- radio 1001
%%%%%
不同用户下的 App 应用权限也是独立的
上面说了 uid 与 userId 存在一种计算关系
appUid = userId * 1000000 + appId
而在系统中对于权限控制也是根据 uid 和对应的 userId 来判定的
因此不同用户下相同应用可以具有不同的权限
查看所有已知的权限组和单独权限组的权限:
- cmcc_jiangsu:/ # pm list permission-groups /* 查看所有已知的权限组 */
- permission group:android.permission-group.CONTACTS
- permission group:android.permission-group.PHONE
- permission group:android.permission-group.CALENDAR
- permission group:android.permission-group.CALL_LOG
- permission group:android.permission-group.CAMERA
- permission group:android.permission-group.SENSORS
- permission group:android.permission-group.LOCATION
- permission group:android.permission-group.STORAGE
- permission group:droidlogic.permission-group.SYSTEM_CONTROL
- permission group:android.permission-group.MICROPHONE
- permission group:android.permission-group.SMS
- cmcc_jiangsu:/ # pm list permissions android.permission-group.CONTACTS /* 查看单独的权限组都有什么权限 */
- All Permissions:
-
- permission:android.permission.WRITE_CONTACTS
- permission:android.permission.GET_ACCOUNTS
- permission:android.permission.READ_CONTACTS
- cmcc_jiangsu:/ # pm list permissions android.permission-group.PHONE
- All Permissions:
-
- permission:android.permission.ACCESS_UCE_OPTIONS_SERVICE
- permission:android.permission.ANSWER_PHONE_CALLS
- permission:android.permission.READ_PHONE_NUMBERS
- permission:android.permission.READ_PHONE_STATE
- permission:android.permission.CALL_PHONE
- permission:android.permission.ACCESS_UCE_PRESENCE_SERVICE
- permission:android.permission.ACCEPT_HANDOVER
- permission:android.permission.USE_SIP
- permission:com.android.voicemail.permission.ADD_VOICEMAIL
- cmcc_jiangsu:/ # pm list permissions android.permission-group.CALENDAR
- All Permissions:
-
- permission:android.permission.READ_CALENDAR
- permission:android.permission.WRITE_CALENDAR
- cmcc_jiangsu:/ # pm list permissions android.permission-group.CALL_LOG
- All Permissions:
-
- permission:android.permission.READ_CALL_LOG
- permission:android.permission.WRITE_CALL_LOG
- permission:android.permission.PROCESS_OUTGOING_CALLS
- cmcc_jiangsu:/ # pm list permissions android.permission-group.CAMERA
- All Permissions:
-
- permission:android.permission.CAMERA
- cmcc_jiangsu:/ # pm list permissions android.permission-group.SENSORS
- All Permissions:
-
- permission:android.permission.BODY_SENSORS
- permission:android.permission.USE_FINGERPRINT
- permission:android.permission.USE_BIOMETRIC
- cmcc_jiangsu:/ # pm list permissions android.permission-group.LOCATION
- All Permissions:
-
- permission:android.permission.ACCESS_FINE_LOCATION
- permission:android.permission.ACCESS_COARSE_LOCATION
- cmcc_jiangsu:/ # pm list permissions android.permission-group.STORAGE
- All Permissions:
-
- permission:android.permission.READ_EXTERNAL_STORAGE
- permission:android.permission.WRITE_EXTERNAL_STORAGE
- cmcc_jiangsu:/ # pm list permissions droidlogic.permission-group.SYSTEM_CONTROL
- All Permissions:
-
- permission:droidlogic.permission.SYSTEM_CONTROL
- cmcc_jiangsu:/ # pm list permissions android.permission-group.MICROPHONE
- All Permissions:
-
- permission:android.permission.RECORD_AUDIO
- cmcc_jiangsu:/ # pm list permissions android.permission-group.SMS
- All Permissions:
-
- permission:android.permission.READ_SMS
- permission:android.permission.RECEIVE_WAP_PUSH
- permission:android.permission.RECEIVE_MMS
- permission:android.permission.RECEIVE_SMS
- permission:android.permission.SEND_SMS
- permission:android.permission.READ_CELL_BROADCASTS
- cmcc_jiangsu:/ #
permissions 的参数可以组合使用:
- -g 按组进行列出权限
- -f 打印所有信息
- -s 简短的摘要
- -d 只有危险的权限列表
- -u 只有权限的用户将看到列表 用户自定义权限
例如:
pm list permissions -g -d 权限组
示例:
- cmcc_jiangsu:/ # pm list permissions -g -d android.permission-group.CONTACTS
- Dangerous Permissions:
-
- group:android.permission-group.CONTACTS
- permission:android.permission.WRITE_CONTACTS
- permission:android.permission.GET_ACCOUNTS
- permission:android.permission.READ_CONTACTS
-
- group:android.permission-group.PHONE
- permission:android.permission.ANSWER_PHONE_CALLS
- permission:android.permission.READ_PHONE_NUMBERS
- permission:android.permission.READ_PHONE_STATE
- permission:android.permission.CALL_PHONE
- permission:android.permission.ACCEPT_HANDOVER
- permission:android.permission.USE_SIP
- permission:com.android.voicemail.permission.ADD_VOICEMAIL
-
- group:android.permission-group.CALENDAR
- permission:android.permission.READ_CALENDAR
- permission:android.permission.WRITE_CALENDAR
-
- group:android.permission-group.CALL_LOG
- permission:android.permission.READ_CALL_LOG
- permission:android.permission.WRITE_CALL_LOG
- permission:android.permission.PROCESS_OUTGOING_CALLS
-
- group:android.permission-group.CAMERA
- permission:android.permission.CAMERA
-
- group:android.permission-group.SENSORS
- permission:android.permission.BODY_SENSORS
-
- group:android.permission-group.LOCATION
- permission:android.permission.ACCESS_FINE_LOCATION
- permission:android.permission.ACCESS_COARSE_LOCATION
-
- group:android.permission-group.STORAGE
- permission:android.permission.READ_EXTERNAL_STORAGE
- permission:android.permission.WRITE_EXTERNAL_STORAGE
-
- group:droidlogic.permission-group.SYSTEM_CONTROL
-
- group:android.permission-group.MICROPHONE
- permission:android.permission.RECORD_AUDIO
-
- group:android.permission-group.SMS
- permission:android.permission.READ_SMS
- permission:android.permission.RECEIVE_WAP_PUSH
- permission:android.permission.RECEIVE_MMS
- permission:android.permission.RECEIVE_SMS
- permission:android.permission.SEND_SMS
- permission:android.permission.READ_CELL_BROADCASTS
-
- ungrouped:
- cmcc_jiangsu:/ #
再或者查看描述:
- cmcc_jiangsu:/ # pm list permissions -s
- All Permissions:
-
- 通讯录: 修改您的通讯录, 查找设备上的帐号, 读取联系人
-
- 电话: null, 接听来电, 读取电话号码, 读取手机状态和身份, 拨打电话, null, null, 拨
- 打/接听SIP电话, 添加语音邮件
-
- 日历: 读取日历活动和详情, 添加或修改日历活动,并在所有者不知情的情况下向邀请对象
- 发送电子邮件
-
- 通话记录: 读取通话记录, 新建/修改/删除通话记录, 重新设置外拨电话的路径
-
- 相机: 拍摄照片和视频
-
- 身体传感器: 访问身体传感器(如心率监测器), 使用指纹硬件, 使用生物特征硬件
-
- 位置信息: 访问确切位置信息(以 GPS 和网络为依据), 访问大致位置信息(以网络为依
- 据)
-
- 存储空间: 读取您的USB存储设备中的内容, 修改或删除您的USB存储设备中的内容
-
- droidlogic权限组: droidlogic 系统控制权限
-
- 麦克风: 录音
-
- 短信: 读取短信, 接收讯息 (WAP), 接收讯息(彩信), 接收讯息(短信), 发送短信, 读
- 取小区广播消息
-
- ungrouped:
- null, null, null, null, null, null, null, 修改系统设置, null, null, null, null,
- null, 建立或中断 WiMAX 网络连接, null, null, null, null, null, null, null, null,
- 关闭其他应用, null, null, null, null, null, null, null, null, 更改您的音频设置,
- null, null, null, null, “勿扰”模式使用权限, null, null, null, null, null, nul
- l, null, null, null, null, null, null, null, null, null, null, null, null, 此应
- 用可显示在其他应用上方, null, 绑定到运营商服务, null, null, null, null, null, nu
- ll, null, null, null, null, 将蓝牙设备列入访问权限白名单。, null, null, null, nu
- ll, null, null, 控制近距离通信, null, null, null, null, null, null, null, null,
- null, null, 发送下载通知。, null, null, null, null, null, 更改网络连接性, null,
- null, 运行前台服务, 让应用始终运行, null, 启用和停用同步, null, 在后台使用数据,
- null, null, null, null, 开机启动, null, null, null, null, null, null, 设置时区,
- null, null, null, 展开/收拢状态栏, 卸载快捷方式, 管理个人资料和设备所有者, 请求
- 忽略电池优化, null, null, 与蓝牙设备配对, null, 允许接收WLAN多播, null, null, nu
- ll, 设置闹钟, null, null, null, null, null, null, null, null, 检索正在运行的应用
- , null, null, null, null, null, 拥有完全的网络访问权限, null, null, 发射红外线,
- null, 对正在运行的应用重新排序, null, null, null, 在后台运行, 访问蓝牙设置, null
- , null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null, 计算应用存储空间, null, null, null, nu
- ll, null, null, null, null, 访问所有系统下载内容, null, null, null, null, null,
- null, null, null, null, null, null, null, null, null, null, null, null, null, nu
- ll, null, null, null, null, null, null, null, null, null, null, null, null, 获取
- 额外的位置信息提供程序命令, null, null, null, 使用即时通讯通话服务, null, 访问下
- 载管理器。, 发送持久广播, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null, null, null, null, null, null, 连接WLAN
- 网络和断开连接, null, null, 读取安装会话, null, null, null, null, null, null, nu
- ll, null, null, 使用下载管理器。, null, null, null, null, null, null, null, null
- , null, null, null, null, null, 查看网络连接, null, null, null, 停用屏幕锁定, nu
- ll, null, null, null, null, null, null, null, null, null, 设置壁纸, null, null,
- 在后台使用数据, null, null, null, null, null, null, null, null, null, null, null
- , null, null, null, null, null, 关闭其他应用, null, null, null, null, null, null
- , null, null, null, null, null, 读取同步统计信息, 通过系统转接来电, null, null,
- null, null, 保留下载缓存中的空间, null, null, null, null, null, 请求删除文件包,
- null, null, null, null, null, null, null, null, null, null, null, null, null, nu
- ll, null, null, null, null, null, null, null, null, null, null, null, null, null
- , null, 调整您的壁纸大小, null, 读取同步设置, null, null, null, null, 在后台运行
- , null, null, null, null, null, null, null, 控制振动, null, null, null, null, nu
- ll, null, null, null, null, null, null, null, null, null, null, null, null, null
- , null, null, null, null, null, null, null, null, null, null, null, null, null,
- 查看WLAN连接, null, null, null, null, null, 更改 WiMAX 状态, null, null, 请求安
- 装文件包, null, null, null, null, null, 安装快捷方式, null, null, null, null, nu
- ll, null, null, null, null, 防止手机休眠, null, 高级下载管理器功能。, null, null
- , null, null, null, null, null, null, null, null, null, null, null
- cmcc_jiangsu:/ #
更简短的:
- cmcc_jiangsu:/ # pm list permissions -g -d -s android.permission-group.CONTACTS
- Dangerous Permissions:
-
- 通讯录: 修改您的通讯录, 查找设备上的帐号, 读取联系人
-
- 电话: 接听来电, 读取电话号码, 读取手机状态和身份, 拨打电话, null, 拨打/接听SIP电
- 话, 添加语音邮件
-
- 日历: 读取日历活动和详情, 添加或修改日历活动,并在所有者不知情的情况下向邀请对象
- 发送电子邮件
-
- 通话记录: 读取通话记录, 新建/修改/删除通话记录, 重新设置外拨电话的路径
-
- 相机: 拍摄照片和视频
-
- 身体传感器: 访问身体传感器(如心率监测器)
-
- 位置信息: 访问确切位置信息(以 GPS 和网络为依据), 访问大致位置信息(以网络为依
- 据)
-
- 存储空间: 读取您的USB存储设备中的内容, 修改或删除您的USB存储设备中的内容
-
- droidlogic权限组: droidlogic 系统控制权限
-
- 麦克风: 录音
-
- 短信: 读取短信, 接收讯息 (WAP), 接收讯息(彩信), 接收讯息(短信), 发送短信, 读
- 取小区广播消息
-
- ungrouped:
-
- cmcc_jiangsu:/ #
——————————
%%%%%
- 平台版本 版本名称 API 级别 版本代码
-
- Android 1.0 无 1 BASE
-
- Android 1.1 无 2 BASE_1_1
-
- Android 1.5 Cupcake 纸杯蛋糕 3 CUPCAKE
-
- Android 1.6 Donut 甜甜圈 4 DONUT
-
- Android 2.0 Eclair 闪电泡芙 5 ECLAIR
-
- Android 2.0.1 Eclair 闪电泡芙 6 ECLAIR_0_1
-
- Android 2.1.x Eclair 闪电泡芙 7 ECLAIR_MR1
-
- Android 2.2.x Froyo 冻酸奶 8 FROYO
-
- Android 2.3/2.3.1/2.3.2 Gingerbread 姜饼 9 GINGERBREAD
-
- Android 2.3.3/2.3.4 Gingerbread 姜饼 10 GINGERBREAD_MR1
-
- Android 3.0.x Honeycomb 蜂巢 11 HONEYCOMB
-
- Android 3.1.x Honeycomb 蜂巢 12 HONEYCOMB_MR1
-
- Android 3.2 Honeycomb 蜂巢 13 HONEYCOMB_MR2
-
- Android 4.0/4.0.1/4.0.2 Ice Cream Sandwich 冰淇凌三明治 14 ICE_CREAM_SANDWICH
-
- Android 4.0.3/4.0.4 Ice Cream Sandwich 冰淇凌三明治 15 ICE_CREAM_SANDWICH_MR1
-
- Android 4.1/4.1.1 Jelly Bean 糖豆 16 JELLY_BEAN
-
- Android 4.2/4.2.2 Jelly Bean 糖豆 17 JELLY_BEAN_MR2
-
- Android 4.3 Jelly Bean 糖豆 18 JELLY_BEAN_MR3
-
- Android 4.4 KitKat 奇巧巧克力棒 19 KITKAT
-
- Android 4.4W KitKat 奇巧巧克力棒 20 KITKAT_WATCH
-
- Android 5.0 Lollipop 棒棒糖 21 LOLLIPOP
-
- Android 5.1 Lollipop 棒棒糖 22 LOLLIPOP_MR1
-
- Android 6.0 Marshmallow 棉花糖 23 M
-
- Android 7.0 Nougat 牛轧糖 24 N
-
- Android 7.1 Nougat 牛轧糖 25 N_MR1
-
- Android 8.0 Oreo 奥利奥 26 O
-
- Android 8.1 Oreo 奥利奥 27 O_MR1
-
- Android 9.0 Pie 馅饼 28 P
-
- Android 10.0 Android 10 29 Q
-
- Android 11 Android 11 R R
%%%%%
- android.permission-group.CONTACTS /* 联系人权限组 */
- 通讯录: 修改您的通讯录, 查找设备上的帐号, 读取联系人
-
- android.permission-group.PHONE /* 电话权限组 */
- 电话: 接听来电, 读取电话号码, 读取手机状态和身份, 拨打电话, null, 拨打/接听SIP电
- 话, 添加语音邮件
-
- android.permission-group.CALENDAR /* 日历权限组组 */
- 日历: 读取日历活动和详情, 添加或修改日历活动,并在所有者不知情的情况下向邀请对象
- 发送电子邮件
-
- android.permission-group.CALL_LOG /* 呼叫功能的权限组 */
- 通话记录: 读取通话记录, 新建/修改/删除通话记录, 重新设置外拨电话的路径
-
- android.permission-group.CAMERA /* 相机权限组 */
- 相机: 拍摄照片和视频
-
- android.permission-group.SENSORS /* 身体传感器权限组 */
- 身体传感器: 访问身体传感器(如心率监测器)
-
- android.permission-group.LOCATION /* 位置权限组 */
- 位置信息: 访问确切位置信息(以 GPS 和网络为依据), 访问大致位置信息(以网络为依
- 据)
-
- android.permission-group.STORAGE /* 外部存储权限组 */
- 存储空间: 读取您的USB存储设备中的内容, 修改或删除您的USB存储设备中的内容
-
- droidlogic.permission-group.SYSTEM_CONTROL /* 系统控制权限组 */
- droidlogic权限组: droidlogic 系统控制权限
-
- android.permission-group.MICROPHONE /* 麦克风权限组 */
- 麦克风: 录音
-
- android.permission-group.SMS /* 短信权限组 */
- 短信: 读取短信, 接收讯息 (WAP), 接收讯息(彩信), 接收讯息(短信), 发送短信, 读
- 取小区广播消息
%%%%%
android.permission-group.CONTACTS /* 联系人权限组_API 级别 23_联系人和配置文件相关的运行时权限 */
- android.permission.WRITE_CONTACTS /* 写入联系人权限 允许应用写入用户联系人数据_保护等级 危险_API 级别 1 */
- android.permission.GET_ACCOUNTS /* 访问谷歌账户权限 国内用不了…… 该权限意味着是否允许访问帐户服务中的帐户列表_保护等级 危险_API 级别 1 */
- android.permission.READ_CONTACTS /* 读取联系人权限 允许应用读取用户联系人数据_保护等级 危险_API 级别 1 */
%%%%%
android.permission-group.PHONE /* 电话权限组_API 级别 23_电话功能相关的权限 */
- android.permission.ACCESS_UCE_OPTIONS_SERVICE /* 允许应用访问 UCE-OPTIONS 权限_保护等级 为 签名|专用 */
- android.permission.ANSWER_PHONE_CALLS /* 允许应用接听来电权限_保护等级为 危险_API 级别 26 */
- android.permission.READ_PHONE_NUMBERS /* 允许应用读取设备的电话号码权限_保护等级为 危险_API 级别 26 */
- android.permission.READ_PHONE_STATE /* 读取手机状态权限 就是允许应用访问电话状态_保护等级为 危险_API 级别 1 */
- android.permission.CALL_PHONE /* 允许应用在不经过拨号界面的情况下启动电话呼叫以便用户确认呼叫权限_保护等级为 危险_API 级别 1 */
- android.permission.ACCESS_UCE_PRESENCE_SERVICE /* 允许应用访问 UCE-Presence 权限_保护等级 为 签名|专用 */
- android.permission.ACCEPT_HANDOVER /* 允许呼叫应用继续在其她应用中启动的呼叫权限 如视频通话应用希望在用户的移动网络上继续语音通话_保护等级为 危险_API 级别 28 */
- android.permission.USE_SIP /* 允许应用使用 SIP 服务权限_保护等级为 危险_API 级别 9 */
- com.android.voicemail.permission.ADD_VOICEMAIL /* 允许应用向系统中添加语音邮件权限_保护等级为 危险_API 级别 14 */
- /* 其她权限例如 MANAGE_OWN_CALLS 允许调用应用通过自我管理的 ConnectionService API 管理自己的调用_保护等级为 正常_API 级别 26 */
%%%%%
android.permission-group.CALENDAR /* 日历权限组_API 级别 17_用户日历相关的运行时权限 */
- android.permission.READ_CALENDAR /* 允许应用读取用户日历数据权限_保护等级 危险_API 级别 1 */
- android.permission.WRITE_CALENDAR /* 允许应用写入用户日历数据权限_保护等级 危险_API 级别 1 */
%%%%%
android.permission-group.CALL_LOG /* 通话记录的权限_API 级别 28 */
- android.permission.READ_CALL_LOG /* 允许应用读取用户通话日志权限_危险_16 */
- android.permission.WRITE_CALL_LOG /* 允许应用写入用户通话日志_危险_16 */
- android.permission.PROCESS_OUTGOING_CALLS /* 允许应用查看拨出呼叫期间拨出的号码_危险_1 */
%%%%%
android.permission-group.CAMERA /* 访问相机或从设备捕获 图像/视频 相关的权限_17 */
android.permission.CAMERA /* 允许访问摄像头_危险|立即_1 */
%%%%%
android.permission-group.SENSORS /* 身体或环境传感器相关的权限_23 */
- android.permission.BODY_SENSORS /* 允许应用访问身体传感器的数据_危险_20 */
- android.permission.USE_FINGERPRINT /* 允许应用使用指纹硬件 API 级别 28 以后不再建议使用_正常_23 */
- android.permission.USE_BIOMETRIC /* 允许应用使用设备支持的生物识别模式_正常_28 */
%%%%%
android.permission-group.LOCATION /* 允许访问设备位置信息的权限_1 */
- android.permission.ACCESS_FINE_LOCATION /* 允许应用访问精确的位置_危险_1 */
- android.permission.ACCESS_COARSE_LOCATION /* 允许应用访问大概的位置_危险_1 */
%%%%%
android.permission-group.STORAGE /* 外部存储相关的运行时权限 API 级别 Q 以后不再建议使用_4 */
- android.permission.READ_EXTERNAL_STORAGE /* 允许应用读取扩展存储 API 级别 Q 以后不再建议使用_危险_16 */
- android.permission.WRITE_EXTERNAL_STORAGE /* 允许应用写入扩展存储 API 级别 Q 以后不再建议使用_危险_4 */
%%%%%
droidlogic.permission-group.SYSTEM_CONTROL /* 未知权限 字面翻译为 安卓逻辑系统.授权-组.系统_控制 */
droidlogic.permission.SYSTEM_CONTROL
%%%%%
android.permission-group.MICROPHONE /* 访问麦克风相关的权限 请注意 电话呼叫也会捕获音频 但属于单独的权限组_17 */
android.permission.RECORD_AUDIO /* 允许应用录音_危险_1 */
%%%%%
android.permission-group.SMS /* 短信相关的运行时权限_23 */
- android.permission.READ_SMS /* 允许应用访问 SMS 信息_危险_1 */
- android.permission.RECEIVE_WAP_PUSH /* 允许应用接收 WAP 推送信息_危险_1 */
- android.permission.RECEIVE_MMS /* 允许应用监视传入的彩信_危险_1 */
- android.permission.RECEIVE_SMS /* 允许应用接收短信_危险_1 */
- android.permission.SEND_SMS /* 允许应用发送短信_危险_1 */
- android.permission.READ_CELL_BROADCASTS /* 允许应用读取小区广播消息_危险 */
%%%%%
- shell@GIONEE_G1605A:/ $ pm list permission-groups
- permission group:android.permission-group.CONTACTS
- permission group:android.permission-group.PHONE
- permission group:android.permission-group.CALENDAR
- permission group:android.permission-group.CAMERA
- permission group:android.permission-group.SENSORS
- permission group:android.permission-group.LOCATION
- permission group:android.permission-group.STORAGE
- permission group:android.permission-group.MICROPHONE
- permission group:android.permission-group.SMS
- shell@GIONEE_G1605A:/ $ pm list permissions -g -d
- Dangerous Permissions:
-
- group:android.permission-group.CONTACTS
- permission:android.permission.WRITE_CONTACTS
- permission:android.permission.GET_ACCOUNTS
- permission:android.permission.READ_CONTACTS
-
- group:android.permission-group.PHONE
- permission:android.permission.READ_CALL_LOG
- permission:android.permission.READ_PHONE_STATE
- permission:android.permission.CALL_PHONE
- permission:android.permission.WRITE_CALL_LOG
- permission:android.permission.USE_SIP
- permission:android.permission.PROCESS_OUTGOING_CALLS
- permission:com.android.voicemail.permission.ADD_VOICEMAIL
-
- group:android.permission-group.CALENDAR
- permission:android.permission.READ_CALENDAR
- permission:android.permission.WRITE_CALENDAR
-
- group:android.permission-group.CAMERA
- permission:android.permission.CAMERA
-
- group:android.permission-group.SENSORS
- permission:android.permission.BODY_SENSORS
-
- group:android.permission-group.LOCATION
- permission:android.permission.ACCESS_FINE_LOCATION
- permission:android.permission.ACCESS_COARSE_LOCATION
-
- group:android.permission-group.STORAGE
- permission:android.permission.READ_EXTERNAL_STORAGE
- permission:android.permission.WRITE_EXTERNAL_STORAGE
-
- group:android.permission-group.MICROPHONE
- permission:android.permission.RECORD_AUDIO
-
- group:android.permission-group.SMS
- permission:android.permission.READ_SMS
- permission:android.permission.RECEIVE_WAP_PUSH
- permission:android.permission.RECEIVE_MMS
- permission:android.permission.RECEIVE_SMS
- permission:android.permission.SEND_SMS
- permission:android.permission.READ_CELL_BROADCASTS
-
- ungrouped:
- shell@GIONEE_G1605A:/ $ pm list permissions -s
- All Permissions:
-
- 通讯录: 修改您的通讯录, 查找设备上的帐户, 读取您的通讯录
-
- 电话: 读取通话记录, 读取手机状态和身份, 使用即时通讯通话服务, 直接拨打电话号码,
- 写入通话记录, 拨打/接听SIP电话, 重新设置外拨电话的路径, 添加语音邮件
-
- 日历: 读取日历活动和机密信息, 添加或修改日历活动,并在所有者不知情的情况下向邀请
- 对象发送电子邮件
-
- 相机: 拍摄照片和视频
-
- 身体传感器: 人体传感器(如心跳速率检测器), 使用指纹硬件
-
- 位置信息: 精确位置(基于GPS和网络), 大致位置(基于网络)
-
- 存储空间: 读取您的SD卡中的内容, 修改或删除您的SD卡中的内容
-
- 麦克风: 录音
-
- 短信: 读取您的讯息(短信或彩信), 接收讯息 (WAP), 接收讯息(彩信), 接收讯息(短
- 信), 发送和查看短信, 读取小区广播消息
-
- ungrouped:
- null, null, null, null, null, 修改系统设置, null, null, 建立或中断 WiMAX 网络连
- 接, null, null, null, null, null, null, Error: java.lang.NullPointerException: A
- ttempt to read from field 'java.lang.String android.content.pm.ApplicationInfo.p
- ublicSourceDir' on a null object reference
- 1|shell@GIONEE_G1605A:/ $
##################################################
——————————
%%%%%
每个程序在安装时都有建立一个系统 ID
用以保护数据不被其她应用获取
例如 app_15
Android 系统会根据不同的用户和组来分配不同权限
比如访问 SD 卡、访问网络等等
底层均映射为 Linux 权限!
%%%%%
Android 安全模型基于 Linux 的权限管理
android 系统充分利用了 linux 的用户权限管理方法
使用沙箱隔离机制将每个应用的进程资源隔离
Android 应用程序在安装时赋予一个 UID
UID 不同的应用程序完全隔离
另一方面 应用如果想使用某种服务 需要在 AndroidManifest.xml 中申请
比如想使用网络的话需要在 AndroidManifest.xml 中添加:
<uses-permission android:name="android.permission.INTERNET" />
INTERNET 权限将被映射到底层的 GID
所以一个应用有一个 UID 可以有多个 GID 来获得多个权限
Android 本身支持在应用程序的 AndroidManifest.xml 中自定义权限
但这种自定义的权限没有被映射到系统底层的用户组中 没有独立的 GID
如果在系统中有一个 C 语言写的服务 只有应用申请了权限才可以使用 我们就需要将这个权限映射到底层
例如在开发中自定义一个类似于上面的 INTERNET 的系统级权限组
- 一个用户可以属于多个组
- 一个文件只能属于某个组
这里主要是在 AndroidManifest.xml 中声明权限
主要是通过在 AndroidManifest.xml 中显式地声明应用程序需要的权限 防止应用程序错误的使用服务 不恰当访问资源
Android 中每种权限都用一个独立的标签表示 示例:
- <uses-permission android:name="android.permission.WAKE_LOCK" />
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.READ_PHONE_STATE" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
当在安装应用程序时 Android 就会给予一个 UID
这个 UID 可连接到该应用程序的 AndroidManifest.xml 文件的内容
所以 User 在安装你的应用程序时在屏幕上的窗口里可以看到这个 AndroidManifest.xml 文件的内容
用户会看到你对应用程序的目的、权限等说明
当你接受这支程序的意图、权限说明之后 Android 就安装她 并给她一个 UID
万一在你的应用程序执行期间有越轨 企图做出非权限范围 的行为时 用户将会得到 Android 的警告讯息
Android 的系统权限不是由用户控制 而是由开发者根据开发的需要控制相关权限的开放与否
例如 AndroidManifest.xml 中有如下内容:
- <uses-permission android:name="android.permission.RECORD_AUDIO" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
表示需要使用存储设备和录音设备 在安装的时候 就会提示用户她需要的权限
%%%%%
安装 APK 时发生了什么:
- 在安装 apk 的时候会解析
- AndroidManifest.xml
- 把相应的信息保存起来
-
- 解析权限调用的是函数
- private Package parsePackage
- 这里保存的都是
- android.permission.WRITE_EXTERNAL_STORAGE
- 这样的字符串
-
- 在解析完后会调用
- private void grantPermissionsLP
- 函数获取对应的
- group_id
- 该函数把相应的组都保存到了 gids 中
-
- 当应用程序启动的过程中会调用
- private final void startProcessLocked
- 这里就是获取前面保存的 gids
- 再后面调用创建了一个新的进程 这里传的参数就有 gids
-
- 创建新进程利用 jni 最终调用
- static pid_t forkAndSpecializeCommon
- 函数
-
- 我们如果研究代码可以看到在子进程里调用
- setgroupsIntarray
- 设置该进程所属的组 这样她就拥有了该组的权限
- 也通过 setgid 及 setuid 决定了应用程序的 uid 及 gid 值
权限控制主要放置在 AndroidManifest.xml 文件中
最后镜像生成在 system\etc\permissions\platform.xml 配置文件中
%%%%%
多用户下的应用其实只安装一次 不同用户下同一个应用的版本和签名都应该相同
不同用户下相同 App 能够独立运行是因为系统为她们创造了不同的运行环境和权限
protectionLevel 分为三类:
- <permission android:name="android.permission.READ_EXTERNAL_STORAGE"
- android:permissionGroup="android.permission-group.STORAGE"
- android:label="@string/permlab_sdcardRead"
- android:description="@string/permdesc_sdcardRead"
- android:protectionLevel="dangerous" />
-
- <!-- Allows applications to access information about Wi-Fi networks./允许应用程序访问有关 Wi-Fi 网络的信息。
- <p>Protection level: normal
- -->
- <permission android:name="android.permission.ACCESS_WIFI_STATE"
- android:description="@string/permdesc_accessWifiState"
- android:label="@string/permlab_accessWifiState"
- android:protectionLevel="normal" />
-
- <!-- @SystemApi Allows applications to set the system time./@SystemApi 允许应用程序设置系统时间。
- <p>Not for use by third-party applications. -->
- <permission android:name="android.permission.SET_TIME"
- android:protectionLevel="signature|privileged" />
normal 是普通权限
在 AndroidManifest.xml 中声明就可以获取的权限
如 INTERNET 权限
dangerous 敏感权限需要动态申请告知用户才能获取
signature|privileged 签名|特权
具有系统签名的系统应用才可以获取的权限
对应上方的安装在 /system/priv-app 的特权应用!
——————————
第一层是在开发人员编写代码时由应用设置 主要是修改 AndroidManifest.xml 文件
AndroidManifest.xml 是 APP 的运行配置文件 她是一个 XML 描述文件 指定了 APP 的运行配置信息
一般都存放在 APP 包下的 manifests 目录下
不过我也见过放在 src/main/res/AndroidManifest.xm 下面的
AndroidManifest.xml 文件的作用:
- 描述 app 的包名
- 描述 app 使用的 android 系统版本信息
- 描述 app 本身的版本信息 这样对于同一个 app 的两个版本 系统就能区分那个新版本旧版本
- 描述应用对外暴露的组件等等
我们将 apk 文件后缀修改成 zip 就可以使用平常的解压工具进行解压了:
第一眼看到的就是 AndroidManifest.xml 配置文件:
AndroidManifest 官方解释是 应用清单 manifest 意思是货单
每个应用的根目录中都必须包含一个 并且文件名必须一模一样
这个文件中包含了 APP 的配置信息 系统需要根据里面的内容运行 APP 的代码 显示界面
AndroidManifest.xml 是每个 apk 文件解压后根目录下的一个文件
每个 apk 都必须包含一个 AndroidManifest.xml 文件 且名字必须与此完全一致.
示例 AndroidManifest.xml 中的一段配置代码:
- <!-- 访问网络 -->
- <uses-permission android:name="android.permission.INTERNET" />
- <!-- 使用振动的权限 -->
- <uses-permission android:name="android.permission.VIBRATE"></uses-permission>
- <!-- 键盘锁权限Allows applications to disable the keyguard -->
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD"></uses-permission>
- <!-- 调用相机权限 -->
- <uses-permission android:name="android.permission.CAMERA"/>
- <!-- 悬浮窗 -->
- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
%%%%%
通过 shareduserid 来实现数据共享有一个限制就是相同的签名
这个是很高要求的
一般都是同一个公司开发出来的 app 才能满足获取内置到第三方 ROM 里面去才能满足
通常的做法是通过 uses-permission 来实现 我们自己定义一个权限!
在需要被访问的地方加上这个权限限制这样就能到达目的!
- normal 权限 也就是一般的权限 不需要用户去确认的 例如一个应用申请连接网络等
- dangerous 权限 这种权限较 normal 权限高一些 需要用户手动点击确认的 例如应用需要读取联系人的信息 因为这些数据是比较隐私的可能会导致你的数据泄露等
- signature 只有当申请权限的应用程序的数字签名与声明此权限的应用程序的数字签名相同时 才能将权限授给她 如果是申请系统权限则需要与系统签名相同
- signatureOrSystem 签名相同 或者申请权限的应用为系统应用 在 system image 中
signature 和 signatureOrSystem 要求是很高 一般的只有是相同公司开发出来的应用才能满足
%%%%%
我们在安装 Android 软件的时候系统会提示该软件所需要的权限
相对于其她系统 Android 的权限非常多
我们在开发软件的时候也需要声明相应的权限,比如希望软件能发短信,需要声明软件调用短信的权限
否则软件运行的时候就会报错
Android 的权限在 AndroidManifest.xml 文件里配置
AndroidManifest 文件中有四个标签与 permission 有关:
<permission>
<permission-group>
<permission-tree>
<uses-permission>
其中最常用的是 <uses-permission>
当我们需要获取某个权限的时候就必须在我们的 manifest 文件中声明 <uses-permission>
- <?xml version="1.0" encoding="utf-8"?>
- <manifest>
- <application>
- </application>
- <uses-permission />
- <permission />
- <permission-tree />
- <permission-group />
- ...
- </manifest>
<permission> 和 <uses-permission> 的作用相似 两者之间的不同之处在于
<uses-permission> 是 android 预定义的权限
<permission> 是自己定义的权限
- <permission> 用的相对较少
- <permission-group> <permission-tree> 这两个标签就更少见了
- 简单说 <permission-group> 就是声明一个标签 该标签代表了一组 permissions
- 而 <permission-tree> 是为一组 permissions 声明了一个 namespace
<permission> 定义方法如下:
- <permission android:description="string resource"
- android:icon="drawable resource"
- android:label="string resource"
- android:name="string"
- android:permissionGroup="string"
- android:protectionLevel=["normal" | "dangerous" |
- "signature" | "signatureOrSystem"] />
解释一下:
- propectionLevel 这个属性是必须声明的
- 告诉系统通知用户的应用要求许可 或允许谁认为获得许可的情况下
- permissionGroup 这个是可选的 与 <permission-group> 配合使用
- label, name 和 icon 用于描述权限
<uses-permission> 是我们用的最多的 例如短信和电话权限的定义:
- <uses-permission android:name="android.permission.CALL_PHONE" />
- <uses-permission android:name="android.permission.SEND_SMS"/>
常见权限:
- <uses-permission android:name="android.permission.ACCESS_CHECKIN_PROPERTIES" ></uses-permission> /* 允许读写访问 properties 表 在 checkin 数据库中 可以修改上传 */
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" ></uses-permission> /* 允许一个程序访问 CellID 或 WiFi 热点来获取粗略的位置 */
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" ></uses-permission> /* 允许一个程序访问精良位置 如 GPS */
- <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" ></uses-permission> /* 允许应用程序访问额外的位置提供命令 */
- <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" ></uses-permission> /* 允许程序创建模拟位置提供用于测试 */
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" ></uses-permission> /* 允许程序访问有关 GSM 网络信息 */
- <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" ></uses-permission> /* 允许程序使用 SurfaceFlinger 底层特性 */
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" ></uses-permission> /* 允许程序访问 Wi-Fi 网络状态信息 */
- <uses-permission android:name="android.permission.ADD_SYSTEM_SERVICE" ></uses-permission> /* 允许程序发布系统级服务 */
- <uses-permission android:name="android.permission.BATTERY_STATS" ></uses-permission> /* 允许程序更新手机电池统计信息 */
- <uses-permission android:name="android.permission.BLUETOOTH" ></uses-permission> /* 允许程序连接到已配对的蓝牙设备 */
- <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" ></uses-permission> /* 允许程序发现和配对蓝牙设备 */
- <uses-permission android:name="android.permission.BRICK" ></uses-permission> /* 请求能够禁用设备 */
- <uses-permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED" ></uses-permission> /* 允许程序广播一个提示消息在一个应用程序包已经移除后 */
- <uses-permission android:name="android.permission.BROADCAST_STICKY" ></uses-permission> /* 允许一个程序广播常用 intents */
- <uses-permission android:name="android.permission.CALL_PHONE" ></uses-permission> /* 允许一个程序初始化一个电话拨号不需通过拨号用户界面需要用户确认 */
- <uses-permission android:name="android.permission.CALL_PRIVILEGED" ></uses-permission> /* 允许一个程序拨打任何号码 包含紧急号码无需通过拨号用户界面需要用户确认 */
- <uses-permission android:name="android.permission.CAMERA" ></uses-permission> /* 请求访问使用照相设备 */
- <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" ></uses-permission> /* 允许一个程序是否改变一个组件或其她的启用或禁用 */
- <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" ></uses-permission> /* 允许一个程序修改当前设置 如本地化 */
- <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" ></uses-permission> /* 允许程序改变网络连接状态 */
- <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" ></uses-permission> /* 允许程序改变 Wi-Fi 连接状态 */
- <uses-permission android:name="android.permission.CLEAR_APP_CACHE" ></uses-permission> /* 允许一个程序清楚缓存从所有安装的程序在设备中 */
- <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" ></uses-permission> /* 允许一个程序清除用户设置 */
- <uses-permission android:name="android.permission.CONTROL_LOCATION_UPDATES" ></uses-permission> /* 允许启用禁止位置更新提示从无线模块 */
- <uses-permission android:name="android.permission.DELETE_CACHE_FILES" ></uses-permission> /* 允许程序删除缓存文件 */
- <uses-permission android:name="android.permission.DELETE_PACKAGES" ></uses-permission> /* 允许一个程序删除包 */
- <uses-permission android:name="android.permission.DEVICE_POWER" ></uses-permission> /* 允许访问底层电源管理 */
- <uses-permission android:name="android.permission.DIAGNOSTIC" ></uses-permission> /* 允许程序 RW 诊断资源 */
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" ></uses-permission> /* 允许程序禁用键盘锁 */
- <uses-permission android:name="android.permission.DUMP" ></uses-permission> /* 允许程序返回状态抓取信息从系统服务 */
-
- android.permission.EXPAND_STATUS_BAR /* 允许一个程序扩展收缩状态栏 */
- android.permission.FACTORY_TEST /* 作为一个工厂测试程序 运行在 root 用户 */
- android.permission.FLASHLIGHT /* 访问闪光灯 */
- android.permission.FORCE_BACK /* 允许程序强行一个后退操作是否在顶层 activities */
- android.permission.FOTA_UPDATE android /* 一个预留权限 */
- android.permission.GET_ACCOUNTS /* 访问一个帐户列表在 Accounts Service 中 */
- android.permission.GET_PACKAGE_SIZE /* 允许一个程序获取任何 package 占用空间容量 */
- android.permission.GET_TASKS /* 允许一个程序获取信息有关当前或最近运行的任务 一个缩略的任务状态 是否活动等等 */
- android.permission.HARDWARE_TEST /* 允许访问硬件 */
- android.permission.INJECT_EVENTS /* 允许一个程序截获用户事件如按键、触摸、轨迹球等等到一个时间流 */
- android.permission.INSTALL_PACKAGES /* 允许一个程序安装 packages */
- android.permission.INTERNAL_SYSTEM_WINDOW /* 允许打开窗口使用系统用户界面 */
- android.permission.INTERNET /* 允许程序打开网络套接字 */
- android.permission.MANAGE_APP_TOKENS /* 允许程序管理程序引用在窗口管理器中 创建、催后、z- order 默认向 z 轴推移 */
- android.permission.MASTER_CLEAR /* 恢复出厂设置权限 清除一切用户数据 */
- android.permission.MODIFY_AUDIO_SETTINGS /* 允许程序修改全局音频设置 */
- android.permission.MODIFY_PHONE_STATE /* 允许修改话机状态,如电源,人机接口等 */
- android.permission.MOUNT_UNMOUNT_FILESYSTEMS /* 允许挂载和反挂载文件系统可移动存储 */
- android.permission.PERSISTENT_ACTIVITY /* 允许一个程序设置她的 activities 显示 */
- android.permission.PROCESS_OUTGOING_CALLS /* 允许程序监视、修改有关播出电话 */
- android.permission.READ_CALENDAR /* 允许程序读取用户日历数据 */
- android.permission.READ_CONTACTS /* 允许程序读取用户联系人数据 */
- android.permission.READ_FRAME_BUFFER /* 允许程序屏幕波或和更多常规的访问帧缓冲数据 */
- android.permission.READ_INPUT_STATE /* 允许程序读取底层系统日志文件 */
- android.permission.READ_OWNER_DATA /* 允许程序读取所有者数据 */
- android.permission.READ_SMS /* 允许程序读取短信息 */
- android.permission.READ_SYNC_SETTINGS /* 允许程序读取同步设置 */
- android.permission.READ_SYNC_STATS /* 允许程序读取同步状态 */
- android.permission.REBOOT /* 请求能够重新启动设备 */
- android.permission.RECEIVE_BOOT_COMPLETED /* 允许一个程序接收到 ACTION_BOOT_COMPLETED 广播在系统完成启动 */
- android.permission.RECEIVE_MMS /* 允许一个程序监控将收到 MMS 彩信 记录或处理 */
- android.permission.RECEIVE_SMS /* 允许程序监控一个将收到短信息 记录或处理 */
- android.permission.RECEIVE_WAP_PUSH /* 允许程序监控将收到 WAP PUSH 信息 */
- android.permission.RECORD_AUDIO /* 允许程序录制音频 */
- android.permission.REORDER_TASKS /* 允许程序改变 Z 轴排列任务 */
- android.permission.RESTART_PACKAGES /* 允许程序重新启动其她程序 */
- android.permission.SEND_SMS /* 允许程序发送 SMS 短信 */
- android.permission.SET_ACTIVITY_WATCHER /* 允许程序监控或控制 activities 已经启动全局系统中 */
- android.permission.SET_ALWAYS_FINISH /* 允许程序控制是否活动间接完成在处于后台时 */
- android.permission.SET_ANIMATION_SCALE /* 修改全局信息比例 */
- android.permission.SET_DEBUG_APP /* 配置一个程序用于调试 */
- android.permission.SET_ORIENTATION /* 允许底层访问设置屏幕方向和实际旋转 */
- android.permission.SET_PREFERRED_APPLICATIONS /* 允许一个程序修改列表参数 PackageManager.addPackageToPreferred() 和 PackageManager.removePackageFromPreferred() 这两个方法 */
- android.permission.SET_PROCESS_FOREGROUND /* 允许程序当前运行程序强行到前台 */
- android.permission.SET_PROCESS_LIMIT /* 允许设置最大的运行进程数量 */
- android.permission.SET_TIME_ZONE /* 允许程序设置时间区域 */
- android.permission.SET_WALLPAPER /* 允许程序设置壁纸 */
- android.permission.SET_WALLPAPER_HINTS /* 允许程序设置壁纸 hits */
- android.permission.SIGNAL_PERSISTENT_PROCESSES /* 允许程序请求发送信号到所有显示的进程中 */
- android.permission.STATUS_BAR /* 允许程序打开、关闭或禁用状态栏及图标 */
- android.permission.SUBSCRIBED_FEEDS_READ /* 允许一个程序访问订阅 RSS Feed 内容提供 */
- android.permission.SUBSCRIBED_FEEDS_WRITE /* 系统暂时保留改设置 */
- android.permission.SYSTEM_ALERT_WINDOW /* 允许一个程序打开窗口使用 TYPE_SYSTEM_ALERT 显示在其她所有程序的顶层 */
- android.permission.VIBRATE /* 允许访问振动设备 */
- android.permission.WAKE_LOCK /* 允许使用 PowerManager 的 WakeLocks 保持进程在休眠时从屏幕消失 */
- android.permission.WRITE_APN_SETTINGS /* 允许程序写入 API 设置 */
- android.permission.WRITE_CALENDAR /* 允许一个程序写入但不读取用户日历数据 */
- android.permission.WRITE_CONTACTS /* 允许程序写入但不读取用户联系人数据 */
- android.permission.WRITE_GSERVICES /* 允许程序修改 Google 服务地图 */
- android.permission.WRITE_OWNER_DATA /* 允许一个程序写入但不读取所有者数据 */
- android.permission.WRITE_SETTINGS /* 允许程序读取或写入系统设置 */
- android.permission.WRITE_SMS /* 允许程序写短信 */
- android.permission.WRITE_SYNC_SETTINGS /* 允许程序写入同步设置 */
——————————
platform.xml 其实是将 aosp 中的配置文件直接拷贝到手机目录中
AOSP 全称 Android Open Source Project 中文意为 Android 开放源代码项目
- 安卓开源项目 开源即开放源代码
- Android 是一个基于 Linux 由 Google 主导的开源系统
- 严格意义上来说 Android = AOSP + GMS
- GMS 即谷歌移动服务 即常刷的谷歌服务包
- 国内无法使用 GMS 所以国内的各种定制 ROM 都是 AOSP 的定制修改加上自家的云服务
- 比如 MIUI、ColorOS 等
- 所以所有的 ROM 最终的根源就是 AOSP 没有 AOSP 也就没有现在的 Android
应用包中 preferences.xml 文件的位置在 res\xml\preferences.xml
设备目录存放的位置在 /system/etc/permissions/platform.xml
在 aosp 中的存放位置是 framework/base/data/etc/platform.xml
%%%%%
编辑的是
root/system/etc/permissions/platform.xml
文件 看到代码如下:
- <permission name="android.permission.WRITE_EXTERNAL_STORAGE" >
- <group gid="sdcard_r" />
- <group gid="sdcard_rw" />
- </permission>
修改为:
- <permission name="android.permission.WRITE_EXTERNAL_STORAGE" >
- <group gid="sdcard_r" />
- <group gid="sdcard_rw" />
- <group gid="media_rw" />
- </permission>
再然后重启就行了
%%%%%
这是对 platform.xml 的解析 注意看注释:
- <?xml version="1.0" encoding="utf-8"?>
- <!-- Copyright (C) 2008 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
- /** 第一部分 >>> 警告部分
- 说明这个文件是处理普通用户和系统权限之间映射的 如果擅自改动会造成大的安全漏洞
-
- 此文件用于定义较低级别系统之间的映射 管理的用户和组 ID 以及更高级别的权限名称在平台旁。
- 编辑此文件时要非常小心!这里犯的错误可能会打开巨大的安全漏洞。
- */
-
- <!-- This file is used to define the mappings between lower-level system
- user and group IDs and the higher-level permission names managed
- by the platform.
- Be VERY careful when editing this file! Mistakes made here can open
- big security holes.
- -->
- <permissions>
-
- <!-- ================================================================== -->
- <!-- ================================================================== -->
- <!-- ================================================================== -->
-
- /** 第二部分 >>> 权限映射
- <permission> 将低等级的 groups id 和权限名称相关联
- 通过指定这样的映射 表明了一个授予了给定权限的应用进程将附带这所给的 group id 运行
- 因此她可以执行这个群组所允许的读写和执行操作
-
- 以下标记将低级组 ID 与权限名称关联
- 通过指定这样一个映射,您的意思是,任何被授予给定权限的应用程序进程也将在其进程附加给定组 ID 的情况下运行
- 因此,她可以执行该组允许的任何文件系统 读、写、执行 操作。
- */
-
- <!-- The following tags are associating low-level group IDs with
- permission names. By specifying such a mapping, you are saying
- that any application process granted the given permission will
- also be running with the given group ID attached to its process,
- so it can perform any filesystem (read, write, execute) operations
- allowed for that group. -->
-
- <permission name="android.permission.BLUETOOTH_ADMIN" >
- <group gid="net_bt_admin" />
- </permission>
-
- <permission name="android.permission.BLUETOOTH" >
- <group gid="net_bt" />
- </permission>
-
- <permission name="android.permission.BLUETOOTH_STACK" >
- <group gid="bluetooth" />
- <group gid="wakelock" />
- <group gid="uhid" />
- </permission>
-
- <permission name="android.permission.NET_TUNNELING" >
- <group gid="vpn" />
- </permission>
-
- <permission name="android.permission.INTERNET" >
- <group gid="inet" />
- </permission>
-
- <permission name="android.permission.READ_LOGS" >
- <group gid="log" />
- </permission>
-
- <permission name="android.permission.WRITE_MEDIA_STORAGE" >
- <group gid="media_rw" />
- <group gid="sdcard_rw" />
- </permission>
-
- <permission name="android.permission.ACCESS_MTP" >
- <group gid="mtp" />
- </permission>
-
- <permission name="android.permission.NET_ADMIN" >
- <group gid="net_admin" />
- </permission>
-
- <!-- The group that /cache belongs to, linked to the permission
- set on the applications that can access /cache -->
- <permission name="android.permission.ACCESS_CACHE_FILESYSTEM" >
- <group gid="cache" />
- </permission>
-
- <!-- RW permissions to any system resources owned by group 'diag'.
- This is for carrier and manufacture diagnostics tools that must be
- installable from the framework. Be careful. -->
- <permission name="android.permission.DIAGNOSTIC" >
- <group gid="input" />
- <group gid="diag" />
- </permission>
-
- <!-- Group that can read detailed network usage statistics -->
- <permission name="android.permission.READ_NETWORK_USAGE_HISTORY">
- <group gid="net_bw_stats" />
- </permission>
-
- <!-- Group that can modify how network statistics are accounted -->
- <permission name="android.permission.UPDATE_DEVICE_STATS">
- <group gid="net_bw_acct" />
- </permission>
-
- <permission name="android.permission.LOOP_RADIO" >
- <group gid="loop_radio" />
- </permission>
-
- <!-- Hotword training apps sometimes need a GID to talk with low-level
- hardware; give them audio for now until full HAL support is added. -->
- <permission name="android.permission.MANAGE_VOICE_KEYPHRASES">
- <group gid="audio" />
- </permission>
-
- <permission name="android.permission.ACCESS_BROADCAST_RADIO" >
- <!-- /dev/fm is gid media, not audio -->
- <group gid="media" />
- </permission>
-
- <permission name="android.permission.USE_RESERVED_DISK">
- <group gid="reserved_disk" />
- </permission>
-
- /** 第三部分 >>> 权限映射的例外部分
-
- 这些权限映射到 GID 但我们需要将其保留在此处 直到支持从 L 升级到当前版本
- 这些权限是内置的 在 L 中没有存储在包中
- 如果在解析包时未在此处定义 则返回 xml
- xml 我们将忽略授予应用程序的这些权限 而不传播授予的状态
- 从 N 开始 我们将内置权限存储在包中
- 与脆弱性相比 作为保存的存储的 xml 可以忽略不计 带有权限的一个标记
- 因为可以删除不再需要映射到 GID 和中断授权传播的内置权限
- */
-
- <!-- These are permissions that were mapped to gids but we need
- to keep them here until an upgrade from L to the current
- version is to be supported. These permissions are built-in
- and in L were not stored in packages.xml as a result if they
- are not defined here while parsing packages.xml we would
- ignore these permissions being granted to apps and not
- propagate the granted state. From N we are storing the
- built-in permissions in packages.xml as the saved storage
- is negligible (one tag with the permission) compared to
- the fragility as one can remove a built-in permission which
- no longer needs to be mapped to gids and break grant propagation. -->
- <permission name="android.permission.READ_EXTERNAL_STORAGE" />
- <permission name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
- <!-- ================================================================== -->
- <!-- ================================================================== -->
- <!-- ================================================================== -->
-
- /** 第四部分 >>> 分配权限
- <assign-permission> 有些用户比较特殊 她们是系统核心用户
- Android 会分配特定的高级权限来允许她们来完成一些高级的操作
-
- 比如 shell 用户有很多权限 这是因为开发者需要比较开放的环境来和 system 进行交互
- shell 用户的权限有时候需要 adb root/adb remount 才能享受
- 对应的需要 userdebug 或者 root 版本
- user 版本下 shell 命令还是有所限制的
- */
-
- <!-- The following tags are assigning high-level permissions to specific
- user IDs. These are used to allow specific core system users to
- perform the given operations with the higher-level framework. For
- example, we give a wide variety of permissions to the shell user
- since that is the user the adb shell runs under and developers and
- others should have a fairly open environment in which to
- interact with the system. -->
-
- <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
- <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" />
- <assign-permission name="android.permission.WAKE_LOCK" uid="media" />
- <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="media" />
- <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="media" />
- <assign-permission name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" uid="media" />
-
- <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="audioserver" />
- <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="audioserver" />
- <assign-permission name="android.permission.WAKE_LOCK" uid="audioserver" />
- <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="audioserver" />
- <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="audioserver" />
- <assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="audioserver" />
-
- <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="cameraserver" />
- <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="cameraserver" />
- <assign-permission name="android.permission.WAKE_LOCK" uid="cameraserver" />
- <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="cameraserver" />
- <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="cameraserver" />
- <assign-permission name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" uid="cameraserver" />
- <assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="cameraserver" />
- <assign-permission name="android.permission.WATCH_APPOPS" uid="cameraserver" />
-
- <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
- <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="graphics" />
- <assign-permission name="android.permission.DUMP" uid="incidentd" />
- <assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="incidentd" />
- <assign-permission name="android.permission.INTERACT_ACROSS_USERS" uid="incidentd" />
-
- <assign-permission name="android.permission.ACCESS_LOWPAN_STATE" uid="lowpan" />
- <assign-permission name="android.permission.MANAGE_LOWPAN_INTERFACES" uid="lowpan" />
-
- <assign-permission name="android.permission.DUMP" uid="statsd" />
- <assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="statsd" />
- <assign-permission name="android.permission.STATSCOMPANION" uid="statsd" />
- <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="statsd" />
-
- /** 第五部分 >>> 库
- <library> 标签设置应用可以链接到的库
- 可以理解为应用可以调用到的 jar 吧?
-
- 这是可供应用程序代码链接的所有库的列表
- */
-
- <!-- This is a list of all the libraries available for application
- code to link against. -->
-
- <library name="android.test.base"
- file="/system/framework/android.test.base.jar" />
- <library name="android.test.mock"
- file="/system/framework/android.test.mock.jar" />
- <library name="android.test.runner"
- file="/system/framework/android.test.runner.jar" />
- <library name="javax.obex"
- file="/system/framework/javax.obex.jar" />
- <library name="org.apache.http.legacy"
- file="/system/framework/org.apache.http.legacy.boot.jar" />
-
- /** 第六部分 >>> 省电优化白名单
- <allow-in-power-save> 表示这个对应于手机中的省电优化设置
- 用这个 tag 配置在这张表中就代表该应用不受省电优化显示 可以在后台访问网络
- 对应应用在原生设置中的电源菜单也是灰显 不可设置优化的
-
- 这些是白名单上的标准软件包始终具有互联网功能
- 可以在省电模式下访问 即使她们不在前台
-
- 这个 tag 也和 doze mode 有些关系
- 就是低耗电模式 什么是低耗电模式:
- 如果用户设备未插电源、处于静止状态一段时间且屏幕关闭 设备将进入该模式
- 该模式下系统会尝试通过限制应用对网络和 CPU 密集型服务的访问来节省电量
- 这还可以阻止引用访问网络并推迟其作业、同步和标准闹铃
-
- 系统会定期退出低耗电模式一会儿 好让应用完成其已推迟的 Activity
- 在此维护时段内 系统会运行所有特定同步 作业和闹铃并允许应用访问网络
- 在每个维护时段结束后系统会再次进入低耗电模式 暂停网络并推迟作业、同步和闹铃
- 随着时间推移 系统安排维护时段的次数越来越少 这有助于设备未连接至充电器情况下长期处于不活动状态时降低电池消耗
-
- 一旦用户通过移动设备、打开屏幕或连接到充电器唤醒设备 系统就会立即退出低耗电模式 并且所有应用都将返回到正常 Activity
-
- 低电耗模式限制:
- 暂停访问网络
- 系统将忽略 wake locks
- 标准 AlarmManager 闹铃将推迟到下一维护时段 包括 setExact() 和 setWindow() 如果需要设置低耗电模式下触发的闹铃请使用 setAndAllowWhileIdle()/setExactAndAllowWhileIdle() 一般情况下使用 setAlarmClock() 设置的闹铃将继续出发 但是系统会在这些闹铃出发之前不久退出低耗电模式
- 系统不执行 Wi-Fi 扫描
- 系统不允许运行 同步适配器
- 系统不允许运行 JobScheduler
-
- 可以使用 dumpsys deviceidle whitelist 命令查看:
- cmcc_jiangsu:/ # dumpsys deviceidle whitelist
- system-excidle,com.android.providers.downloads,10002
- system-excidle,com.android.shell,2000
- system,com.android.providers.downloads,10002
- system,com.android.shell,2000
- cmcc_jiangsu:/ #
- */
-
- <!-- These are the standard packages that are white-listed to always have internet
- access while in power save mode, even if they aren't in the foreground. -->
- <allow-in-power-save package="com.android.providers.downloads" />
-
- /** 第七部分 >>> 数据白名单
-
- 这些是白名单上的标准软件包 在数据模式下始终可以访问互联网 即使她们不在前台
- */
-
- <!-- These are the standard packages that are white-listed to always have internet
- access while in data mode, even if they aren't in the foreground. -->
- <allow-in-data-usage-save package="com.android.providers.downloads" />
-
- /** 第八部分 >>> 省电优化白名单
-
- 这是一个需要在后台自由运行的核心平台组件
-
- <allow-in-power-save-except-idle> 是白名单系统提供商
- */
-
- <!-- This is a core platform component that needs to freely run in the background -->
- <allow-in-power-save package="com.android.cellbroadcastreceiver" />
- <allow-in-power-save package="com.android.shell" />
-
- <!-- Whitelist system providers -->
- <allow-in-power-save-except-idle package="com.android.providers.calendar" />
- <allow-in-power-save-except-idle package="com.android.providers.contacts" />
-
- /** 第九部分 >>> 系统应用白名单
-
- 这些是白名单上的软件包 可以作为系统用户运行
- */
-
- <!-- These are the packages that are white-listed to be able to run as system user -->
- <system-user-whitelisted-app package="com.android.settings" />
-
- /** 第十部分 >>> 系统应用黑名单
-
- 这些软件包不应作为系统用户运行
- */
-
- <!-- These are the packages that shouldn't run as system user -->
- <system-user-blacklisted-app package="com.android.wallpaper.livepicker" />
- </permissions>
%%%%%
xml 肯定是需要解析才能用的
/frameworks/core/java/com/android/server/SystemConfig.java
这个 SystemConfig 就是来解析 platform.xml 然后供一个个系统接口用作返回值的依据:
- void readPermissions(File libraryDir, int permissionFlag) {
- // Read permissions from given directory.
- if (!libraryDir.exists() || !libraryDir.isDirectory()) {
- if (permissionFlag == ALLOW_ALL) {
- Slog.w(TAG, "No directory " + libraryDir + ", skipping");
- }
- return;
- }
- if (!libraryDir.canRead()) {
- Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
- return;
- }
-
- // Iterate over the files in the directory and scan .xml files
- File platformFile = null;
- for (File f : libraryDir.listFiles()) {
- // We'll read platform.xml last
- if (f.getPath().endsWith("etc/permissions/platform.xml")) {
- platformFile = f;
- continue;
- }
-
- if (!f.getPath().endsWith(".xml")) {
- Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
- continue;
- }
- if (!f.canRead()) {
- Slog.w(TAG, "Permissions library file " + f + " cannot be read");
- continue;
- }
-
- readPermissionsFromXml(f, permissionFlag);
- }
-
- // Read platform permissions last so it will take precedence
- if (platformFile != null) {
- readPermissionsFromXml(platformFile, permissionFlag);
- }
- }
-
- private void readPermissionsFromXml(File permFile, int permissionFlag) {
- FileReader permReader = null;
- try {
- permReader = new FileReader(permFile);
- } catch (FileNotFoundException e) {
- Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
- return;
- }
-
- final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
-
- try {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(permReader);
-
- int type;
- while ((type=parser.next()) != parser.START_TAG
- && type != parser.END_DOCUMENT) {
- ;
- }
-
- if (type != parser.START_TAG) {
- throw new XmlPullParserException("No start tag found");
- }
-
- if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) {
- throw new XmlPullParserException("Unexpected start tag in " + permFile
- + ": found " + parser.getName() + ", expected 'permissions' or 'config'");
- }
-
- boolean allowAll = permissionFlag == ALLOW_ALL;
- boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0;
- boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0;
- boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0;
- boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0;
- boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS) != 0;
- boolean allowApiWhitelisting = (permissionFlag & ALLOW_HIDDENAPI_WHITELISTING) != 0;
- while (true) {
- XmlUtils.nextElement(parser);
- if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
- break;
- }
-
- String name = parser.getName();
- if ("group".equals(name) && allowAll) {
- String gidStr = parser.getAttributeValue(null, "gid");
- if (gidStr != null) {
- int gid = android.os.Process.getGidForName(gidStr);
- mGlobalGids = appendInt(mGlobalGids, gid);
- } else {
- Slog.w(TAG, "<group> without gid in " + permFile + " at "
- + parser.getPositionDescription());
- }
-
- XmlUtils.skipCurrentTag(parser);
- continue;
- } else if ("permission".equals(name) && allowPermissions) {
- String perm = parser.getAttributeValue(null, "name");
- if (perm == null) {
- Slog.w(TAG, "<permission> without name in " + permFile + " at "
- + parser.getPositionDescription());
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
- perm = perm.intern();
- readPermission(parser, perm);
-
- } else if ("assign-permission".equals(name) && allowPermissions) {
- String perm = parser.getAttributeValue(null, "name");
- if (perm == null) {
- Slog.w(TAG, "<assign-permission> without name in " + permFile + " at "
- + parser.getPositionDescription());
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
- String uidStr = parser.getAttributeValue(null, "uid");
- if (uidStr == null) {
- Slog.w(TAG, "<assign-permission> without uid in " + permFile + " at "
- + parser.getPositionDescription());
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
- int uid = Process.getUidForName(uidStr);
- if (uid < 0) {
- Slog.w(TAG, "<assign-permission> with unknown uid \""
- + uidStr + " in " + permFile + " at "
- + parser.getPositionDescription());
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
- perm = perm.intern();
- ArraySet<String> perms = mSystemPermissions.get(uid);
- if (perms == null) {
- perms = new ArraySet<String>();
- mSystemPermissions.put(uid, perms);
- }
- perms.add(perm);
- XmlUtils.skipCurrentTag(parser);
-
- } else if ("library".equals(name) && allowLibs) {
- String lname = parser.getAttributeValue(null, "name");
- String lfile = parser.getAttributeValue(null, "file");
- if (lname == null) {
- Slog.w(TAG, "<library> without name in " + permFile + " at "
- + parser.getPositionDescription());
- } else if (lfile == null) {
- Slog.w(TAG, "<library> without file in " + permFile + " at "
- + parser.getPositionDescription());
- } else {
- //Log.i(TAG, "Got library " + lname + " in " + lfile);
- mSharedLibraries.put(lname, lfile);
- }
- XmlUtils.skipCurrentTag(parser);
- continue;
-
- } else if ("feature".equals(name) && allowFeatures) {
- String fname = parser.getAttributeValue(null, "name");
- int fversion = XmlUtils.readIntAttribute(parser, "version", 0);
- boolean allowed;
- if (!lowRam) {
- allowed = true;
- } else {
- String notLowRam = parser.getAttributeValue(null, "notLowRam");
- allowed = !"true".equals(notLowRam);
- }
- if (fname == null) {
- Slog.w(TAG, "<feature> without name in " + permFile + " at "
- + parser.getPositionDescription());
- } else if (allowed) {
- addFeature(fname, fversion);
- }
- XmlUtils.skipCurrentTag(parser);
- continue;
-
- } else if ("unavailable-feature".equals(name) && allowFeatures) {
- String fname = parser.getAttributeValue(null, "name");
- if (fname == null) {
- Slog.w(TAG, "<unavailable-feature> without name in " + permFile + " at "
- + parser.getPositionDescription());
- } else {
- mUnavailableFeatures.add(fname);
- }
- XmlUtils.skipCurrentTag(parser);
- continue;
-
- } else if ("allow-in-power-save-except-idle".equals(name) && allowAll) {
- String pkgname = parser.getAttributeValue(null, "package");
- if (pkgname == null) {
- Slog.w(TAG, "<allow-in-power-save-except-idle> without package in "
- + permFile + " at " + parser.getPositionDescription());
- } else {
- mAllowInPowerSaveExceptIdle.add(pkgname);
- }
- XmlUtils.skipCurrentTag(parser);
- continue;
-
- } else if ("allow-in-power-save".equals(name) && allowAll) {
- String pkgname = parser.getAttributeValue(null, "package");
- if (pkgname == null) {
- Slog.w(TAG, "<allow-in-power-save> without package in " + permFile + " at "
- + parser.getPositionDescription());
- } else {
- mAllowInPowerSave.add(pkgname);
- }
- XmlUtils.skipCurrentTag(parser);
- continue;
-
- } else if ("allow-in-data-usage-save".equals(name) && allowAll) {
- String pkgname = parser.getAttributeValue(null, "package");
- if (pkgname == null) {
- Slog.w(TAG, "<allow-in-data-usage-save> without package in " + permFile
- + " at " + parser.getPositionDescription());
- } else {
- mAllowInDataUsageSave.add(pkgname);
- }
- XmlUtils.skipCurrentTag(parser);
- continue;
-
- } else if ("allow-unthrottled-location".equals(name) && allowAll) {
- String pkgname = parser.getAttributeValue(null, "package");
- if (pkgname == null) {
- Slog.w(TAG, "<allow-unthrottled-location> without package in "
- + permFile + " at " + parser.getPositionDescription());
- } else {
- mAllowUnthrottledLocation.add(pkgname);
- }
- XmlUtils.skipCurrentTag(parser);
- continue;
-
- } else if ("allow-implicit-broadcast".equals(name) && allowAll) {
- String action = parser.getAttributeValue(null, "action");
- if (action == null) {
- Slog.w(TAG, "<allow-implicit-broadcast> without action in " + permFile
- + " at " + parser.getPositionDescription());
- } else {
- mAllowImplicitBroadcasts.add(action);
- }
- XmlUtils.skipCurrentTag(parser);
- continue;
-
- } else if ("app-link".equals(name) && allowAppConfigs) {
- String pkgname = parser.getAttributeValue(null, "package");
- if (pkgname == null) {
- Slog.w(TAG, "<app-link> without package in " + permFile + " at "
- + parser.getPositionDescription());
- } else {
- mLinkedApps.add(pkgname);
- }
- XmlUtils.skipCurrentTag(parser);
- } else if ("system-user-whitelisted-app".equals(name) && allowAppConfigs) {
- String pkgname = parser.getAttributeValue(null, "package");
- if (pkgname == null) {
- Slog.w(TAG, "<system-user-whitelisted-app> without package in " + permFile
- + " at " + parser.getPositionDescription());
- } else {
- mSystemUserWhitelistedApps.add(pkgname);
- }
- XmlUtils.skipCurrentTag(parser);
- } else if ("system-user-blacklisted-app".equals(name) && allowAppConfigs) {
- String pkgname = parser.getAttributeValue(null, "package");
- if (pkgname == null) {
- Slog.w(TAG, "<system-user-blacklisted-app without package in " + permFile
- + " at " + parser.getPositionDescription());
- } else {
- mSystemUserBlacklistedApps.add(pkgname);
- }
- XmlUtils.skipCurrentTag(parser);
- } else if ("default-enabled-vr-app".equals(name) && allowAppConfigs) {
- String pkgname = parser.getAttributeValue(null, "package");
- String clsname = parser.getAttributeValue(null, "class");
- if (pkgname == null) {
- Slog.w(TAG, "<default-enabled-vr-app without package in " + permFile
- + " at " + parser.getPositionDescription());
- } else if (clsname == null) {
- Slog.w(TAG, "<default-enabled-vr-app without class in " + permFile
- + " at " + parser.getPositionDescription());
- } else {
- mDefaultVrComponents.add(new ComponentName(pkgname, clsname));
- }
- XmlUtils.skipCurrentTag(parser);
- } else if ("backup-transport-whitelisted-service".equals(name) && allowFeatures) {
- String serviceName = parser.getAttributeValue(null, "service");
- if (serviceName == null) {
- Slog.w(TAG, "<backup-transport-whitelisted-service> without service in "
- + permFile + " at " + parser.getPositionDescription());
- } else {
- ComponentName cn = ComponentName.unflattenFromString(serviceName);
- if (cn == null) {
- Slog.w(TAG,
- "<backup-transport-whitelisted-service> with invalid service name "
- + serviceName + " in "+ permFile
- + " at " + parser.getPositionDescription());
- } else {
- mBackupTransportWhitelist.add(cn);
- }
- }
- XmlUtils.skipCurrentTag(parser);
- } else if ("disabled-until-used-preinstalled-carrier-associated-app".equals(name)
- && allowAppConfigs) {
- String pkgname = parser.getAttributeValue(null, "package");
- String carrierPkgname = parser.getAttributeValue(null, "carrierAppPackage");
- if (pkgname == null || carrierPkgname == null) {
- Slog.w(TAG, "<disabled-until-used-preinstalled-carrier-associated-app"
- + " without package or carrierAppPackage in " + permFile + " at "
- + parser.getPositionDescription());
- } else {
- List<String> associatedPkgs =
- mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get(
- carrierPkgname);
- if (associatedPkgs == null) {
- associatedPkgs = new ArrayList<>();
- mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put(
- carrierPkgname, associatedPkgs);
- }
- associatedPkgs.add(pkgname);
- }
- XmlUtils.skipCurrentTag(parser);
- } else if ("privapp-permissions".equals(name) && allowPrivappPermissions) {
- readPrivAppPermissions(parser);
- } else if ("hidden-api-whitelisted-app".equals(name) && allowApiWhitelisting) {
- String pkgname = parser.getAttributeValue(null, "package");
- if (pkgname == null) {
- Slog.w(TAG, "<hidden-api-whitelisted-app> without package in " + permFile
- + " at " + parser.getPositionDescription());
- } else {
- mHiddenApiPackageWhitelist.add(pkgname);
- }
- XmlUtils.skipCurrentTag(parser);
- } else {
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
- }
- } catch (XmlPullParserException e) {
- Slog.w(TAG, "Got exception parsing permissions.", e);
- } catch (IOException e) {
- Slog.w(TAG, "Got exception parsing permissions.", e);
- } finally {
- IoUtils.closeQuietly(permReader);
- }
-
- // Some devices can be field-converted to FBE, so offer to splice in
- // those features if not already defined by the static config
- if (StorageManager.isFileEncryptedNativeOnly()) {
- addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
- addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
- }
-
- if (ActivityManager.isLowRamDeviceStatic()) {
- addFeature(PackageManager.FEATURE_RAM_LOW, 0);
- } else {
- addFeature(PackageManager.FEATURE_RAM_NORMAL, 0);
- }
-
- for (String featureName : mUnavailableFeatures) {
- removeFeature(featureName);
- }
- }
-
- private void addFeature(String name, int version) {
- FeatureInfo fi = mAvailableFeatures.get(name);
- if (fi == null) {
- fi = new FeatureInfo();
- fi.name = name;
- fi.version = version;
- mAvailableFeatures.put(name, fi);
- } else {
- fi.version = Math.max(fi.version, version);
- }
- }
-
- private void removeFeature(String name) {
- if (mAvailableFeatures.remove(name) != null) {
- Slog.d(TAG, "Removed unavailable feature " + name);
- }
- }
-
- void readPermission(XmlPullParser parser, String name)
- throws IOException, XmlPullParserException {
- if (mPermissions.containsKey(name)) {
- throw new IllegalStateException("Duplicate permission definition for " + name);
- }
-
- final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false);
- final PermissionEntry perm = new PermissionEntry(name, perUser);
- mPermissions.put(name, perm);
-
- int outerDepth = parser.getDepth();
- int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG
- || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG
- || type == XmlPullParser.TEXT) {
- continue;
- }
-
- String tagName = parser.getName();
- if ("group".equals(tagName)) {
- String gidStr = parser.getAttributeValue(null, "gid");
- if (gidStr != null) {
- int gid = Process.getGidForName(gidStr);
- perm.gids = appendInt(perm.gids, gid);
- } else {
- Slog.w(TAG, "<group> without gid at "
- + parser.getPositionDescription());
- }
- }
- XmlUtils.skipCurrentTag(parser);
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。