Skip to content

Car Service & Framework

The android.car API map

Which manager owns what, which permission each needs, and how to work out whether the thing you want to build is even possible on AAOS.

Intermediate4 minCar API · App development · Permissions

The most common question from an app team new to AAOS is "can I get X?" This page is the map that answers it.

Everything starts at Car#

The entry point
val car = Car.createCar(context)
 
val properties = car.getCarManager(Car.PROPERTY_SERVICE) as CarPropertyManager
val audio      = car.getCarManager(Car.AUDIO_SERVICE) as CarAudioManager
val restrict   = car.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE)
        as CarUxRestrictionsManager

Car is a connection to Car Service, and the managers are handles into its subservices. Read the constants in Car.java — it is the authoritative list of what exists on your platform version.

The managers worth knowing#

ManagerWhat it gives youTypical permission
CarPropertyManagerAll vehicle propertiesPer property
CarAudioManagerZones, volume groups, focusCAR_CONTROL_AUDIO_VOLUME
CarUxRestrictionsManagerDriver distraction statenone to read
CarPackageManagerIs this activity distraction-optimised?none to read
CarPowerManagerPower state, shutdown callbacksCAR_POWER
CarUserManagerUser switching and lifecycleMANAGE_USERS
CarOccupantZoneManagerDisplays, seats, usersvaries
CarWatchdogManagerHealth reportingnone to register
CarInfoManagerStatic vehicle info (make, model, year)CAR_INFO
CarSensorManagerLegacy sensor wrapper — prefer propertiesvaries
CarNavigationStatusManagerPush turn-by-turn to the clusterCAR_NAVIGATION_MANAGER

Permissions, and the two-tier reality#

Car permissions split into two very different groups, and confusing them wastes weeks.

Normal/dangerous permissions any app can request, subject to user consent:

Requestable by a normal app
<uses-permission android:name="android.car.permission.CAR_INFO"/>
<uses-permission android:name="android.car.permission.CAR_ENERGY"/>
<uses-permission android:name="android.car.permission.CAR_SPEED"/>
<uses-permission android:name="android.car.permission.CAR_EXTERIOR_ENVIRONMENT"/>

Signature/privileged permissions that require the platform key or a privapp-permissions grant:

System apps only
<uses-permission android:name="android.car.permission.CONTROL_CAR_CLIMATE"/>
<uses-permission android:name="android.car.permission.CONTROL_CAR_DOORS"/>
<uses-permission android:name="android.car.permission.CONTROL_CAR_SEATS"/>
<uses-permission android:name="android.car.permission.CAR_POWER"/>

Anything that actuates the vehicle is signature-level

Reading speed is a normal permission. Moving a window is not. If your feature writes a property that physically moves something, your app must be part of the system image — which means the OEM ships it, and your release cadence becomes theirs. Find this out during scoping, not during integration.

Deciding whether something is possible#

A reliable four-step check, in order:

1. Does a system property already exist for it? Search VehiclePropertyIds.java. If yes, you inherit the permission mapping and CTS coverage.

2. Does this vehicle actually implement it? A property existing in AOSP says nothing about this trim.

adb shell dumpsys car_service --list-properties | grep -i window

3. What permission does it need, and can you hold it? If it is signature-level and you are not in the system image, the answer is no until the OEM includes you.

4. Is it restricted while driving? Even with access, CarUxRestrictionsManager may block the interaction above a speed threshold.

Feature detection, not assumption#

Different vehicles, trims and platform versions expose different things. Ask:

Detect, do not assume
// Is this an automotive build at all?
val isCar = context.packageManager
    .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
 
// Does this vehicle support the property, in this area?
val supported = properties.propertyList.any {
    it.propertyId == VehiclePropertyIds.WINDOW_POS
}
 
// Is it available right now? (trailer absent, module asleep, …)
val available = properties.isPropertyAvailable(
    VehiclePropertyIds.WINDOW_POS, VehicleAreaWindow.WINDOW_ROW_1_LEFT,
)

Every one of those can differ between two cars rolling off the same line with different option packages.

The distraction rules apply to you#

Responding to UX restrictions
val manager = car.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE)
        as CarUxRestrictionsManager
 
manager.registerListener { restrictions ->
    val noVideo = restrictions.isRequiresDistractionOptimization &&
        (restrictions.activeRestrictions and
            CarUxRestrictions.UX_RESTRICTIONS_NO_VIDEO) != 0
 
    if (noVideo) pauseVideoPlayback()
}

The restriction set includes limits on video, keyboard entry, string length and the number of items in a list. They change with driving state, and the framework enforces the important ones whether you cooperate or not — cooperating just makes the experience less jarring.

The Javadoc in car-lib is genuinely good and is the fastest way to answer "what does this actually do".

Next#

Multi-user is the part of the framework that most surprises engineers arriving from phone Android.

References & further reading

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