Serviço de plug-in de áudio para carro

Os novos serviços de plug-in de OEM de carro no Android 14 permitem configurar alguns componentes do veículo. Especificamente para áudio, três novos serviços de plug-in foram introduzidos, permitindo que os OEMs configurem de maneira flexível o gerenciamento de áudio em dispositivos AAOS:

  • Controle de seleção de áudio
  • Controle de volume e desativação do som
  • Controle de redução de áudio

Arquitetura de serviço do plug-in de carro

A figura abaixo mostra uma visão geral dos serviços automotivos e da relação deles com o serviço automotivo do OEM. Assim como os processos de apps e de serviços automotivos, o processo de serviços automotivos do OEM ocupa um espaço próprio.

imagem

O serviço de carro inicia o serviço de carro do OEM encontrando o componente definido em config_oemCarService. Se a configuração estiver vazia, o serviço do OEM não vai existir e nenhum serviço será iniciado. O componente precisa estender OemCarService. O serviço de áudio do carro precisa substituir as APIs para adquirir o serviço OEM de áudio do carro:

public final class OemCarServiceImp extends OemCarService {
    @Override
    public OemCarAudioFocusService getOemAudioFocusService();

    @Override
    public OemCarAudioDuckingService getOemAudioDuckingService();

    @Override
    public OemCarAudioVolumeService getOemAudioVolumeService();
}

Por exemplo, consulte o app de teste de referência definido em packages/services/Car/tests/OemCarServiceTestApp.

Embora o serviço seja iniciado pelo serviço de carro, ele não herda automaticamente as permissões disponíveis para o serviço de áudio do carro. Assim, qualquer permissão exigida pelos serviços do OEM precisa ser adquirida com o mecanismo adequado. Por exemplo, consulte packages/services/Car/data/etc/com.android.car.oemcarservice.testapp.xml.

Serviço de áudio automotivo com arquitetura de serviço OEM

No AAOS, o serviço de áudio do carro gerencia estas ações:

  • Roteamento de áudio
  • Seleção de áudio
  • Redução de áudio
  • Volume e desativar som

Antes do Android 14, esse comportamento era basicamente estático e só podia ser modificado nas configurações, embora para um conjunto muito limitado de casos. O Android 14 introduziu um mecanismo para que o serviço de áudio do carro se comunique com um componente definido pelo OEM que gerencia:

  • Seleção de áudio
  • Redução de áudio
  • Volume e desativar som

A figura abaixo mostra uma arquitetura simplificada para o serviço de áudio do carro e o serviço OEM do carro. O serviço de áudio do carro define diferentes hooks que podem chamar o serviço de áudio do OEM do carro para gerenciar o comportamento do áudio. Isso só acontece se o componente de serviço de áudio do carro OEM correspondente estiver definido. Caso contrário, o serviço de áudio do carro usará o comportamento padrão.

imagem

Para garantir que o serviço de áudio do carro e o serviço de áudio do OEM do carro estejam sempre sincronizados, em cada chamada, o serviço de áudio do carro transmite as partes necessárias do estado atual da pilha de áudio para o serviço de áudio do OEM do carro. Por exemplo, quando o serviço de áudio do carro intercepta uma solicitação para avaliar o foco de áudio, ele transmite o estado atual da pilha para o serviço de áudio do OEM do carro. O estado atual inclui o detentor e os perdedores de foco atuais. Os perdedores de foco são solicitações de foco que ainda fazem parte da pilha, mas que perderam o foco temporariamente.

O serviço de áudio do carro precisa gerenciar toda a atividade de áudio no veículo. Se o serviço de áudio do carro não gerenciar algumas partes do comportamento de áudio, as informações expostas ao serviço de áudio do OEM do carro vão estar incompletas. Por exemplo, se um OEM substituir o processamento de foco de áudio no serviço de carro registrando a própria política de foco de áudio, o serviço de áudio do carro não poderá fornecer informações completas ao serviço de áudio do OEM do carro. Isso pode afetar a capacidade do serviço de áudio do OEM do carro de tomar decisões, já que ele pode não ter informações não visíveis para o serviço de áudio do carro.

Para realizar ações, o serviço de áudio do carro chama os serviços do carro do OEM. Essas chamadas são feitas entre processos, o que exige comunicação entre processos (IPC). A IPC adiciona latência a cada chamada. É importante minimizar a latência no serviço do OEM.

Como as chamadas de serviço de áudio do carro para o serviço OEM são de bloqueio, o serviço OEM não deve chamar o serviço de áudio do carro em avaliações diretas da API. Em vez disso, o serviço de áudio do carro fornece as informações necessárias para que as chamadas entre os dois processos precisem viajar apenas em uma direção.

