Distraction optimization (DO) is provided as a tool to reduce the driver's interaction with the Settings app while a car is moving. Some settings may need to be changed while driving, so the app isn't completely blocked. However, by default, most preferences are disabled with only key and easily updated preferences being enabled.
Figure 1. Enabled apps while driving
Entire activities can also be blocked if they aren't distraction optimized, as shown below. This method is currently used primarily for settings search.
Figure 2. All activities blocked
Basic customizations to the performance of DO can be done through configuration overlays. If you require more fine-grained customization, additional changes can be made through code.
High-level customization
When a preference is disabled while driving, tapping on it displays a toast
message stating that the preference isn't available while driving, provided the preference
has a preference controller attached to it. The message uses the
restricted_while_driving
string, which can be customized with an overlay
(provided the string is less than the 60-character limit).
Figure 3. Customized overlay
The entire DO framework can be disabled using config_always_ignore_ux_restrictions
.
Setting this to true means that the driver can interact with every aspect of the
Settings app.
<bool name="config_always_ignore_ux_restrictions">true</bool>
If the configuration above is set to false, the Settings app falls back to
config_ignore_ux_restrictions
to determine which preferences should be enabled while driving. The strings provided here
should point to the strings defined in preference_keys.xml.
Example
To show how to enable a deeply nested setting while driving, this example
demonstrates how to enable the Text-to-Speech (TTS) output settings. For this to work,
add all the settings in the hierarchy to config_ignore_ux_restrictions
.
This includes the system, languages and input, and TTS preferences to the config, since our hierarchy is
System->Languages & Input->Text-to-speech output. However, the preferences
within the text-to-speech fragment is still disabled. To enable them, we
need to add the keys for the preferences we want to be accessible. In this
example, we want to enable the playback preferences but not the engine
preference so we add pk_tts_playback_group
to our config.
<string-array name="config_ignore_ux_restrictions"> [...] <item>@string/pk_system_settings_entry</item> <item>@string/pk_languages_and_input_settings</item> <item>@string/pk_tts_settings_entry</item> <item>@string/pk_tts_playback_group</item> </string-array>
Detailed customization
There are some preferences that might require more customized behavior than simply enabling/disabling a preference based on the driving state. For example, Bluetooth and Wi-Fi have already been modified to show saved Bluetooth devices or Wi-Fi access points while driving.
Currently there's no configuration based solution to make these kinds of
adjustments. Instead you can create a custom class that extends
PreferenceController and overrides onApplyUxRestrictions()
to make the desired
changes.
When a custom preference controller is created, you can overlay the relevant XML file to replace the default preference controller with your own implementation.
Examples
In CarSettings, some preferences have this more customized behavior, which can be used as examples for additional customization. For example, in the Wi-Fi access point list, the desired behavior is to only show saved access points while driving (and hiding the rest). To achieve this, do the following:
} else if (shouldApplyUxRestrictions(getUxRestrictions())) { wifiEntries = getCarWifiManager().getSavedWifiEntries(); } else { wifiEntries = getCarWifiManager().getAllWifiEntries(); }
Because the access points that appear here are already restricted, you
don't want to apply additional UxRestrictions
to these preferences.
Therefore, override onApplyUxRestrictions
and perform an intentional
no-op:
@Override protected void onApplyUxRestrictions(CarUxRestrictions uxRestrictions) { // Since the list dynamically changes based on the UX restrictions, we // enable this fragment regardless of the restriction. Intentional no-op. }
Another example is provided in Bluetooth-bonded devices.
To continue to enable Bluetooth devices to be connected to and disconnected from but wanted to
disable the ability to access additional settings for these devices. To achieve this, we
again override onApplyUxRestrictions
but this time, if the NO_SETUP
restriction is active, hide the secondary action on the preference.
@Override protected void onApplyUxRestrictions(CarUxRestrictions uxRestrictions) { super.onApplyUxRestrictions(uxRestrictions); if (CarUxRestrictionsHelper.isNoSetup(uxRestrictions)) { updateActionVisibility(getPreference(), /* isActionVisible= */ false); } }