The permissions model
Android has 365 documented permissions, four protection levels that matter, three grant mechanisms, and a second permission system most developers never see. Here is how they fit together.
An app's sandbox is a set of things it cannot do. Permissions are the things it can be allowed to do anyway. The whole system exists to make that "can be allowed" a decision someone makes deliberately, rather than a consequence of installing a package.
TL;DR#
- A is a named capability, declared in the manifest by the app that wants it, and granted by the platform or the user.
- The protection level decides who can grant it:
normalautomatically,dangerousby the user,signatureonly to apps with the same signing key,privilegedonly to system-image apps. - Runtime permissions (API 23Android 6.0) moved the
dangerousdecision from install to use. - is a second, finer-grained system for operations that are not permissions: clipboard access, background starts, camera use by a background app.
- Android has 365 permissions documented in this site's dataset, and the protection levels are
overwhelmingly not
dangerous.
Mental model#
Think of a hotel with two kinds of access control.
The room key is the sandbox: it opens your room and nothing else. That is a property of who you are, not what you asked for.
The facilities pass is a permission: the gym, the pool, the car park. You request it at reception, and reception may say yes, no, or "ask the manager". Some passes are given to anyone who checks in; some require a membership; some require the manager's key, which only staff have.
Where the analogy breaks#
A hotel gives you one facilities pass. Android gives you a set, and the set can change while you are staying — a permission can be revoked, auto-reset, or granted "only this once". The decision is not made once at check-in; it is made continuously, and the app has to cope with the answer changing.
The big picture#
Text description of this diagram
The security onion, with permissions and consent as the fifth ring from the outside. The sandbox ring inside it defines what an app can never do; the permissions ring defines what it may be allowed to do. This ordering is the key insight: permissions do not weaken the sandbox for other apps, they widen it for one app, and only in the specific dimension the permission names.
Deep dive#
The protection levels#
This site's dataset has 365 permissions parsed from the official reference. Their protection levels are not evenly distributed, and the distribution is itself the story.
| Protection level | Permissions | Who can hold it |
|---|---|---|
| dangerous | 43 | Any app, with explicit user consent at runtime |
| normal | 62 | Any app, granted automatically at install |
| signature | 23 | Only apps signed with the defining app's certificate |
| signature|privileged | 16 | Platform-signed apps on the system image |
| internal|role | 89 | Internal platform roles; not a public API |
| unknown | 88 | Documented without a stated level in the parsed source |
The first thing to notice is that only 43 of 365 are dangerous. The vast majority are either
granted automatically, restricted by signature, or reserved for the platform. The user-facing
permission dialog is a small part of a much larger capability system.
The second thing to notice is signature. A signature permission is granted only to apps signed with
the same certificate as the app that defined it. That is how one developer's suite of apps shares
capabilities without exposing them to anyone else, and it is why the signing key is a security asset
rather than a formality.
The three grant mechanisms#
Install-time. normal permissions are granted when the package is installed. The user sees them
in the store listing but is not asked.1 signature and privileged permissions are granted at install
if the signer or image position qualifies.
Runtime. Since API 23Android 6.0, dangerous permissions require an explicit user decision at
the moment of use. The app calls requestPermissions, the system shows a dialog, and the result can
be granted, denied, or (since API 30Android 11) granted only once.
Special access. A small set of capabilities are neither: they are granted through a Settings screen rather than a dialog. "Display over other apps", "accessibility service", "notification listener" and "usage access" are the classic examples. They are powerful enough that the platform wants the user to leave the app to grant them.
The dangerous set, by API level#
The number of dangerous permissions added per release tells the privacy story better than any
narrative. Totals may not sum to 43, because the dataset also places a handful at API 36 and 37.
| API | Release | New dangerous | Examples |
|---|---|---|---|
| 1 | 1.0 | 17 | CAMERA, RECORD_AUDIO, READ_CONTACTS, CALL_PHONE, ACCESS_FINE_LOCATION |
| 4 | 1.6 | 1 | WRITE_EXTERNAL_STORAGE |
| 9 | 2.3 | 1 | USE_SIP |
| 14 | 4.0 | 1 | ADD_VOICEMAIL |
| 16 | 4.1 | 3 | READ_CALL_LOG, WRITE_CALL_LOG, READ_EXTERNAL_STORAGE |
| 20 | 4.4W | 1 | BODY_SENSORS |
| 26 | 8.0 | 2 | ANSWER_PHONE_CALLS, READ_PHONE_NUMBERS |
| 28 | 9 | 1 | ACCEPT_HANDOVER |
| 29 | 10 | 3 | ACCESS_BACKGROUND_LOCATION, ACCESS_MEDIA_LOCATION, ACTIVITY_RECOGNITION |
| 31 | 12 | 4 | BLUETOOTH_SCAN, BLUETOOTH_CONNECT, BLUETOOTH_ADVERTISE, UWB_RANGING |
| 33 | 13 | 6 | POST_NOTIFICATIONS, READ_MEDIA_IMAGES/VIDEO/AUDIO, NEARBY_WIFI_DEVICES, BODY_SENSORS_BACKGROUND |
| 34 | 14 | 1 | READ_MEDIA_VISUAL_USER_SELECTED |
Two entries are worth dwelling on. POST_NOTIFICATIONS (API 33Android 13) made notifications a
runtime permission, which is the single largest behavioural change to notifications since channels.2
ACCESS_BACKGROUND_LOCATION (API 29Android 10) split location into foreground and background,
and it is granted through a separate, more deliberate flow than the foreground permission.3
AppOps: the second system#
AppOps records whether an app may perform a specific operation, independently of the manifest permission. The two are related but not identical:
- A permission is a capability the app declares it needs.
- An app-op is a decision about a particular use of that capability, right now.
The Settings privacy toggles are app-ops. Turning off camera access for an app does not revoke the
CAMERA permission; it sets the camera app-op to denied, and the framework checks the op at the call
site. That is why an app can hold a permission and still be blocked — a fact that confuses a great
deal of debugging.
Signature permissions and the signing key#
A signature permission is granted only to apps signed with the same certificate as the definer.4
That makes the signing key a capability in its own right: an attacker who obtains your signing key
can publish an app that holds every signature permission your app defines.
This is one reason Play App Signing exists. It separates the app signing key (held by Google) from the upload key (held by the developer), so a compromised developer machine does not immediately compromise the signing identity.
Privileged apps#
A privileged permission is granted only to apps on the system image, allowlisted by the platform.
That allowlist is a security boundary: adding an app to it grants capabilities that no user consent
can provide.
The combination signature|privileged is the most common in AOSP manifests: it is available to
platform-signed apps on the image, which is a small and controlled set.
What the model does not cover#
Three limits are worth naming:
- A granted permission is not bounded. Camera permission is the whole camera. There is no "one photo" version, which is why the photo picker exists as an alternative that grants access to specific items rather than to the gallery.
- The user cannot evaluate most permissions. "Read your contacts" is comprehensible; "bind to a notification listener" is not. The model relies on defaults and on the store's review, not on informed consent for every grant.
- The system trusts the app to be honest about its use. An app with location permission can use location for anything; the platform does not check that the use matches the stated purpose.
How it evolved#
| API | Version | What changed |
|---|---|---|
| 18 | 4.3 Jelly Bean |
|
| 23 | 6.0 Marshmallow |
|
| 28 | 9 Pie |
|
| 30 | 11 |
|
| 31 | 12 |
|
| 33 | 13 Tiramisu |
|
| 37 | 17 Cinnamon Bun |
|
Three eras: install-time consent (1.0–5.x), runtime consent (6.0–10), and fine-grained consent with auto-reset and one-time grants (11 onward). The trajectory is towards narrower grants and more frequent decisions, at the cost of more code in every app that uses a dangerous permission.
Under the hood#
- AndroidManifest.xmlthe platform's own permission definitions and their protection levels
- PermissionManagerService.javapermission definitions, grant state and policy
- AppOpsService.javathe second permission system
- PermissionInfo.javathe protection-level constants
Curiosity corner#
- The permission namespace is shared. Any app can define a permission, and a badly-chosen name can collide with a future platform permission. That is why the convention is to prefix with your package name.
signatureOrSystemis legacy. It used to grant to system apps as well as same-signature apps; the modern equivalent issignature|privileged, which is narrower.- Auto-reset is on by default for unused apps. Since API 30Android 11, an app that has not been used for a few months loses its runtime grants, and the app has to handle that as a normal state.
Try it#
adb shell dumpsys package com.example.app | grep -A30 "runtime permissions"
adb shell appops get com.example.app
adb shell pm list permissions -g -d | head -30
The first shows declared versus granted. The second shows app-ops, which is where the interesting denials live. The third lists the dangerous permissions grouped by category.
Check yourself#
Check yourself
Which layer enforces the app sandbox?
Sources#
Sources
Every version number, API level, class name and date on this page is traced to one of these. Pages are re-verified against them; last_verified above says when.
- docsPermissions on Android | Privacydeveloper.android.comaccessed 2026-10-27↩
- docsBehavior changes: Apps targeting Android 13 or higherdeveloper.android.comaccessed 2026-10-27↩
- docsBehavior changes: Apps targeting Android 10developer.android.comaccessed 2026-10-27↩
- docsManifest.permission | API referencedeveloper.android.comaccessed 2026-10-27↩
- docsApplication sandboxsource.android.comaccessed 2026-10-27↩
- docsSELinuxsource.android.comaccessed 2026-10-27↩
- docsPerubahan Perilaku Android 8.0developer.android.comaccessed 2026-10-27↩
- docsPerubahan perilaku: aplikasi yang menargetkan API level 28+developer.android.comaccessed 2026-10-27↩
- docsBehavior changes: Apps targeting Android 14developer.android.comaccessed 2026-10-27↩
- docsBehavior changes: Apps targeting Android 17developer.android.comaccessed 2026-10-27↩