Propriedades do usuário HAL

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 assento e ajustes de espelho. Com base nas arquiteturas atuais de hardware e 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 conecte um acessório externo, como um chaveiro, ao seu usuário do Android. Então, quando o motorista se aproxima do veículo, uma ECU é ativada e detecta o chaveiro. Esta ECU indica ao HAL qual usuário Android o infoentretenimento deve iniciar uma inicialização, o que reduz o tempo que um motorista espera pelo carregamento de seu usuário Android.

Habilite o usuário HAL

As propriedades do 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 não precise ser configurado manualmente.) Verifique se user_hal_enabled=true está ativado 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 shell getprop android.car.user_hal_enabled ou adb logcat CarServiceHelper *:s . Se a propriedade estiver desativada, uma mensagem como a seguinte será exibida quando system_server for iniciado:

I CarServiceHelper: Not using User HAL

Para ativar 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 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 HAL do usuário

Propriedades do ciclo de vida do usuário

As propriedades a seguir fornecem as informações 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.

Observação: quando o usuário HAL é compatível, 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:
  • O comportamento padrão definido pelo Android (mudar para o último usuário usado ou criar um novo usuário se esta for a primeira inicialização).
  • Mude para um usuário existente.
  • Crie um novo usuário (com as propriedades opcionais de nome, sinalizadores, localidade do sistema e assim por diante) e alterne para esse novo usuário.

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 conseguir 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 for detectado um chaveiro para um usuário diferente, a ECU substitui a propriedade HAL e, durante a inicialização, o sistema Android muda para iniciar naquele usuário especificado.

SWITCH_USER
(LER ESCREVER)
Essa propriedade é chamada ao alternar o usuário do Android em primeiro plano ativo. 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:
  • Moderno. Interruptor iniciado a partir de CarUserManager .
  • Legado. Alternar iniciado a partir do ActivityManager .
  • Veículo. Chamado pelo HAL para solicitar uma troca de usuário.

O fluxo de trabalho moderno usa uma abordagem de confirmação de duas fases para garantir que o sistema Android e a ECU externa estejam sincronizados. Quando o Android inicia a troca:

  1. Verifique o HAL para determinar se o usuário pode ser trocado.

    O HAL responde com SUCCESS ou FAILURE , para que o Android saiba se deve prosseguir ou não.

  2. Conclua a troca de usuário do Android.

    O Android envia uma resposta ANDROID_POST_SWITCH ao HAL para indicar o sucesso ou a falha da troca.

O HAL deve esperar até que a resposta ANDROID_POST_SWITCH atualize seu estado para sincronizar as ECUs ou atualizar outras propriedades do HAL.

Por exemplo, enquanto está em movimento, um motorista tenta trocar de usuário do Android na IU do 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 de usuário. Assim, a ECU que controla os assentos não confirma a troca, o HAL responde com uma falha e o usuário do 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 só é chamado na inicialização (após a troca inicial de usuário) ou para aplicativos que chamam ActivityManager.switchUser() em vez de CarUserManager.switchUser() . As Settings de referência e os aplicativos SystemUI já usam o último, mas se um OEM fornecer seus próprios aplicativos de configurações para alternar usuários, os OEMs devem alterar o uso.

Por exemplo, se um aplicativo usar ActivityManager.switchUser() para alternar usuários, uma chamada unidirecional será enviada ao HAL para informar que ocorreu uma troca de usuário.

O fluxo de trabalho do veículo se origina do HAL, não do sistema Android:

  1. O HAL solicita uma troca de usuário.
  2. O sistema conclui a troca de usuário do Android.
  3. O Android envia uma resposta ANDROID_POST_SWITCH ao HAL para indicar o sucesso ou a falha da troca.

Por exemplo , Bob usou o chaveiro de Alice para abrir o carro e o HAL respondeu à solicitação INITIAL_USER_INFO com o ID de usuário de Alice. Em seguida, um sensor biométrico ECU identificou o motorista como Bob, então o usuário HAL enviou uma solicitação SWITCH_USER para trocar de usuário.

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 SUCCESS ou FAILURE . Se o HAL responder com uma falha, o sistema Android remove o usuário.

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 sobre o usuário recém-criado. Outros subsistemas e ECUs então associam seu ID de usuário interno ao ID de usuário do Android.

REMOVE_USER
(somente ESCRITA)
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 IU do infoentretenimento. O HAL é informado e os demais subsistemas e ECUs do veículo são informados sobre a 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 oferecer suporte ao User HAL.

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 essa mesma propriedade para get ou set associações.

Por exemplo, um motorista toca em um ícone de IU 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 simplificada em objetos VehiclePropValue padrão (consulte os exemplos abaixo). Para facilitar o desenvolvimento, uma biblioteca auxiliar C++ é fornecida no AOSP para converter automaticamente structs User HAL em um VehiclePropValue (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:

fluxo de trabalho

Figura 1. Fluxo de trabalho de propriedades de 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-comutação de fluxo de trabalho moderno

Essa resposta geralmente ocorre quando uma troca de Android é bem-sucedida:

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-troca de fluxo de trabalho moderno

Essa resposta geralmente ocorre quando uma opção do 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-troca do fluxo de trabalho herdado

Essa resposta geralmente ocorre quando uma troca de Android é bem-sucedida:

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
}