Bluetooth

Android bietet eine vollständige Bluetooth-Implementierung mit Unterstützung für viele gängige Bluetooth-Profile im Auto. Darüber hinaus gibt es viele Verbesserungen, die die Leistung und das Erlebnis mit anderen Geräten und Diensten verbessern.

Bluetooth-Verbindungsverwaltung

Innerhalb von Android verwaltet CarBluetoothService die Bluetooth-Geräte und Prioritätslisten des aktuellen Benutzers für jede Profilverbindung zum IVI. Geräte werden in einer definierten Prioritätsreihenfolge mit Profilen verbunden. Wann Geräte aktiviert, deaktiviert und mit einem Profil verbunden werden sollen, wird durch eine Standardverbindungsrichtlinie gesteuert, die bei Bedarf durch die Verwendung eines Ressourcen-Overlays außer Kraft gesetzt werden kann.

Konfigurieren Sie das Automotive-Verbindungsmanagement

Deaktivieren Sie die Standard-Telefonrichtlinie

Der Android-Bluetooth-Stack verwaltet eine Verbindungsrichtlinie für Telefone, die standardmäßig aktiviert ist. Diese Richtlinie muss auf Ihrem Gerät deaktiviert werden, damit sie nicht mit der beabsichtigten Automobilrichtlinie in CarBluetoothService in Konflikt steht. Während das Car-Produkt-Overlay dies für Sie erledigen sollte, können Sie die Telefonrichtlinie in einem Ressourcen-Overlay deaktivieren, indem Sie enable_phone_policy in MAXIMUM_CONNECTED_DEVICES in /packages/apps/Bluetooth/res/values/config.xml auf false setzen.

Verwenden Sie die Standard-Automobilrichtlinie

CarBluetoothService behält die Standardprofilberechtigungen bei. Die Liste der bekannten Geräte und deren Profil-Wiederverbindungsprioritäten finden Sie in service/src/com/android/car/BluetoothProfileDeviceManager.java .

Außerdem finden Sie die Bluetooth-Verbindungsverwaltungsrichtlinie in service/src/com/android/car/BluetoothDeviceConnectionPolicy.java . Standardmäßig definiert diese Richtlinie Instanzen, in denen Bluetooth eine Verbindung zu verbundenen Geräten herstellen und diese trennen soll. Es verwaltet auch fahrzeugspezifische Fälle, wann der Adapter ein- und ausgeschaltet werden sollte.

Erstellen Sie Ihre eigene benutzerdefinierte Richtlinie für die Verbindungsverwaltung im Automobilbereich

Wenn die standardmäßige Kfz-Richtlinie Ihren Anforderungen nicht genügt, können Sie sie auch zugunsten Ihrer eigenen benutzerdefinierten Richtlinie deaktivieren. Zumindest Ihre benutzerdefinierte Richtlinie bestimmt, wann der Bluetooth-Adapter aktiviert und deaktiviert wird und wann Geräte verbunden werden. Es ist möglich, eine Vielzahl von Ereignissen zu verwenden, um den Bluetooth-Adapter zu aktivieren/deaktivieren und Geräteverbindungen zu initiieren, einschließlich Ereignissen aufgrund von Änderungen an bestimmten Fahrzeugeigenschaften.

Deaktivieren Sie die Standard-Automobilrichtlinie

Um eine benutzerdefinierte Richtlinie verwenden zu können, muss zunächst die Standard-Automobilrichtlinie deaktiviert werden, indem useDefaultBluetoothConnectionPolicy in einem Ressourcen-Overlay auf false gesetzt wird. Diese Ressource ist ursprünglich als Teil von MAXIMUM_CONNECTED_DEVICES in packages/services/Car/service/res/values/config.xml definiert.

Bluetooth-Adapter aktivieren und deaktivieren

Eine der Kernfunktionen Ihrer Richtlinie besteht darin, den Bluetooth-Adapter zu den entsprechenden Zeiten ein- und auszuschalten. Sie können die Framework-APIs BluetoothAdapter.enable() und BluetoothAdapter.disable() verwenden, um den Adapter zu aktivieren und zu deaktivieren. Diese Aufrufe sollten den dauerhaften Status berücksichtigen, den der Benutzer über die Einstellungen oder auf andere Weise ausgewählt hat. Eine Möglichkeit, dies zu tun, ist wie folgt:

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

Bestimmen Sie, wann der Bluetooth-Adapter ein- und ausgeschaltet werden soll

Mit Ihrer benutzerdefinierten Richtlinie können Sie frei bestimmen, welche Ereignisse die besten Zeiten zum Aktivieren und Deaktivieren des Adapters angeben. Eine Möglichkeit hierfür ist die Verwendung der Energiezustände 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;
        }
    }
};

Bestimmen Sie, wann Geräte angeschlossen werden sollen

Wenn Sie die Ereignisse bestimmen, die den Beginn von Geräteverbindungen auslösen sollen, stellt CarBluetoothManager in ähnlicher Weise den API-Aufruf connectDevices() bereit, der die Geräte basierend auf den für jedes Bluetooth-Profil definierten Prioritätslisten verbindet.

