Bluetooth

O Android fornece uma implementação completa de Bluetooth com suporte para muitos perfis Bluetooth comuns em automóveis. Existem também muitas melhorias que melhoram o desempenho e a experiência com outros dispositivos e serviços.

Gerenciamento de conexão Bluetooth

No Android, CarBluetoothService mantém os dispositivos Bluetooth do usuário atual e listas de prioridades para cada conexão de perfil ao IVI. Os dispositivos são conectados aos perfis em uma ordem de prioridade definida. O momento de ativar, desativar 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.

Configurar o gerenciamento de conexões automotivas

Desative a política telefônica padrão

A pilha Bluetooth do Android mantém uma política de conexão para telefones habilitada por padrão. Esta política deve ser desativada no seu dispositivo para que não entre em conflito com a política automotiva pretendida em CarBluetoothService . Embora a sobreposição do produto Car deva cuidar disso para você, você pode desabilitar a política telefônica em uma sobreposição de recursos 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 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.

Crie sua própria política personalizada de gerenciamento de conexões automotivas

Se a política automotiva padrão não for suficiente para suas necessidades, ela também poderá ser desativada em favor de sua própria política personalizada. Sua política personalizada, 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 desabilitada definindo useDefaultBluetoothConnectionPolicy como false em um recurso overlay . Este recurso é originalmente definido como parte de MAXIMUM_CONNECTED_DEVICES em packages/services/Car/service/res/values/config.xml .

Habilite e desabilite o adaptador Bluetooth

Uma das principais funções da 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 selecionado pelo usuário nas Configurações ou por 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 does 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 customizada, você pode determinar quais eventos indicam os melhores horários para ativar e desativar o adaptador. Uma maneira de fazer isso é usar os estados de energia MAXIMUM_CONNECTED_DEVICES no 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 perceives 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;
        }
    }
};

Determine quando conectar dispositivos

Da mesma forma, quando você determina os eventos que devem acionar o início das conexões de dispositivos, CarBluetoothManager fornece a chamada de API connectDevices() que prossegue para conectar dispositivos com base nas listas de prioridades definidas para cada perfil Bluetooth.

Um exemplo de quando você pode querer fazer isso é sempre que o adaptador Bluetooth for 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 app's context
                Car car = Car.createCar(mContext);
                CarBluetoothManager carBluetoothManager =
                        (CarBluetoothManager) car.getCarManager(Car.BLUETOOTH_SERVICE);
                carBluetoothManager.connectDevices();
            }
        }
    }
}

Verifique o gerenciamento de conexões automotivas

A maneira mais fácil de verificar o comportamento da sua política de conexão é habilitar o Bluetooth no seu IVI e validar se ele se conecta automaticamente aos dispositivos corretos na ordem apropriada. Você pode alternar o adaptador Bluetooth por meio da IU 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 às 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 personalizado requer o controle dos eventos que você escolheu para acionar conexões de dispositivos.

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 em modo viva-voz de qualquer um dos dispositivos.

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

Perfil mãos-livres

O perfil mãos-livres Bluetooth (HFP) permite que o veículo faça e receba chamadas através 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 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 Dialer padrão não oferece suporte a vários dispositivos HFP conectados simultaneamente. Para implementar o HFP para vários dispositivos, é necessária personalização para permitir que os usuários selecionem qual conta de dispositivo usar ao fazer uma chamada. O aplicativo então chama telecomManager.placeCall com a conta correta. Você precisa verificar se outras funcionalidades de vários dispositivos também funcionam conforme planejado.

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 via Bluetooth.
  3. Escolha um telefone. Faça uma chamada diretamente do telefone e faça uma chamada usando o IVI.
    1. Em ambas as 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. Em ambas as vezes, verifique se o streaming de áudio é pausado 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 do carro. Existem 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
  • Depender de um telefone Bluetooth conectado quando nenhum sistema integrado estiver disponível

Conectar uma chamada de emergência

Embora o equipamento eCall seja fundamental para a segurança, atualmente não está integrado ao Android. É possível usar o ConnectionService para expor recursos de chamadas 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);
    }
}

Ative o Bluetooth para chamadas de emergência

Chamar a emergência antes do Android 10 envolvia discagem direta de um telefone e invocar equipamento especial, se disponível (por exemplo, acionamento automático após detecção de perigo ou ação do usuário). No Android 10 e superior, o discador no carro pode ligar diretamente para um número de emergência, desde que MAXIMUM_CONNECTED_DEVICES esteja 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 desta forma, 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 de cliente PBAP separada, resultando na associação dos contatos ao dispositivo adequado ao fazer uma chamada.

O PBAP é unidirecional e, portanto, requer que o IVI instancie conexões com qualquer MAXIMUM_CONNECTED_DEVICES em PbapClientService define o número máximo de conexões simultâneas de dispositivos PBAP permitidas com o IVI. O cliente PBAP armazena os contatos de cada dispositivo conectado no Provedor de Contatos , que pode então 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 a 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 associados ao dispositivo conectado anteriormente.

Perfil de acesso a mensagens

O perfil de acesso a mensagens Bluetooth (MAP) permite que o veículo envie e receba mensagens SMS através 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 uma instância de Intent , que pode então ser recebida 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 avançado de distribuição de áudio

O perfil avançado de distribuição de áudio Bluetooth (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 é imposto na pilha nativa e não em Java. O valor está atualmente codificado como 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 em reprodutores de mídia em um dispositivo remoto conectado. Como o IVI desempenha o papel de um controlador AVRCP, quaisquer controles acionados que afetem a reprodução de áudio dependem de uma conexão A2DP com o dispositivo alvo.

Para que um reprodutor de mídia específico em um telefone Android possa ser navegado pelo IVI via AVRCP, o aplicativo de mídia no telefone deve fornecer um MediaBrowserService e permitir acesso com.android.bluetooth a esse serviço. Construir um serviço de navegador de mídia explica como fazer isso em detalhes.