Consumo do estado de condução do carro e restrições de UX

Este artigo explica como os aplicativos podem fazer a transição para interfaces de usuário otimizadas para distração (DO). Ele descreve como consumir o estado de condução de um carro, bem como as restrições de experiência do usuário correspondentes. Para obter mais informações sobre as regras de restrições da experiência do usuário do carro (UX), consulte Restrições da experiência do usuário do carro , que detalha os três estados de condução: estacionado, ocioso e em movimento.

Público

Este conteúdo é fornecido para aqueles que desejam projetar aplicativos que se adaptem às mudanças no estado de condução de um carro e às restrições de UX impostas correspondentes.

Detalhes técnicos

CarDrivingStateManager

O estado de condução de um carro (estacionado, ocioso ou em movimento) é derivado dos valores do sensor fornecidos pela Camada de abstração de hardware do veículo (VHAL). As informações básicas do sensor, como velocidade do veículo e seleção de marcha atual, são usadas para derivar o estado de condução atual do veículo.

Essas informações são expostas a clientes privilegiados por meio do CarDrivingStateManager , que fornece @SystemApis, o que significa que apenas Platform Internals, Bundled APKs (como SysUI ou Settings) e Privileged APKs (como) GMSCore podem acessar as APIs. As APIs são protegidas por permissões específicas para o estado de condução android.car.permission.CAR_DRIVING_STATE . Os clientes que exigem acesso às informações do estado de condução devem solicitar essa permissão.

CarUxRestrictionsManager

Os aplicativos que exibem uma interface de usuário dependente do estado de condução devem ouvir CarUxRestrictionsManager , que abstrai o mapeamento do estado de condução para as restrições de UX para que os aplicativos não precisem se ajustar a diferentes requisitos de segurança do mercado.

Observação : essas atividades devem ser marcadas como DistractionOptimized, conforme descrito em Diretrizes de distração do motorista . Se as atividades não estiverem marcadas de acordo, elas serão bloqueadas.

Em vez disso, os aplicativos monitoram as restrições expostas pelo CarUxRestrictionsManager e não um estado de condução absoluto exposto pelo CarDrivingStateManager para qualquer coisa relacionada à interface do usuário ou à experiência do usuário.

Amostra de código

O código de amostra a seguir ilustra como um aplicativo monitora as restrições de UX:

  1. Importe os pacotes da biblioteca do carro:
    import android.car.Car;
    /* For CarUxRestrictions */
    import android.car.drivingstate.CarUxRestrictions;
    import android.car.drivingstate.CarUxRestrictionsManager;
    
  2. Implemente o CarUxRestrictionManager.OnUxRestrictionsChangedListener ( mUxRChangeListener ). Este listener, uma vez registrado no CarUxRestrictionsManager , será chamado quando ocorrer uma alteração nas restrições de UX. Manipule as alterações de restrição para serem otimizadas para distração, conforme necessário:
    @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. Chame as APIs de carro para criar uma instância de carro chamada mCar e conecte-se ao serviço de carro:
    mCar = Car.createCar(context);
    if (mCar == null) {
    // handle car connection error
    }
    
  4. Chame mCar.getCarManager() - mCarUxRestrictionsManager para obter o CarUxRestrictionsManager :
    CarUxRestrictionsManager carUxRestrictionsManager = (CarUxRestrictionsManager)
    mCar.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);
    
  5. Para registrar mUxRChangeListener implementado na Etapa 2 acima com o CarUxRestrictionsManager chame mCarUxRestrictionsManager.registerListener() :
    mCarUxRestrictionsManager.registerListener(mUxrChangeListener);
    mUxrChangeListener.onUxRestrictionsChanged(
    mCarUxRestrictionsManager.getCurrentCarUxRestrictions());
    

O bloco de código de amostra concluído (criado na Etapa 3 até a Etapa 5) resulta nas alterações de restrição de recebimento do ouvinte quando o estado da unidade é alterado:

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

O objeto CarUxRestrictions fornece dois tipos de informações:

  1. Existe um requisito atual para ser Otimizado para Distração?
  2. Em caso afirmativo, quais restrições estão em vigor atualmente?

Depois que CarUxRestrictions é obtido de getCurrentUxRestrictions() ou do retorno de chamada do ouvinte, os aplicativos agora podem usar a API isRequiresDistractionOptimization() para determinar se o Distraction Optimized é necessário. Se isso retornar falso, não há necessidade de ser Otimizado para Distração e um aplicativo pode executar com segurança qualquer atividade.

Se a otimização for necessária, use a API getActiveRestrictions() para obter o conjunto de restrições em vigor. Essa API retorna um int, que é uma máscara de bits de todas as restrições atualmente em vigor. O conjunto de restrições atualmente notificado está listado em CarUxRestrictions .

Nota : Prevê-se que pequenas alterações no conjunto de restrições ocorram em um futuro próximo.

Por exemplo, se um aplicativo deseja determinar se existe uma restrição para reproduzir vídeo, ao obter o objeto CarUxRestrictions, o aplicativo deve verificar a restrição:

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

Estado de condução

CarDrivingStateManager apresenta o estado real de condução do veículo (estacionado, em marcha lenta ou em movimento). As APIs CarDrivingStateManager podem ser chamadas de forma semelhante ao CarUxRestrictionsManager. Os aplicativos podem registrar um ouvinte e/ou obter o estado de condução atual. O estado de condução é retornado como CarDrivingStateEvent.

Semelhante às APIs CarUxRestrictionsManager, os clientes podem registrar um ouvinte para o estado de condução usando registerListener() e passar uma implementação do CarDrivingStateEventListener . Ao conduzir mudanças de estado, o método onDrivingStateChanged() será chamado com o novo CarDrivingStateEvent .

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();
   }
};

Teste

Você pode imitar a mudança de marchas e velocidade para alterar o estado de condução. Use um comando shell ADB para injetar eventos de veículo. Isso pode ser útil para desenvolvimento e teste.

Para simular eventos de direção:

  1. Para definir a velocidade para 0:
    adb shell dumpsys activity service com.android.car inject-vhal-event 0x11600207 0
    
  2. Para definir a marcha para Parked (para simular CarDrivingStateEvent apontando para PARKED):
    adb shell dumpsys activity service com.android.car inject-vhal-event 0x11400400 4
    
  3. Para definir a marcha para Drive, com velocidade ainda em 0 (para simular CarDrivingStateEvent apontando para IDLING):
    adb shell dumpsys activity service com.android.car inject-vhal-event 0x11400400 8
    
  4. Para definir a velocidade para 30 metros por segundo (para simular CarDrivingStateEvent apontando para MOVING):
    adb shell dumpsys activity service com.android.car inject-vhal-event 0x11600207 30