Car Settings (packages/apps/Car/Settings
) is provided specifically for the
Android Automotive OS (AAOS). Car Settings differs from Phone Settings
(packages/apps/Settings
). While Car Settings contains some familiar phone settings,
Car Settings provides a car-ified visual user interface, driver distraction optimizations,
and numerous customization entry points for OEMs.
In addition to the overview of Car Settings provided below, see these related topics to learn more about Car Settings:
- Adding Car Settings
- Rearranging Car Settings
- Distraction Optimization in Car Settings
- Car Settings Search Indexing
- Dual Pane Customization
Architecture and guidelines
Most of the pages in Car Settings are implemented as a series of fragments
that extend SettingsFragment, each having their own activity defined in
CarSettingActivities. These static activities are extended from BaseCarSettingsActivity. While there are a few exceptions to this rule, such as some special fragments extending
BaseFragment rather than SettingsFragment
and some Activities residing outside CarSettingActivities, all of which should be regarded as exceptions (not as patterns to follow).
Static preferences
A static preference is defined in XML using the Preference
or CarUiPreference
tag. A SettingsFragment
implementation uses the getPreferenceScreenResId()
method to define which XML file contains the static list of preferences to display.
Dynamic preferences
Dynamic preferences use the PreferenceGroup tag or an implementation of PreferenceGroup.
Within the CarSettings app, dynamic preferences represent a normal set of preferences that direct the user to additional pages within CarSettings, but which have been added via the Preference Controller instead of in the XML. An example is the Manage keyboards preference under Languages & Input preference which dynamically adds input methods to the preference page based on whether these input methods are permitted or not.
Action bars
The top of every settings screen has an action bar, which can contain a "back" navigation, a screen title, and supplementary action widgets (for example, buttons and switches). These action bars are similar to the ActionBar provided by Android, but are actually custom views. In Android 11 and above, this toolbar is included in the chassis base layout, which contains the views for the toolbar and a framelayout for the rest of the app content.
Supplementary action widgets are MenuItem classes and should be created in
the onCreate
of the respective SettingsFragment
or
BaseFragment
. Properties such as visibility, state, and so on should
be controlled by setters in the business logic of the SettingsFragment
.
// ExampleSettingsFragment.java public class ExampleSettingsFragment extends SettingsFragment { @Override protected List<MenuItem> getToolbarMenuItems() { return Collections.singletonList(mClearConfirmButton); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mButton = new MenuItem.Builder(getContext()) .setTitle(R.string.text) .setOnClickListener(mOnClickListener) .setUxRestrictions(CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP) .build(); } private void updateState() { button.setVisible(false); } }
The action bars come with support for
Distraction Optimization in Car Settings.
Set the UXRestrictions in the MenuItem.Builder
on creation.
Preference controllers
Each settings page can hold a number of various Preferences.
See the following image for how these components are related:
Figure 1. CarSettings Components
The PreferenceController
is a lifecycle-aware component that helps to
encapsulate the business logic pertaining to specific Preferences.
PreferenceControllers
can only be attached to the relevant Preference through
XML.
// example_settings_fragment.xml <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res-auto" android:title="@string/example_settings_title"> <Preference android:key="@string/pk_example_preference_key" android:title="@string/example_preference_title" settings:controller="com.android.car.settings.example.ExamplePreferenceController"/> </PreferenceScreen>
Car Settings explicitly prevents the creation of PreferenceController
through code in order to make it easier to modify the Settings hierarchy with minimal
changes to the Java code.
It's possible that a PreferenceController
needs some dynamic data
to operate correctly. For example, a PreferenceController
that turns off
notifications for an app needs to know which app to act on.
Because PreferenceControllers
are always defined in XML, there is no
way to provide additional constructor arguments. Instead, these additional values are
provided through public setters on the PreferenceController
and set using the
use(...)
method from the SettingsFragment
.
// ExamplePreferenceController.java public class ExamplePreferenceContorller extends PreferenceController<Preference> { private ExampleArg mExampleArg; public ExamplePreferenceController(...) { ... } public void setExampleArg(ExampleArg exampleArg) { mExampleArg = exampleArg; } } // ExampleSettingsFragment.java public class ExampleSettingsFragment extends SettingsFragment { @Override @XmlRes protected int getPreferenceScreenResId() { Return R.xml.example_settings_fragment; } @Override public void onAttach(Context context) { ExampleArg arg = (ExampleArg) getArguments().getSerializeable(ARG_KEY); ExamplePreferenceController controller = use(ExamplePreferenceController.class, R.string.pk_example_preference_key); controller.setExampleArg(arg); } }
The more often the use(...)
method is used, the harder it becomes to keep
the original goal of being able to rearrange the settings hierarchy with minimal changes to
the Java code, because large sections of the existing fragment code needs to be copied to
the newly created fragment. One way to minimize the difficulty of doing this is to:
- Minimize your usage of
use(...)
. - Try to keep every call to
use(...)
in one place in the fragment (for example, in theonAttach()
method).
Intent handling
All of the intents that should be handled by the Car Settings app are defined in the manifest file. Intents are generally defined and handled like most standard Android apps, with all the activities and intent filters defined in the manifest.
Change the root fragment
If desired, the Exit icon can be displayed or hidden using config_show_settings_root_exit_icon
.
Customize the theme
Customize other attributes and resources
The Car Settings app primarily uses the CarSettingTheme
,
which is an extension of Theme.CarUi
. This theme is used to standardize the
look-and-feel of system apps to ensure consistency in the system.
Customize preferences
Customizing preferences spans these additional locations:
- The layout of some base preference classes is defined in
car_preference
and overlaid for car builds. Any customization layouts for the base preference classes can be replaced here. - Car Settings uses some custom preferences defined primarily in the
common
package. These should be overlaid within the Car Settings module separately from the base preference classes.