1## Annotations {#annotation} 2 3### Annotation processors {#annotation-processor} 4 5Annotation processors should opt-in to incremental annotation processing to 6avoid triggering a full recompilation on every client source code change. See 7Gradle's 8[Incremental annotation processing](https://docs.gradle.org/current/userguide/java_plugin.html#sec:incremental_annotation_processing) 9documentation for information on how to opt-in. 10 11### `@RequiresOptIn` APIs {#experimental-api} 12 13Jetpack libraries may choose to annotate API surfaces as unstable using either 14Kotlin's 15[`@RequiresOptIn` meta-annotation](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-requires-opt-in/) 16for APIs written in Kotlin or Jetpack's 17[`@RequiresOptIn` meta-annotation](https://developer.android.com/reference/kotlin/androidx/annotation/RequiresOptIn) 18for APIs written in Java. 19 20> `@RequiresOptIn` at-a-glance: 21> 22> * Use for unstable API surfaces 23> * Can be called by anyone 24> * Documented in public documentation 25> * Does not maintain compatibility 26 27For either annotation, API surfaces marked as opt-in are considered alpha and 28will be excluded from API compatibility guarantees. Due to the lack of 29compatibility guarantees, stable libraries *must never* call experimental APIs 30exposed by other libraries outside of their 31[same-version group](#same-version-atomic-groups) and *may not* use the `@OptIn` 32annotation except in the following cases: 33 34* A library within a same-version group *may* call an experimental API exposed 35 by another library **within its same-version group**. In this case, API 36 compatibility guarantees are covered under the same-version group policies 37 and the library *may* use the `@OptIn` annotation to prevent propagation of 38 the experimental property. **Library owners must exercise care to ensure 39 that post-alpha APIs backed by experimental APIs actually meet the release 40 criteria for post-alpha APIs.** 41* An `alpha` library may use experimental APIs from outside its same-version 42 group. These usages must be removed when the library moves to `beta`. 43 44NOTE JetBrains's own usage of `@RequiresOptIn` in Kotlin language libraries 45varies and may indicate binary instability, functional instability, or simply 46that an API is really difficult to use. Jetpack libraries should treat instances 47of `@RequiresOptIn` in JetBrains libraries as indicating **binary instability** 48and avoid using them outside of `alpha`; however, teams are welcome to obtain 49written assurance from JetBrains regarding binary stability of specific APIs. 50`@RequiresOptIn` APIs that are guaranteed to remain binary compatible *may* be 51used in `beta`, but usages must be removed when the library moves to `rc`. 52 53#### When to mark an API surface as experimental 54 55*Do not* use `@RequiresOptIn` for a stable API surface that is difficult to use. 56It is not a substitute for a properly-designed API surface. 57 58*Do not* use `@RequiresOptIn` for an API surface that is unreliable or unstable 59because it is missing tests. It is not a substitute for a properly-tested API 60surface, and all APIs -- including those in `alpha` -- are expected to be 61functionally stable. 62 63*Do not* use `@RequiresOptIn` for an internal-facing API surface. Use either the 64appropriate language visibility (ex. `private` or `internal`) or `@RestrictTo`. 65 66*Do not* use `@RequiresOptIn` for an API that you expect library developers to 67call. Experimental APIs do not maintain binary compatibility guarantees, and you 68will put external clients in a difficult situation. 69 70*Do* use `@RequiresOptIn` for API surfaces that must be publicly available and 71documented but need the flexibility to stay in `alpha` during the rest of the 72library's `beta`, `rc`, or stable cycles, and continue to break compatibility in 73`beta`. 74 75#### How to mark an API surface as experimental 76 77All libraries using `@RequiresOptIn` annotations *must* depend on the 78`androidx.annotation:annotation-experimental` artifact regardless of whether 79they are using the `androidx` or Kotlin annotation. This artifact provides Lint 80enforcement of experimental usage restrictions for Kotlin callers as well as 81Java (which the Kotlin annotation doesn't handle on its own, since it's a Kotlin 82compiler feature). Libraries *may* include the dependency as `api`-type to make 83`@OptIn` available to Java clients; however, this will also unnecessarily expose 84the `@RequiresOptIn` annotation. 85 86```java 87dependencies { 88 implementation(project(":annotation:annotation-experimental")) 89} 90``` 91 92See Kotlin's 93[opt-in requirements documentation](https://kotlinlang.org/docs/reference/opt-in-requirements.html) 94for general usage information. If you are writing experimental Java APIs, you 95will use the Jetpack 96[`@RequiresOptIn` annotation](https://developer.android.com/reference/kotlin/androidx/annotation/RequiresOptIn) 97rather than the Kotlin compiler's annotation. 98 99#### How to transition an API out of experimental 100 101When an API surface is ready to transition out of experimental, the annotation 102may only be removed during an alpha pre-release stage. Removing the experimental 103marker from an API is equivalent to adding the API to the current API surface. 104 105When transitioning an entire feature surface out of experimental, you *should* 106remove the definition for the associated experimental marker annotation. 107 108When making any change to the experimental API surface, you *must* run 109`./gradlew updateApi` prior to uploading your change. 110 111NOTE Experimental marker annotation *are themselves* experimental, meaning that 112it's considered binary compatible to refactor or remove an experimental marker 113annotation. 114 115Note: Experimental APIs are reviewed by API Council both when the APIs are first 116introduced, and when they are stabilized. API Council may have additional 117feedback during stabilization. 118 119### `@RestrictTo` APIs {#restricted-api} 120 121Jetpack's library tooling supports hiding JVM-visible (ex. `public` and 122`protected`) APIs from developers using a combination of the `@RestrictTo` 123source annotation. 124 125> `@RestrictTo` at-a-glance: 126> 127> * Use for internal-facing API surfaces 128> * Can be called within the specified `Scope` 129> * Does not appear in public documentation 130> * Does not maintain compatibility in most scopes 131 132While restricted APIs do not appear in documentation and Android Studio will 133warn against calling them, hiding an API does *not* provide strong guarantees 134about usage: 135 136* There are no runtime restrictions on calling hidden APIs 137* Android Studio will not warn if hidden APIs are called using reflection 138* Hidden APIs will still show in Android Studio's auto-complete 139 140These annotations indicate that developers should not call an API that is 141*technically* public from a JVM visibility perspective. Hiding APIs is often a 142sign of a poorly-abstracted API surface, and priority should be given to 143creating public, maintainable APIs and using Java visibility modifiers. 144 145*Do not* use `@RestrictTo` to bypass API tracking and review for production 146APIs; instead, rely on API+1 and API Council review to ensure APIs are reviewed 147on a timely basis. 148 149*Do not* use `@RestrictTo` for implementation detail APIs that are used between 150libraries and could reasonably be made public. 151 152*Do* use `@RestrictTo(LIBRARY)` for implementation detail APIs used within a 153single library (but prefer Java language `private` or `default` visibility). 154 155#### `RestrictTo.Scope` and inter- versus intra-library API surfaces {#private-api-types} 156 157To maintain binary compatibility between different versions of libraries, 158restricted API surfaces that are used between libraries within Jetpack 159(inter-library APIs) must follow the same Semantic Versioning rules as public 160APIs. Inter-library APIs should be annotated with the 161`@RestrictTo(LIBRARY_GROUP)` source annotation. 162 163Restricted API surfaces used within a single library (intra-library APIs), on 164the other hand, may be added or removed without any compatibility 165considerations. It is safe to assume that developers *never* call these APIs, 166even though it is technically feasible. Intra-library APIs should be annotated 167with the `@RestrictTo(LIBRARY)` source annotation. 168 169In all cases, correctness and compatibility tracking are handled by AndroidX's 170build system and lint checks. 171 172The following table shows the visibility of a hypothetical API within Maven 173coordinate `androidx.concurrent:concurrent` when annotated with a variety of 174scopes: 175 176<table> 177 <tr> 178 <td><code>RestrictTo.Scope</code></td> 179 <td>Visibility by Maven coordinate</td> 180 <td>Versioning</td> 181 <td>Note</td> 182 </tr> 183 <tr> 184 <td><code>LIBRARY</code></td> 185 <td><code>androidx.concurrent:concurrent</code></td> 186 <td>No compatibility guarantees (same as private)</td> 187 <td></td> 188 </tr> 189 <tr> 190 <td><code>LIBRARY_GROUP</code></td> 191 <td><code>androidx.concurrent:*</code></td> 192 <td>Semantic versioning (including deprecation)</td> 193 <td></td> 194 </tr> 195 <tr> 196 <td><code>LIBRARY_GROUP_PREFIX</code></td> 197 <td><code>androidx.*:*</code></td> 198 <td>Semantic versioning (including deprecation)</td> 199 <td></td> 200 </tr> 201 <tr> 202 <td><code>TEST</code></td> 203 <td><code>*</code></td> 204 <td>No compatibility guarantees (same as private)</td> 205 <td>Not allowed in Jetpack, use `@VisibleForTesting`</td> 206 </tr> 207</table> 208 209#### Test APIs and `@VisibleForTesting` 210 211For library APIs that should only be used from test code -- including the 212library's own tests, integration test apps, app developers' tests, or 213third-party testing libraries -- use the `@VisibleForTesting` annotation to 214ensure that the API is only called from test source sets. 215 216Libraries targeted at multi-platform usage in IntelliJ may use `@TestOnly` to 217ensure that the IDE enforces usage restrictions. 218 219Jetpack prefers that libraries expose test APIs as public API and maintain 220binary compatibility. This ensures that whatever a library needs in its own 221integration test app is available to app developers and may be safely called in 222third-party testing libraries. 223 224In cases where a test API needs restricted visibility or flexibility around 225binary compatibility, the `@VisibleForTesting` annotation may be combined with a 226`@RestrictTo` scope or `@RequiresOptIn` feature group. 227 228#### `@IntDef` `@StringDef` and `@LongDef` and visibility 229 230All `@IntDef`, `@StringDef`, and `@LongDef` will be stripped from resulting 231artifacts to avoid issues where compiler inlining constants removes information 232as to which `@IntDef` defined the value of `1`. The annotations are extracted 233and packaged separately to be read by Android Studio and lint which enforces the 234types in application code. 235 236* Libraries *must* `@RestrictTo` all `@IntDef`, `@StringDef`, and `@LongDef` 237 declarations to create a warning when the type is used incorrectly. 238* Libraries *must* expose constants used to define the `@IntDef` etc at the 239 same Java visibility as the hidden `@IntDef` 240 241Here is a complete example of an `@IntDef` 242 243```java 244// constants match Java visibility of ExifStreamType 245// code outside this module interacting with ExifStreamType uses these constants 246public static final int STREAM_TYPE_FULL_IMAGE_DATA = 1; 247public static final int STREAM_TYPE_EXIF_DATA_ONLY = 2; 248 249@RestrictTo(RestrictTo.Scope.LIBRARY) // Don't export ExifStreamType outside module 250@Retention(RetentionPolicy.SOURCE) 251@IntDef({ 252 STREAM_TYPE_FULL_IMAGE_DATA, 253 STREAM_TYPE_EXIF_DATA_ONLY, 254}) 255public @interface ExifStreamType {} 256``` 257 258Java visibility should be set as appropriate for the code in question 259(`private`, `package`, or `public`) and is unrelated to hiding. 260 261For more, read the section in 262[Android API Council Guidelines](https://android.googlesource.com/platform/developers/docs/+/refs/heads/main/api-guidelines/framework.md#framework-hide-typedefs) 263 264#### `*current.txt` File Explanation {#currenttxt} 265 266In this example, `1.3.0-beta02.txt` is just used for an example. This will match 267the current library version. 268 269<table> 270 <tr> 271 <td><code>api/current.txt</code></td> 272 <td>All public APIs.</td> 273 </tr> 274 <tr> 275 <td><code>api/1.3.0-beta02.txt</code></td> 276 <td>All public APIs available in version <code>1.3.0-beta02</code>. 277 Used to enforce compatibility in later versions. This file is only 278 generated during Beta.</td> 279 </tr> 280 <tr> 281 <td><code>api/public_plus_experimental_current.txt </code></td> 282 <td>Superset of all public APIs (<code>api/current.txt</code>) and all 283 experimental/<code>RequiresOptIn</code> APIs. 284 </td> 285 </tr> 286 <tr> 287 <td><code>api/public_plus_experimental_1.3.0-beta03.txt</code></td> 288 <td>Superset of all public APIs (<code>api/1.3.0-beta02.txt.txt</code>) and all 289 experimental/RequiresOptIn APIs, as available in version 290 <code>1.3.0-beta02.txt</code>. Only generated during Beta.</td> 291 <tr> 292 <td><code>api/restricted_current.txt</code></td> 293 <td>Superset of all public APIs (<code>api/current.txt</code>) and 294 all <code>RestrictTo</code> APIs that require compatibility across 295 versions. 296 <p/>Specifically, includes <code>@RestrictTo(LIBRARY_GROUP)</code> 297 (for non-atomically versioned groups) and 298 <code>@RestrictTo(LIBRARY_GROUP_PREFIX)</code> (for all libraries).</td> 299 </tr> 300 <tr> 301 <td><code>api/restricted_1.3.0-beta02.txt.txt</code></td> 302 <td>Superset of all public APIs (<code>api/current.txt</code>) and 303 all <code>RestrictTo</code> APIs that require compatibility across 304 versions, as available in version <code>1.3.0-beta02.txt</code>. 305 <p/> 306 Specifically, includes <code>@RestrictTo(LIBRARY_GROUP)</code> 307 (for non-atomically versioned groups) and 308 <code>@RestrictTo(LIBRARY_GROUP_PREFIX)</code> (for all libraries). 309 This file is only generated during Beta.</td> 310 </tr> 311</table> 312