1<!-- 2 Copyright (C) 2020 The Android Open Source Project 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License 15 --> 16 17# App-ops 18 19App-ops are used for two purposes: Access control and tracking. 20 21App-ops cover a wide variety of functionality from helping with runtime permissions to battery 22consumption tracking. 23 24App-ops are defined in `AppOpsManager` as `OP_...` and need to be continuously numbered. The 25integer values of the app-ops are not exposed. For app-ops visible to 3rd party apps, 26the name of the app-op might be exposed as `OPSTR_`. As the integers are not part of the API, they 27might (and have) changed between platform versions and OEM implementations. 28`AppOpsManager.opToPublicName` and `AppOpsManager.strOpToOp` allow for conversion between integer 29and string identifier for the op. 30 31## App-ops as access restrictions 32 33App-ops can either be controlled for each [uid](../os/Users.md#int-uid) or for each package. Which 34one is used depends on the API provider maintaining this app-op. 35 36For any security or privacy related app-ops the provider needs to control the app-op per uid 37as all security and privacy is based on uid in Android. 38 39App-op used for non-security related tasks are usually controlled per package to provide finer 40granularity. 41 42### Setting the app-op mode 43 44To control access the app-op can be set to: 45 46`MODE_DEFAULT` 47: Default behavior, might differ from app-op to app-op 48 49`MODE_ALLOWED` 50: Allow the access 51 52`MODE_FOREGROUND` 53: Allow the access but only if the app is currently in the [foreground](#foreground) 54 55`MODE_IGNORED` 56: Don't allow the access, i.e. don't perform the requested action or return dummy data 57 58`MODE_ERRORED` 59: Throw a `SecurityException` on access. This can be suppressed by using a `...noThrow` method to 60check the mode 61 62The initial state of an app-op is defined in `AppOpsManager.sOpDefaultMode`. Confusingly the 63initial state is often not `MODE_DEFAULT` 64 65Per-package modes can be set using `AppOpsManager.setMode` and per-uid modes can be set using 66`AppOpsManager.setUidMode`. 67 68**Warning**: Do not use `setMode` and `setUidMode` for the same app-op. Due to the way the 69internal storage for the mode works this can lead to very confusing behavior. If this ever happened 70by accident this needs to be cleaned up for any affected user as the app-op mode is retained over 71reboot. 72 73App-ops can also be set via the shell using the `appops set` command. The target package/uid can be 74defined via parameters to this command. 75 76The current state of the app-op can be read via the `appops get` command or via `dumpsys appops`. 77If the app-op is not mentioned in the output the app-op is in it's initial state. 78 79For example `dumpsys appops`: 80``` 81[...] 82 Uid 2000: 83 [...] 84 COARSE_LOCATION: mode=foreground 85 START_FOREGROUND: mode=foreground 86 LEGACY_STORAGE: mode=ignore 87 [...] 88``` 89 90### Guarding access based on app-ops 91 92API providers need to check the mode returned by `AppOpsManager.noteOp` if they are are allowing 93access to operations gated by the app-op. `AppOpsManager.unsafeCheckOp` should be used to check the 94mode if no access is granted. E.g. this can be for displaying app-op state in the UI or when 95checking the state before later calling `noteOp` anyway. 96 97If an operation refers to a time span (e.g. a audio-recording session) the API provider should 98use `AppOpsManager.startOp` and `AppOpsManager.finishOp` instead of `noteOp`. 99 100`noteOp` and `startOp` take a `packageName` and `featureId` parameter. These need to be read from 101the calling apps context as `Context.getOpPackageName` and `Context.getFeatureId`, then send to 102the data provider and then passed on the `noteOp`/`startOp` method. 103 104#### App-ops and permissions 105 106Access guarding is often done in combination with permissions using [runtime permissions 107](../permission/Permissions.md#runtime-permissions-and-app-ops) or [app-op permissions 108](../permission/Permissions.md#app-op-permissions). This is preferred over just using an app-op 109 as permissions a concept more familiar to app developers. 110 111### Foreground 112 113The `AppOpsService` tracks the apps' proc state (== foreground-ness) by following the 114`ActivityManagerService`'s proc state. It reduces the possible proc states to only those needed 115for app-ops. It also delays the changes by a _settle time_. This delay is needed as the proc state 116can fluctuate when switching apps. By delaying the change the appops service is not affected by 117those. 118 119In addition to proc state, the `AppOpsService` also receives process capability update from the 120`ActivityManagerService`. Proc capability specifies what while-in-use(`MODE_FOREGROUND`) operations 121 the proc is allowed to perform in its current proc state. There are three proc capabilities 122 defined so far: 123`PROCESS_CAPABILITY_FOREGROUND_LOCATION`, `PROCESS_CAPABILITY_FOREGROUND_CAMERA` and 124`PROCESS_CAPABILITY_FOREGROUND_MICROPHONE`, they correspond to the while-in-use operation of 125location, camera and microphone (microphone is `RECORD_AUDIO`). 126 127In `ActivityManagerService`, `PROCESS_STATE_TOP` and `PROCESS_STATE_PERSISTENT` have all 128three capabilities, `PROCESS_STATE_FOREGROUND_SERVICE` has capabilities defined by 129 `foregroundServiceType` that is specified in foreground service's manifest file. A client process 130 can pass its capabilities to service using `BIND_INCLUDE_CAPABILITIES` flag. 131 132The proc state and capability are used for two use cases: Firstly, Tracking remembers the proc state 133 for each tracked event. Secondly, `noteOp`/`checkOp` calls for app-op that are set to 134 `MODE_FOREGROUND` are translated using the `AppOpsService.UidState.evalMode` method into 135 `MODE_ALLOWED` when the app has the capability and `MODE_IGNORED` when the app does not have the 136 capability. `checkOpRaw` calls are not affected. 137 138The current proc state and capability for an app can be read from `dumpsys appops`. 139The tracking information can be read from `dumpsys appops` 140 141``` 142Uid u0a118: 143 state=fg 144 capability=6 145``` 146 147## App-ops for tracking 148 149App-ops track many important events, including all accesses to runtime permission protected 150APIs. This is done by tracking when an app-op was noted or started. The tracked data can only be 151read by system components. 152 153**Note:** Only `noteOp`/`startOp` calls are tracked; `unsafeCheckOp` is not tracked. Hence it is 154important to eventually call `noteOp` or `startOp` when providing access to protected operations 155or data. 156 157Some apps are forwarding access to other apps. E.g. an app might get the location from the 158system's location provider and then send the location further to a 3rd app. In this case the 159app passing on the data needs to call `AppOpsManager.noteProxyOp` to signal the access proxying. 160This might also make sense inside of a single app if the access is forwarded between two features of 161the app. In this case an app-op is noted for the forwarding app (proxy) and the app that received 162the data (proxied). As any app can do it is important to track how much the system trusts this 163proxy-access-tracking. For more details see `AppOpService.noteProxyOperation`. 164 165The tracking information can be read from `dumpsys appops` split by feature, proc state and 166proxying information with the syntax 167 168``` 169Package THE_PACKAGE_NAME: 170 AN_APP_OP (CURRENT_MODE): 171 FEATURE_ID (or null for default feature)=[ 172 ACCESS_OR_REJECT: [PROC_STATE-PROXYING_TAG] TIME proxy[INFO_ABOUT_PROXY IF_PROXY_ACCESS] 173``` 174 175Example: 176 177``` 178Package com.google.android.gms: 179 READ_CONTACTS (allow): 180 null=[ 181 Access: [fgsvc-s] 2020-02-14 14:24:10.559 (-3d23h15m43s642ms) 182 Access: [fgsvc-tp] 2020-02-14 14:23:58.189 (-3d23h15m56s12ms) 183 ] 184 apkappcontext=[ 185 Access: [fg-tp] 2020-02-17 14:24:54.721 (-23h14m59s480ms) 186 ] 187 com.google.android.gms.icing=[ 188 Access: [fgsvc-tpd] 2020-02-14 14:26:27.018 (-3d23h13m27s183ms) proxy[uid=10070, pkg=com.android.providers.contacts, feature=null] 189 Access: [fg-tpd] 2020-02-18 02:26:08.711 (-11h13m45s490ms) proxy[uid=10070, pkg=com.android.providers.contacts, feature=null] 190 Access: [bg-tpd] 2020-02-14 14:34:55.310 (-3d23h4m58s891ms) proxy[uid=10070, pkg=com.android.providers.contacts, feature=null] 191 ] 192 MANAGE_EXTERNAL_STORAGE (default): 193 null=[ 194 Reject: [fg-s]2020-02-18 08:00:04.444 (-5h39m49s757ms) 195 Reject: [bg-s]2020-02-18 08:00:04.427 (-5h39m49s774ms) 196 ] 197``` 198 199### Tracking an app's own private data accesses 200 201An app can register an `AppOpsManager.OnOpNotedCallback` to get informed about what accesses the 202system is tracking for it. As each runtime permission has an associated app-op this API is 203particularly useful for an app that want to find unexpected private data accesses. 204 205## Listening to app-op events 206 207System apps (with the appropriate permissions) can listen to most app-op events, such as 208 209`noteOp` 210: `startWatchingNoted` 211 212`startOp`/`finishOp` 213: `startWatchingActive` 214 215mode changes 216: `startWatchingMode` 217 218[foreground](#foreground)-ness changes 219: `startWatchingMode` using the `WATCH_FOREGROUND_CHANGES` flag 220 221Watching such events is only ever as good as the tracked events. E.g. if the audio provider does 222not call `startOp` for a audio-session, the app's activeness for the record-audio app-op is not 223changed. Further there were cases where app-ops were noted even though no data was accessed or 224operation was performed. Hence before relying on the data from app-ops, double check if the data 225is actually reliable. 226