Skip to content

Support app cloning (cross-user) awareness in access control and app list cache - #866

Open
allenyelger-hash wants to merge 1 commit into
MetaCubeX:mainfrom
allenyelger-hash:feat/cross-user-access-control
Open

allenyelger-hash wants to merge 1 commit into
MetaCubeX:mainfrom
allenyelger-hash:feat/cross-user-access-control

Conversation

@allenyelger-hash

Copy link
Copy Markdown

Problem

Apps installed via the OS "app cloning" feature (应用分身 on ColorOS/MIUI/etc., clone user) are invisible to Clash Meta for Android:

  • They never appear in the Access Control app list, which only enumerates the main user's packages (discussion #803)
  • Connections from cloned app instances cannot be resolved to an app name, and PROCESS-NAME rules cannot match them, because the app list cache (AppListCacheModule) only knows main-user uids
  • On Android 17 this got worse: cloned apps can lose network access entirely when the VPN is on (discussion #865, OnePlus 13 / Android 17)

Android VPNs are strictly per-user: a VpnService established in the main profile never covers apps in other users, and there is no app-reachable API to change that. PR #788 already added the INTERACT_ACROSS_USERS permission (ADB-grantable) as groundwork for cross-profile scenarios — this PR builds on that.

Changes

All cross-user enumeration fails soft (empty/null on missing permission or blocked hidden API), so without the ADB grant behavior is unchanged.

  1. New helper common/.../compat/CrossUser.kt

    • Context.crossUserProfiles(): non-main profiles via UserManager.getUserProfiles() (work profile / app-cloning clone user)
    • Context.getInstalledPackagesAsUserCompat(): reflection-based PackageManager.getInstalledPackagesAsUser with the already-declared INTERACT_ACROSS_USERS
  2. Access Control list (AccessControlActivity): appends cloned app instances (same filters as the main list), with a (clone) label suffix. Since selection is keyed by package name, main and cloned instances share one switch — no schema change. When clone profiles are detected but enumeration is denied, a one-time dialog explains the per-user VPN limitation and shows the ADB grant command (EN + zh-CN strings).

  3. App list cache (AppListCacheModule): additionally reports uids from clone profiles (their uids already carry the user offset), so connections from cloned apps resolve to the right package name and PROCESS-NAME rules can match them.

Notes

  • This does not (and cannot) make the main-profile VPN route cloned apps' traffic — Android keeps VPNs per user. The dialog guidance mentions the practical workarounds (disable "Block connections without VPN"; clone CMFA itself and run it inside the cloned profile).
  • Only values/values-zh strings are added; other locales fall back to English.
  • No storage schema change; TunService's allow/deny application logic is untouched.

Test plan

  • ./gradlew :app:compileDebugKotlin / assembleDebug locally
  • Without ADB grant: access control list unchanged (no crash when clone profiles exist)
  • With adb shell pm grant --user 0 com.github.metacubex.clash.meta android.permission.INTERACT_ACROSS_USERS: cloned instances appear with (clone) suffix; hint dialog no longer shown
  • Connections from cloned apps show the package name (not a raw uid)

Refs: #788, discussions #803, #865

…pp list cache

- Enumerate cloned-app (dual app / clone user) instances in the access
  control list with a (clone) label suffix, sharing the selection state
  of their main-profile counterpart
- Report cloned instances' uids in the app list cache so connections
  from cloned apps resolve to package names and PROCESS-NAME rules can
  match them
- Show a one-time dialog with ADB grant instructions when clone profiles
  are detected but cross-user enumeration is denied
- All cross-user enumeration fails soft and is a no-op without the
  ADB-granted INTERACT_ACROSS_USERS permission (declared since MetaCubeX#788)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant