自 2025 年 3 月 27 日起,我们建议您使用 android-latest-release
而非 aosp-main
构建 AOSP 并为其做出贡献。如需了解详情,请参阅 AOSP 的变更。
使用汽车的驾驶状态和用户体验限制
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
本页将说明应用可以如何顺利转换到经过防分心优化 (DO) 的界面,并介绍如何使用汽车的驾驶状态以及相应的用户体验限制。
如需详细了解汽车用户体验 (UX) 限制,请参阅汽车用户体验限制,其中详细介绍了已驻车、空转和行车中这三种驾驶状态。
受众群体
本文所述内容的受众群体是有如下设计需求的开发者:想要设计的应用能够适用汽车的驾驶状态变化和相应的用户体验限制。
技术详情
CarDrivingStateManager
汽车的驾驶状态(已驻车、空转或行车中)通过车载硬件抽象层 (VHAL) 提供的传感器值推导得出。系统使用基本传感器信息(例如车辆速度和当前档位选择)来推导出当前的驾驶状态。
CarDrivingStateEvent
。
该 API 提供 @SystemApis,这意味着只有平台内部架构、捆绑的 APK(例如 SysUI 或设置)和特权 APK(例如 GMSCore)可以访问这些 API。这些 API 受特定于驾驶状态
android.car.permission.CAR_DRIVING_STATE
的权限保护。如果客户端需要访问驾驶状态信息,则必须请求此权限。
CarUxRestrictionsManager
根据驾驶状态显示界面的应用必须监听 CarUxRestrictionsManager
,后者会抽象出从驾驶状态到用户体验限制的映射,这样应用就不需要根据不同的市场安全要求进行调整。
注意:这些 activity 必须标记为经过防分心优化,如有关防止驾驶员分心的准则中所述。如果未相应地标记这些 activity,则它们会被阻止。
相反,应用会监控 CarUxRestrictionsManager 公开的限制,而不是由 CarDrivingStateManager 公开的绝对驾驶状态,以了解与界面或用户体验相关的所有信息。
代码示例
以下示例代码说明了应用如何监控用户体验限制:
- 导入汽车库软件包:
import android.car.Car;
/* For CarUxRestrictions */
import android.car.drivingstate.CarUxRestrictions;
import android.car.drivingstate.CarUxRestrictionsManager;
- 实现
CarUxRestrictionManager.OnUxRestrictionsChangedListener
(mUxRChangeListener
)。向 CarUxRestrictionsManager 注册此监听器后,当用户体验限制发生变化时,系统将调用此监听器。请根据需要对限制变化进行防分心优化:
@Nullable private CarUxRestrictionsManager mCarUxRestrictionsManager;
private CarUxRestrictions mCurrentUxRestrictions;
/* Implement the onUxRestrictionsChangedListener interface */
private CarUxRestrictionsManager.OnUxRestrictionsChangedListener mUxrChangeListener =
new CarUxRestrictionsManager.OnUxRestrictionsChangedListener()
{
@Override
public void onUxRestrictionsChanged(CarUxRestrictions carUxRestrictions) {
mCurrentUxRestrictions = carUxRestrictions;
/* Handle the new restrictions */
handleUxRestrictionsChanged(carUxRestrictions);
}
};
- 调用 Car API 以创建名为 mCar 的汽车实例,并连接到汽车服务:
mCar = Car.createCar(context);
if (mCar == null) {
// handle car connection error
}
- 调用
mCar.getCarManager() - mCarUxRestrictionsManager
以获取 CarUxRestrictionsManager
:
CarUxRestrictionsManager carUxRestrictionsManager = (CarUxRestrictionsManager)
mCar.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);
- 如需向
CarUxRestrictionsManager
注册在上文第 2 步中实现的 mUxRChangeListener
,调用 mCarUxRestrictionsManager.registerListener()
:mCarUxRestrictionsManager.registerListener(mUxrChangeListener);
mUxrChangeListener.onUxRestrictionsChanged(
mCarUxRestrictionsManager.getCurrentCarUxRestrictions());
执行完示例代码块(在第 3 步至第 5 步中创建)后,监听器就会在驾驶状态发生变化时收到限制变化:
mCar = Car.createCar(context);
if (mCar == null) {
// handle car connection error
}
CarUxRestrictionsManager carUxRestrictionsManager = (CarUxRestrictionsManager)
mCar.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);
mCarUxRestrictionsManager.registerListener(mUxrChangeListener);
mUxrChangeListener.onUxRestrictionsChanged(
mCarUxRestrictionsManager.getCurrentCarUxRestrictions());
CarUxRestrictions
CarUxRestrictions 对象提供两类信息:
- 当前是否有要求需要进行防分心优化?
- 如果有,目前存在哪些限制?
从 getCurrentUxRestrictions()
或监听器回调获取 CarUxRestrictions 后,应用现在可以使用 isRequiresDistractionOptimization()
API 确定是否需要进行防分心优化。如果此 API 返回的是 false
,则不存在需要进行防分心优化的要求,并且应用可安全地运行任何 activity。
如果需要进行优化,请使用 getActiveRestrictions() API 获取现有限制集。此 API 会返回一个整数值,这是当前生效的所有限制的位掩码。当前已知的限制集列在 CarUxRestrictions
下。
注意:预计会在不久的将来对限制集进行细微更改。
例如,如果应用需要确定是否存在视频播放限制,那么在获取 CarUxRestrictions 对象时,应用必须检查此限制:
int activeUxR = mCurrentCarUxRestrictions.getActiveRestrictions();
if ((activeUxR & CarUxRestrictions.UX_RESTRICTIONS_NO_VIDEO) != 0) {
handleStopPlayingVideo();
}
DrivingState
CarDrivingStateManager 显示车辆的实际驾驶状态(已驻车、空转或行车中)。可以调用 CarDrivingStateManager API,这类似于调用 CarUxRestrictionsManager。
应用可以注册监听器或获取当前驾驶状态。驾驶状态以 CarDrivingStateEvent 的形式返回。
CarDrivingStateEvent
。
发生变化时,系统会使用新的
CarDrivingStateEvent
调用
onDrivingStateChanged()
方法。
import android.car.Car;
/* For CarDrivingState */
import android.car.drivingstate.CarDrivingStateEvent;
import android.car.drivingstate.CarDrivingStateManager;
mDrivingStateManager = (CarDrivingStateManager) mCar.getCarManager(
Car.CAR_DRIVING_STATE_SERVICE);
/* Register the listener (implemented below) */
mDrivingStateManager.registerListener(mDrivingStateEventListener);
/* While we wait for a change to be notified, query the current state */
mDrivingStateEvent = mDrivingStateManager.getCurrentCarDrivingState();
private final CarDrivingStateManager.CarDrivingStateEventListener
mDrivingStateEventListener =
new CarDrivingStateManager.CarDrivingStateEventListener() {
@Override
public void onDrivingStateChanged(CarDrivingStateEvent event) {
mDrivingStateEvent = event;
/* handle the state change accordingly */
handleDrivingStateChange();
}
};
测试
您可以通过模拟档位和速度的变化来更改驾驶状态。使用 adb shell 命令来注入车辆事件。这对开发和测试会很有帮助。
如需模拟驾驶事件,请执行以下操作:
- 如需将速度设置为 0,请运行以下命令:
adb shell dumpsys activity service com.android.car inject-vhal-event 0x11600207 0
- 如需将档位设置为“停车”(模拟指向“PARKED”的 CarDrivingStateEvent),请运行以下命令:
adb shell dumpsys activity service com.android.car inject-vhal-event 0x11400400 4
- 如需将档位设置为“行驶”,而使速度仍为 0(模拟指向“IDLING”的CarDrivingStateEvent),请运行以下命令:
adb shell dumpsys activity service com.android.car inject-vhal-event 0x11400400 8
- 如需将速度设为每秒 30 米(模拟指向“MOVING”的 CarDrivingStateEvent),请运行以下命令:
adb shell dumpsys activity service com.android.car inject-vhal-event 0x11600207 30
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-07-27。
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-07-27。"],[],[],null,["# Consume car driving state and UX restrictions\n\nThis page explains how apps can transition gracefully to distraction\noptimized (DO) user interfaces. It describes how to consume a car's driving state as well as the\ncorresponding user experience restrictions.\n\nFor more information about Car User Experience (UX) restrictions, see\n[Car User Experience Restrictions](/docs/automotive/driver_distraction/car_uxr),\nwhich details the three driving states of Parked, Idling, and Moving.\n\nAudience\n--------\n\nThis content is provided for those who want to design apps that adapt to changes in a\ncar's driving state and the correspondingly imposed UX restrictions.\n\nTechnical details\n-----------------\n\n### CarDrivingStateManager\n\nA car's driving state (Parked, Idling, or Moving) is derived from the sensor values provided by\nthe Vehicle Hardware Abstraction Layer (VHAL). Basic sensor information, such as vehicle speed and\ncurrent gear selection, is used to derive the vehicle's current driving state.\n[CarDrivingStateEvent](https://android.googlesource.com/platform/packages/services/Car/+/android16-release/car-lib/src/android/car/drivingstate/CarDrivingStateEvent.java?autodive=0%2F%2F%2F%2F%2F).\n\n\u003cbr /\u003e\n\nwhich provides @SystemApis, meaning that only Platform Internals, Bundled APKs (such as SysUI or Settings), and Privileged APKs (such as) GMSCore can access the APIs. The APIs are protected by permissions specific to driving state `android.car.permission.CAR_DRIVING_STATE`. Clients that require access to driving state information must request this permission.\n\n\u003cbr /\u003e\n\n### CarUxRestrictionsManager\n\nThose apps that display a user interface dependent upon driving state must listen to\n[CarUxRestrictionsManager](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictionsManager),\nwhich abstracts the mapping from driving state to UX restrictions so that apps don't need to\nadjust for different market safety requirements.\n\n**Note** : These activities *must* be marked as\ndistraction optimized, as described\nin [Driver distraction guidelines](/docs/automotive/driver_distraction/guidelines).\nIf the activities aren't marked accordingly, they're blocked.\n\nInstead, apps monitor restrictions exposed by the CarUxRestrictionsManager and not an\nabsolute driving state exposed by the CarDrivingStateManager for anything related to the user\ninterface or the user experience.\n\nCode sample\n-----------\n\nThe following sample code illustrates how an app monitors UX restrictions:\n\n1. Import the car library packages: \n\n ```python\n import android.car.Car;\n /* For CarUxRestrictions */\n import android.car.drivingstate.CarUxRestrictions;\n import android.car.drivingstate.CarUxRestrictionsManager;\n ```\n2. Implement `CarUxRestrictionManager.OnUxRestrictionsChangedListener` (`mUxRChangeListener`). This listener, when registered with the [CarUxRestrictionsManager](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictionsManager), is called when a change in the UX restrictions occurs. Handle the restriction changes to be distraction optimized, as needed: \n\n ```transact-sql\n @Nullable private CarUxRestrictionsManager mCarUxRestrictionsManager;\n private CarUxRestrictions mCurrentUxRestrictions;\n\n /* Implement the onUxRestrictionsChangedListener interface */\n private CarUxRestrictionsManager.OnUxRestrictionsChangedListener mUxrChangeListener =\n new CarUxRestrictionsManager.OnUxRestrictionsChangedListener()\n {\n @Override\n public void onUxRestrictionsChanged(CarUxRestrictions carUxRestrictions) {\n mCurrentUxRestrictions = carUxRestrictions;\n /* Handle the new restrictions */\n handleUxRestrictionsChanged(carUxRestrictions);\n }\n };\n \n ```\n3. Call the car APIs to create a car instance named mCar and connect to the car service: \n\n ```text\n mCar = Car.createCar(context);\n if (mCar == null) {\n // handle car connection error\n }\n ```\n4. Call `mCar.getCarManager() - mCarUxRestrictionsManager` to get the `CarUxRestrictionsManager`: \n\n ```scdoc\n CarUxRestrictionsManager carUxRestrictionsManager = (CarUxRestrictionsManager)\n mCar.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);\n ```\n5. To register `mUxRChangeListener` implemented in Step 2 above with the `CarUxRestrictionsManager` call `mCarUxRestrictionsManager.registerListener()`: \n\n ```verilog\n mCarUxRestrictionsManager.registerListener(mUxrChangeListener);\n mUxrChangeListener.onUxRestrictionsChanged(\n mCarUxRestrictionsManager.getCurrentCarUxRestrictions());\n ```\n\nThe completed block of sample code (created in Step 3 through Step 5) results in the listener\nreceiving restriction changes when the drive state changes: \n\n```verilog\nmCar = Car.createCar(context);\nif (mCar == null) {\n// handle car connection error\n}\n\nCarUxRestrictionsManager carUxRestrictionsManager = (CarUxRestrictionsManager)\nmCar.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);\n\nmCarUxRestrictionsManager.registerListener(mUxrChangeListener);\nmUxrChangeListener.onUxRestrictionsChanged(\nmCarUxRestrictionsManager.getCurrentCarUxRestrictions());\n```\n\nCarUxRestrictions\n-----------------\n\nThe [CarUxRestrictions](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictions) object provides two types of information:\n\n1. Is there a current requirement to be distraction optimized?\n2. If so, what restrictions are currently in place?\n\nWhen [CarUxRestrictions](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictions) is obtained from either\n[getCurrentUxRestrictions()](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictionsManager.html#getCurrentCarUxRestrictions()) or the listener callback, apps can now use\nthe [isRequiresDistractionOptimization()](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictions.html#isRequiresDistractionOptimization()) API to determine if Distraction\nOptimized\nis required. If this returns `false`, there is no requirement to be Distraction\nOptimized and an app can safely run any activity.\n\nIf optimization is required, then use the [getActiveRestrictions()](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictions.html#getActiveRestrictions()) API to obtain the set of restrictions in place. This\nAPI returns an *int* , which is a bit mask of all the restrictions currently in effect. The\nset of restrictions currently notified is listed under ` `[CarUxRestrictions](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictions).\n\n**Note:** Minor changes to the set of restrictions are anticipated to\noccur in the near future.\n\nFor example, if an app wants to determine if a restriction to play video exists, upon\ngetting the CarUxRestrictions object, the app must check for the restriction: \n\n```scdoc\nint activeUxR = mCurrentCarUxRestrictions.getActiveRestrictions();\nif ((activeUxR & CarUxRestrictions.UX_RESTRICTIONS_NO_VIDEO) != 0) {\n handleStopPlayingVideo();\n}\n```\n\nDrivingState\n------------\n\nCarDrivingStateManager presents the actual driving state of the vehicle (Parked, Idling, or\nMoving). CarDrivingStateManager APIs can be called similar to the CarUxRestrictionsManager.\nApps can register a listener or get current driving state. The driving state is returned\nas CarDrivingStateEvent.\n[CarDrivingStateEvent](https://android.googlesource.com/platform/packages/services/Car/+/android16-release/car-lib/src/android/car/drivingstate/CarDrivingStateEvent.java?autodive=0%2F%2F%2F%2F%2F).\n\n\u003cbr /\u003e\n\nchanges, the `onDrivingStateChanged()` method is called with the new [CarDrivingStateEvent](https://android.googlesource.com/platform/packages/services/Car/+/android16-release/car-lib/src/android/car/drivingstate/CarDrivingStateEvent.java?autodive=0%2F%2F%2F%2F%2F).\n\n\u003cbr /\u003e\n\n```python\nimport android.car.Car;\n/* For CarDrivingState */\nimport android.car.drivingstate.CarDrivingStateEvent;\nimport android.car.drivingstate.CarDrivingStateManager;\n\nmDrivingStateManager = (CarDrivingStateManager) mCar.getCarManager(\n Car.CAR_DRIVING_STATE_SERVICE);\n/* Register the listener (implemented below) */\nmDrivingStateManager.registerListener(mDrivingStateEventListener);\n/* While we wait for a change to be notified, query the current state */\nmDrivingStateEvent = mDrivingStateManager.getCurrentCarDrivingState();\n\nprivate final CarDrivingStateManager.CarDrivingStateEventListener\nmDrivingStateEventListener =\n new CarDrivingStateManager.CarDrivingStateEventListener() {\n @Override\n public void onDrivingStateChanged(CarDrivingStateEvent event) {\n mDrivingStateEvent = event;\n /* handle the state change accordingly */\n handleDrivingStateChange();\n }\n};\n```\n\nTesting\n-------\n\nYou can mimic the changing of gears and speed to change the driving state. Use an ADB shell\ncommand to inject vehicle events. This can be useful development and testing.\n\nTo simulate driving events:\n\n1. To set speed to 0: \n\n ```text\n adb shell dumpsys activity service com.android.car inject-vhal-event 0x11600207 0\n ```\n2. To set gear to Parked (to simulate CarDrivingStateEvent pointing to PARKED): \n\n ```text\n adb shell dumpsys activity service com.android.car inject-vhal-event 0x11400400 4\n ```\n3. To set gear to Drive, with speed still at 0 (to simulate CarDrivingStateEvent pointing to IDLING): \n\n ```text\n adb shell dumpsys activity service com.android.car inject-vhal-event 0x11400400 8\n ```\n4. To set speed to 30 meters per second (to simulate CarDrivingStateEvent pointing to MOVING): \n\n ```text\n adb shell dumpsys activity service com.android.car inject-vhal-event 0x11600207 30\n ```"]]