Android 10 includes behavior changes that may affect your app. The changes listed on this page apply to your app when running on Android 10, regardless of the app's`targetSdkVersion`. You should test your app and modify it as needed to support these changes properly.

If your app's targetSdkVersion is`29`or higher, you'll also need to support additional changes. Make sure to read[behavior changes for apps targeting 29](https://developer.android.com/about/versions/10/behavior-changes-10)for details.  
**Note:**In addition to the changes listed on this page, Android 10 introduces a large number of privacy-based changes and restrictions, including the following:

- Background access to device location
- Background activity starts
- Contacts affinity information
- MAC address randomization
- Camera metadata
- Permissions model

These changes affect all apps and enhance user privacy. To learn more about how to support these changes, see the[Privacy changes](https://developer.android.com/about/versions/10/privacy/changes)page.

## Non-SDK interface restrictions

To help ensure app stability and compatibility, the platform started restricting which[non-SDK interfaces](https://developer.android.com/guide/app-compatibility/restrictions-non-sdk-interfaces)your app can use in Android 9 (API level 28). Android 10 includes updated lists of restricted non-SDK interfaces based on collaboration with Android developers and the latest internal testing. Our goal is to make sure that public alternatives are available before we restrict non-SDK interfaces.

If you will not be targeting Android 10 (API level 29), some of these changes might not immediately affect you. However, while you can currently use some non-SDK interfaces ([depending on your app's target API level](https://developer.android.com/guide/app-compatibility/restrictions-non-sdk-interfaces#list-names)), using any non-SDK method or field always carries a high risk of breaking your app.

If you are unsure if your app uses non-SDK interfaces, you can[test your app](https://developer.android.com/guide/app-compatibility/restrictions-non-sdk-interfaces#test-for-non-sdk)to find out. If your app relies on non-SDK interfaces, you should begin planning a migration to SDK alternatives. Nevertheless, we understand that some apps have valid use cases for using non-SDK interfaces. If you cannot find an alternative to using a non-SDK interface for a feature in your app, you should[request a new public API](https://developer.android.com/guide/app-compatibility/restrictions-non-sdk-interfaces#feature-request).

To learn more, see[Updates to non-SDK interface restrictions in Android 10](https://developer.android.com/about/versions/10/non-sdk-q)and see[Restrictions on non-SDK interfaces](https://developer.android.com/guide/app-compatibility/restrictions-non-sdk-interfaces).

## Gesture Navigation

Beginning with Android 10, users can enable gesture navigation across the device. If a user enables gesture navigation, this affects all apps on the device, whether or not the app targets API level 29. For example, if the user swipes in from the edge of the screen, the system interprets that gesture as a Back navigation, unless an app[specifically overrides that gesture](https://developer.android.com/guide/navigation/gesturenav#conflicting-gestures)for portions of the screen.

To make your app compatible with gesture navigation, you'll want to extend the app content from edge to edge, and handle conflicting gestures appropriately. For information, see the[Gesture navigation](https://developer.android.com/guide/navigation/gesturenav)documentation.

## NDK

Android 10 includes the following NDK changes.

### Shared objects cannot contain text relocations

Android 6.0 (API level 23)[disallowed use](https://android.googlesource.com/platform/bionic/+/master/android-changes-for-ndk-developers.md#text-relocations-enforced-for-api-level-23)of text relocations in shared objects. Code must be loaded as-is, and must not be modified. This change improves app load times and security.

SELinux enforces this restriction on apps that target Android 10 or higher. If these apps continue to use shared objects that contain text relocations, they're at high risk of breaking.

## Changes to Bionic libraries and dynamic linker paths

Starting in Android 10, several paths are symbolic links instead of regular files. Apps that have been relying on the paths being regular files might break:

- `/system/lib/libc.so`-\>`/apex/com.android.runtime/lib/bionic/libc.so`
- `/system/lib/libm.so`-\>`/apex/com.android.runtime/lib/bionic/libm.so`
- `/system/lib/libdl.so`-\>`/apex/com.android.runtime/lib/bionic/libdl.so`
- `/system/bin/linker`-\>`/apex/com.android.runtime/bin/linker`

These changes apply to the 64-bit variants of the file as well, with`lib/`replaced with`lib64/`.

For compatibility, the symlinks are provided at the old paths. For example,`/system/lib/libc.so`is a symlink to`/apex/com.android.runtime/lib/bionic/libc.so`. So`dlopen("/system/lib/libc.so")`continues to work, but apps will find the difference when they actually try to examine the loaded libraries by reading`/proc/self/maps`or similar, which is not usual but we've found that some apps do that as part of their anti-hacking process. If so, the`/apex/...`paths should be added as valid paths for the Bionic files.

## System binaries/libraries mapped to execute-only memory

Starting in Android 10, executable segments of system binaries and libraries are mapped into memory execute-only (non-readable) as a hardening technique against code-reuse attacks. If your app performs read operations into memory segments marked as execute-only -- whether from bug, vulnerability, or intentional memory inspection -- the system sends a`SIGSEGV`signal to your app.

You can identify whether this behavior caused a crash by examining the related tombstone file in`/data/tombstones/`. An execute-only related crash contains the following abort message:  

```
Cause: execute-only (no-read) memory access error; likely due to data in .text.
```

To work around this issue to perform operations like memory inspection, it's possible to mark execute-only segments as read+execute by calling`mprotect()`. However, we strongly recommend setting it back to execute-only afterwards, as this access permission setting provides better protection for your app and users.
| **Note:** Calls to`ptrace`are unaffected by this behavior, allowing you to debug`ptrace`.

## Security

Android 10 includes the following security changes.

### TLS 1.3 enabled by default

In Android 10 and higher, TLS 1.3 is enabled by default for all TLS connections. Here are a few important details about our TLS 1.3 implementation:

- The TLS 1.3 cipher suites cannot be customized. The supported TLS 1.3 cipher suites are always enabled when TLS 1.3 is enabled. Any attempt to disable them by calling[`setEnabledCipherSuites()`](https://developer.android.com/reference/javax/net/ssl/SSLSocket#setEnabledCipherSuites(java.lang.String%5B%5D))is ignored.
- When TLS 1.3 is negotiated,[`HandshakeCompletedListener`](https://developer.android.com/reference/javax/net/ssl/HandshakeCompletedListener)objects are called*before* sessions are added to the session cache. (In TLS 1.2 and other previous versions, these objects are called*after*sessions are added to the session cache.)
- In some situations where`SSLEngine`instances throw an[`SSLHandshakeException`](https://developer.android.com/reference/javax/net/ssl/SSLHandshakeException)on previous versions of Android, these instances throw an[`SSLProtocolException`](https://developer.android.com/reference/javax/net/ssl/SSLProtocolException)instead on Android 10 and higher.
- 0-RTT mode isn't supported.

If desired, you can obtain an`SSLContext`that has TLS 1.3 disabled by calling[`SSLContext.getInstance("TLSv1.2")`](https://developer.android.com/reference/javax/net/ssl/SSLContext#getInstance(java.lang.String)). You can also enable or disable protocol versions on a per-connection basis by calling[`setEnabledProtocols()`](https://developer.android.com/reference/javax/net/ssl/SSLSocket#setEnabledProtocols(java.lang.String%5B%5D))on an appropriate object.

### Certificates signed with SHA-1 aren't trusted in TLS

In Android 10, certificates that use the SHA-1 hash algorithm aren't trusted in TLS connections. Root CAs haven't issued such certificate since 2016, and they are no longer trusted in Chrome or other major browsers.

Any attempt to connect fails if the connection is to a site that presents a certificate using SHA-1.

### KeyChain behavior changes and improvements

Some browsers, such as Google Chrome, allow users to choose a certificate when a TLS server sends a certificate request message as part of a TLS handshake. As of Android 10,[`KeyChain`](https://developer.android.com/reference/android/security/KeyChain)objects honor the issuers and key specification parameters when calling`KeyChain.choosePrivateKeyAlias()`to show users a certificate selection prompt. In particular, this prompt doesn't contain choices that don't adhere to server specifications.

If there are no user-selectable certificates available, as is the case when no certificates match the server specification or a device doesn't have any certificates installed, the certificate selection prompt doesn't appear at all.

In addition, it isn't necessary on Android 10 or higher to have a device screen lock to import keys or CA certificates into a`KeyChain`object.

### Other TLS and cryptography changes

There have been several minor changes in the TLS and cryptography libraries that take effect on Android 10:

- The AES/GCM/NoPadding and ChaCha20/Poly1305/NoPadding ciphers return more accurate buffer sizes from`getOutputSize()`.
- The`TLS_FALLBACK_SCSV`cipher suite is omitted from connection attempts with a max protocol of TLS 1.2 or above. Because of improvements in TLS server implementations, we don't recommend attempting TLS-external fallback. Instead, we recommend relying on TLS version negotiation.
- ChaCha20-Poly1305 is an alias for ChaCha20/Poly1305/NoPadding.
- Hostnames with trailing dots aren't considered valid SNI hostnames.
- The supported_signature_algorithms extension in`CertificateRequest`is respected when choosing a signing key for certificate responses.
- Opaque signing keys, such as those from Android Keystore, can be used with RSA-PSS signatures in TLS.

## Wi-Fi Direct broadcasts

On Android 10, the following broadcasts related to[Wi-Fi Direct](https://developer.android.com/training/connect-devices-wirelessly/wifi-direct)aren't sticky:

- [`WIFI_P2P_CONNECTION_CHANGED_ACTION`](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#WIFI_P2P_CONNECTION_CHANGED_ACTION)
- [`WIFI_P2P_THIS_DEVICE_CHANGED_ACTION`](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#WIFI_P2P_THIS_DEVICE_CHANGED_ACTION)

If your app has relied on receiving these broadcasts at registration because they had been sticky, use the appropriate`get()`method at initialization to obtain the information instead.

## Wi-Fi Aware capabilities

Android 10 adds support to ease TCP/UDP Socket creation using Wi-Fi Aware datapaths. To create a TCP/UDP socket connecting to a`ServerSocket`, the client device needs to know the IPv6 address and port of the server. This previously needed to be communicated out-of-band, such as by using BT or Wi-Fi Aware layer 2 messaging, or discovered in-band using other protocols, such as mDNS. With Android 10, the information can be communicated as part of the network setup.

The server can do either of the following:

- Initialize a`ServerSocket`and either set or obtain the port to be used.
- Specify the port information as part of the Wi-Fi Aware network request.

The following code sample shows how to specify port information as part of the network request:  

### Kotlin

```kotlin
val ss = ServerSocket()
val ns = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle)
  .setPskPassphrase("some-password")
  .setPort(ss.localPort)
  .build()

val myNetworkRequest = NetworkRequest.Builder()
  .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
  .setNetworkSpecifier(ns)
  .build()
```

### Java

```java
ServerSocket ss = new ServerSocket();
WifiAwareNetworkSpecifier ns = new WifiAwareNetworkSpecifier
  .Builder(discoverySession, peerHandle)
  .setPskPassphrase("some-password")
  .setPort(ss.getLocalPort())
  .build();

NetworkRequest myNetworkRequest = new NetworkRequest.Builder()
  .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
  .setNetworkSpecifier(ns)
  .build();
```

The client then performs a Wi-Fi Aware network request to obtain the IPv6 and the port supplied by the server:  

### Kotlin

```kotlin
val callback = object : ConnectivityManager.NetworkCallback() {
  override fun onAvailable(network: Network) {
    ...
  }
  
  override fun onLinkPropertiesChanged(network: Network,
      linkProperties: LinkProperties) {
    ...
  }

  override fun onCapabilitiesChanged(network: Network,
      networkCapabilities: NetworkCapabilities) {
    ...
    val ti = networkCapabilities.transportInfo
    if (ti is WifiAwareNetworkInfo) {
       val peerAddress = ti.peerIpv6Addr
       val peerPort = ti.port
    }
  }
  override fun onLost(network: Network) {
    ...
  }
};

connMgr.requestNetwork(networkRequest, callback)
```

### Java

```java
callback = new ConnectivityManager.NetworkCallback() {
  @Override
  public void onAvailable(Network network) {
    ...
  }
  @Override
  public void onLinkPropertiesChanged(Network network,
      LinkProperties linkProperties) {
    ...
  }
  @Override
  public void onCapabilitiesChanged(Network network,
      NetworkCapabilities networkCapabilities) {
    ...
    TransportInfo ti = networkCapabilities.getTransportInfo();
    if (ti instanceof WifiAwareNetworkInfo) {
       WifiAwareNetworkInfo info = (WifiAwareNetworkInfo) ti;
       Inet6Address peerAddress = info.getPeerIpv6Addr();
       int peerPort = info.getPort();
    }
  }
  @Override
  public void onLost(Network network) {
    ...
  }
};

connMgr.requestNetwork(networkRequest, callback);
```

## SYSTEM_ALERT_WINDOW on Go devices

Apps running on Android 10 (Go edition) devices cannot receive the[`SYSTEM_ALERT_WINDOW`](https://developer.android.com/reference/android/Manifest.permission#SYSTEM_ALERT_WINDOW)permission. This is because drawing overlay windows uses excessive memory, which is particularly harmful to the performance of low-memory Android devices.

If an app running on a Go edition device running Android 9 or lower receives the`SYSTEM_ALERT_WINDOW`permission, the app retains the permission even if the device is upgraded to Android 10. However, apps which do not already have that permission cannot be granted it after the device is upgraded.

If an app on a Go device sends an intent with the action[`ACTION_MANAGE_OVERLAY_PERMISSION`](https://developer.android.com/reference/android/provider/Settings#ACTION_MANAGE_OVERLAY_PERMISSION), the system automatically denies the request, and takes the user to a**Settings** screen which says that the permission isn't allowed because it slows the device. If an app on a Go device calls[`Settings.canDrawOverlays()`](https://developer.android.com/reference/android/provider/Settings#canDrawOverlays(android.content.Context)), the method always returns false. Again, these restrictions do not apply to apps which received the`SYSTEM_ALERT_WINDOW`permission before the device was upgraded to Android 10.

## Warnings for apps targeting older Android versions

Devices running Android 10 or higher warn users the first time they run any app that targets Android 5.1 (API level 22) or lower. If the app requires the user to grant permissions, the user is also given an opportunity to adjust the app's permissions before the app is allowed to run for the first time.

Due to Google Play's[target API requirements](https://support.google.com/googleplay/android-developer/answer/113469#targetsdk), a user sees these warnings only when they run an app that hasn't been updated recently. For apps that are distributed through other stores, similar target API requirements are taking effect during 2019. For more information about these requirements, see[Expanding target API level requirements in 2019](https://android-developers.googleblog.com/2019/02/expanding-target-api-level-requirements.html).

## SHA-2 CBC cipher suites removed

The following SHA-2 CBC cipher suites have been removed from the platform:

- `TLS_RSA_WITH_AES_128_CBC_SHA256`
- `TLS_RSA_WITH_AES_256_CBC_SHA256`
- `TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256`
- `TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384`
- `TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256`
- `TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384`

These cipher suites are less secure than the similar cipher suites that use GCM, and most servers either support both the GCM and CBC variants of these cipher suites or support neither of them.
| **Note:** Apps and libraries should intersect their desired set of cipher suites with the return value from[`getSupportedCipherSuites()`](https://developer.android.com/reference/javax/net/ssl/SSLSocket#getSupportedCipherSuites())to future-proof cipher suite selection against future removals.

## App usage

Android 10 introduces the following behavior changes related to app usage:

- **UsageStats app usage improvements** - Android 10 accurately tracks app usage with[UsageStats](https://developer.android.com/reference/android/app/usage/UsageStats)when apps are used in split-screen or picture-in-picture mode. Additionally, Android 10 correctly tracks instant app usage.

- **Per-app grayscale**- Android 10 can set a grayscale display mode on a per-app basis.

- **Per-app distraction state**- Android 10 can selectively set apps to a "distraction state" where their notifications are suppressed and they do not appear as suggested apps.

- **Suspension and playback**- In Android 10, suspended apps are not able to play audio.

## HTTPS connection changes

If an app running Android 10 passes`null`into[`setSSLSocketFactory()`](https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection#setSSLSocketFactory(javax.net.ssl.SSLSocketFactory)), an[`IllegalArgumentException`](https://developer.android.com/reference/java/lang/IllegalArgumentException)occurs. In previous versions, passing`null`into`setSSLSocketFactory()`had the same effect as passing in the current[default factory](https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection#getDefaultSSLSocketFactory()).

## android.preference library is deprecated

The`android.preference`library is deprecated as of Android 10. Developers should instead use the AndroidX preference library, part of[Android Jetpack](https://developer.android.com/jetpack). For additional resources to aid in migration and development, check out the updated[Settings Guide](https://developer.android.com/guide/topics/ui/settings)along with our[public sample app](https://github.com/android/user-interface-samples/tree/main/Preferences)and[reference documentation](https://developer.android.com/reference/androidx/preference/package-summary).

## ZIP file utility library changes

Android 10 introduces the following changes to classes in the`java.util.zip`package, which handles ZIP files. These changes make the library's behavior more consistent between Android and other platforms that use`java.util.zip`.

### Inflater

In previous versions, some methods in the`Inflater`class threw an[`IllegalStateException`](https://developer.android.com/reference/java/lang/IllegalStateException)if they were invoked after a call to[`end()`](https://developer.android.com/reference/java/util/zip/Inflater#end()). In Android 10, these methods throw a[`NullPointerException`](https://developer.android.com/reference/java/lang/NullPointerException)instead.

### ZipFile

In Android 10 and higher, the[constructor for`ZipFile`](https://developer.android.com/reference/java/util/zip/ZipFile#ZipFile(java.io.File,%20int,%20java.nio.charset.Charset))that takes arguments of type`File`,`int`, and`Charset`doesn't throw a[`ZipException`](https://developer.android.com/reference/java/util/zip/ZipException)if the supplied ZIP file doesn't contain any files.

### ZipOutputStream

In Android 10 and higher, the[`finish()`](https://developer.android.com/reference/java/util/zip/ZipOutputStream#finish())method in`ZipOutputStream`doesn't throw a[`ZipException`](https://developer.android.com/reference/java/util/zip/ZipException)if it tries to write an output stream for a ZIP file that doesn't contain any files.

## Camera changes

Many camera-using apps assume that if the device is in a portrait configuration, then the physical device is also in the portrait orientation, as described in[Camera orientation](https://source.android.com/compatibility/9/android-9-cdd.html#7_5_5_camera_orientation). This was a safe assumption in the past, but that has changed with the expansion of available form factors, such as foldables. That assumption on these devices can lead to either incorrectly rotated or scaled (or both) display of the camera viewfinder.

Applications that target API level 24 or above should explicitly set`android:resizeableActivity`and provide necessary functionality to handle multi-window operation.

## Battery usage tracking

Beginning with Android 10,[`SystemHealthManager`](https://developer.android.com/reference/android/os/health/SystemHealthManager)resets its battery usage statistics whenever the device is unplugged after a*major charging event*. Broadly speaking, a major charging event is either: The device has been fully charged, or the device has gone from mostly depleted to mostly charged.

Before Android 10, the battery usage statistics reset whenever the device was unplugged, no matter how little change there had been to the battery level.

## Android Beam deprecation

In Android 10 we're officially deprecating Android Beam, an older feature for initiating data sharing across devices through Near Field Communication (NFC). We're also deprecating several of the related NFC APIs. Android Beam remains optionally available to device-maker partners who want to use it, but it's no longer in active development. Android will continue to support other NFC capabilities and APIs, however, and use-cases like reading from tags and payments will continue to work as expected.

## java.math.BigDecimal.stripTrailingZeros() behavior change

`BigDecimal.stripTrailingZeros()`no longer preserves trailing zeroes as a special case if the input value is zero.

## java.util.regex.Matcher and Pattern behavior changes

The result of`split()`was changed to no longer start with an empty`String`("") when there is a zero-width match at the start of the input. This also affects`String.split()`. For example,`"x".split("")`now returns`{"x"}`whereas it used to return`{"", "x"}`on older versions of Android.`"aardvark".split("(?=a)"`now returns`{"a", "ardv", "ark"}`rather than`{"", "a", "ardv", "ark"}`.

Exception behavior for invalid arguments has also been improved:

- `appendReplacement(StringBuffer, String)`now throws an`IllegalArgumentException`instead of`IndexOutOfBoundsException`if the replacement`String`ends with a lone backslash, which is illegal. The same exception is now thrown if the replacement`String`ends with a`$`. Previously, no exception was thrown in this scenario.
- `replaceFirst(null)`no longer calls`reset()`on the`Matcher`if it throws a`NullPointerException`.`NullPointerException`is now also thrown when there is no match. Previously, it was thrown only when there was a match.
- `start(int group)`,`end(int group)`and`group(int group)`now throw a more general`IndexOutOfBoundsException`if the group index is out of bounds. Previously, these methods threw`ArrayIndexOutOfBoundsException`.

## Default angle for GradientDrawable is now TOP_BOTTOM

In Android 10, if you define a[`GradientDrawable`](https://developer.android.com/reference/android/graphics/drawable/GradientDrawable)in XML and do not provide an angle measurement, the gradient orientation defaults to[`TOP_BOTTOM`](https://developer.android.com/reference/android/graphics/drawable/GradientDrawable.Orientation#TOP_BOTTOM). This is a change from previous versions of Android, where the default was[`LEFT_RIGHT`](https://developer.android.com/reference/android/graphics/drawable/GradientDrawable.Orientation#LEFT_RIGHT).

As a workaround, if you update to the most recent version of[AAPT2](https://developer.android.com/studio/command-line/aapt2), the tool sets an angle measurement of 0 for legacy apps if no angle measurement is specified.

## Logging for serialized objects using default SUID

Beginning with Android 7.0 (API level 24), the platform made a[fix to the default`serialVersionUID`for serializable objects](https://developer.android.com/about/versions/nougat/android-7.0-changes#n-serialization). This fix did not affect apps that targeted API level 23 or lower.

Beginning with Android 10, if an app targets API level 23 or lower and relies on the old, incorrect, default`serialVersionUID`, the system logs a warning and suggests a code fix.

Specifically, the system logs a warning if all of the following are true:

- The app targets API level 23 or lower.
- A class is serialized.
- The serialized class uses the default`serialVersionUID`, instead of explicitly setting a`serialVersionUID`.
- The default`serialVersionUID`is different than the`serialVersionUID`would be if the app targeted API level 24 or higher.

This warning is logged once for each affected class. The warning message includes a suggested fix, which is to explicitly set the`serialVersionUID`to the default value that would be calculated if the app targeted API level 24 or higher. By using that fix, you can ensure that if an object from that class is serialized on an app that targets API level 23 or lower, the object will be correctly read by apps that target 24 or higher, and vice versa.

## java.io.FileChannel.map() changes

Starting in Android 10,`FileChannel.map()`isn't supported for non-standard files, like`/dev/zero`, whose size cannot be changed using[`truncate()`](http://man7.org/linux/man-pages/man2/truncate.2.html). Previous versions of Android swallowed the errno returned by`truncate()`, but Android 10 throws an IOException. If you need the old behavior, you must use native code.