Bluetooth

O Android fornece uma implementação completa do 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 ao 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 com o uso de uma sobreposição de recursos , se desejado.

Configurando o gerenciamento de conexão automotiva

Desativar a política de telefone padrão

A pilha Android Bluetooth mantém uma política de conexão para telefones que é habilitada 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 em CarBluetoothService . Embora a sobreposição do produto Carro deva cuidar disso para você, você pode desativar a política de telefone em uma sobreposição de recurso definindo enable_phone_policy como false em MAXIMUM_CONNECTED_DEVICES 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á 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 do carro para quando o adaptador deve ser ligado e desligado.

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

Se a política automotiva padrão não for suficiente para suas necessidades, ela também pode ser desativada em favor de sua própria política personalizada. Sua política personalizada será, no mínimo, responsável por determinar quando ativar e desativar 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 em 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 desativada definindo useDefaultBluetoothConnectionPolicy como false em uma sobreposição de recurso . Este recurso é originalmente definido como parte de MAXIMUM_CONNECTED_DEVICES in 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 ativar e desativar 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);
}

Determine quando ligar e desligar o adaptador Bluetooth

Com sua política personalizada, você pode determinar quais eventos indicam os melhores horários para ativar e desativar o adaptador. Uma maneira de fazer isso é usando os estados de energia MAXIMUM_CONNECTED_DEVICES em 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, o CarBluetoothManager fornece a chamada de 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 seguinte comando 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, a verificação de qualquer comportamento de conexão personalizada 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 viva-voz de qualquer um dos dispositivos.

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 com o TelecomManager , que anuncia todas as contas de telefone disponíveis para os aplicativos IVI.

O IVI pode se conectar a vários dispositivos via HFP. MAX_STATE_MACHINES_POSSIBLE MAXIMUM_CONNECTED_DEVICES em 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 observar que o aplicativo Discador padrão não oferece suporte a 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 o Bluetooth, conecte um dispositivo ao IVI e transmita o áudio do dispositivo.
  2. Conecte dois telefones ao IVI via 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. Nas duas vezes, verifique se o streaming de áudio é interrompido e se 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 de iniciar uma chamada de emergência 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 crítico para a segurança, atualmente não está integrado ao Android. É possível usar ConnectionService para expor recursos de chamada de emergência por meio do Android, que também tem a vantagem de introduzir opções de acessibilidade para chamadas de emergência. Para saber mais, consulte Construindo 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.registerPhoneAccount(account);
        mTelecomManager.enablePhoneAccount(account.getAccountHandle(), true);
    }
}

Ativando o Bluetooth para chamadas de emergência

Ligar para emergência antes do Android 10 envolvia discagem direta de um telefone e chamada de equipamento especial, se disponível (por exemplo, acionamento automático após a detecção de 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 seja MAXIMUM_CONNECTED_DEVICES 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 a chamada 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 Bluetooth Phone Book Access Profile (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 cliente PBAP separada, resultando em contatos sendo associados ao dispositivo adequado ao fazer uma chamada.

O PBAP é unidirecional e, portanto, requer que o IVI crie conexões para qualquer MAXIMUM_CONNECTED_DEVICES em PbapClientService define o número máximo de conexões de dispositivo PBAP simultâneas permitidas com o IVI. O cliente PBAP armazena os contatos de cada dispositivo conectado no Provedor de contatos , que pode ser acessado por um aplicativo para obter 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 de dispositivo MAP simultâneas 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 Avançado de Distribuição de Áudio

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/btif/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 por reprodutores de mídia em um dispositivo remoto conectado. Como o IVI desempenha o papel de um controlador AVRCP, todos os controles acionados que afetam a reprodução de áudio dependem de uma conexão A2DP com o dispositivo de destino.

Para que um reprodutor de mídia específico em um telefone Android possa ser pesquisado 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.