Bluetooth

O Android fornece uma implementação completa de Bluetooth com suporte para muitos perfis comuns de Bluetooth no carro. Há também muitos aprimoramentos que melhoram o desempenho e a experiência com outros dispositivos e serviços.

Gerenciamento de conexão Bluetooth

No Android, o CarBluetoothService mantém os dispositivos Bluetooth do usuário atual e as listas de prioridades para cada conexão de perfil com o IVI. Os dispositivos são conectados aos perfis em uma ordem de prioridade definida. Quando habilitar, desabilitar e conectar dispositivos a um perfil é determinado por uma política de conexão padrão que pode ser substituída pelo uso de uma sobreposição de recursos , se desejado.

Configurando o gerenciamento de conexão automotiva

Desative a política de telefone padrão

A pilha Bluetooth do Android mantém uma política de conexão para telefones ativada por padrão. Esta política deve ser desativada em seu dispositivo para que não entre em conflito com a política automotiva pretendida no CarBluetoothService . Embora a sobreposição do produto Carro deva cuidar disso para você, você pode desabilitar a política de telefone em uma sobreposição de recursos definindo enable_phone_policy como false em /packages/apps/Bluetooth/res/values/config.xml .

Use a política automotiva padrão

CarBluetoothService mantém as permissões de perfil padrão. A lista de dispositivos conhecidos e suas prioridades de reconexão de perfil estão em service/src/com/android/car/BluetoothProfileDeviceManager.java .

Além disso, a política de gerenciamento de conexão Bluetooth pode ser encontrada em service/src/com/android/car/BluetoothDeviceConnectionPolicy.java . Por padrão, esta política define as instâncias em que o Bluetooth deve se conectar e desconectar de dispositivos vinculados. Ele também gerencia casos específicos de carros para quando o adaptador deve ser ligado e desligado.

Criando sua própria política de gerenciamento de conexão automotiva personalizada

Se a política automotiva padrão não for suficiente para suas necessidades, ela também pode ser desabilitada em favor de sua própria política personalizada. Sua política personalizada será, no mínimo, responsável por determinar quando habilitar e desabilitar o adaptador Bluetooth, bem como quando conectar dispositivos. É possível usar uma variedade de eventos para ativar/desativar o adaptador Bluetooth e iniciar conexões de dispositivos, incluindo eventos devido a alterações nas propriedades específicas do carro.

Desative a política automotiva padrão

Primeiro, para usar uma política personalizada, a política automotiva padrão deve ser desabilitada definindo useDefaultBluetoothConnectionPolicy como false em uma sobreposição de recurso . Este recurso é originalmente definido como parte de packages/services/Car/service/res/values/config.xml .

Ativar e desativar o adaptador Bluetooth

Uma das principais funções de sua política é ligar e desligar o adaptador Bluetooth nos momentos apropriados. Você pode usar as APIs de estrutura BluetoothAdapter.enable() e BluetoothAdapter.disable() para habilitar e desabilitar o adaptador. Essas chamadas devem respeitar o estado persistente que o usuário selecionou por meio de Configurações ou qualquer outro meio. Uma maneira de fazer isso é a seguinte:

/**
 * Turn on the Bluetooth Adapter.
 */
private void enableBluetooth() {
    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (bluetoothAdapter == null) {
        return;
    }
    bluetoothAdapter.enable();
}

/**
 * Turn off the Bluetooth Adapter
 */
private void disableBluetooth() {
    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (bluetoothAdapter == null) {
        return;
    }
    // Will shut down _without_ persisting the off state as the desired state
    // of the Bluetooth adapter for next start up. This will do nothing if the adapter
    // is already off, keeping the existing saved desired state for next reboot.
    bluetoothAdapter.disable(false);
}

Determinar quando ligar e desligar o adaptador Bluetooth

Com sua política customizada, você pode determinar quais eventos indicam os melhores momentos para ativar e desativar o adaptador. Uma maneira de fazer isso é usando os estados de energia mantidos pelo CarPowerManager :

private final CarPowerStateListenerWithCompletion mCarPowerStateListener =
        new CarPowerStateListenerWithCompletion() {
    @Override
    public void onStateChanged(int state, CompletableFuture<Void> future) {
        if (state == CarPowerManager.CarPowerStateListener.ON) {
            if (isBluetoothPersistedOn()) {
                enableBluetooth();
            }
            return;
        }

        // "Shutdown Prepare" is when the user will perceive the car as off
        // This is a good time to turn off Bluetooth
        if (state == CarPowerManager.CarPowerStateListener.SHUTDOWN_PREPARE) {
            disableBluetooth();

            // Let CarPowerManagerService know we're ready to shut down
            if (future != null) {
                future.complete(null);
            }
            return;
        }
    }
};

Determinar quando conectar dispositivos

Da mesma forma, depois de determinar os eventos que devem acionar as conexões do dispositivo, CarBluetoothManager fornece a chamada da API connectDevices() que prosseguirá para conectar os dispositivos com base nas listas de prioridade definidas para cada perfil Bluetooth.

