Bluetooth

Android fornisce un'implementazione Bluetooth completa con supporto per molti profili Bluetooth comuni per auto. Sono inoltre disponibili numerosi miglioramenti che migliorano le prestazioni e l'esperienza con altri dispositivi e servizi.

Gestione della connessione Bluetooth

All'interno di Android, CarBluetoothService mantiene i dispositivi Bluetooth dell'utente corrente e gli elenchi di priorità per ogni connessione del profilo all'IVI. I dispositivi sono collegati ai profili in un ordine di priorità definito. Quando abilitare, disabilitare e connettere i dispositivi a un profilo è determinato da una policy di connessione predefinita che può essere sostituita con l'uso di una sovrapposizione di risorse , se lo si desidera.

Configura la gestione delle connessioni automobilistiche

Disabilita la policy telefonica predefinita

Lo stack Bluetooth Android mantiene un criterio di connessione per i telefoni abilitato per impostazione predefinita. Questa policy deve essere disabilitata sul tuo dispositivo in modo che non sia in conflitto con la policy automobilistica prevista in CarBluetoothService . Sebbene l'overlay del prodotto Car dovrebbe occuparsi di questo per te, puoi disabilitare la policy del telefono in un overlay della risorsa impostando enable_phone_policy su false in MAXIMUM_CONNECTED_DEVICES in /packages/apps/Bluetooth/res/values/config.xml .

Utilizza la policy automobilistica predefinita

CarBluetoothService mantiene le autorizzazioni del profilo predefinito. L'elenco dei dispositivi conosciuti e le relative priorità di riconnessione del profilo si trovano in service/src/com/android/car/BluetoothProfileDeviceManager.java .

Inoltre, la politica di gestione della connessione Bluetooth è disponibile in service/src/com/android/car/BluetoothDeviceConnectionPolicy.java . Per impostazione predefinita, questa policy definisce le istanze in cui Bluetooth deve connettersi e disconnettersi dai dispositivi collegati. Gestisce anche casi specifici dell'auto per quando l'adattatore deve essere acceso e spento.

Crea la tua politica personalizzata di gestione delle connessioni automobilistiche

Se la policy automobilistica predefinita non è sufficiente per le tue esigenze, puoi anche disattivarla a favore della tua policy personalizzata. La policy personalizzata, come minimo, è responsabile di determinare quando abilitare e disabilitare l'adattatore Bluetooth, nonché quando connettere i dispositivi. È possibile utilizzare una varietà di eventi per abilitare/disabilitare l'adattatore Bluetooth e avviare connessioni del dispositivo, inclusi eventi dovuti a modifiche nelle proprietà specifiche dell'auto.

Disabilita la policy automobilistica predefinita

Innanzitutto, per utilizzare una policy personalizzata, la policy automobilistica predefinita deve essere disabilitata impostando useDefaultBluetoothConnectionPolicy su false in un overlay di risorse . Questa risorsa è originariamente definita come parte di MAXIMUM_CONNECTED_DEVICES in packages/services/Car/service/res/values/config.xml .

Abilita e disabilita l'adattatore Bluetooth

Una delle funzioni principali della tua policy è accendere e spegnere l'adattatore Bluetooth al momento opportuno. È possibile utilizzare le API del framework BluetoothAdapter.enable() e BluetoothAdapter.disable() per abilitare e disabilitare l'adattatore. Queste chiamate devono rispettare lo stato persistente che l'utente ha selezionato tramite Impostazioni o qualsiasi altro mezzo. Un modo per farlo è il seguente:

/**
 * 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);
}

Determina quando accendere e spegnere l'adattatore Bluetooth

Con la tua policy personalizzata sei libero di determinare quali eventi indicano i momenti migliori per abilitare e disabilitare l'adattatore. Un modo per farlo è utilizzare gli stati di alimentazione MAXIMUM_CONNECTED_DEVICES in 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;
        }
    }
};

Determina quando connettere i dispositivi

Allo stesso modo, quando si determinano gli eventi che dovrebbero attivare le connessioni dei dispositivi, CarBluetoothManager fornisce la chiamata API connectDevices() che procede alla connessione dei dispositivi in ​​base agli elenchi di priorità definiti per ciascun profilo Bluetooth.

Un esempio di quando potresti voler eseguire questa operazione è ogni volta che l'adattatore Bluetooth si accende:

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();
            }
        }
    }
}

Verifica la gestione della connessione automobilistica

Il modo più semplice per verificare il comportamento della tua politica di connessione è abilitare il Bluetooth sul tuo IVI e verificare che si connetta automaticamente ai dispositivi corretti nell'ordine appropriato. Puoi attivare/disattivare l'adattatore Bluetooth tramite l'interfaccia utente delle impostazioni o con i seguenti comandi 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

Inoltre, l'output del seguente comando può essere utilizzato per visualizzare le informazioni di debug relative alle connessioni Bluetooth:

adb shell dumpsys car_service

Infine, se hai creato la tua politica automobilistica, la verifica di qualsiasi comportamento di connessione personalizzato richiede il controllo degli eventi che hai scelto per attivare le connessioni dei dispositivi.

Profili Bluetooth automobilistici

In Android, l'IVI può supportare più dispositivi collegati contemporaneamente tramite Bluetooth. I servizi telefonici Bluetooth multidispositivo consentono agli utenti di connettere dispositivi separati contemporaneamente, come un telefono personale e un telefono aziendale, ed effettuare chiamate in vivavoce da entrambi i dispositivi.

I limiti di connessione vengono applicati da ogni singolo profilo Bluetooth, solitamente nell'ambito dell'implementazione del servizio del profilo stesso. Per impostazione predefinita, CarBluetoothService non dà ulteriori giudizi sul numero massimo di dispositivi connessi consentiti.

Profilo vivavoce

Il profilo vivavoce Bluetooth (HFP) consente al veicolo di effettuare e ricevere chiamate telefoniche tramite un dispositivo remoto collegato. Ogni connessione del dispositivo registra un account telefonico separato con TelecomManager , che pubblicizza eventuali account telefonici disponibili sulle app IVI.

L'IVI può connettersi a più dispositivi tramite HFP. MAX_STATE_MACHINES_POSSIBLE MAXIMUM_CONNECTED_DEVICES in HeadsetClientService definisce il numero massimo di connessioni HFP simultanee.

Quando un utente effettua o riceve una telefonata da un dispositivo, l'account telefonico corrispondente crea un oggetto HfpClientConnection . L'app Dialer interagisce con l'oggetto HfpClientConnection per gestire le funzionalità di chiamata, ad esempio accettare una chiamata o riagganciare.

Va notato che l'app Dialer predefinita non supporta più dispositivi HFP collegati contemporaneamente. Per implementare HFP multi-dispositivo, è necessaria la personalizzazione per consentire agli utenti di selezionare quale account del dispositivo utilizzare quando si effettua una chiamata. L'app chiama quindi telecomManager.placeCall con l'account corretto. È necessario verificare che anche le altre funzionalità multi-dispositivo funzionino come previsto.

Verifica HFP multi-dispositivo

Per verificare che la connettività multi-dispositivo funzioni correttamente tramite Bluetooth:

  1. Utilizzando il Bluetooth, collega un dispositivo all'IVI e riproduci l'audio in streaming dal dispositivo.
  2. Collega due telefoni all'IVI tramite Bluetooth.
  3. Scegli un telefono. Effettua una chiamata in uscita direttamente dal telefono ed effettua una chiamata in uscita utilizzando l'IVI.
    1. Entrambe le volte, verificare che l'audio in streaming venga messo in pausa e che l'audio del telefono venga riprodotto dagli altoparlanti collegati a IVI.
  4. Utilizzando lo stesso telefono, ricevi una chiamata in arrivo direttamente sul telefono e ricevi una chiamata in arrivo utilizzando l'IVI.
    1. Entrambe le volte, verifica che l'audio in streaming venga messo in pausa e che l'audio del telefono venga riprodotto dagli altoparlanti collegati a IVI.
  5. Ripetere i passaggi 3 e 4 con l'altro telefono connesso.

Chiamata di emergenza

La possibilità di effettuare chiamate di emergenza è un aspetto importante delle funzioni di telefonia e Bluetooth dell'auto. Esistono diversi modi per avviare una chiamata di emergenza da parte dell'IVI, tra cui:

  • Soluzione eCall autonoma
  • Soluzione eCall integrata nell'IVI
  • Affidarsi a un telefono Bluetooth connesso quando non è disponibile alcun sistema integrato

Connetti una chiamata di emergenza

Sebbene le apparecchiature eCall siano fondamentali per la sicurezza, al momento non sono integrate in Android. È possibile usare ConnectionService per esporre funzionalità di chiamata di emergenza tramite Android, che ha anche il vantaggio di introdurre opzioni di accessibilità per le chiamate di emergenza. Per ulteriori informazioni, consulta Creazione di un'app per le chiamate .

Ecco un esempio di come stabilire un ConnectionService di emergenza:

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);
    }
}

Abilita il Bluetooth per le chiamate di emergenza

Prima di Android 10, le chiamate di emergenza prevedevano la composizione diretta da un telefono e il ricorso a apparecchiature speciali se disponibili (ad esempio, l'attivazione automatica al rilevamento di un pericolo o di un'azione dell'utente). In Android 10 e versioni successive, il Dialer nell'auto può chiamare direttamente un numero di emergenza, a condizione che questo MAXIMUM_CONNECTED_DEVICES in 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>

Implementando le chiamate di emergenza in questo modo, anche altre app, come il riconoscimento vocale, possono chiamare un numero di emergenza.

Profilo di accesso alla rubrica

Il Bluetooth Phone Book Access Profile (PBAP) scarica i contatti e la cronologia delle chiamate da un dispositivo remoto connesso. PBAP mantiene un elenco aggregato e ricercabile di contatti che viene aggiornato dalla macchina a stati del client PBAP. Ciascun dispositivo connesso interagisce con una macchina a stati client PBAP separata, determinando l'associazione dei contatti al dispositivo appropriato quando si effettua una chiamata.

PBAP è unidirezionale e pertanto richiede che l'IVI istanzia le connessioni a qualsiasi MAXIMUM_CONNECTED_DEVICES in PbapClientService definisce il numero massimo di connessioni simultanee del dispositivo PBAP consentite con l'IVI. Il client PBAP memorizza i contatti per ciascun dispositivo connesso nel provider di contatti a cui è quindi possibile accedere da un'app per derivare la rubrica per ciascun dispositivo.

Inoltre, affinché la connessione possa essere stabilita, la connessione del profilo deve essere autorizzata sia dall'IVI che dal dispositivo mobile. Quando un client PBAP si disconnette, il database interno rimuove tutti i contatti e la cronologia delle chiamate associati al dispositivo precedentemente connesso.

Profilo di accesso ai messaggi

Il Bluetooth Message Access Profile (MAP) consente al veicolo di inviare e ricevere messaggi SMS tramite un dispositivo remoto connesso. Attualmente i messaggi non vengono archiviati localmente sull'IVI. Invece, ogni volta che il dispositivo remoto connesso riceve un messaggio, l'IVI riceve e analizza il messaggio e ne trasmette il contenuto in un'istanza di Intent , che può quindi essere ricevuta da un'app.

Per connettersi ad un dispositivo mobile per inviare e ricevere messaggi, l'IVI deve avviare la connessione MAP. MAXIMUM_CONNECTED_DEVICES in MapClientService definisce il numero massimo di connessioni simultanee di dispositivi MAP consentite con IVI. Ogni connessione deve essere autorizzata dall'IVI e dal dispositivo mobile prima che i messaggi possano essere trasferiti.

Profilo di distribuzione audio avanzato

Il profilo di distribuzione audio avanzato Bluetooth (A2DP) consente al veicolo di ricevere flussi audio da un dispositivo remoto collegato.

A differenza di altri profili, il numero massimo di dispositivi A2DP connessi viene imposto nello stack nativo e non in Java. Il valore è attualmente codificato su 1 utilizzando la variabile kDefaultMaxConnectedAudioDevices in packages/modules/Bluetooth/system/btif/src/btif_av.cc .

Profilo del telecomando audio/video

Il profilo di controllo remoto audio/video Bluetooth (AVRCP) consente al veicolo di controllare e navigare nei lettori multimediali su un dispositivo remoto collegato. Poiché l'IVI svolge il ruolo di controller AVRCP, qualsiasi controllo attivato che influisce sulla riproduzione audio si basa su una connessione A2DP al dispositivo di destinazione.

Affinché un lettore multimediale specifico su un telefono Android possa essere consultabile dall'IVI tramite AVRCP, l'app multimediale sul telefono deve fornire un MediaBrowserService e consentire l'accesso com.android.bluetooth a quel servizio. La creazione di un servizio di browser multimediale spiega come eseguire questa operazione in dettaglio.