Ein Beispiel dafür, wann Sie dies tun möchten, ist, wann immer sich der Bluetooth-Adapter einschaltet:

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

Überprüfen Sie das Automotive-Verbindungsmanagement

Der einfachste Weg, das Verhalten Ihrer Verbindungsrichtlinie zu überprüfen, besteht darin, Bluetooth auf Ihrem IVI zu aktivieren und zu überprüfen, ob es automatisch eine Verbindung zu den richtigen Geräten in der richtigen Reihenfolge herstellt. Sie können den Bluetooth-Adapter über die Einstellungsoberfläche oder mit den folgenden ADB-Befehlen umschalten:

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

Darüber hinaus kann die Ausgabe des folgenden Befehls verwendet werden, um Debug-Informationen zu Bluetooth-Verbindungen anzuzeigen:

adb shell dumpsys car_service

Wenn Sie schließlich Ihre eigene Automotive-Richtlinie erstellt haben, erfordert die Überprüfung eines benutzerdefinierten Verbindungsverhaltens die Steuerung der Ereignisse, die Sie zum Auslösen von Geräteverbindungen ausgewählt haben.

Automotive-Bluetooth-Profile

Unter Android kann das IVI mehrere Geräte unterstützen, die gleichzeitig über Bluetooth verbunden sind. Mit Bluetooth-Telefondiensten für mehrere Geräte können Benutzer gleichzeitig separate Geräte verbinden, z. B. ein privates Telefon und ein Arbeitstelefon, und von beiden Geräten aus freihändig telefonieren.

Verbindungsbeschränkungen werden von jedem einzelnen Bluetooth-Profil erzwungen, normalerweise innerhalb der Implementierung des Profildiensts selbst. Standardmäßig nimmt CarBluetoothService keine weitere Beurteilung der maximal zulässigen Anzahl verbundener Geräte vor.

Freisprechprofil

Das Bluetooth Hands-Free Profile (HFP) ermöglicht dem Fahrzeug das Tätigen und Empfangen von Telefonanrufen über ein angeschlossenes Remote-Gerät. Jede Geräteverbindung registriert ein separates Telefonkonto bei TelecomManager , das den IVI-Apps alle verfügbaren Telefonkonten ankündigt.

Das IVI kann über HFP eine Verbindung zu mehreren Geräten herstellen. MAX_STATE_MACHINES_POSSIBLE MAXIMUM_CONNECTED_DEVICES in HeadsetClientService definiert die maximale Anzahl gleichzeitiger HFP-Verbindungen.

Wenn ein Benutzer einen Anruf von einem Gerät tätigt oder empfängt, erstellt das entsprechende Telefonkonto ein HfpClientConnection -Objekt. Die Dialer-App interagiert mit dem HfpClientConnection -Objekt, um Anruffunktionen wie das Annehmen eines Anrufs oder das Auflegen zu verwalten.

Es ist zu beachten, dass die Standard-Dialer-App nicht mehrere gleichzeitig verbundene HFP-Geräte unterstützt. Um HFP mit mehreren Geräten zu implementieren, ist eine Anpassung erforderlich, damit Benutzer auswählen können, welches Gerätekonto sie beim Tätigen eines Anrufs verwenden möchten. Die App ruft dann telecomManager.placeCall mit dem richtigen Konto auf. Sie müssen überprüfen, ob auch andere Multi-Geräte-Funktionen wie vorgesehen funktionieren.

Überprüfen Sie das HFP für mehrere Geräte

So überprüfen Sie, ob die Verbindung mehrerer Geräte über Bluetooth ordnungsgemäß funktioniert:

  1. Verbinden Sie über Bluetooth ein Gerät mit dem IVI und streamen Sie Audio vom Gerät.
  2. Verbinden Sie zwei Telefone über Bluetooth mit dem IVI.
  3. Wählen Sie ein Telefon aus. Tätigen Sie einen ausgehenden Anruf direkt vom Telefon aus und tätigen Sie einen ausgehenden Anruf über das IVI.
    1. Vergewissern Sie sich in beiden Fällen, dass das gestreamte Audio pausiert und der Telefonton über die mit IVI verbundenen Lautsprecher abgespielt wird.
  4. Nehmen Sie mit demselben Telefon einen eingehenden Anruf direkt auf dem Telefon entgegen und nehmen Sie einen eingehenden Anruf über das IVI entgegen.
    1. Überprüfen Sie in beiden Fällen, ob das Audio-Streaming pausiert und der Ton des Telefons über die mit IVI verbundenen Lautsprecher abgespielt wird.
  5. Wiederholen Sie die Schritte 3 und 4 mit dem anderen verbundenen Telefon.

Notruf

Die Möglichkeit, Notrufe zu tätigen, ist ein wichtiger Bestandteil der Telefonie- und Bluetooth-Funktionen im Auto. Es gibt verschiedene Möglichkeiten, einen Notruf vom IVI aus einzuleiten, darunter:

  • Eigenständige eCall-Lösung
  • eCall-Lösung im IVI integriert
  • Verlassen Sie sich auf ein verbundenes Bluetooth-Telefon, wenn kein integriertes System verfügbar ist

