消费汽车驾驶状态和用户体验限制

本文解释了应用程序如何优雅地过渡到分心优化 (DO) 用户界面。它描述了如何消费汽车的驾驶状态以及相应的用户体验限制。有关汽车用户体验 (UX) 限制规则的更多信息,请参阅汽车用户体验限制,其中详细介绍了停车、怠速和行驶中的三种驾驶状态。

观众

此内容是为那些想要设计适应汽车驾驶状态变化和相应施加的用户体验限制的应用程序的人提供的。

技术细节

汽车驾驶状态管理器

汽车的驾驶状态(停车、怠速或行驶)源自车辆硬件抽象层 (VHAL) 提供的传感器值。基本传感器信息,例如车速和当前档位选择,用于得出车辆的当前驾驶状态。

此信息通过提供 @SystemApis 的CarDrivingStateManager向特权客户端公开,这意味着只有 Platform Internals、捆绑的 APK(例如 SysUI 或 Settings)和 Privileged APK(例如)GMSCore 可以访问 API。 API 受特定于驾驶状态android.car.permission.CAR_DRIVING_STATE的权限的保护。需要访问驾驶状态信息的客户必须请求此权限。

CarUxRestrictionsManager

那些根据驾驶状态显示用户界面的应用程序必须监听CarUxRestrictionsManager ,它抽象了从驾驶状态到 UX 限制的映射,因此应用程序无需针对不同的市场安全要求进行调整。

注意:这些活动必须标记为 DistractionOptimized,如驾驶员分心指南中所述。如果活动没有相应地标记,它们将被阻止。

相反,应用程序监视 CarUxRestrictionsManager 公开的限制,而不是 CarDrivingStateManager 公开的与用户界面或用户体验相关的任何内容的绝对驾驶状态。

代码示例

以下示例代码说明了应用程序如何监控 UX 限制:

  1. 导入汽车库包:
    import android.car.Car;
    /* For CarUxRestrictions */
    import android.car.drivingstate.CarUxRestrictions;
    import android.car.drivingstate.CarUxRestrictionsManager;
    
  2. 实现CarUxRestrictionManager.OnUxRestrictionsChangedListener ( mUxRChangeListener )。这个监听器一旦注册到CarUxRestrictionsManager ,就会在 UX 限制发生变化时被调用。根据需要处理限制更改以优化分心:
    @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);
            }
        };
      
  3. 调用汽车 API 创建一个名为 mCar 的汽车实例并连接到汽车服务:
    mCar = Car.createCar(context);
    if (mCar == null) {
    // handle car connection error
    }
    
  4. 调用mCar.getCarManager() - mCarUxRestrictionsManager以获取CarUxRestrictionsManager
    CarUxRestrictionsManager carUxRestrictionsManager = (CarUxRestrictionsManager)
    mCar.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);
    
  5. 使用CarUxRestrictionsManager调用mCarUxRestrictionsManager.registerListener()注册上面第 2 步中实现的mUxRChangeListener
    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());

CarUx 限制

CarUxRestrictions对象提供两种类型的信息:

  1. 当前是否有分散注意力优化的要求?
  2. 如果是这样,目前有哪些限制?

getCurrentUxRestrictions()或侦听器回调获得CarUxRestrictions后,应用程序现在可以使用isRequiresDistractionOptimization() API 来确定是否需要 Distraction Optimized。如果返回 false,则不需要进行分心优化,应用程序可以安全地运行任何活动。

如果需要优化,则使用getActiveRestrictions() API 来获取适当的限制集。此 API 返回一个int,它是当前有效的所有限制的位掩码。当前通知的一组限制列在CarUxRestrictions下。

注意:预计在不久的将来会发生对限制集的微小更改。

例如,如果应用程序想要确定是否存在播放视频的限制,则在获取 CarUxRestrictions 对象后,应用程序必须检查该限制:

int activeUxR = mCurrentCarUxRestrictions.getActiveRestrictions();
if ((activeUxR & CarUxRestrictions.UX_RESTRICTIONS_NO_VIDEO) != 0) {
      handleStopPlayingVideo();
}

驾驶状态

CarDrivingStateManager 呈现车辆的实际驾驶状态(停车、怠速或移动)。 CarDrivingStateManager API 的调用方式与 CarUxRestrictionsManager 类似。应用程序可以注册一个监听器和/或获取当前的驾驶状态。驾驶状态作为 CarDrivingStateEvent 返回。

与 CarUxRestrictionsManager API 类似,客户端可以使用registerListener()为驾驶状态注册一个监听器,并传递CarDrivingStateEventListener的实现。在驾驶状态发生变化时,将使用新的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 命令注入车辆事件。这可能是有用的开发和测试。

模拟驾驶事件:

  1. 将速度设置为 0:
    adb shell dumpsys activity service com.android.car inject-vhal-event 0x11600207 0
    
  2. 将档位设置为 Parked(模拟 CarDrivingStateEvent 指向 PARKED):
    adb shell dumpsys activity service com.android.car inject-vhal-event 0x11400400 4
    
  3. 将档位设置为 Drive,速度仍为 0(模拟 CarDrivingStateEvent 指向 IDLING):
    adb shell dumpsys activity service com.android.car inject-vhal-event 0x11400400 8
    
  4. 将速度设置为每秒 30 米(模拟 CarDrivingStateEvent 指向 MOVING):
    adb shell dumpsys activity service com.android.car inject-vhal-event 0x11600207 30