Definições de serviços de áudio automotivo do OEM

Serviço de seleção de áudio do carro OEM

O serviço de áudio do carro gerencia solicitações de seleção de áudio de apps registrando um listener de seleção de política de áudio. O serviço de áudio do carro tem um mecanismo para gerenciar o comportamento do foco com base em uma matriz de interação estática. A matriz define três tipos diferentes de interações:

  • Interação simultânea. Os detentores de foco podem manter o foco ao mesmo tempo.

  • Interações exclusivas. A solicitação de foco recebida tira o foco do detentor atual.

  • Rejeitar interação. Solicitação de foco recebida rejeitada com base no detentor do foco atual.

Embora isso seja suficiente para alguns casos de uso automotivo, não atende a todas as necessidades de interação, que podem variar devido aos requisitos do OEM. Para isso, apresentamos o OemCarAudioFocusService:

public interface OEmCarAudioFocusService {
    OemCarAuddioFocusResults evaluateAudioFocusRequest(
        OemCarAudioFocusEvaluationRequest request);
    
    void notifyAudioFocusChange(
        List<AudioFocusEntry> holder,
        List<AudioFocusEntry> losers, int zoneId);
}

A API evaluateAudioFocusRequest é chamada pelo serviço de áudio do carro sempre que há uma solicitação de foco de áudio que precisa ser avaliada. É uma API bidirecional que bloqueia o retorno dos resultados. A solicitação contém informações sobre o estado atual da pilha de áudio:

Essas informações podem ser usadas para avaliar o newFocusRequest em comparação com os detentores de foco atuais em focusHolders e os perdedores de foco atuais em focusLosers. A API retorna os resultados:

class OemCarAudioFocusResult {
    int audioZoneId;
    int audioFocusEvaluationResults;
    AudioFocusEntry focusResult;
    List<AudioFocusEntry> newLosers;
    List<AudioFocusEntry> newlyBlocked;
}

Ele contém as informações sobre os resultados reais da avaliação em audioFocusEvaluationResults, que indica se a solicitação atual foi concedida, atrasada ou falhou. Todas as mudanças na pilha de foco atual devem ser definidas nas entradas newLosers e newlyBlocked, dependendo da natureza da mudança na pilha.

Em que o newLosers contém entradas que estavam em foco anteriormente, mas agora precisam perder o foco, de forma permanente ou temporária. Os perdedores de seleção permanente serão removidos da pilha de seleção de áudio, e os perdedores de seleção temporária serão movidos para a pilha atual de perdedores de seleção até que recuperem a seleção ou sejam abandonados pelo solicitante de seleção original. De qualquer forma, o listener de foco para as solicitações vai receber uma perda de foco correspondente.

A lista newlyBlocked contém entradas que estavam na lista de perdedores de foco, mas agora estão bloqueadas pela nova entrada. O bloqueio pode ser permanente ou temporário. No caso de um bloqueio permanente, a entrada será removida da pilha e a perda de foco será enviada aos listeners de foco. Para perda de foco temporária, a entrada vai permanecer na pilha de perdedores de foco, mas um novo bloqueador de foco será adicionado à lista. Nenhuma perda de foco será enviada, já que uma foi enviada anteriormente quando o foco foi bloqueado pela primeira vez. A solicitação será desbloqueada quando todos os bloqueadores atuais forem removidos ou será removida da pilha se o foco for abandonado.

A segunda API, notifyAudioFocusChange, é uma via única chamada em cada solicitação ou abandono de foco de áudio. A API é usada principalmente para informar o serviço do OEM sobre mudanças de foco, que podem afetar o comportamento do serviço de áudio do carro do OEM.

Diretrizes para avaliação de foco

No AAOS, o foco de áudio é usado para gerenciar a reprodução de áudio e determinar qual app precisa aderir para oferecer uma experiência ideal ao usuário. Assim, o serviço de plug-in do OEM precisa considerar o seguinte ao gerenciar uma solicitação de foco de áudio:

  • Sem nenhum foco de áudio de alta prioridade (como uma ligação, emergência ou segurança), os apps precisam conseguir o foco de áudio de forma temporária ou permanente.

  • Enquanto um foco de mídia estiver ativo, os apps que solicitarem:

    • Chame o foco de uso, que precisa receber o foco simultânea ou exclusivamente.

    • O foco no uso da navegação precisa ser capaz de receber o foco simultânea ou exclusivamente.

    • O foco do uso do Google Assistente. Ele precisa ser capaz de receber foco simultânea ou exclusivamente.

  • Enquanto apps com foco de áudio de alta prioridade (como uma ligação, um alerta de emergência ou um alerta de segurança) estão ativos, qualquer solicitação de foco de áudio atrasada recebida deve ser concedida ou adiada conforme necessário.

