Bluetooth

Android proporciona una implementación completa de Bluetooth con soporte para muchos perfiles comunes de Bluetooth en el automóvil. También hay muchas mejoras que mejoran el rendimiento y la experiencia con otros dispositivos y servicios.

Gestión de conexión Bluetooth

Dentro de Android, CarBluetoothService mantiene los dispositivos Bluetooth del usuario actual y las listas de prioridades para cada perfil de conexión al IVI. Los dispositivos están conectados a perfiles en un orden de prioridad definido. Cuándo habilitar, deshabilitar y conectar dispositivos a un perfil depende de una política de conexión predeterminada que se puede anular con el uso de una superposición de recursos , si lo desea.

Configuración de la gestión de conexiones de automoción

Deshabilitar la política de teléfono predeterminada

La pila Bluetooth de Android mantiene una política de conexión para teléfonos que está habilitada de forma predeterminada. Esta política debe estar deshabilitada en su dispositivo para que no entre en conflicto con la política automotriz prevista en CarBluetoothService . Si bien la superposición del producto Car debe encargarse de esto por usted, puede deshabilitar la política del teléfono en una superposición de recursos configurando enable_phone_policy en false en /packages/apps/Bluetooth/res/values/config.xml .

Usar la política automotriz predeterminada

CarBluetoothService mantiene los permisos de perfil predeterminados. La lista de dispositivos conocidos y sus prioridades de reconexión de perfil se encuentran en service/src/com/android/car/BluetoothProfileDeviceManager.java .

Además, la política de administración de la conexión Bluetooth se puede encontrar en service/src/com/android/car/BluetoothDeviceConnectionPolicy.java . De forma predeterminada, esta política define instancias en las que Bluetooth debe conectarse y desconectarse de dispositivos vinculados. También administra los casos específicos del automóvil para saber cuándo se debe encender y apagar el adaptador.

Crear su propia política personalizada de administración de conexiones automotrices

Si la política automotriz predeterminada no es suficiente para sus necesidades, también se puede deshabilitar a favor de su propia política personalizada. Su política personalizada será, como mínimo, responsable de determinar cuándo habilitar y deshabilitar el adaptador Bluetooth, así como cuándo conectar dispositivos. Es posible usar una variedad de eventos para habilitar/deshabilitar el adaptador Bluetooth e iniciar conexiones de dispositivos, incluidos eventos debido a cambios en las propiedades específicas del automóvil.

Deshabilitar la política automotriz predeterminada

En primer lugar, para usar una política personalizada, la política automotriz predeterminada debe deshabilitarse configurando useDefaultBluetoothConnectionPolicy en false en una superposición de recursos . Este recurso se definió originalmente como parte de packages/services/Car/service/res/values/config.xml .

Habilitar y deshabilitar el adaptador Bluetooth

Una de las funciones principales de su póliza es encender y apagar el adaptador Bluetooth en los momentos apropiados. Puede usar las API de marco BluetoothAdapter.enable() y BluetoothAdapter.disable() para habilitar y deshabilitar el adaptador. Estas llamadas deben respetar el estado persistente que el usuario ha seleccionado a través de Configuración o cualquier otro medio. Una forma de hacer esto es la siguiente:

