Skip to content

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

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

ItemPathNotes
Runtime permissions (8 to 10)/data/system/users/<user>/runtime-permissions.xmlPer user
Runtime permissions (11+)/data/misc_de/<user>/apexdata/com.android.permission/runtime-permissions.xmlMoved into the permission mainline module
App Ops state/data/system/appops.xmlCurrent 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_FIXED for "don't ask again", POLICY_FIXED for device policy, GRANTED_BY_DEFAULT or SYSTEM_FIXED for 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 attributeMeaning
<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)
mMode: 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 appops and cmd 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

See also