Skip to content

HMI, System UI & UX

Accessibility in a vehicle

Screen readers, large text and switch access in a car — where automotive accessibility differs from a phone, and why the distraction rules and accessibility rules sometimes pull in opposite directions.

Intermediate6 minAccessibility · HMI · Inclusive design

Accessibility in a vehicle is easy to skip and increasingly not optional. It is also genuinely different from a phone, because the driver is not the only user and the platform is already restricting the interface for safety reasons.

Who this is actually for#

The tension nobody warns you about#

Content descriptions, and why they matter more here#

Every non-text control needs a label a screen reader can announce.

Wrong — a screen reader announces nothing useful
<ImageButton
    android:id="@+id/climate"
    android:src="@drawable/ic_climate"/>
Right
<ImageButton
    android:id="@+id/climate"
    android:src="@drawable/ic_climate"
    android:contentDescription="@string/open_climate_controls"/>
And in Compose
Icon(
    painter = painterResource(R.drawable.ic_climate),
    contentDescription = stringResource(R.string.open_climate_controls),
)

Mark purely decorative images so they are skipped rather than announced:

<ImageView
    android:src="@drawable/decorative_divider"
    android:importantForAccessibility="no"/>

Touch targets#

Android's general guidance is 48dp. Automotive guidance is larger — the defaults are well above it — because the user is at arm's length, the vehicle is moving, and precision is not available.

Read the platform's value rather than inventing one
<Button
    android:minWidth="@dimen/car_ui_touch_target_size"
    android:minHeight="@dimen/car_ui_touch_target_size"/>

Focus order is accessibility and rotary at once#

The keyboard and rotary navigation work from the same topic applies directly here. A screen that can be navigated with a rotary controller can be navigated by switch access and by a keyboard.

Group related controls so focus moves sensibly
<com.android.car.ui.FocusArea
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <LinearLayout android:orientation="horizontal">
        <Button android:id="@+id/temp_down" .../>
        <TextView android:id="@+id/temp_value" .../>
        <Button android:id="@+id/temp_up" .../>
    </LinearLayout>
</com.android.car.ui.FocusArea>

Announcing changes the user cannot see#

When something changes without user action — a value updates, an error appears — a sighted user notices. A screen reader user does not, unless you say so.

Announce a change that matters
view.announceForAccessibility(
    context.getString(R.string.charging_started),
)
Or mark a region as live
statusText.accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_POLITE

Colour and contrast#

The general standard is 4.5:1 for normal text. In a vehicle the practical requirement is higher, because the viewing conditions are far worse than a desk: direct sunlight, headlight glare, polarised sunglasses, a screen at an angle.

Testing it#

Turn the tools on
# Screen reader
adb shell settings put secure enabled_accessibility_services \
  com.google.android.marvin.talkback/.TalkBackService
adb shell settings put secure accessibility_enabled 1
 
# Font scaling
adb shell settings put system font_scale 1.5
adb shell settings put system font_scale 1.0   # restore
 
# Display size
adb shell wm density 200
adb shell wm density reset
Automating the basics
@Test fun everyInteractiveControlHasALabel() {
    launchActivity<ClimateActivity>()
 
    onView(withId(R.id.climate_root)).check { view, _ ->
        view.findViewsWithMissingContentDescription().let {
            assertThat(it).isEmpty()
        }
    }
}

Accessibility Scanner and the accessibility-test-framework checks integrate with Espresso and catch missing labels, small targets and low contrast automatically.

Next#

The settings surface, where much of this configuration lives.

References & further reading

Code links target the main branch on cs.android.com. AOSP moves — if a path 404s, search the symbol instead.