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 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 page.
Non-SDK interface restrictions
To help ensure app stability and compatibility, the platform started restricting which 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), 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 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.
To learn more, see Updates to non-SDK interface restrictions in Android 10 and see Restrictions on 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 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 documentation.
NDK
Android 10 includes the following NDK changes.
Shared objects cannot contain text relocations
Android 6.0 (API level 23) disallowed use 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.
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()
is ignored. - When TLS 1.3 is negotiated,
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 anSSLHandshakeException
on previous versions of Android, these instances throw anSSLProtocolException
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")
.
You can also enable or disable protocol versions on a per-connection basis by
calling setEnabledProtocols()
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
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 aren't sticky:
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
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
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
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
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
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
,
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()
,
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, 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.
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.
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 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()
,
an IllegalArgumentException
occurs. In previous versions, passing null
into setSSLSocketFactory()
had the same effect as passing in the current default
factory.
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. For additional resources to aid in migration and
development, check out the updated Settings
Guide along with our public sample
app
and reference documentation.
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
if they
were invoked after a call to end()
.
In Android 10, these methods throw a
NullPointerException
instead.
ZipFile
In Android 10 and higher, the constructor for
ZipFile
that takes arguments of type File
, int
, and Charset
doesn't throw a
ZipException
if the supplied ZIP file
doesn't contain any files.
ZipOutputStream
In Android 10 and higher, the
finish()
method in
ZipOutputStream
doesn't throw a
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. 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
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 anIllegalArgumentException
instead ofIndexOutOfBoundsException
if the replacementString
ends with a lone backslash, which is illegal. The same exception is now thrown if the replacementString
ends with a$
. Previously, no exception was thrown in this scenario.replaceFirst(null)
no longer callsreset()
on theMatcher
if it throws aNullPointerException
.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)
andgroup(int group)
now throw a more generalIndexOutOfBoundsException
if the group index is out of bounds. Previously, these methods threwArrayIndexOutOfBoundsException
.
Default angle for GradientDrawable is now TOP_BOTTOM
In Android 10, if you define a
GradientDrawable
in XML and do not provide an angle measurement, the gradient orientation
defaults to
TOP_BOTTOM
.
This is a change from previous versions of Android, where the default was
LEFT_RIGHT
.
As a workaround, if you update to the most recent version of 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. 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 aserialVersionUID
. - The default
serialVersionUID
is different than theserialVersionUID
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()
. 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.