Um exemplo de quando você pode querer fazer isso é sempre que o adaptador Bluetooth é ligado:

private class BluetoothBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
        if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
            int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
            if (state == BluetoothAdapter.STATE_ON) {
                // mContext should be your application’s context
                Car car = Car.createCar(mContext);
                CarBluetoothManager carBluetoothManager =
                        (CarBluetoothManager) car.getCarManager(Car.BLUETOOTH_SERVICE);
                carBluetoothManager.connectDevices();
            }
        }
    }
}

Verificando o gerenciamento de conexão automotiva

A maneira mais fácil de verificar o comportamento de sua política de conexão é habilitar o Bluetooth em seu IVI e validar se ele se conecta automaticamente aos dispositivos corretos na ordem apropriada. Você pode alternar o adaptador Bluetooth por meio da interface do usuário de configurações ou com os seguintes comandos adb:

adb shell su u$(adb shell am get-current-user)_system svc bluetooth disable
adb shell su u$(adb shell am get-current-user)_system svc bluetooth enable

Além disso, a saída do comando a seguir pode ser usada para ver informações de depuração relacionadas a conexões Bluetooth:

adb shell dumpsys car_service

Por fim, se você criou sua própria política automotiva, verificar qualquer comportamento de conexão personalizado exigirá o controle dos eventos que você escolheu para acionar as conexões do dispositivo.

Perfis Bluetooth automotivos

No Android, o IVI pode suportar vários dispositivos conectados simultaneamente por Bluetooth. Os serviços de telefone Bluetooth para vários dispositivos permitem que os usuários conectem dispositivos separados simultaneamente, como um telefone pessoal e um telefone comercial, e façam chamadas com viva-voz de qualquer dispositivo.

Os limites de conexão são impostos por cada perfil Bluetooth individual, geralmente dentro da implementação do próprio serviço de perfil. Por padrão, o CarBluetoothService não faz mais julgamentos sobre o número máximo de dispositivos conectados permitidos.

Perfil mãos-livres

O Bluetooth Hands-Free Profile (HFP) permite que o veículo faça e receba chamadas telefônicas por meio de um dispositivo remoto conectado. Cada conexão de dispositivo registra uma conta de telefone separada no TelecomManager , que anuncia quaisquer contas de telefone disponíveis para os aplicativos IVI.

O IVI pode se conectar a vários dispositivos via HFP. MAX_STATE_MACHINES_POSSIBLE no HeadsetClientService define o número máximo de conexões HFP simultâneas.

Quando um usuário faz ou recebe uma chamada telefônica de um dispositivo, a conta de telefone correspondente cria um objeto HfpClientConnection . O aplicativo Dialer interage com o objeto HfpClientConnection para gerenciar recursos de chamada, como aceitar uma chamada ou desligar.

Deve-se notar que o aplicativo Dialer padrão não suporta vários dispositivos HFP conectados simultaneamente. Para implementar o HFP de vários dispositivos, a personalização é necessária para permitir que os usuários selecionem qual conta de dispositivo usar ao fazer uma chamada. O aplicativo chamará telecomManager.placeCall com a conta correta. Você precisará verificar se outras funcionalidades de vários dispositivos também funcionam conforme o esperado.

Verifique o HFP de vários dispositivos

Para verificar se a conectividade de vários dispositivos funciona corretamente por Bluetooth:

  1. Usando Bluetooth, conecte um dispositivo ao IVI e transmita áudio do dispositivo.
  2. Conecte dois telefones ao IVI por Bluetooth.
  3. Escolha um telefone. Faça uma chamada de saída diretamente do telefone e faça uma chamada de saída usando o IVI.
    1. Nas duas vezes, verifique se o áudio transmitido é pausado e se o áudio do telefone é reproduzido nos alto-falantes conectados ao IVI.
  4. Usando o mesmo telefone, receba uma chamada diretamente no telefone e receba uma chamada usando o IVI.
    1. Ambas as vezes, verifique se o áudio do streaming é pausado e o áudio do telefone é reproduzido nos alto-falantes conectados ao IVI.
  5. Repita as etapas 3 e 4 com o outro telefone conectado.

Chamada de Emergência

A capacidade de fazer chamadas de emergência é um aspecto importante das funções de telefonia e Bluetooth no carro. Há várias maneiras pelas quais uma chamada de emergência pode ser iniciada a partir do IVI, incluindo:

  • Solução autônoma de eCall
  • Solução eCall integrada no IVI
  • Confiar em um telefone Bluetooth conectado quando nenhum sistema integrado está disponível

Conectando uma chamada de emergência

Embora o equipamento eCall seja essencial para a segurança, atualmente ele não está integrado ao Android. É possível usar ConnectionService para expor recursos de chamadas de emergência por meio do Android, que também tem o benefício de introduzir opções de acessibilidade para chamadas de emergência. Para saber mais, consulte Criando um aplicativo de chamada .