/**
 * 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 cuándo encender y apagar el adaptador Bluetooth

Con su política personalizada, puede determinar qué eventos indican los mejores momentos para habilitar y deshabilitar el adaptador. Una forma de hacerlo es mediante el uso de los estados de energía mantenidos por 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 cuándo conectar dispositivos

De manera similar, una vez que haya determinado los eventos que deberían desencadenar el inicio de las conexiones de los dispositivos, CarBluetoothManager proporciona la llamada a la API connectDevices() que procederá a conectar los dispositivos según las listas de prioridad definidas para cada perfil de Bluetooth.

Un ejemplo de cuándo podría querer hacer esto es cada vez que se enciende el adaptador Bluetooth:

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

Verificación de la gestión de conexiones automotrices

La forma más fácil de verificar el comportamiento de su política de conexión es habilitar Bluetooth en su IVI y validar que se conecta automáticamente a los dispositivos correctos en el orden apropiado. Puede alternar el adaptador Bluetooth a través de la interfaz de usuario de configuración o con los siguientes 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

Además, la salida del siguiente comando se puede usar para ver información de depuración relacionada con las conexiones Bluetooth:

adb shell dumpsys car_service

Finalmente, si ha creado su propia política automotriz, verificar cualquier comportamiento de conexión personalizado requerirá controlar los eventos que ha elegido para desencadenar conexiones de dispositivos.

Perfiles de Bluetooth para automóviles

En Android, el IVI puede admitir múltiples dispositivos conectados simultáneamente a través de Bluetooth. Los servicios telefónicos Bluetooth para dispositivos múltiples permiten a los usuarios conectar dispositivos separados al mismo tiempo, como un teléfono personal y un teléfono de trabajo, y realizar llamadas manos libres desde cualquier dispositivo.

Cada perfil de Bluetooth individual impone límites de conexión, generalmente dentro de la implementación del propio servicio de perfil. De manera predeterminada, CarBluetoothService no juzga más la cantidad máxima de dispositivos conectados permitidos.

Perfil manos libres

El perfil de manos libres Bluetooth (HFP) permite que el vehículo haga y reciba llamadas telefónicas a través de un dispositivo remoto conectado. Cada conexión de dispositivo registra una cuenta de teléfono separada con TelecomManager , que anuncia cualquier cuenta de teléfono disponible para las aplicaciones de IVI.

El IVI puede conectarse a múltiples dispositivos a través de HFP. MAX_STATE_MACHINES_POSSIBLE en HeadsetClientService define la cantidad máxima de conexiones HFP simultáneas.

Cuando un usuario realiza o recibe una llamada telefónica desde un dispositivo, la cuenta de teléfono correspondiente crea un objeto HfpClientConnection . La aplicación Dialer interactúa con el objeto HfpClientConnection para administrar funciones de llamada, como aceptar una llamada o colgar.

Cabe señalar que la aplicación Dialer predeterminada no admite varios dispositivos HFP conectados simultáneamente. Para implementar HFP multidispositivo, se requiere personalización para permitir a los usuarios seleccionar qué cuenta de dispositivo utilizar al realizar una llamada. Luego, la aplicación llamará a telecomManager.placeCall con la cuenta correcta. Deberá verificar que otras funciones multidispositivo también funcionen según lo previsto.

Verificar HFP multidispositivo

Para comprobar que la conectividad multidispositivo funciona correctamente a través de Bluetooth:

  1. Usando Bluetooth, conecte un dispositivo al IVI y transmita audio desde el dispositivo.
  2. Conecte dos teléfonos al IVI a través de Bluetooth.
  3. Elige un teléfono. Realice una llamada saliente directamente desde el teléfono y realice una llamada saliente utilizando el IVI.
    1. En ambas ocasiones, verifique que el audio transmitido haga una pausa y que el audio del teléfono se reproduzca en los parlantes conectados a IVI.
  4. Usando el mismo teléfono, reciba una llamada entrante directamente en el teléfono y reciba una llamada entrante usando el IVI.
    1. En ambas ocasiones, verifique que la transmisión de audio se detenga y el audio del teléfono se reproduzca a través de los altavoces conectados a IVI.
  5. Repita los pasos 3 y 4 con el otro teléfono conectado.

Llamadas de emergencia

La capacidad de realizar llamadas de emergencia es un aspecto importante de las funciones de telefonía y Bluetooth del automóvil. Hay varias formas en que se puede iniciar una llamada de emergencia desde el IVI, que incluyen:

  • Solución eCall independiente
  • Solución eCall integrada en el IVI
  • Confiar en un teléfono Bluetooth conectado cuando no hay un sistema integrado disponible

Conexión de una llamada de emergencia

Si bien el equipo eCall es fundamental para la seguridad, actualmente no está integrado en Android. Es posible usar ConnectionService para exponer funciones de llamadas de emergencia a través de Android, que también tiene la ventaja de presentar opciones de accesibilidad para llamadas de emergencia. Para obtener más información, consulte Creación de una aplicación de llamadas .

Aquí hay un ejemplo de cómo establecer un servicio de conexión de emergencia:

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

Activación de Bluetooth para llamadas de emergencia

Llamar a emergencias antes de Android 10 implicaba la marcación directa desde un teléfono y la invocación de un equipo especial si estaba disponible (por ejemplo, activación automática al detectar un peligro o una acción del usuario). Desde Android 10, el marcador en el automóvil puede llamar directamente a un número de emergencia, siempre que este código esté contenido en 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>

Al implementar las llamadas de emergencia de esta manera, otras aplicaciones, como el reconocimiento de voz, también pueden llamar a un número de emergencia.

Perfil de acceso a la agenda telefónica

El perfil de acceso a la libreta de teléfonos Bluetooth (PBAP) descarga contactos e historiales de llamadas desde un dispositivo remoto conectado. PBAP mantiene una lista agregada de contactos que se puede buscar y que es actualizada por la máquina de estado del cliente PBAP. Cada dispositivo conectado interactúa con una máquina de estado de cliente PBAP separada, lo que da como resultado que los contactos se asocien con el dispositivo adecuado al realizar una llamada.

PBAP es unidireccional y, por lo tanto, requiere que el IVI cree instancias de conexiones a cualquier dispositivo móvil deseado. MAXIMUM_DEVICES en PbapClientService define la cantidad máxima de conexiones de dispositivos PBAP simultáneas permitidas con el IVI. El cliente PBAP almacena los contactos de cada dispositivo conectado en el proveedor de contactos , al que luego puede acceder una aplicación para derivar la guía telefónica de cada dispositivo.

Además, la conexión del perfil debe estar autorizada tanto por el IVI como por el dispositivo móvil para poder realizar la conexión. Cuando un cliente PBAP se desconecta, la base de datos interna elimina todos los contactos y el historial de llamadas asociado con el dispositivo conectado anteriormente.

Perfil de acceso a mensajes

El perfil de acceso a mensajes Bluetooth (MAP) permite que el vehículo envíe y reciba mensajes SMS a través de un dispositivo remoto conectado. Actualmente, los mensajes no se almacenan localmente en el IVI. En cambio, cada vez que el dispositivo remoto conectado recibe un mensaje, el IVI recibe y analiza el mensaje y transmite su contenido en un Intent , que luego puede ser recibido por una aplicación.

Para conectarse a un dispositivo móvil con el fin de enviar y recibir mensajes, el IVI debe iniciar la conexión MAP. MAXIMUM_CONNECTED_DEVICES en MapClientService define el número máximo de conexiones de dispositivos MAP simultáneas permitidas con el IVI. Cada conexión debe ser autorizada por el IVI y el dispositivo móvil antes de que se puedan transferir los mensajes.

Perfil de distribución de audio avanzado

El perfil de distribución de audio avanzado de Bluetooth (A2DP) permite que el vehículo reciba transmisiones de audio desde un dispositivo remoto conectado.

A diferencia de otros perfiles, la cantidad máxima de dispositivos A2DP conectados se impone en la pila nativa y no en Java. El valor actualmente está codificado en 1 usando la variable kDefaultMaxConnectedAudioDevices en packages/modules/Bluetooth/system/vtif/src/btif_av.cc .

Perfil de control remoto de audio/video

El perfil de control remoto de audio/video Bluetooth (AVRCP) permite que el vehículo controle y busque reproductores multimedia en un dispositivo remoto conectado. Dado que el IVI desempeña el papel de un controlador AVRCP, cualquier control activado que afecte la reproducción de audio depende de una conexión A2DP al dispositivo de destino.

Para que el IVI pueda navegar por un reproductor multimedia específico en un teléfono Android a través de AVRCP, la aplicación multimedia del teléfono debe proporcionar un MediaBrowserService y permitir el acceso de com.android.bluetooth a ese servicio. Creación de un servicio de navegador de medios explica cómo hacer esto en detalle.