fix(xsmscode): add Android 16 (SDK 36) PermissionManagerService hook#70
Merged
magisk317 merged 3 commits intomagisk317:devfrom Feb 19, 2026
Merged
fix(xsmscode): add Android 16 (SDK 36) PermissionManagerService hook#70magisk317 merged 3 commits intomagisk317:devfrom
magisk317 merged 3 commits intomagisk317:devfrom
Conversation
Reviewer's Guide为 Android 16(SDK 36+)新增一个 Android 16 中通过 PermissionManagerServiceHook36 在安装应用时授予权限的时序图sequenceDiagram
participant SystemServer
participant PermissionManagerService as PMS
participant XposedFramework as Xposed
participant PermissionManagerServiceHook36 as Hook36
participant PackageManagerInternal as PMInt
participant App
SystemServer->>PMS: onPackageInstalled(AndroidPackage pkg, ... , int userId)
PMS->>Xposed: invoke hooked onPackageInstalled
Xposed->>Hook36: after(param)
Hook36->>Hook36: afterOnPackageInstalled(param)
Hook36->>Hook36: resolve packageName from pkg
Hook36->>Hook36: lookup permissions from PACKAGE_PERMISSIONS
alt userId == USER_ALL
Hook36->>PMS: get mPackageManagerInt
PMS-->>Hook36: PMInt
Hook36->>PMInt: getUsers(true)
PMInt-->>Hook36: IntArray userIds
else specific user
Hook36->>Hook36: create IntArray with userId
end
loop for each userId and permission
Hook36->>PMS: get mPermissionManagerServiceImpl
PMS-->>Hook36: impl or PMS
Hook36->>impl: grantRuntimePermission(packageName, permission, PERSISTENT_DEVICE_ID_DEFAULT, userId)
impl-->>Hook36: result or exception
end
Hook36-->>Xposed: after hook completes
PMS-->>SystemServer: onPackageInstalled returns
Android 16 中通过 onSystemReady hook 在开机阶段授予权限的时序图sequenceDiagram
participant SystemServer
participant PermissionManagerService as PMS
participant XposedFramework as Xposed
participant PermissionManagerServiceHook36 as Hook36
participant PackageManagerInternal as PMInt
SystemServer->>PMS: onSystemReady()
PMS->>Xposed: invoke hooked onSystemReady
Xposed->>Hook36: after(param)
Hook36->>Hook36: grantAllTargetPermissions(pms)
Hook36->>PMS: get mPackageManagerInt
PMS-->>Hook36: PMInt
Hook36->>PMInt: getUsers(true)
PMInt-->>Hook36: IntArray userIds (or failure -> default 0)
loop for each (packageName, permissions) in PACKAGE_PERMISSIONS
loop for each userId
loop for each permission
Hook36->>PMS: get mPermissionManagerServiceImpl
PMS-->>Hook36: impl or PMS
Hook36->>impl: grantRuntimePermission(packageName, permission, PERSISTENT_DEVICE_ID_DEFAULT, userId)
impl-->>Hook36: result or exception
end
end
end
Hook36-->>Xposed: after hook completes
PMS-->>SystemServer: onSystemReady returns
新增 Android 16 PermissionManagerServiceHook36 以及更新后 PermissionGranterHook 的类图classDiagram
class BaseHook
class BaseSubHook{
-ClassLoader mClassLoader
+startHook()
}
class MethodHookWrapper{
+before(param)
+after(param)
}
class PermissionGranterHook{
+startHook()
}
class PermissionManagerServiceHook34{
+PermissionManagerServiceHook34(classLoader)
+startHook()
}
class PermissionManagerServiceHook36{
-ClassLoader mClassLoader
+PermissionManagerServiceHook36(classLoader)
+startHook()
-hookOnSystemReady()
-hookOnPackageInstalled()
-grantAllTargetPermissions(pms)
-afterOnPackageInstalled(param)
-grantPermissionsForPackage(pms, packageName, permissions, userId)
-getAllUserIds(pms)
<<companion>>
-CLASS_PMS : String
-CLASS_ANDROID_PACKAGE : String
-PERSISTENT_DEVICE_ID_DEFAULT : String
}
BaseHook <|-- PermissionGranterHook
BaseSubHook <|-- PermissionManagerServiceHook34
BaseSubHook <|-- PermissionManagerServiceHook36
PermissionManagerServiceHook36 ..> MethodHookWrapper : uses
class AndroidBuild{
+SDK_INT : Int
}
PermissionGranterHook ..> PermissionManagerServiceHook34 : creates
PermissionGranterHook ..> PermissionManagerServiceHook36 : creates
PermissionGranterHook ..> AndroidBuild : reads_SDK_INT
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your Experience访问你的 dashboard 以:
Getting HelpOriginal review guide in EnglishReviewer's GuideAdds a new PermissionManagerService hook implementation for Android 16 (SDK 36+) and wires the permission granter dispatcher to use it, ensuring runtime permissions are granted correctly after framework changes removed PermissionManagerServiceImpl. Sequence diagram for Android 16 package install permission granting via PermissionManagerServiceHook36sequenceDiagram
participant SystemServer
participant PermissionManagerService as PMS
participant XposedFramework as Xposed
participant PermissionManagerServiceHook36 as Hook36
participant PackageManagerInternal as PMInt
participant App
SystemServer->>PMS: onPackageInstalled(AndroidPackage pkg, ... , int userId)
PMS->>Xposed: invoke hooked onPackageInstalled
Xposed->>Hook36: after(param)
Hook36->>Hook36: afterOnPackageInstalled(param)
Hook36->>Hook36: resolve packageName from pkg
Hook36->>Hook36: lookup permissions from PACKAGE_PERMISSIONS
alt userId == USER_ALL
Hook36->>PMS: get mPackageManagerInt
PMS-->>Hook36: PMInt
Hook36->>PMInt: getUsers(true)
PMInt-->>Hook36: IntArray userIds
else specific user
Hook36->>Hook36: create IntArray with userId
end
loop for each userId and permission
Hook36->>PMS: get mPermissionManagerServiceImpl
PMS-->>Hook36: impl or PMS
Hook36->>impl: grantRuntimePermission(packageName, permission, PERSISTENT_DEVICE_ID_DEFAULT, userId)
impl-->>Hook36: result or exception
end
Hook36-->>Xposed: after hook completes
PMS-->>SystemServer: onPackageInstalled returns
Sequence diagram for Android 16 boot-time permission granting via onSystemReady hooksequenceDiagram
participant SystemServer
participant PermissionManagerService as PMS
participant XposedFramework as Xposed
participant PermissionManagerServiceHook36 as Hook36
participant PackageManagerInternal as PMInt
SystemServer->>PMS: onSystemReady()
PMS->>Xposed: invoke hooked onSystemReady
Xposed->>Hook36: after(param)
Hook36->>Hook36: grantAllTargetPermissions(pms)
Hook36->>PMS: get mPackageManagerInt
PMS-->>Hook36: PMInt
Hook36->>PMInt: getUsers(true)
PMInt-->>Hook36: IntArray userIds (or failure -> default 0)
loop for each (packageName, permissions) in PACKAGE_PERMISSIONS
loop for each userId
loop for each permission
Hook36->>PMS: get mPermissionManagerServiceImpl
PMS-->>Hook36: impl or PMS
Hook36->>impl: grantRuntimePermission(packageName, permission, PERSISTENT_DEVICE_ID_DEFAULT, userId)
impl-->>Hook36: result or exception
end
end
end
Hook36-->>Xposed: after hook completes
PMS-->>SystemServer: onSystemReady returns
Class diagram for new Android 16 PermissionManagerServiceHook36 and updated PermissionGranterHookclassDiagram
class BaseHook
class BaseSubHook{
-ClassLoader mClassLoader
+startHook()
}
class MethodHookWrapper{
+before(param)
+after(param)
}
class PermissionGranterHook{
+startHook()
}
class PermissionManagerServiceHook34{
+PermissionManagerServiceHook34(classLoader)
+startHook()
}
class PermissionManagerServiceHook36{
-ClassLoader mClassLoader
+PermissionManagerServiceHook36(classLoader)
+startHook()
-hookOnSystemReady()
-hookOnPackageInstalled()
-grantAllTargetPermissions(pms)
-afterOnPackageInstalled(param)
-grantPermissionsForPackage(pms, packageName, permissions, userId)
-getAllUserIds(pms)
<<companion>>
-CLASS_PMS : String
-CLASS_ANDROID_PACKAGE : String
-PERSISTENT_DEVICE_ID_DEFAULT : String
}
BaseHook <|-- PermissionGranterHook
BaseSubHook <|-- PermissionManagerServiceHook34
BaseSubHook <|-- PermissionManagerServiceHook36
PermissionManagerServiceHook36 ..> MethodHookWrapper : uses
class AndroidBuild{
+SDK_INT : Int
}
PermissionGranterHook ..> PermissionManagerServiceHook34 : creates
PermissionGranterHook ..> PermissionManagerServiceHook36 : creates
PermissionGranterHook ..> AndroidBuild : reads_SDK_INT
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - 我发现了两个问题,并提供了一些整体层面的反馈:
afterOnPackageInstalled钩子依赖param.args[3]一定是rawUserId,这对方法签名的变更非常脆弱;建议更稳健地定位 userId 参数(例如,通过方法参数的类型/长度,或匹配已知重载)来避免在后续平台更新中出现索引错误。getAllUserIds假设mPackageManagerInt.getUsers(true)返回的是IntArray,但在较新的PackageManagerInternal中通常返回的是用户对象;相比直接强转为IntArray并在失败时静默地回退到用户 0,更安全的做法是处理包含用户结构的List/数组并从中提取 ID。
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `afterOnPackageInstalled` hook relies on `param.args[3]` being the `rawUserId`, which is brittle against signature changes; consider locating the userId argument more defensively (e.g., by using the method’s parameter types/length or matching known overloads) to avoid mis-indexing on future platform updates.
- `getAllUserIds` assumes `mPackageManagerInt.getUsers(true)` returns an `IntArray`, but modern `PackageManagerInternal` typically returns user objects; it may be safer to handle `List`/array of user structures and extract their IDs rather than hard-casting to `IntArray` and silently falling back to user 0.
## Individual Comments
### Comment 1
<location> `app/src/main/java/com/tianma/xsmscode/xp/hook/permission/PermissionManagerServiceHook36.kt:35` </location>
<code_context>
+ */
+class PermissionManagerServiceHook36(classLoader: ClassLoader) : BaseSubHook(classLoader) {
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ override fun startHook() {
+ try {
</code_context>
<issue_to_address>
**suggestion:** The @RequiresApi annotation doesn’t match the stated Android 16+/API 36 behavior.
The class targets Android 16+/API 36, but `@RequiresApi(Build.VERSION_CODES.TIRAMISU)` is API 33, which is misleading for tools and readers. Since the logic relies on reflection, the annotation isn’t strictly needed; consider removing it for now or updating it once an API 36 constant exists.
Suggested implementation:
```
class PermissionManagerServiceHook36(classLoader: ClassLoader) : BaseSubHook(classLoader) {
override fun startHook() {
```
You may also want to remove the now-unused import for `androidx.annotation.RequiresApi` (and possibly `android.os.Build`) at the top of the file if they are only used here, to keep imports clean and avoid warnings.
</issue_to_address>
### Comment 2
<location> `app/src/main/java/com/tianma/xsmscode/xp/hook/permission/PermissionManagerServiceHook36.kt:129` </location>
<code_context>
+
+ val permissions = PACKAGE_PERMISSIONS[packageName] ?: return
+ // param.args[3] = rawUserId
+ val rawUserId = param.args[3] as Int
+ val pms = param.thisObject
+
</code_context>
<issue_to_address>
**issue (bug_risk):** Accessing param.args[3] assumes a stable onPackageInstalled signature and may be brittle.
This assumes `onPackageInstalled` will always have `package` at index 0 and `rawUserId` at index 3 with the same types. If the framework signature changes, this could become a `ClassCastException` or `ArrayIndexOutOfBoundsException`. Consider validating `args.size` and the type of `args[3]`, and logging a warning or safely returning when the layout doesn’t match.
</issue_to_address>Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Original comment in English
Hey - I've found 2 issues, and left some high level feedback:
- The
afterOnPackageInstalledhook relies onparam.args[3]being therawUserId, which is brittle against signature changes; consider locating the userId argument more defensively (e.g., by using the method’s parameter types/length or matching known overloads) to avoid mis-indexing on future platform updates. getAllUserIdsassumesmPackageManagerInt.getUsers(true)returns anIntArray, but modernPackageManagerInternaltypically returns user objects; it may be safer to handleList/array of user structures and extract their IDs rather than hard-casting toIntArrayand silently falling back to user 0.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `afterOnPackageInstalled` hook relies on `param.args[3]` being the `rawUserId`, which is brittle against signature changes; consider locating the userId argument more defensively (e.g., by using the method’s parameter types/length or matching known overloads) to avoid mis-indexing on future platform updates.
- `getAllUserIds` assumes `mPackageManagerInt.getUsers(true)` returns an `IntArray`, but modern `PackageManagerInternal` typically returns user objects; it may be safer to handle `List`/array of user structures and extract their IDs rather than hard-casting to `IntArray` and silently falling back to user 0.
## Individual Comments
### Comment 1
<location> `app/src/main/java/com/tianma/xsmscode/xp/hook/permission/PermissionManagerServiceHook36.kt:35` </location>
<code_context>
+ */
+class PermissionManagerServiceHook36(classLoader: ClassLoader) : BaseSubHook(classLoader) {
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ override fun startHook() {
+ try {
</code_context>
<issue_to_address>
**suggestion:** The @RequiresApi annotation doesn’t match the stated Android 16+/API 36 behavior.
The class targets Android 16+/API 36, but `@RequiresApi(Build.VERSION_CODES.TIRAMISU)` is API 33, which is misleading for tools and readers. Since the logic relies on reflection, the annotation isn’t strictly needed; consider removing it for now or updating it once an API 36 constant exists.
Suggested implementation:
```
class PermissionManagerServiceHook36(classLoader: ClassLoader) : BaseSubHook(classLoader) {
override fun startHook() {
```
You may also want to remove the now-unused import for `androidx.annotation.RequiresApi` (and possibly `android.os.Build`) at the top of the file if they are only used here, to keep imports clean and avoid warnings.
</issue_to_address>
### Comment 2
<location> `app/src/main/java/com/tianma/xsmscode/xp/hook/permission/PermissionManagerServiceHook36.kt:129` </location>
<code_context>
+
+ val permissions = PACKAGE_PERMISSIONS[packageName] ?: return
+ // param.args[3] = rawUserId
+ val rawUserId = param.args[3] as Int
+ val pms = param.thisObject
+
</code_context>
<issue_to_address>
**issue (bug_risk):** Accessing param.args[3] assumes a stable onPackageInstalled signature and may be brittle.
This assumes `onPackageInstalled` will always have `package` at index 0 and `rawUserId` at index 3 with the same types. If the framework signature changes, this could become a `ClassCastException` or `ArrayIndexOutOfBoundsException`. Consider validating `args.size` and the type of `args[3]`, and logging a warning or safely returning when the layout doesn’t match.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
app/src/main/java/com/tianma/xsmscode/xp/hook/permission/PermissionManagerServiceHook36.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/tianma/xsmscode/xp/hook/permission/PermissionManagerServiceHook36.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/tianma/xsmscode/xp/hook/permission/PermissionGranterHook.kt
Fixed
Show fixed
Hide fixed
app/src/main/java/com/tianma/xsmscode/xp/hook/permission/PermissionManagerServiceHook36.kt
Fixed
Show fixed
Hide fixed
app/src/main/java/com/tianma/xsmscode/xp/hook/permission/PermissionManagerServiceHook36.kt
Fixed
Show fixed
Hide fixed
app/src/main/java/com/tianma/xsmscode/xp/hook/permission/PermissionManagerServiceHook36.kt
Fixed
Show fixed
Hide fixed
Owner
|
ci build报错,需要修复 |
- Fix unresolved USER_ALL reference in PermissionManagerServiceHook36 - Fix magic number in PermissionGranterHook - Improve argument validation in onPackageInstalled - Handle List<UserInfo> return type in getAllUserIds - Remove incorrect @RequiresApi annotation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PermissionManagerServiceImpl was removed in Android 16 QPR2. The implementation was merged into PermissionManagerService which now extends IPermissionManager.Stub directly. This caused ClassNotFoundException in XSmsCode's PermissionManagerServiceHook34.
Changes:
Summary by Sourcery
为 Android 16(SDK 36)添加专用的权限管理器 Hook,并将新设备路由到该 Hook,以保持自动授予权限的行为。
Bug 修复:
PermissionManagerService的 Hook 替换已被移除的PermissionManagerServiceImplHook,防止在 Android 16+ 上出现ClassNotFoundException。增强功能:
PermissionManagerService的生命周期方法,在 Android 16+ 上为目标应用授予权限,涵盖开机阶段和安装后的两种场景。Original summary in English
Summary by Sourcery
Add a dedicated permission manager hook for Android 16 (SDK 36) and route new devices to it to maintain automatic permission granting.
Bug Fixes:
Enhancements: