本文介绍,在MTK Android 12的系统定制过程中,项目需求需要为某些关键应用设置默认权限,以确保它们能够正常运行。这篇博客将详细介绍如何通过修改系统代码来为XXX IoT应用添加默认权限,同时对这些修改进行技术分析。
背景
Android高版本系统对于应用权限的管理是非常严格,尤其是针对某些敏感权限(如存储权限)。为了某些特定应用能够正常运行,需要在系统层面上预先授予它们一些权限。这可以通过修改系统服务代码来实现,这样在应用安装时,系统会自动授予这些预定义的权限。
调试技巧
1.AppOps 状态查询分析
查询结果
列出所有 AppOps 记录来查看所有操作的状态。
dumpsys appops
输出结果如下,全部复制出来,搜索想要的包名,或者权限即可
Error: Mode com.xxx.mtk_87xx_12_ota is not valid
Package com.xxx.mtk_87xx_12_ota:
READ_EXTERNAL_STORAGE (allow):
Uid u0a58:
state=bg
capability=----
appWidgetVisible=false
READ_EXTERNAL_STORAGE: mode=ignore
WRITE_EXTERNAL_STORAGE: mode=ignore
LEGACY_STORAGE: mode=allow
ACCESS_MEDIA_LOCATION: mode=ignore
Package com.google.android.inputmethod.pinyin:
VIBRATE (allow):
null=[
Access: [top-s] 2024-07-15 12:25:18.108 (-1h38m0s762ms) duration=+17ms
Access: [fg-s] 2024-07-15 12:25:23.733 (-1h37m55s137ms) duration=+17ms
]
READ_CONTACTS (allow):
null=[
Access: [bg-s] 2024-07-15 13:57:27.262 (-5m51s608ms)
]
RUN_IN_BACKGROUND (allow):
null=[
Access: [bg-s] 2024-07-15 12:23:30.490 (-1h39m48s380ms)
]
Uid u0a40:
state=fgsvc
capability=---N
appWidgetVisible=false
LEGACY_STORAGE: mode=allow
Package com.xxx.iot.master:
SYSTEM_ALERT_WINDOW (default):
null=[
Reject: [bg-s]2024-07-15 12:23:26.721 (-1h39m52s149ms)
]
RUN_IN_BACKGROUND (allow):
null=[
Access: [fgsvc-s] 2024-07-15 12:25:26.220 (-1h37m52s650ms)
Access: [cch-s] 2024-07-15 12:23:26.586 (-1h39m52s284ms)
]
BIND_ACCESSIBILITY_SERVICE (allow):
null=[
Access: [fgsvc-s] 2024-07-15 14:01:27.681 (-1m51s189ms)
Access: [cch-s] 2024-07-15 12:23:24.653 (-1h39m54s217ms)
]
START_FOREGROUND (allow):
null=[
Access: [fgsvc-s] 2024-07-15 12:23:26.850 (-1h39m52s20ms) duration=+8m37s917ms
Access: [bg-s] 2024-07-15 12:23:26.849 (-1h39m52s21ms) duration=+1ms
Running start at: +8m37s909ms
startNesting=2
]
com.xxx.mtk_87xx_12_ota
包的权限信息
Package com.xxx.mtk_87xx_12_ota:
READ_EXTERNAL_STORAGE (allow):
包名 com.xxx.mtk_87xx_12_ota
被授予了 READ_EXTERNAL_STORAGE
权限。
UID u0a58
的权限信息
Uid u0a58:
state=bg
capability=----
appWidgetVisible=false
READ_EXTERNAL_STORAGE: mode=ignore
WRITE_EXTERNAL_STORAGE: mode=ignore
LEGACY_STORAGE: mode=allow
ACCESS_MEDIA_LOCATION: mode=ignore
显示了 UID 为 u0a58
的应用的权限状态:
READ_EXTERNAL_STORAGE
: 被忽略(ignore)WRITE_EXTERNAL_STORAGE
: 被忽略(ignore)LEGACY_STORAGE
: 允许(allow)ACCESS_MEDIA_LOCATION
: 被忽略(ignore)
2.应用权限信息查询分析
查询结果
执行以下命令查询 com.xxx.iot.unisdkdemo
应用的权限信息:
dumpsys package com.xxx.iot.unisdkdemo
输出结果例如:
//申请的权限 ,应用在 AndroidManifest.xml 文件中声明的权限列表。这些权限是应用在安装时请求的权限。
requested permissions:
android.permission.INTERNET
android.permission.READ_PHONE_STATE
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_WIFI_STATE
。。。
//安装时授予的权限,应用在安装时被授予的权限, 系统自动授予的权限。
install permissions:
android.permission.ACCESS_CACHE_FILESYSTEM: granted=false
android.permission.DOWNLOAD_WITHOUT_NOTIFICATION: granted=true
。。。
// 运行时权限,应用在运行时被授予的权限。这些权限需要用户在应用运行时手动授予。
runtime permissions:
android.permission.READ_SMS: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED|RESTRICTION_INSTALLER_EXEMPT]
android.permission.READ_CALENDAR: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
android.permission.READ_CALL_LOG: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED|RESTRICTION_INSTALLER_EXEMPT]
android.permission.ACCESS_FINE_LOCATION: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
android.permission.RECEIVE_WAP_PUSH: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED|RESTRICTION_INSTALLER_EXEMPT]
android.permission.BODY_SENSORS: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
android.permission.RECEIVE_MMS: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED|RESTRICTION_INSTALLER_EXEMPT]
。。。
技术分析与修改步骤
1. 修改PackageManagerService
类
修改内容
PackageManagerService
类中添加了一个特殊处理逻辑,以便在检查某些应用的权限时,可以绕过默认的权限审核。
文件路径:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -24464,7 +24464,11 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public boolean isPermissionsReviewRequired(String packageName, int userId) {
if("com.xxx.iot.master".equals(packageName) || "com.xxx.iot.service".equals(packageName)){
return false;
}
return mPermissionManager.isPermissionsReviewRequired(packageName, userId);
}
分析
目的:绕过权限审核。
isPermissionsReviewRequired
方法是系统在安装应用时用于检查该应用是否需要权限审核的方法。默认情况下,所有的权限都需要经过审核。通过添加if
判断,可以针对特定包名(如XXX IoT应用)返回false
,让这些应用不需要经过权限审核。
2. 修改DefaultPermissionGrantPolicy
类
修改内容
在DefaultPermissionGrantPolicy
类中,添加了逻辑,使系统在初始化时,为XXX IoT应用自动授予存储权限。
文件路径:frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -532,6 +532,15 @@ public final class DefaultPermissionGrantPolicy {
ArrayUtils.firstOrNull(getKnownPackages(
PackageManagerInternal.PACKAGE_INSTALLER, userId)),
userId, STORAGE_PERMISSIONS);
+ Log.i(TAG, "XXX: grantDefaultPermission for xxx apps");
+ grantSystemFixedPermissionsToSystemPackage(pm,
+ "com.xxx.iot.master",
+ userId, STORAGE_PERMISSIONS);
+ grantSystemFixedPermissionsToSystemPackage(pm,
+ "com.xxx.iot.service",
+ userId, STORAGE_PERMISSIONS);
// Verifier
final String verifier = ArrayUtils.firstOrNull(getKnownPackages(
分析
目的:自动授予应用某些默认权限。
grantSystemFixedPermissionsToSystemPackage
方法用于为指定包名的应用授予系统固定权限。在此,针对XXX IoT应用授予存储权限。使XXX IoT应用在安装时,自动获得所需的存储权限,无需用户手动授权。
3. 修改Permission
类
修改内容
在Permission
类中,修改了权限检查逻辑,这样会导致系统默认允许所有运行时权限,不需要手动授权(这里也可以增加一些包名判断)。
文件路径:frameworks/base/services/core/java/com/android/server/pm/permission/Permission.java
@@ -206,12 +206,14 @@ public final class Permission {
}
public boolean isNormal() {
- return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
- == PermissionInfo.PROTECTION_NORMAL;
+ /*return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
+ == PermissionInfo.PROTECTION_NORMAL;*/
+ return true;
}
public boolean isRuntime() {
- return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
- == PermissionInfo.PROTECTION_DANGEROUS;
+ /*return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
+ == PermissionInfo.PROTECTION_DANGEROUS;*/
+ return false;
}
技术分析
目的:修改权限类型判断逻辑。
isNormal
和 isRuntime
方法用于检查权限类型。默认情况下,系统根据权限的保护级别来判断权限类型。修改后的逻辑使得所有权限都被认为是普通权限(isNormal
返回 true
),而没有权限被认为是运行时权限(isRuntime
返回 false
)
4. 修改AppOpsManager
类
修改内容
在AppOpsManager
类中,调整了默认权限模式,使其在访问存储权限时返回允许状态。
文件路径:frameworks/base/core/java/android/app/AppOpsManager.java
@@ -1704,10 +1704,10 @@ public class AppOpsManager {
- AppOpsManager.MODE_DEFAULT, // READ_EXTERNAL_STORAGE
- AppOpsManager.MODE_DEFAULT, // WRITE_EXTERNAL_STORAGE
+ AppOpsManager.MODE_ALLOWED, // READ_EXTERNAL_STORAGE
+ AppOpsManager.MODE_ALLOWED, // WRITE_EXTERNAL_STORAGE
技术分析
目的:调整权限模式。
AppOpsManager
是应用程序操作权限管理类,核心实现类为 AppOpsService
。AppOpsManager
允许开发者在运行时检查和控制应用的操作权限。修改默认权限模式,使其在读取和写入外部存储时返回允许状态,确保特定应用在访问外部存储时不会受到限制。
总结
通过以上步骤的修改,我在MTK Android 12中成功为XXX IoT应用设置了默认权限。确保了这些应用在安装后能够顺利运行。这样的修改方法同样适用于其他需要特殊权限的应用