Muitas arquiteturas de veículos atuais contêm várias unidades de controle eletrônico (ECUs) fora do sistema de infoentretenimento que controlam a ergonomia, como configurações de assentos e ajustes de espelhos. Com base no hardware atual e nas arquiteturas de energia, muitas ECUs ligam antes que o sistema de infoentretenimento baseado em Android seja ligado. Essas ECUs podem interagir com um sistema de infoentretenimento baseado em Android por meio da Camada de Abstração de Hardware do Veículo (VHAL) .
A partir do Android 11, o Android Automotive OS (AAOS) introduziu um novo conjunto de propriedades no VHAL para criar, alternar, remover e associar acessórios externos para identificar usuários. Por exemplo, essas novas propriedades permitem que um motorista vincule um acessório externo, como um chaveiro, ao usuário Android. Então, quando o motorista se aproxima do veículo, uma ECU acorda e detecta o chaveiro. Essa ECU indica ao HAL qual usuário do Android o infotainment deve iniciar uma inicialização, o que reduz o tempo que um driver espera pelo carregamento do usuário do Android.
Habilitar o usuário HAL
As propriedades User HAL devem ser habilitadas explicitamente, garantindo que a propriedade do sistema android.car.user_hal_enabled
esteja definida como true
. (Isso também pode ser feito no arquivo car.mk
, para que ele não precise ser definido manualmente.) Verifique se user_hal_enabled=true
está habilitado despejando o UserHalService
:
$ adb shell dumpsys car_service --hal UserHalService|grep enabled user_hal_enabled=true
Você também pode verificar user_hal_enabled
usando adb logcat CarServiceHelper *:s
. Se a propriedade estiver desabilitada, uma mensagem como a seguinte será exibida quando o system_server
for iniciado:
I CarServiceHelper: Not using User HAL
Para habilitar manualmente user_hal_enabled
, defina a propriedade do sistema android.car.user_hal_enabled
e reinicie system_server
:
$ adb shell setprop android.car.user_hal_enabled true $ adb shell stop && adb shell start
A saída do logcat
aparece da seguinte forma:
I CarServiceHelper: User HAL enabled with timeout of 5000ms D CarServiceHelper: Got result from HAL: OK I CarServiceHelper: User HAL returned DEFAULT behavior
Propriedades do usuário HAL
Propriedades do ciclo de vida do usuário
As propriedades a seguir fornecem as informações de HAL para os estados do ciclo de vida do usuário, que permitem a sincronização do ciclo de vida do usuário entre o sistema Android e uma ECU externa. Essas propriedades usam um protocolo de solicitação e resposta, no qual o sistema Android faz uma solicitação definindo um valor de propriedade e o HAL responde emitindo um evento de alteração de propriedade.
Nota: Quando o usuário HAL é suportado, todas as propriedades a seguir devem ser implementadas.
Propriedade HAL | Descrição |
---|---|
INITIAL_USER_INFO (LER ESCREVER) | Essa propriedade é chamada pelo sistema Android para determinar qual usuário do Android o sistema iniciará quando o dispositivo for inicializado ou retomado de Suspend-to-RAM (STR). Quando chamado, o HAL deve responder com uma destas opções:
Nota: Se o HAL não responder, o comportamento padrão é executar após um período de tempo limite (cinco (5) segundos por padrão), o que atrasa a inicialização. Se o HAL responder, mas o sistema Android não executar a ação (por exemplo, se o número máximo de usuários for atingido), o comportamento padrão será usado. Por exemplo, por padrão, o sistema Android inicia no último usuário ativo na inicialização. Se um chaveiro de um usuário diferente for detectado, a ECU substituirá a propriedade HAL e, durante a inicialização, o sistema Android alternará para iniciar nesse usuário especificado. |
SWITCH_USER (LER ESCREVER) | Essa propriedade é chamada ao alternar o usuário Android ativo em primeiro plano. A propriedade pode ser chamada pelo sistema Android ou pelo HAL para solicitar uma troca de usuário. Os três fluxos de trabalho são:
O fluxo de trabalho moderno usa uma abordagem de confirmação de duas fases para garantir que o sistema Android e a ECU externa sejam sincronizados. Quando o Android inicia a troca:
O HAL deve esperar até depois da resposta Por exemplo, enquanto estiver em movimento, um motorista tenta alternar usuários do Android na interface do usuário de infoentretenimento. No entanto, como as configurações do assento do carro estão vinculadas ao usuário do Android, o assento se moverá durante a troca do usuário. Assim, a ECU que controla os assentos não confirma a troca, o HAL responde com uma falha e o usuário Android não é trocado. O fluxo de trabalho legado é uma chamada unidirecional enviada após a troca do usuário (portanto, o HAL não pode bloquear a troca). Ele é chamado apenas na inicialização (após a troca inicial do usuário) ou para aplicativos que chamam Por exemplo, se um aplicativo usa O fluxo de trabalho do veículo se origina do HAL, não do sistema Android:
Por exemplo , Bob usou o chaveiro de Alice para abrir o carro e o HAL respondeu à solicitação |
CREATE_USER (LER ESCREVER) | Esta propriedade é chamada pelo sistema Android quando um novo usuário Android é criado (usando a API CarUserManager.createUser() ). O HAL responde com Por exemplo, um motorista toca em um ícone de interface do usuário de infoentretenimento para criar um novo usuário do Android. Isso envia uma solicitação ao HAL e ao restante dos subsistemas do veículo. As ECUs são informadas do usuário recém-criado. Outros subsistemas e ECUs associam seu ID de usuário interno ao ID de usuário do Android. |
REMOVE_USER (APENAS ESCREVER) | O sistema Android chama essa propriedade depois que um usuário Android é removido (com a API CarUserManager.removeUser() ).Esta é uma chamada unidirecional — nenhuma resposta é esperada do HAL. Por exemplo, um motorista toca para remover um usuário Android existente na interface do usuário do infotainment. O HAL é informado e os demais subsistemas e ECUs do veículo são informados da remoção do usuário para que possam remover seu ID de usuário interno. |
Propriedades adicionais
A seguir estão propriedades adicionais, não relacionadas aos estados do ciclo de vida do usuário. Cada um pode ser implementado sem suportar o HAL do Usuário.
Propriedade HAL | Descrição |
---|---|
USER_IDENTIFICATION_ASSOCIATION (LER ESCREVER) | Use esta propriedade para associar qualquer usuário do Android a um mecanismo de identificação, como um chaveiro ou telefone. Use esta mesma propriedade para get ou set associações.Por exemplo, um motorista toca em um ícone de interface do usuário de infoentretenimento para associar o chaveiro usado para abrir o veículo (KEY_123) ao usuário Android ativo atual (USER_11). |
Bibliotecas auxiliares
Todos os objetos usados nas mensagens de solicitação e resposta (como UserInfo
, InitialUserInfoRequest
, InitialUSerInfoResponse
e assim por diante) têm uma representação de alto nível usando C++ struct
, mas a remoção deve ser nivelada em objetos VehiclePropValue
padrão (veja os exemplos abaixo). Para facilitar o desenvolvimento, uma biblioteca auxiliar C++ é fornecida no AOSP para converter automaticamente VehiclePropValue
structs
e vice-versa).
Exemplos
INITIAL_USER_INFO
Exemplo de solicitação (na primeira inicialização)
VehiclePropValue { // flattened from InitialUserInfoRequest prop: 299896583 // INITIAL_USER_INFO prop.values.int32Values: [0] = 1 // Request ID [1] = 1 // InitialUserInfoRequestType.FIRST_BOOT [2] = 0 // user id of current user [3] = 1 // flags of current user (SYSTEM) [4] = 1 // number of existing users [5] = 0 // existingUser[0].id [6] = 1 // existingUser[0].flags }
Exemplo de resposta (criar usuário administrador)
VehiclePropValue { // flattened from InitialUserInfoResponse prop: 299896583 // INITIAL_USER_INFO prop.values.int32Values: [0] = 1 // Request ID (must match request) [1] = 2 // InitialUserInfoResponseAction.CREATE [2] = -10000 // user id (not used on CREATE) [3] = 8 // user flags (ADMIN) prop.values.stringValue: "en-US||Car Owner" // User locale and User name }
MUDAR DE UTILIZADOR
O nome real das classes e propriedades difere um pouco, mas o fluxo de trabalho geral é o mesmo, conforme ilustrado abaixo:
Figura 1. Fluxo de trabalho de propriedades HAL do usuário
Exemplo de solicitação de fluxo de trabalho moderno
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896585 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID [1] = 2 // SwitchUserMessageType::ANDROID_SWITCH ("modern") [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 10,8 // current user id (10) and flags (ADMIN) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
Exemplo de resposta de fluxo de trabalho moderno
VehiclePropValue { // flattened from SwitchUserResponse prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID (must match request) [1] = 3 // SwitchUserMessageType::VEHICLE_RESPONSE [2] = 1 // SwitchUserStatus::SUCCESS }
Exemplo de resposta pós-switch de fluxo de trabalho moderno
Essa resposta geralmente ocorre quando um switch Android é bem-sucedido:
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID (must match "pre"-SWITCH_USER request ) [1] = 5 // SwitchUserMessageType::ANDROID_POST_SWITCH [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 11,0 // current user id (11) and flags (none in this case) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
Resposta pós-switch de fluxo de trabalho moderno
Essa resposta geralmente ocorre quando um switch Android falha:
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID (must match "pre"-SWITCH_USER request ) [1] = 5 // SwitchUserMessageType::ANDROID_POST_SWITCH [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 10,8 // current user id (10) and flags (ADMIN) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
Exemplo de solicitação de fluxo de trabalho legado
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 2 // Request ID [1] = 1 // SwitchUserMessageType::LEGACY_ANDROID_SWITCH [2,3] = 10,8 // target user id (10) and flags (ADMIN) [4,5] = 0,1 // current user id (0) and flags (SYSTEM) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
Exemplo de solicitação de fluxo de trabalho do veículo
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = -108 // Request ID (must be negative) [1] = 4 // SwitchUserMessageType::VEHICLE_REQUEST [2] = 11 // target user id }
Resposta pós-switch do fluxo de trabalho legado
Essa resposta geralmente ocorre quando um switch Android é bem-sucedido:
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = -108 // Request ID (must match from vehicle request ) [1] = 5 // SwitchUserMessageType::ANDROID_POST_SWITCH [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 11,0 // current user id (11) and flags (none in this case) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
CREATE_USER
Exemplo de solicitação
VehiclePropValue { // flattened from CreateUserRequest prop: 299896585 // CREATE_USER prop.values.int32Values: [0] = 42 // Request ID [1,2] = 11,6 // Android id of the created user and flags (id=11, flags=GUEST, EPHEMERAL) [3,4] = 10,0 // current user id (10) and flags (none in this case) [5] = 3 // number of existing users (0, 10, 11) [6,7] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [8,9] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [10,11] = 11,6 // newUser[2] (id=11, flags=GUEST,EPHEMERAL) }
Exemplo de resposta
VehiclePropValue { // flattened from CreateUserResponse prop: 299896585 // CREATE_USER prop.values.int32Values: [0] = 42 // Request ID (must match request) [1] = 3 // CreateUserStatus::SUCCESS }
REMOVE_USER
Exemplo de solicitação
VehiclePropValue { // flattened from RemoveUserRequest prop: 299896586 // REMOVE_USER prop.values.int32Values: [0] = 42 // Request ID [1,2] = 11,0 // Android id of the removed user and flags (none in this case) [3,4] = 10,0 // current user id (10) and flags (none in this case) [5] = 2 // number of existing users (0, 10) [6,7] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [8,9] = 10,8 // existingUser[1] (id=10, flags=ADMIN) }
USER_IDENTIFICATION_ASSOCIATION
Definir exemplo (chaveiro associado ao usuário 10)
VehiclePropValue { // flattened from UserIdentificationSetRequest prop: 299896587 // USER_IDENTIFICATION_ASSOCIATION prop.values.int32Values: [0] = 43 // Request ID [1,2] = 10,0 // Android id (10) and flags (none in this case) [3] = 1 // number of associations being set [4] = 1 // 1st type: UserIdentificationAssociationType::KEY_FOB [5] = 1 // 1st value: UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER }