Os novos serviços de plug-in OEM de carros no Android 14 permitem que alguns componentes do carro sejam configurados. Para áudio especificamente, três novos serviços de plug-in foram introduzidos, permitindo que os OEMs configurem flexivelmente o gerenciamento de áudio em dispositivos AAOS:
- Controle de seleção de áudio
- Controle de volume e mudo de áudio
- Controle de redução de áudio
Arquitetura do serviço de plug-in do carro
A figura abaixo mostra uma visão geral dos serviços de carro e a relação deles com o serviço de carro OEM. Assim como os processos de app e de serviço de carro, o processo de serviço de carro OEM ocupa o próprio espaço de processo.
O serviço de carro inicia o serviço de carro OEM encontrando o componente definido em
config_oemCarService
. Se a configuração estiver vazia, o serviço OEM não 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();
}
Como
exemplo, consulte
o app de teste de referência definido em
packages/services/Car/tests/OemCarServiceTestApp
.
Mesmo que 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. Portanto, qualquer
permissão exigida pelos serviços 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 de carro 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 bastante estático e só podia ser modificado por configurações, embora em 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 OEM do carro para gerenciar o comportamento de áudio. O último ocorre apenas se o componente de serviço de áudio do carro OEM correspondente estiver definido. Caso contrário, o serviço de áudio do carro vai usar o comportamento padrão.
Para garantir que o serviço de áudio do carro e o serviço de áudio do OEM do carro estejam sempre em sincronia, 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 OEM do carro. O estado atual inclui o detentor de foco atual 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 temporariamente o foco.
O serviço de áudio do carro precisa gerenciar todas as atividades de áudio no carro. Se o serviço de áudio do carro não gerenciar algumas partes do comportamento do áudio, as informações expostas ao serviço de áudio OEM do carro serão 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 OEM do carro. Isso pode afetar a capacidade do serviço de áudio OEM do carro de tomar decisões, já que pode faltar 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 de carro OEM. Essas chamadas são feitas entre processos, o que exige comunicação interprocesso (IPC). O IPC adiciona latência a cada chamada. É importante minimizar a latência no serviço OEM.
Como as chamadas do serviço de áudio do carro para o serviço OEM estão bloqueadas, o serviço OEM não pode chamar o serviço de áudio do carro em avaliações diretas de 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 de carro OEM
Serviço de seleção de áudio do carro OEM
O serviço de áudio do carro gerencia solicitações de foco de áudio de apps registrando um listener de foco de política de áudio. O serviço de áudio do carro tem um mecanismo para gerenciar o comportamento de 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 de foco atual.
Recusar interação. A solicitação de foco recebida foi rejeitada com base no detentor de foco atual.
Embora isso seja suficiente para alguns casos de uso automotivo, ele não atende a todas as
necessidades de interação que podem ser diferentes 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. Ela é uma API bidirecional
que bloqueia os resultados para que eles sejam retornados. 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 precisa retornar 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 indicam se a solicitação atual foi
concedida, adiada ou falhou. Qualquer mudança na pilha de foco atual
precisa ser definida nas entradas newLosers
e newlyBlocked
, dependendo da natureza
da mudança da pilha.
Onde newLosers
contém entradas que antes mantinham o foco, mas
agora precisam perdê-lo, seja permanentemente ou temporariamente. Os perdedores de foco permanentes
serão removidos da pilha de foco de áudio, e os perdedores de foco temporários
serão movidos para a pilha de perdedores de foco atual até que recuperem o foco ou sejam
abandonados pelo solicitante de foco 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
transitório. No caso de 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 perdas de foco, mas um novo bloqueador de foco será
adicionado à lista de bloqueadores. Nenhuma perda de foco será enviada, já que uma foi enviada
quando o bloqueio foi feito 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 que é chamada em cada
solicitação ou abandono de foco de áudio. A API é usada principalmente para informar ao serviço OEM
sobre mudanças de foco, o que pode afetar o comportamento do serviço de áudio do carro OEM.
Diretrizes para a 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. Portanto, o serviço de plug-in OEM precisa levar em consideração 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 temporariamente ou permanentemente.
Enquanto o foco de mídia estiver ativo, os apps que solicitarem:
O foco de uso de chamada precisa ser capaz de receber foco simultaneamente ou exclusivamente.
O foco de uso da navegação precisa ser capaz de receber foco simultaneamente ou exclusivamente.
O foco de uso do Google Assistente precisa ser capaz de receber foco simultaneamente ou exclusivamente.
Enquanto os apps de foco de áudio de alta prioridade (como uma ligação, um alerta de emergência ou de segurança) estiverem ativos, qualquer solicitação de foco de áudio atrasada recebida precisa 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 solicitam o foco possam receber o foco quando não há sons de alta prioridade ativos. Mesmo quando os sons de alta prioridade estão ativos, as solicitações de foco atrasadas ainda precisam ser respeitadas e precisam ser capazes de receber o foco quando o som de alta prioridade parar.
Serviço de volume do carro OEM
O serviço de áudio do carro gerencia eventos de tecla de volume detectando 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 reprodutores 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 no topo e a mais baixa na parte de baixo. Por exemplo, se o áudio de navegação e o áudio da música estiverem ativos ao mesmo tempo, o volume de navegação será alterado durante um evento de tecla de volume.
- Navegação
- Ligar
- Música
- Aviso
- Comando de voz
- Toque da chamada
- Som do sistema
- Segurança
- Alarme
- Notificação
- Status do veículo
- Emergência
Para tornar o gerenciamento de eventos de tecla de volume menos complexo, o serviço de áudio do carro tem uma segunda lista de prioridade de contexto de áudio:
- Ligar
- Mídia
- Aviso
- 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, podem ser gerenciados apenas pela interface de 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,
OemCarAudioVolumeService
foi introduzido 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 os atributos de áudio atualmente ocultos. 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 foi alterado. true
indica que
há uma mudança e que o grupo de volume precisa ser atualizado. O
volumeGroupChanged
é o grupo de volume real que precisa ser alterado. Esse
grupo precisa ser alterado de acordo com o parâmetro volumeAdjustment
original
transmitido para a 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 da navegação.
Serviço de redução de volume de carro OEM
O serviço de áudio do carro gerencia o abatimento de áudio monitorando as mudanças de foco de áudio e
enviando um sinal para a HAL AudioControl
sobre quais dispositivos de áudio devem ser abafados.
Quando o foco muda, todos os detentores de foco ativos são avaliados para determinar
qual deles precisa ser reduzido com base neste conjunto de regras
de redução estática:
- Os sons de emergência silenciam tudo, exceto os sons de chamada
- A segurança silencia tudo, exceto os sons de emergência
- A navegação silencia tudo, exceto sons de segurança e emergência
- O Call ducks silencia tudo, exceto sons de segurança, emergência e navegação
- O Voice ignora os sons de toque de ligação
- A música e os avisos precisam ser abafados por tudo
Essas regras não são exaustivas, e os OEMs continuam sendo responsáveis por determinar
como os sons devem ser abafados 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 quando o foco de áudio muda. Ele reutiliza
o OemCarAudioVolumeRequest
introduzido no
serviço de volume de carro OEM e contém as informações
relevantes para tomar a decisão sobre quais atributos evitar. A lista de
atributos de áudio para pular da API é comparada ao estado de áudio atual:
Atributo de áudio atualmente silenciado:
- Na lista, continua sendo ignorado
- Não está na lista, o recurso de abatimento está desativado
Atributo de áudio não silenciado no momento:
- Na lista, abaixado
- Não está na lista, o recurso de abatimento está desativado
O serviço de áudio do carro determina a quais dispositivos de saída de áudio os atributos de áudio pertencem e os adiciona à lista de dispositivos de saída de áudio com ruído ou à lista de dispositivos de áudio sem ruído, respectivamente. Isso é enviado ao HAL AudioControl para realizar o ducking necessário no nível do hardware.
A figura abaixo mostra um diagrama de sequência simplificado do controle de abatimento de áudio para uma solicitação de foco quando o serviço de abatimento do OEM é usado:
A sequência começa quando um app solicita
Gerenciar seleção de áudio
por APIs públicas de gerenciamento de áudio. A solicitação é encaminhada ao serviço de áudio
do carro para determinar os resultados. Quando o foco do áudio é decidido, o abatimento de áudio
é avaliado pelo serviço de áudio do carro que chama OemCarAudioDuckingService
para
avaliar quais atributos de áudio precisam ser abafados. Depois que os resultados são retornados
da API evaluateAttributesToDuck
, os dispositivos de áudio para redução de volume são calculados
e, finalmente, as informações são enviadas para o AudioControl
para aplicar a redução de volume
ao hardware de áudio.
Implementação de referência do serviço de áudio de carro OEM
O AAOS fornece uma implementação de referência do serviço de carro OEM em
packages/services/Car/tests/OemCarServiceTestApp
, que implementa o
OemCarService
, junto com OemCarAudioFocusService
,
OemCarAudioDuckingService
e 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 a evaluateAudioFocusRequest
é chamada.
Depuração de referência do app de teste
O app de teste de serviço de carro OEM faz parte do código-fonte do AOSP. Os OEMs podem fazer
mudanças de acordo com as necessidades. 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 OEM usa o comando dump
do serviço de carro para o
serviço 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 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, em que true
indica que ele está pronto e false
indica que ele não está pronto.