Security & malwareDevice & system
Runtime Permissions and App Ops on Android
runtime-permissions.xml and appops.xml: which dangerous permissions each app holds, grant flags, last access and reject times, and Privacy dashboard history.
- Location
- /data/misc_de/<user>/apexdata/com.android.permission/runtime-permissions.xml (11+), /data/system/users/<user>/runtime-permissions.xml (8 to 10), /data/system/appops.xml
- Proves
- Which runtime permissions (location, camera, microphone, SMS, contacts, call log) each app was granted or denied and how, and when an app last used or was refused a protected operation
- Timestamps
- runtime-permissions.xml: none per grant; appops: last access and last reject times in Unix milliseconds (UTC) per operation; discrete history on Android 11+ for the Privacy dashboard
- Access
- Full file system (root, exploit or agent): both files are in device-encrypted storage, so BFU readable by a privileged extraction. Logical (no root): dumpsys package and dumpsys appops, cmd appops get. Bugreport: included. Not in ADB backup.
- Retention
- Current grants only; appops last-access times are overwritten by the next access; discrete access history covers a short recent window (about 24 hours to 7 days depending on the release)
- Collection
- Full file system extraction, adb shell dumpsys package, adb shell dumpsys appops, adb shell cmd appops get <package>, adb bugreport, androidqf
Tools
Compare all tools- dumpsysCLI · on the device
- appopsCLI · on the device
- pmCLI · on the device
- abx2xmlCLI · on the device
- ccl_abxLibrary · open source
- xmllintCLI · open source
- MVTCLI · open source
- androidqfCLI · open source
- ALEAPPCLI · open source
What it is
Android protects sensitive data behind permissions. Normal permissions are granted at install time and recorded in packages.xml. Dangerous permissions (location, camera, microphone, SMS, call log, contacts, storage, nearby devices, notifications on Android 13+) are runtime permissions: the user grants them in a dialog or in Settings, and the system records the result in runtime-permissions.xml.
A second layer, App Ops, tracks individual protected operations (reading location, using the camera, reading the clipboard, drawing over other apps, accessing usage stats) with their current mode and the last time each was allowed or rejected. App Ops also holds several special accesses that are not ordinary permissions, such as SYSTEM_ALERT_WINDOW, GET_USAGE_STATS and REQUEST_INSTALL_PACKAGES.
Together these files answer the core stalkerware question: which app could read what, and when did it last do so.
Where it lives
| Item | Path | Notes |
|---|---|---|
| Runtime permissions (8 to 10) | /data/system/users/<user>/runtime-permissions.xml | Per user |
| Runtime permissions (11+) | /data/misc_de/<user>/apexdata/com.android.permission/runtime-permissions.xml | Moved into the permission mainline module |
| App Ops state | /data/system/appops.xml | Current modes and last access or reject times; later builds may keep it under /data/system/appops/ (verify) |
| Discrete access history | /data/system/appops/discrete/ | Android 11+ individual accesses for the Privacy dashboard |
| Install-time permissions | /data/system/packages.xml | <perms> per package |
Android 12 and later write these files in Android Binary XML on most builds.
What it proves
- Each app's runtime permission state: granted or not, and flags that say how (
USER_SET,USER_FIXEDfor "don't ask again",POLICY_FIXEDfor device policy,GRANTED_BY_DEFAULTorSYSTEM_FIXEDfor preinstalled apps,ONE_TIME,REVOKED_COMPAT). - Background location (
ACCESS_BACKGROUND_LOCATION) separately from foreground location. - The last time an app accessed a protected operation (
t) or was rejected (r), and for how long (d), per operation and sometimes per attribution tag. - Special accesses such as overlay, usage stats and install from unknown sources.
- On Android 12+, the recent list of individual accesses that feeds the Privacy dashboard and the camera and microphone indicators.
It does not prove the user consciously chose the grant: an accessibility service or device owner can grant permissions, and some flags reveal exactly that.
Key fields
| Element or attribute | Meaning |
|---|---|
<pkg name> / <shared-user name> | Package or shared UID |
<item name granted flags> | Permission, grant state, hex flag bits |
<uid n> / <pkg n> (appops) | UID and package |
<op n> | Operation code (numeric; for example 0 coarse location, 1 fine location, 26 camera, 27 record audio, 24 system alert window, 43 get usage stats, 66 request install packages) |
<st ... t r d> | Last allowed time, last rejected time, duration (ms) |
m | Mode: 0 allowed, 1 ignored, 2 errored, 3 default, 4 foreground |
Op codes are defined in AppOpsManager and new ones are added in each release; resolve them with the table for your Android version or read names from dumpsys appops, which prints them.
Timestamps
App Ops times are Unix milliseconds in UTC. dumpsys appops prints them relative to now (+1h2m3s ago), so note the exact time you ran it.
adb shell dumpsys appops > dumpsys_appops.txt
adb shell cmd appops get com.example.suspect
adb shell dumpsys package com.example.suspect | grep -A50 'runtime permissions:'
Retention
Grant state is current only. Each operation keeps just its latest access and reject time. The discrete history for the Privacy dashboard covers a short recent window (24 hours on Android 12, up to 7 days on later releases) and is pruned continuously. Uninstalling an app removes its entries.
Collection
- Full file system extraction: both XML files and the
appops/folder, available even in BFU. - Logical:
dumpsys package,dumpsys appopsandcmd appops get <pkg>per suspicious package. androidqf collects these automatically. - Bugreport: includes package and appops dumps.
Parsing
- MVT flags apps with dangerous permission combinations and special accesses from androidqf output or a bugreport.
- abx2xml or ccl_abx for Android 12+ files, then
xmllint. - ALEAPP reports permissions on some versions.
Investigator tips
- Line up the last access of
RECORD_AUDIOorFINE_LOCATIONwith usagestats: access while the app never came to the foreground is a strong indicator of background surveillance. REQUEST_INSTALL_PACKAGESgranted to a browser or file manager explains a sideload; the APK's installer is in installed packages.- Combine with accessibility and device admin and settings findings; the malware triage guide walks through the full check.