Android Q introduces great new features and capabilities for users and developers. This document highlights what's new for developers.
To learn about the new APIs, read the API diff report or visit the Android API reference — new APIs are highlighted to make them easy to see. Also be sure to check out Android Q behavior changes (for apps targeting Q and for all apps), as well as privacy changes, to learn about areas where platform changes may affect your apps.
Security enhancements
Android Q introduces a number of security features, which the following sections summarize.
Improved biometric authentication dialogs
Android Q introduces the following improvements to the unified biometric authentication dialogs added in Android 9:
Specify user confirmation requirements
You can now provide a hint that tells the system not to require user confirmation after the user has authenticated using an implicit biometric modality. For example, you could tell the system that no further confirmation should be required after a user has authenticated using Face authentication.
By default, the system requires user confirmation. Typically, users want to
confirm sensitive or high-risk actions (for example, making a purchase).
However, if you have certain low-risk actions for your app, you can provide a
hint to not require user confirmation by passing false to the
setConfirmationRequired()
method. Because this flag is passed as a hint to the system, the system may
ignore the value if the user has changed their system settings for biometric
authentication.
Figure 1.Face authentication with no user confirmation
Figure 2.Face authentication that requires user confirmation
Improved fallback support for device credentials
You can now tell the system to allow a user to authenticate using their device
PIN, pattern, or password if they cannot authenticate using their biometric
input for some reason. To enable this fallback support, use the
setDeviceCredentialAllowed()
method.
If your app currently uses
createConfirmDeviceCredentialIntent()
to fall back to device credentials, switch to using the new method instead.
Check device for biometric capability
You can now check if a device supports biometric authentication prior to
invoking BiometricPrompt
by using the canAuthenticate()
method in the BiometricManager
class.
Run embedded DEX code directly from APK
You can now tell the platform to run embedded DEX code directly from your app’s APK file. This option can help prevent an attack if an attacker ever managed to tamper with the locally compiled code on the device.
To enable this feature, set the value of the android:useEmbeddedDex attribute
to true in the <application>
element of your app’s manifest file. You must also build an APK that contains
uncompressed DEX code that ART can access directly. Add the following options
to your Gradle or Bazel configuration file to build an APK with uncompressed
DEX code:
Gradle
aaptOptions {
noCompress 'dex'
}
Bazel
android_binary( ..., nocompress_extensions = [“.dex”], )
TLS 1.3 support
The platform's TLS implementation now supports TLS 1.3. TLS 1.3 is a major revision to the TLS standard that includes performance benefits and enhanced security. Our benchmarks indicate that secure connections can be established as much as 40% faster with TLS 1.3 compared to TLS 1.2.
TLS 1.3 is enabled by default for all TLS connections. 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.
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, and any attempt to disable
them via a call to
setEnabledCipherSuites()is ignored. - When TLS 1.3 is negotiated,
HandshakeCompletedListenersare called before sessions are added to the session cache (which is the opposite of TLS 1.2 and other previous versions). SSLEngineinstances will throw anSSLProtocolExceptionin some circumstances where they would have thrown anSSLHandshakeExceptionpreviously.- 0-RTT mode is not supported.
Public Conscrypt API
The Conscrypt security provider now includes a public API for TLS functionality. In the past, users could access this functionality via reflection. However, due to restrictions on calling non-public APIs added in P, this has been greylisted in Q and will be further restricted in future releases.
This update adds a collection of classes under android.net.ssl that contain
static methods to access functionality not available from the generic
javax.net.ssl APIs. The names for these classes can be inferred as the plural
of the associated javax.net.ssl class. For example, code that operates on
javax.net.ssl.SSLSocket instances can use methods from the new
android.net.ssl.SSLSockets class.
Connectivity features
Android Q includes several improvements related to networking and connectivity.
Wi-Fi network connection API
Android Q adds support for peer-to-peer connections. This feature enables your
app to prompt the user to change the access point that the device is connected
to by using WifiNetworkSpecifier
to describe properties of a requested network. The peer-to-peer connection is
used for non-network-providing purposes, such as bootstrapping configuration for
secondary devices like Chromecast and Google Home hardware.
You will use the following flow when using this API:
Create a Wi-Fi network specifier using
WifiNetworkSpecifier.Builder.Set a network filter to match networks to connect to, along with required credentials.
Decide on a combination of
SSID,SSID pattern,BSSID, andBSSID patternto set the network filter in each request, subject to the following requirements:- Each request should provide at least one of
SSID,SSID pattern,BSSID, orBSSID pattern - Each request can set only one of
SSIDorSSID pattern - Each request can set only one of
BSSIDorBSSID pattern
- Each request should provide at least one of
Add the specifiers to the network request along with a
NetworkCallbackinstance to track the status of the request.If the user accepts the request and the connection to the network is successful,
NetworkCallback.onAvailable()is invoked on the callback object. If the user denies the request or if the connection to the network is unsuccessful,NetworkCallback.onUnavailable()is invoked on the callback object.
Peer-to-peer connections do not require Location or Wi-Fi permissions. Initiating the request to connect to a peer device launches a dialog box on the same device, from which that device's user can accept the connection request.
Bypassing user approval
Once the user approves a network to connect to in response to a request from a specific app, the device stores the approval for the particular access point. If the app makes a specific request to connect to that access point again, the device will skip the user approval phase and automatically connect to the network. If the user chooses to forget the network while connected to a network requested by the API, then this stored approval for that combination of app and network is removed, and any future request from the app will need to be approved by the user again. If the app makes a non-specific (such as with an SSID or BSSID pattern) request, then the user will need to approve the request.
Code sample
The following code sample shows how to connect to an open network with a SSID prefix of "test" and a BSSID OUI of "10:03:23":
Kotlin
val specifier = WifiNetworkSpecifier.Builder()
.setSsidPattern(PatternMatcher("test", PatternMatcher.PATTERN_PREFIX))
.setBssidPattern(MacAddress.fromString("10:03:23:00:00:00"), MacAddress.fromString("ff:ff:ff:00:00:00"))
.build()
val request = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setNetworkSpecifier(specifier)
.build()
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkCallback = object : ConnectivityManager.NetworkCallback() {
...
override fun onAvailable(network: Network?) {
// do success processing here..
}
override fun onUnavailable() {
// do failure processing here..
}
...
}
connectivityManager.requestNetwork(request, networkCallback)
...
// Release the request when done.
connectivityManager.unregisterNetworkCallback(networkCallback)
Java
final NetworkSpecifier specifier =
new WifiNetworkSpecifier.Builder()
.setSsidPattern(new PatternMatcher("test", PatterMatcher.PATTERN_PREFIX))
.setBssidPattern(MacAddress.fromString("10:03:23:00:00:00"), MacAddress.fromString("ff:ff:ff:00:00:00"))
.build();
final NetworkRequest request =
new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setNetworkSpecifier(specifier)
.build();
final ConnectivityManager connectivityManager = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkCallback networkCallback = new NetworkCallback() {
...
@Override
void onAvailable(...) {
// do success processing here..
}
@Override
void onUnavailable(...) {
// do failure processing here..
}
...
};
connectivityManager.requestNetwork(request, networkCallback);
...
// Release the request when done.
connectivityManager.unregisterNetworkCallback(networkCallback);
Wi-Fi network suggestion API
Android Q adds support for your app to add network credentials for a device to
auto-connect to a Wi-Fi access point. You can supply suggestions for which
network to connect to using
WifiNetworkSuggestion.
The platform ultimately chooses which access point to accept based on the
input from your app and others.
The following code sample shows how to provide credentials for one open, one WPA2, and one WPA3 network:
Kotlin
val suggestion1 = WifiNetworkSuggestion.Builder()
.setSsid("test111111")
.setIsAppInteractionRequired() // Optional (Needs location permission)
.build()
val suggestion2 = WifiNetworkSuggestion.Builder()
.setSsid("test222222")
.setWpa2Passphrase("test123456")
.setIsAppInteractionRequired() // Optional (Needs location permission)
.build()
val suggestion3 = WifiNetworkSuggestion.Builder()
.setSsid("test333333")
.setWpa3Passphrase("test6789")
.setIsAppInteractionRequired() // Optional (Needs location permission)
.build()
val suggestionsList = listOf(suggestion1, suggestion2, suggestion3)
val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
val status = wifiManager.addNetworkSuggestions(suggestionsList);
if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
// do error handling here
}
// Optional (Wait for post connection broadcast to one of your suggestions)
val intentFilter = IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);
val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (!intent.action.equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
return;
}
// do post connect processing here
}
};
context.registerReceiver(broadcastReceiver, intentFilter);
Java
final WifiNetworkSuggestion suggestion1 =
new WifiNetworkSuggestion.Builder()
.setSsid("test111111")
.setIsAppInteractionRequired() // Optional (Needs location permission)
.build()
final WifiNetworkSuggestion suggestion2 =
new WifiNetworkSuggestion.Builder()
.setSsid("test222222")
.setWpa2Passphrase("test123456")
.setIsAppInteractionRequired() // Optional (Needs location permission)
.build()
final WifiNetworkSuggestion suggestion3 =
new WifiNetworkSuggestion.Builder()
.setSsid("test333333")
.setWpa3Passphrase("test6789")
.setIsAppInteractionRequired() // Optional (Needs location permission)
.build()
final List<WifiNetworkSuggestion> suggestionsList =
new ArrayList<WifiNetworkSuggestion> {{
add(suggestion1);
add(suggestion2);
add(suggestion3);
}};
final WifiManager wifiManager =
(WifiManager) context.getSystemService(Context.WIFI_SERVICE);
final int status = wifiManager.addNetworkSuggestions(suggestionsList);
if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
// do error handling here…
}
// Optional (Wait for post connection broadcast to one of your suggestions)
final IntentFilter intentFilter =
new IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);
final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (!intent.getAction().equals(
WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
return;
}
// do post connect processing here..
}
};
context.registerReceiver(broadcastReceiver, intentFilter);
The suggestions from the app must be approved by the user before the platform initiates a connection to them. This approval is provided by the user in response to a notification the first time the platform finds a network matching one of the suggestions from the app in scan results. When the platform connects to one of the network suggestions, the settings will show text that attributes the network connection to the corresponding suggester app.
Handling user disconnects
If the user uses the Wi-Fi picker to explicitly disconnect from one of the network suggestions when connected to it, then that network is blacklisted for 24 hours. During the blacklist period, that network will not be considered for auto-connection, even if the app removes and re-adds the network suggestion corresponding to the network.
Changing approval status for app
A user declining the network suggestion notification removes the
CHANGE_WIFI_STATE permission from the app. The user can grant this approval
later by going into the Wi-Fi control menu (Settings >
Apps & notifications > Special App
access > Wi-Fi Control > App name).
Improvements to Wi-Fi high-performance and low-latency modes
Android Q allows you to provide a hint to the underlying modem to minimize latency.
Android Q extends the Wi-Fi lock API to effectively support high-performance mode and low-latency mode. Wi-Fi power save is disabled for high-performance and low-latency mode, and further latency optimization may be enabled in low-latency mode, depending on modem support.
Low-latency mode is only enabled when the application acquiring the lock is running in the foreground and the screen is on. The low-latency mode is especially helpful for real-time mobile gaming applications.
Specialized lookups in DNS resolver
Android Q adds native support for specialized DNS lookups using both cleartext
lookups and DNS-over-TLS mode. Previously, the platform DNS resolver supported
only A and AAAA records, which allow looking up only the IP addresses associated
with a name, but did not support any other record types. The
DnsResolver API provides generic,
asynchronous resolution, enabling you to look up SRV, NAPTR, and other
record types. Note that parsing the response is left to the app to perform.
For NDK-based apps, see
android_res_nsend.
Wi-Fi Easy Connect
Android Q enables you to use Easy Connect to provision Wi-Fi credentials to a
peer device, as a replacement of WPS which has been deprecated. Apps can integrate
Easy Connect into their setup and provisioning flow by using the
ACTION_PROCESS_WIFI_EASY_CONNECT_URI intent. This intent requires a URI.
The calling app can retrieve the URI through various methods,
including scanning a QR code from a sticker or display, or through scanning
Bluetooth LE or NFC advertisements.
Once the URI is available, you can provision the peer device’s Wi-Fi credentials
with the ACTION_PROCESS_WIFI_EASY_CONNECT_URI intent. This allows the
user to select a Wi-Fi network to share and securely transfers the credentials.
Easy Connect does not require Location or Wi-Fi permissions.
Wi-Fi Direct connection API
The WifiP2pConfig and WifiP2pManager API classes have updates in Android Q
to support fast connection establishment capabilities to Wi-Fi Direct using
predetermined information. This information is shared via a side channel, such
as Bluetooth or NFC.
The following code sample shows how to create a group using predetermined information:
Kotlin
val manager = getSystemService(Context.WIFI_P2P_SERVICE) as WifiP2pManager
val channel = manager.initialize(this, mainLooper, null)
// prefer 5G band for this group
val config = WifiP2pConfig.Builder()
.setNetworkName("networkName")
.setPassphrase("passphrase")
.enablePersistentMode(false)
.setGroupOperatingBand(WifiP2pConfig.GROUP_OWNER_BAND_5GHZ)
.build()
// create a non-persistent group on 5GHz
manager.createGroup(channel, config, null)
Java
WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
Channel channel = manager.initialize(this, getMainLooper(), null);
// prefer 5G band for this group
WifiP2pConfig config = new WifiP2pConfig.Builder()
.setNetworkName("networkName")
.setPassphrase("passphrase")
.enablePersistentMode(false)
.setGroupOperatingBand(WifiP2pConfig.GROUP_OWNER_BAND_5GHZ)
.build();
// create a non-persistent group on 5GHz
manager.createGroup(channel, config, null);
To join a group using credentials, replace manager.createGroup() with the
following:
Kotlin
manager.connect(channel, config, null)
Java
manager.connect(channel, config, null);
Bluetooth LE Connection Oriented Channels (CoC)
Android Q enables your app to use BLE CoC connections to transfer larger data streams between two BLE devices. This interface abstracts Bluetooth and connectivity mechanics to simplify implementation.
Telephony features
Android Q includes several improvements related to telephony.
Call quality improvements
Android Q adds the ability to collect information about the quality of ongoing IP Multimedia Subsystem (IMS) calls, including quality to and from the network, on devices that support the feature.
Call screening and caller ID
Android Q provides your app with a means to identify calls not in the user's
address book as potential spam calls, and to have spam calls silently rejected on
behalf of the user. Information about these blocked calls is logged as blocked
calls in the call log to provide greater transparency to the user when they are
missing calls. Use of this new API eliminates the requirement to obtain
READ_CALL_LOG permissions from the user to provide call screening and caller
ID functionality.
Call redirection service API
Android Q changes how call intents are handled. The NEW_OUTGOING_CALL
broadcast is deprecated and is replaced with the CallRedirectionService API.
The CallRedirectionService API provides interfaces for you to modify outgoing
calls made by the Android platform. For example, third-party apps might cancel
calls and reroute them over VoIP.
Improvements in creating files on external storage
In addition to introducing the scoped storage privacy behavior change, Android Q provides more flexibility in writing files and introduces capabilities to help you influence where those files get saved on an external storage device.
Pending status for new media files
Android Q introduces the
IS_PENDING
flag, which gives your app exclusive access to a media file as it's written to
disk.
The following code snippet shows how to use the IS_PENDING flag when creating
a new image in your app:
Kotlin
val values = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, "IMG1024.JPG")
put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
put(MediaStore.Images.Media.IS_PENDING, 1)
}
val resolver = context.getContentResolver()
val collection = MediaStore.Images.Media
.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val item = resolver.insert(collection, values)
resolver.openFileDescriptor(item, "w", null).use { pfd ->
// Write data into the pending image.
}
// Now that we're finished, release the "pending" status, and allow other apps
// to view the image.
values.clear()
values.put(MediaStore.Images.Media.IS_PENDING, 0)
resolver.update(item, values, null, null)
Java
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DISPLAY_NAME, "IMG1024.JPG");
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.IS_PENDING, 1);
ContentResolver resolver = context.getContentResolver();
Uri collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
Uri item = resolver.insert(collection, values);
try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(item, "w", null)) {
// Write data into the pending image.
} catch (IOException e) {
e.printStackTrace();
}
// Now that we're finished, release the "pending" status, and allow other apps
// to view the image.
values.clear();
values.put(MediaStore.Images.Media.IS_PENDING, 0);
resolver.update(item, values, null, null);
Influence on storage location
Android Q introduces several capabilities to help you organize the files that your app contributes to external storage.
Directory hints
When your app contributes media on a device running Android Q, the media is organized based on its type by default. For example, new image files are placed in a "pictures" directory by default.
If your app is aware of a specific location where files should be stored, such
as Pictures/MyVacationPictures, you can set
MediaColumns.RELATIVE_PATH
to provide the system a hint for where to store the newly-written files.
Similarly, you can move files on disk during a call to
update()
by changing MediaColumns.RELATIVE_PATH or
MediaColumns.DISPLAY_NAME.
Device selection
In Android 9 (API level 28) and lower, all files saved to external storage
devices appear under a single volume called external. Android Q, on the other
hand, gives each external storage device a unique volume name. This new naming
system helps you efficiently organize and index content, and it gives you
control over where new content is stored.
The primary shared storage device is always called VOLUME_EXTERNAL_PRIMARY.
You can discover other volumes by calling MediaStore.getExternalVolumeNames().
To query, insert, update, or delete a specific volume, pass the volume name to
any of the getContentUri() methods available in the
MediaStore API, such as in the
following code snippet:
// Publish an audio file onto a specific external storage device.
val values = ContentValues().apply {
put(MediaStore.Audio.Media.RELATIVE_PATH, "Music/My Album/My Song")
put(MediaStore.Audio.Media.DISPLAY_NAME, "My Song.mp3")
}
// Assumes that the storage device of interest is the 2nd one
// that your app recognizes.
val volumeNames = MediaStore.getExternalVolumeNames(context)
val selectedVolumeName = volumeNames[1]
val collection = MediaStore.Audio.Media.getContentUri(selectedVolumeName)
val item = resolver.insert(collection, values)
Media and graphics
Android Q introduces the following new media and graphics features and APIs:
Audio playback capture
Android Q gives an app the ability to capture audio playback from other apps. For full information, see Playback capture.
Native MIDI API
The Android Native MIDI API (AMidi) gives application developers the ability to send and receive MIDI data with C/C++code, integrating more closely with their C/C++ audio/control logic and minimizing the need for JNI.
For more information, see Android Native MIDI API.
MediaCodecInfo improvements
There are new methods in
MediaCodecInfo that
reveal more information about a codec:
isSoftwareOnly()- Returns true if the codec runs in software only. Software codecs make no guarantees about rendering performance.
isHardwareAccelerated()- Returns true if a codec is accelerated by hardware.
isVendor()- Returns true if the codec is provided by the device vendor or false if provided by the Android platform.
isAlias()MediaCodecListmay contain additional entries for the same underlying codec using an alternate codec name/s (alias/es). This method returns true if the codec in this entry is an alias for another codec.
In addition,
MediaCodec.getCanonicalName()
returns the underlying codec name for codecs created via an alias.
Performance Points
A performance point represents a codec's ability to render video at a specific
height, width and frame rate. For example, the UHD_60 performance point
represents Ultra High Definition video (3840x2160 pixels) rendered at 60 frames
per second.
The method
MediaCodecInfo.VideoCapabilities.getSupportedPerformancePoints()
returns a list of
PerformancePoint
entries that the codec can render or capture.
You can check whether a given PerformancePoint covers another by calling
PerformancePoint.covers(PerformancePoint).
For example, UHD_60.covers(UHD_50) returns true.
A list of performance points is provided for all hardware-accelerated codecs. This could be an empty list if the codec does not meet even the lowest standard performance point.
Note that devices which have been upgraded to Q without updating the vendor
image will not have performance point data, because this data comes from the
vendor HAL. In this case, getSupportedPerformancePoints() returns null.
ANGLE
With the release of Android Q, Android developers and partners have the option to run using ANGLE, a project in the Chrome organization that layers ES on top of Vulkan, instead of using the vendor-provided ES driver.
For details, see ANGLE.
Thermal API
When devices get too warm, they may throttle the CPU and/or GPU, and this can affect apps and games in unexpected ways. Apps using complex graphics, heavy computation, or sustained network activity are more likely to hit issues, and those can vary across devices based on chipset and core frequencies, levels of integration, and also device packaging and form factor.
Now in Android Q, apps and games can use a thermal API to monitor changes on the device and take action to maintain lower power usage to restore normal temperature. Apps register a listener in PowerManager, through which the system reports ongoing thermal status ranging from light and moderate to severe, critical, emergency, and shutdown.
When the device reports thermal stress, apps and games can help by backing off ongoing activities to reduce power usage on various ways. For example, streaming apps could reduce resolution/bit rate or network traffic, a camera app could disable flash or intensive image enhancement, a game could reduce frame rate or polygon tesselation, a media app could reduce speaker volume, and a maps app could turn off GPS.
The thermal API requires a new device HAL layer—it's currently supported on Pixel devices running Android Q and we’re working with our device-maker partners to bring broad support to the ecosystem as quickly as possible.
Camera and images
Android Q introduces the following new camera- and image-related features:
Monochrome camera support
Android 9 (API level 28) first introduced monochrome camera capability. Android Q adds several enhancements to monochrome camera support:
- New Y8 stream format support to improve memory efficiency.
- Support for monochrome raw DNG capture.
- Introduction of MONO and NIR CFA enumerations to distinguish between regular monochrome camera and near infrared cameras.
You may use this feature to capture a native monochrome image. A logical multi-camera device may use a monochrome camera as a physical sub-camera to achieve better low-light image quality.
Dynamic Depth Format
Starting in Android Q, cameras can store the depth data for an image in a separate file, using a new schema called Dynamic Depth Format (DDF). Apps can request both the JPG image and its depth metadata, using that information to apply any blur they want in post-processing without modifying the original image data.
To read the specification for the new format, see Dynamic Depth Format.
High Efficiency Image File format
High Efficiency Image File (HEIF) format is a standard image and video format that introduces higher-quality encoding and smaller file size when compared to other file formats.
For more information about the file format, see HEIC.
Improvements in multi-camera
Android Q improves the fusing of multiple cameras into a single logical camera, a feature introduced in Android 9 (API level 28). The following were added to the Camera2 API:
isSessionConfigurationSupported(SessionConfiguration sessionConfig)—enables you to query whether or not the passed session configuration can be used to create a camera capture session.LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID—enables you to determine the ID of the active physical camera backing a logical camera device. You can use the IDs returned to request logical streams and physical subcamera streams to achieve better power efficiency.
Accessibility services API
Android Q introduces the following new accessibility service features and APIs:
AccessibilityNodeInfo entry key flag
In Android Q, AccessibilityNodeInfo has been enhanced with a new flag
designating whether it represents a text entry key. You can access this flag
using the method AccessibilityNodeInfo.isTextEntryKey().
Accessibility dialog spoken feedback
When an accessibility service requires the user to repeat the accessibility shortcut to start the service, the dialog can now be accompanied by a text-to-speech prompt if the service requests it.
Accessibility shortcut for physical keyboards
In Android Q, users can now trigger the accessibility shortcut on a physical keyboard by pressing Control+Alt+Z.
Soft keyboard controller enhancement
In Android Q, accessibility services can now request that the soft keyboard be displayed even when the device detects a hard keyboard attached. Users can override this behavior.
User-defined accessibility timeouts
Android Q introduces the API method
AccessibilityManager.getRecommendedTimeoutMillis(), providing support for
user-defined timeouts for interactive and non-interactive Accessibility UI
elements. The return value is influenced by both user preferences and
accessibility service APIs.
Autofill improvements
Android Q contains the following improvements to the autofill service.
Compatibility-related autofill requests
You can now use the
FillRequest.FLAG_COMPATIBILITY_MODE_REQUEST
flag to determine whether an autofill request was generated via compatibility
mode.
Save username and password simultaneously
You can now support cases where an application uses multiple activities to
display username, password, and other fields by using the
SaveInfo.FLAG_DELAY_SAVE
flag.
User interaction with the Save UI
You can now show and hide a password field in a save dialog by setting an action listener on the dialog and changing the visibility of the corresponding password remote view.
Support for updating datasets
Autofill can now update existing passwords. For example, if a user has already stored a password, and they save a new password, Autofill now prompts the user to update the existing password instead of saving a new one.
Field Classification improvements
Android Q contains the following improvements to the Field Classification API.
UserData.Builder constructor
The
UserData.Builder
constructor has changed to better align to the Builder pattern.
Allow a Value to be mapped to multiple types of Category IDs
When using
UserData.Builder in
Android Q, you can now map a value to multiple types of category IDs. In
previous releases, an exception was thrown if a value was added more than once.
Improved support for credit card numbers
Field classification can now detect four-digit numbers as the last four digits of a credit card number.
Support for app-specific field classification
Android Q adds
FillResponse.setUserData(),
which allows you to set app-specific user data for the duration of the session.
This helps the autofill service detect types for fields with app-specific
content.
UI and system controls
Android Q provides the following user-interface improvements:
Support JVMTI PopFrame caps
Android Q adds support for the
can_pop_frames
capability in the Android JVMTI implementation. When debugging, this feature
allows you to re-run functions after pausing at a breakpoint and adjusting
locals, globals, or implementation of a function. For more information, see
Oracle's Pop Frame reference page.
Surface control API
Android Q provides a
SurfaceControl API
for low-level access to the system-compositor
(SurfaceFlinger). For
most users, SurfaceView is the correct way to leverage the compositor. The
SurfaceControl API can be useful in certain cases, for example:
- Synchronization of multiple surfaces
- Cross-process surface embedding
- Lower-level lifetime management
The SurfaceControl API is available in both
SDK and NDK bindings.
The NDK implementation includes an API for manual exchange of buffers with the
compositor. This provides an alternative for users who have run up against the
limitations of
BufferQueue.
WebView hung renderer detection
Android Q introduces a new
WebViewRenderProcessClient
abstract class, which apps can use to detect if a
WebView has become unresponsive. To
use this class:
- Define your own subclass and implement its
onRenderProcessResponsive()andonRenderProcessUnresponsive()methods. - Attach an instance of your
WebViewRenderProcessClientto one or moreWebViewobjects. - If the
WebViewbecomes unresponsive, the system calls the client'sonRenderProcessUnresponsive()method, passing theWebViewandWebViewRenderProcess. (If theWebViewis single-process, theWebViewRenderProcessparameter is null.) Your app can take appropriate action, such as showing a dialog box to the user asking if they want to halt the rendering process.
If the WebView remains unresponsive, the system calls onRenderProcessUnresponsive()
periodically (no more than once every five seconds), but takes no other action.
If the WebView becomes responsive
again, the system calls onRenderProcessResponsive() just once.
Settings panels
Android Q introduces Settings Panels, an API which allows apps to show settings to users in the context of their app. This prevents users from needing to go into Settings to change things like NFC or Mobile data in order to use the app.
For example, suppose a user opens a web browser while their device is in airplane mode. Prior to Android Q, the app could only display a generic message asking the user to open Settings to restore connectivity. With Android Q, the browser app can display an inline panel showing key connectivity settings such as airplane mode, Wi-Fi (including nearby networks), and mobile data. With this panel, users can restore connectivity without leaving the app.
To display a settings panel, fire an intent with the one of the new
Settings.Panel actions:
Kotlin
val panelIntent = Intent(Settings.Panel.settings_panel_type) startActivityForResult(panelIntent)
Java
Intent panelIntent = new Intent(Settings.Panel.settings_panel_type); startActivityForResult(panelIntent);
settings_panel_type can be one of:
ACTION_INTERNET_CONNECTIVITY- Shows settings related to internet connectivity, such as Airplane mode, Wi-Fi, and Mobile Data.
ACTION_WIFI:- Shows Wi-Fi settings, but not the other connectivity settings. This is useful for apps that need a Wi-Fi connection to perform large uploads or downloads.
ACTION_NFC- Shows all settings related to near-field communication (NFC).
ACTION_VOLUME- Shows volume settings for all audio streams.
We are planning to introduce an AndroidX wrapper for this functionality. When called on devices running Android 9 (API level 28) or lower, the wrapper will open the most-appropriate page in the Settings app.
Sharing improvements
Android Q provides a number of improvements to sharing. For full information, see Sharing improvements in Android Q.
Dark theme
Android Q offers a new Dark theme that applies to both the Android system UI and apps running on the device. For full information, see Dark theme.
Foreground service types
Android Q introduces a new XML manifest attribute,
foregroundServiceType,
that you include in the definition of several specific services. It's possible,
though rarely appropriate, to assign multiple foreground service types to a
particular service.
The following table shows the different foreground service types and the services where it's appropriate to declare a specific type:
| Foreground service type | Example use case for a service that should declare this type |
|---|---|
connectedDevice
| Monitor a wearable fitness tracker |
dataSync
| Download files from a network |
location
| Continue a user-initiated action |
mediaPlayback
| Play an audio book, podcast, or music |
mediaProjection
| Record a video of the device's display over a short period of time |
phoneCall
| Handle ongoing phone call |
Kotlin
Android Q includes the following updates for Kotlin development.
Nullability annotations for libcore APIs
Android Q improves the coverage of nullability annotations in the SDK for libcore APIs. These annotations enable app developers who are using either Kotlin or Java nullability analysis in Android Studio to get nullness information when interacting with these APIs.
Normally, nullability contract violations in Kotlin result in compilation
errors. To ensure compatibility with your existing code, any new annotations
are limited to @RecentlyNullable and @RecentlyNonNull. This means that
nullability violations result in warnings instead of errors.
In addition, any @RecentlyNullable or @RecentlyNonNull annotations that were
added in Android 9 are changing to @Nullable and @NonNull, respectively.
This means that nullability violations now lead to errors instead of warnings.
For more information about annotation changes, see Android Pie SDK is now more Kotlin-friendly on the Android Developers Blog.
NDK
Android Q includes the following NDK changes.
Improved debugging of file descriptor ownership
Android Q adds fdsan, which helps you find and fix file descriptor ownership issues more easily.
Bugs related to mishandling of file descriptor ownership, which tend to manifest as use-after-close and double-close, are analogous to the memory allocation use-after-free and double-free bugs, but tend to be much more difficult to diagnose and fix. fdsan attempts to detect and/or prevent file descriptor mismanagement by enforcing file descriptor ownership.
For more information about crashes related to these issues, see Error detected by fdsan. For more information about fdsan, see the Googlesource page on fdsan.
ELF TLS
Applications built using the NDK with a minimum API level 29 no
longer need to use emutls, but can instead use ELF TLS. Dynamic and static
linker support has been added to support the new method of handling thread-local
variables.
For apps built for API level 28 and lower, improvements have been implemented
for libgcc/compiler-rt to work around some emutls issues.
For more information, see Android changes for NDK developers.
Runtime
Android Q includes the following runtime change.
Mallinfo-based garbage collection triggering
When small platform Java objects reference huge objects in the C++ heap, the C++ objects can often be reclaimed only when the Java object is collected and, for example, finalized. In previous releases, the platform estimated the sizes of many C++ objects associated with Java objects. This estimation was not always accurate and occasionally resulted in greatly increased memory usage, as the platform failed to garbage collect when it should have.
In Q, the garbage collector (GC) tracks the total size of the heap allocated by
system malloc(), ensuring that large malloc() allocations are always
included in GC-triggering calculations. Apps interleaving large numbers of C++
allocations with Java execution might see an increase in garbage collection
frequency as a result. Other apps might see a small decrease.
Testing and debugging
Android Q includes the following improvements for testing and debugging.
Improvements for on-device system tracing
You can now specify limits for the size and duration of a trace when you perform an on-device system trace. When you specify either value, the system performs a long trace, periodically copying the trace buffer to the destination file while the trace is recorded. The trace completes when the size or duration limits that you specified are reached.
Use these additional parameters to test different use cases than you would test with a standard trace. For example, you might be diagnosing a performance bug that only occurs after your app has been running for a long period of time. In this case, you could record a long trace over an entire day, and then analyze the CPU scheduler, disk activity, app threads, and other data in the report to help you determine the cause of the bug.
TextClassifier improvements
Android Q provides additional text classification functionality in the
TextClassifier
interface.
Language detection
TextClassifier now features the
detectLanguage()
method. This method works similarly to existing classification methods, receiving a
TextLanguage.Request
object and returning a
TextLanguage
object.
The new TextLanguage object consists of a list of ordered
pairs. Each pair contains a locale and a corresponding confidence score for the
requested text sample.
Suggested conversation actions
TextClassifier now features the
suggestConversationActions()
method. This method works similarly to existing classification methods,
receiving a
ConversationActions.Request
object and returning a
ConversationActions
object.
The new ConversationActions object consists of a list of
ConversationAction
objects. Each ConversationAction object includes a potential
suggested action and its confidence score.
Smart replies/actions in notifications
Android 9 introduced the ability to display suggested replies within a notification. Beginning in Android Q, notifications can also include suggested intent-based actions. Furthermore, the system can now generate these suggestions automatically. Apps can still provide their own suggestions, or opt out of system-generated suggestions.
The API used to generate these replies is part of
TextClassifier,
and has also been directly exposed to developers in Android Q. Please read
the section on TextClassifier improvements
for more information.
If your app provides its own suggestions, the platform doesn't generate any
automatic suggestions. If you don't want your app's notifications to display
any suggested replies or actions, you can opt out of system-generated replies
and actions by using
setAllowGeneratedReplies()
and
setAllowSystemGeneratedContextualActions().