As sugestões acima não são exaustivas, mas podem ajudar a garantir que os apps que pedem foco consigam isso quando não houver sons ativos de alta prioridade. Mesmo quando sons de alta prioridade estão ativos, as solicitações de foco atrasado ainda precisam ser respeitadas e podem ganhar foco quando o som de alta prioridade para.

Serviço de volume de carros OEM

O serviço de áudio do carro gerencia eventos de tecla de volume ouvindo ajustes de volume do sistema de áudio ou eventos de tecla de volume diretamente do serviço de entrada do carro. Em cada caso, o comportamento padrão do serviço de áudio do carro é determinar qual grupo de volume mudar com base nos players de áudio ativos e em uma lista de prioridade de contexto de áudio.

Oferecemos duas listas de prioridade de volume. A primeira lista considera todos os contextos de áudio nesta ordem. A lista é apresentada em ordem decrescente, com a prioridade mais alta na parte de cima e a mais baixa na parte de baixo. Por exemplo, se o áudio de navegação e o de música estiverem ativos ao mesmo tempo, o volume de navegação será alterado durante um evento de tecla de volume.

  1. Navegação
  2. Ligar
  3. Música
  4. Aviso
  5. Comando de voz
  6. Toque da chamada
  7. Som do sistema
  8. Segurança
  9. Alarme
  10. Notificação
  11. Status do veículo
  12. Emergência

Para simplificar o gerenciamento de eventos da tecla de volume, o serviço de áudio do carro tem uma segunda lista de prioridade de contexto de áudio:

  1. Ligar
  2. Mídia
  3. Aviso
  4. Comando de voz

Essa lista também é apresentada em ordem decrescente. O objetivo dessa segunda lista é permitir que sons mais comuns sejam alterados por eventos principais. Sons incomuns, talvez de duração mais curta, só podem ser gerenciados pela interface do usuário das configurações de áudio.

A versão real do volume pode ser definida com a configuração audioVolumeAdjustmentContextsVersion. A configuração pode ser definida como 1 ou 2 (2 é o padrão).

Para oferecer mais flexibilidade ao gerenciamento de volume, o OemCarAudioVolumeService foi lançado no Android 14:

public interface OemCarAudioVolumeService {
    OemCarvolumeChangeInfo getSuggestedGroupForVolumeChange(
OemCarAudioVolumeRequest request, int volumeAdjustment);
}

O serviço de volume de áudio do carro OEM tem um único método, que recebe um volumeAdjustment e um OemCarAudioVolumeRequest:

class OemCarAudioVolumeRequest {
    int audioZoneId;
    int callState;
    List<AudioAttributes> activePlaybackAttributes;
    List<AudioAttributes> duckedAttributes;
    List<CarVolumeGroupInfo> volumeGroupState;
}

O activePlaybackAttributes da solicitação tem os atributos de áudio ativos. Os duckedAttributes são todos atributos de áudio reduzidos no momento. O volumeGroupState tem o estado atual do grupo de volumes. A solicitação representa o estado atual da pilha de áudio e pode ser usada para determinar qual grupo de volume precisa ser alterado. Os resultados precisam ser retornados em OemCarVolumeChangeInfo:

class OemCarVolumeChangeInfo {
    boolean change;
    CarVolumeGroupInfo volumeGroupChanged;
}

O booleano change indica se algum volume mudou, e true indica que há uma mudança e que o grupo de volume precisa ser atualizado. O volumeGroupChanged é o grupo de volumes real que precisa ser mudado. Esse grupo precisa ser alterado de acordo com o parâmetro volumeAdjustment original transmitido à API. Por exemplo, se os resultados indicarem que o grupo de volume de navegação precisa ser silenciado, o booleano será true e o grupo de volume retornado será o de navegação.

Serviço de redução de volume de carro OEM

O serviço de áudio do carro gerencia a redução de áudio monitorando as mudanças de foco e enviando um sinal para a HAL AudioControl sobre quais dispositivos de áudio reduzir. Quando o foco muda, todos os detentores de foco ativos são avaliados para determinar qual deles deve ser reduzido com base neste conjunto de regras estáticas de redução:

  • Os sons de emergência diminuem tudo, exceto os sons de chamada
  • A segurança silencia tudo, exceto sons de emergência
  • A navegação reduz o volume de tudo, exceto os sons de segurança e emergência
  • Chamar patos tudo, exceto sons de segurança, emergência e navegação
  • O Voice reduz os sons de toque de chamada
  • Músicas e anúncios precisam ser reduzidos por tudo