Verbinden Sie einen Notruf

Obwohl eCall-Geräte sicherheitskritisch sind, sind sie derzeit nicht in Android integriert. Es ist möglich, ConnectionService zu verwenden, um Notruffunktionen über Android verfügbar zu machen, was auch den Vorteil hat, Barrierefreiheitsoptionen für Notrufe einzuführen. Weitere Informationen finden Sie unter Erstellen einer Anruf-App .

Hier ist ein Beispiel für die Einrichtung eines Notfall- ConnectionService :

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

Aktivieren Sie Bluetooth für Notrufe

Der Notruf vor Android 10 erforderte das direkte Wählen von einem Telefon aus und das Aufrufen spezieller Geräte, sofern verfügbar (z. B. automatische Auslösung bei Erkennung einer Gefahr oder einer Benutzeraktion). In Android 10 und höher kann der Dialer im Auto direkt eine Notrufnummer anrufen, vorausgesetzt dies 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>

Durch die Implementierung des Notrufs auf diese Weise können auch andere Apps, beispielsweise die Spracherkennung, eine Notrufnummer anrufen.

Telefonbuch-Zugriffsprofil

Das Bluetooth Phone Book Access Profile (PBAP) lädt Kontakte und Anrufverläufe von einem angeschlossenen Remote-Gerät herunter. PBAP verwaltet eine aggregierte, durchsuchbare Liste von Kontakten, die von der PBAP-Client-Statusmaschine aktualisiert wird. Jedes verbundene Gerät interagiert mit einer separaten PBAP-Client-Zustandsmaschine, was dazu führt, dass Kontakte beim Tätigen eines Anrufs dem richtigen Gerät zugeordnet werden.

PBAP ist unidirektional und erfordert daher, dass das IVI Verbindungen zu allen MAXIMUM_CONNECTED_DEVICES in instanziiert. PbapClientService definiert die maximale Anzahl gleichzeitiger PBAP-Geräteverbindungen, die mit dem IVI zulässig sind. Der PBAP-Client speichert die Kontakte für jedes angeschlossene Gerät im Kontaktanbieter , auf den dann eine App zugreifen kann, um das Telefonbuch für jedes Gerät abzuleiten.

Darüber hinaus muss die Profilverbindung sowohl vom IVI als auch vom Mobilgerät autorisiert werden, damit eine Verbindung hergestellt werden kann. Wenn ein PBAP-Client die Verbindung trennt, entfernt die interne Datenbank alle Kontakte und den Anrufverlauf, die mit dem zuvor verbundenen Gerät verknüpft sind.

Nachrichtenzugriffsprofil

Das Bluetooth Message Access Profile (MAP) ermöglicht dem Fahrzeug das Senden und Empfangen von SMS-Nachrichten über ein verbundenes Remote-Gerät. Derzeit werden Nachrichten nicht lokal auf dem IVI gespeichert. Stattdessen empfängt und analysiert das IVI jedes Mal, wenn das verbundene Remote-Gerät eine Nachricht empfängt, die Nachricht und sendet ihren Inhalt in einer Intent- Instanz, die dann von einer App empfangen werden kann.

Um eine Verbindung zu einem mobilen Gerät zum Senden und Empfangen von Nachrichten herzustellen, muss das IVI die MAP-Verbindung initiieren. MAXIMUM_CONNECTED_DEVICES in MapClientService definiert die maximale Anzahl gleichzeitiger MAP-Geräteverbindungen, die mit dem IVI zulässig sind. Jede Verbindung muss vom IVI und dem Mobilgerät autorisiert werden, bevor Nachrichten übertragen werden können.

Erweitertes Audioverteilungsprofil

Das Bluetooth Advanced Audio Distribution Profile (A2DP) ermöglicht dem Fahrzeug den Empfang von Audiostreams von einem angeschlossenen Remote-Gerät.

Im Gegensatz zu anderen Profilen wird die maximale Anzahl verbundener A2DP-Geräte im nativen Stack und nicht in Java erzwungen. Der Wert ist derzeit mithilfe der Variablen kDefaultMaxConnectedAudioDevices in packages/modules/Bluetooth/system/btif/src/btif_av.cc fest auf 1 codiert.

Audio-/Video-Fernbedienungsprofil

Mit dem Bluetooth Audio/Video Remote Control Profile (AVRCP) kann das Fahrzeug Mediaplayer auf einem angeschlossenen Remote-Gerät steuern und durchsuchen. Da der IVI die Rolle eines AVRCP-Controllers spielt, sind alle ausgelösten Steuerungen, die sich auf die Audiowiedergabe auswirken, auf eine A2DP-Verbindung zum Zielgerät angewiesen.

Damit ein bestimmter Medienplayer auf einem Android-Telefon vom IVI über AVRCP durchsucht werden kann, muss die Medien-App auf dem Telefon einen MediaBrowserService bereitstellen und com.android.bluetooth Zugriff auf diesen Dienst ermöglichen. Der Aufbau eines Medienbrowserdienstes erläutert die Vorgehensweise im Detail.