Aqui está um exemplo de como estabelecer um ConnectionService de emergência:

public class YourEmergencyConnectionService extends ConnectionService {

    @Override
    public Connection onCreateOutgoingConnection(
            PhoneAccountHandle connectionManagerAccount,
            ConnectionRequest request) {
        // Your equipment specific procedure to make ecall
        // ...
    }

    private void onYourEcallEquipmentReady() {

        PhoneAccountHandle handle =
            new PhoneAccountHandle(new ComponentName(context, YourEmergencyConnectionService),
                    YourEmergencyConnectionId);
        PhoneAccount account =
            new PhoneAccount.Builder(handle, eCallOnlyAccount)
            .setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_TEL))
            .setCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS
                    | PhoneAccount.CAPABILITY_MULTI_USER)
            .build():
        mTelecomManager.registerPhoneAcccount(account);
        mTelecomManager.enablePhoneAccount(account.getAccountHandle(), true);
    }
}

Ativando o Bluetooth para chamadas de emergência

A chamada de emergência antes do Android 10 envolvia discagem direta de um telefone e a chamada de equipamento especial, se disponível (por exemplo, acionamento automático ao detectar um perigo ou uma ação do usuário). Desde o Android 10, o Discador no carro pode ligar diretamente para um número de emergência, desde que este código esteja contido em apps/Bluetooth/res/values/config.xml :

<!-- For supporting emergency call through the hfp client connection service --> <bool name=”hfp_client_connection_service_support_emergency_call”>true</bool>

Ao implementar chamadas de emergência dessa maneira, outros aplicativos, como reconhecimento de voz, também podem ligar para um número de emergência.

Perfil de acesso à lista telefônica

O perfil de acesso à lista telefônica Bluetooth (PBAP) baixa contatos e históricos de chamadas de um dispositivo remoto conectado. O PBAP mantém uma lista agregada e pesquisável de contatos que é atualizada pela máquina de estado do cliente PBAP. Cada dispositivo conectado interage com uma máquina de estado do cliente PBAP separada, resultando em contatos sendo associados ao dispositivo adequado ao fazer uma chamada.

O PBAP é unidirecional e, portanto, requer que o IVI instancia conexões com qualquer dispositivo móvel desejado. MAXIMUM_DEVICES em PbapClientService define o número máximo de conexões de dispositivos PBAP simultâneas permitidas com o IVI. O cliente PBAP armazena os contatos de cada dispositivo conectado no Provedor de Contatos , que podem ser acessados ​​por um aplicativo para derivar a lista telefônica de cada dispositivo.

Além disso, a conexão do perfil deve ser autorizada tanto pelo IVI quanto pelo dispositivo móvel para que uma conexão seja feita. Quando um cliente PBAP se desconecta, o banco de dados interno remove todos os contatos e o histórico de chamadas associado ao dispositivo conectado anteriormente.

Perfil de acesso a mensagens

O Bluetooth Message Access Profile (MAP) permite que o veículo envie e receba mensagens SMS por meio de um dispositivo remoto conectado. Atualmente, as mensagens não são armazenadas localmente no IVI. Em vez disso, sempre que o dispositivo remoto conectado recebe uma mensagem, o IVI recebe e analisa a mensagem e transmite seu conteúdo em um Intent , que pode ser recebido por um aplicativo.

Para se conectar a um dispositivo móvel com a finalidade de enviar e receber mensagens, o IVI deve iniciar a conexão MAP. MAXIMUM_CONNECTED_DEVICES em MapClientService define o número máximo de conexões simultâneas de dispositivos MAP permitidas com o IVI. Cada conexão deve ser autorizada pelo IVI e pelo dispositivo móvel antes que as mensagens possam ser transferidas.

Perfil de distribuição de áudio avançado

O Bluetooth Advanced Audio Distribution Profile (A2DP) permite que o veículo receba fluxos de áudio de um dispositivo remoto conectado.

Ao contrário de outros perfis, o número máximo de dispositivos A2DP conectados é aplicado na pilha nativa e não em Java. O valor está atualmente codificado para 1 usando a variável kDefaultMaxConnectedAudioDevices em packages/modules/Bluetooth/system/vtif/src/btif_av.cc .

Perfil de controle remoto de áudio/vídeo

O perfil de controle remoto de áudio/vídeo Bluetooth (AVRCP) permite que o veículo controle e navegue em players de mídia em um dispositivo remoto conectado. Como o IVI desempenha o papel de um controlador AVRCP, qualquer controle acionado que afete a reprodução de áudio depende de uma conexão A2DP com o dispositivo de destino.

Para que um player de mídia específico em um telefone Android seja navegável pelo IVI via AVRCP, o aplicativo de mídia no telefone deve fornecer um MediaBrowserService e permitir o acesso com.android.bluetooth a esse serviço. A criação de um serviço de navegador de mídia explica como fazer isso em detalhes.