Essas regras não são exaustivas, e os OEMs continuam responsáveis por determinar como os sons devem ser reduzidos com base nessas diretrizes. Os OEMs podem controlar essas recomendações de forma mais ativa com base nos requisitos disponíveis. O OemCarDuckingService foi introduzido no Android 14:

class OemCarAudioDuckingService {
List<AudioAttributes>   evaluateAttributesToDuck(
        OemCarAudioVolumeRequest request);
}

Essa API é chamada pelo serviço de áudio do carro em mudanças de seleção de áudio. Ele reutiliza o OemCarAudioVolumeRequest apresentado no serviço de volume de carros OEM e contém as informações relevantes para decidir quais atributos ocultar. A lista de atributos de áudio a serem reduzidos da API é comparada ao estado atual do áudio:

  • Atributo de áudio atualmente reduzido:

    • Na lista, continua sendo evitado
    • Não está na lista, a ação de abaixar foi desativada
  • Atributo de áudio não reduzido no momento:

    • Na lista, com redução
    • Não está na lista, a ação de abaixar foi desativada

Em seguida, o serviço de áudio do carro determina a quais dispositivos de saída de áudio os atributos pertencem e os adiciona à lista de dispositivos de saída de áudio reduzidos ou não reduzidos, respectivamente. Isso é enviado para a HAL AudioControl para realizar a redução necessária no nível do hardware.

A figura abaixo mostra um diagrama de sequência simplificado do controle de redução de áudio para uma solicitação de foco quando o serviço de redução do OEM é usado:

imagem

A sequência começa quando um app solicita Gerenciar seleção de áudio usando APIs públicas do gerenciador de áudio. A solicitação é encaminhada ao serviço de áudio do carro para determinar os resultados. Quando o foco de áudio é decidido, o ducking de áudio é avaliado pelo serviço de áudio do carro que chama o OemCarAudioDuckingService para avaliar quais atributos de áudio precisam ser reduzidos. Depois que os resultados são retornados da API evaluateAttributesToDuck, os dispositivos de áudio a serem reduzidos são calculados e, por fim, as informações são enviadas ao AudioControl para aplicar a redução ao hardware de áudio.

Implementação de referência do serviço de áudio do carro OEM

O AAOS oferece uma implementação de referência do serviço de carro OEM em packages/services/Car/tests/OemCarServiceTestApp, que implementa o OemCarService, além de OemCarAudioFocusService, OemCarAudioDuckingService e o OemCarAudioVolumeService. Para o último, cada serviço usa um arquivo XML para carregar um comportamento estático. Por exemplo, OemCarAudioFocusServiceImp carrega o oem_focus_config.xml, que contém uma matriz de interação. A matriz é usada para avaliar a solicitação de foco quando o evaluateAudioFocusRequest é chamado.

Depuração do app de teste de referência

O app de teste de serviço de carro do OEM faz parte do código-fonte do AOSP. Os OEMs podem fazer mudanças de acordo com as necessidades deles. Para depurar, use a configuração config_oemCarService para ativar o app de teste.

<!-- This is the component name for the OEM customization service. OEM can choose to implement
this service to customize car service behavior for different policies. If OEMs choose to
implement it, they have to implement a service extending OemCarService exposed by car-lib,
and implement the required component services.
If the component name is invalid, CarService would not connect to any OEM service.
Component name can not be a third party package. It should be pre-installed -->
<string name="config_oemCarService" translatable="false">
com.android.car.oemcarservice.testapp/.OemCarServiceImpl
</string>

Para verificar se o serviço de carro do OEM usa o comando dump do serviço de carro para o serviço do OEM:

adb shell dumpsys car_service --oem-service

Os resultados podem ser semelhantes à saída abaixo:

***CarOemProxyService dump***
  mIsFeatureEnabled: true
  mIsOemServiceBound: true
  mIsOemServiceReady: true
  mIsOemServiceConnected: true
  mInitComplete: true
  OEM_CAR_SERVICE_CONNECTED_TIMEOUT_MS: 5000
  OEM_CAR_SERVICE_READY_TIMEOUT_MS: 5000
  mComponentName: com.android.car.oemcarservice.testapp/.OemCarServiceImpl

Cada booleano em cada lote de informações de dump determina o estado do recurso e do serviço. Por exemplo, as informações de despejo mIsOemServiceReady especificam se o serviço está pronto para uso. true indica que está pronto, e false indica que não está.