Android proporciona una implementación completa de Bluetooth con compatibilidad para muchos perfiles de Bluetooth comunes en el automóvil. También hay muchas mejoras que optimizan el rendimiento y la experiencia con otros dispositivos y servicios.
Administración de conexiones Bluetooth
En Android, CarBluetoothService mantiene los dispositivos Bluetooth del usuario actual y las listas de prioridad para cada conexión de perfil al IVI. Los dispositivos se conectan a los perfiles en un orden de prioridad definido. Cuándo habilitar, inhabilitar y conectar dispositivos a un perfil se basa en una política de conexión predeterminada que se puede anular con el uso de una superposición de recursos, si se desea.
Configura la administración de conexiones automotrices
Inhabilita la política de teléfono predeterminada
La pila de Bluetooth de Android mantiene una política de conexión para teléfonos que está habilitada de forma predeterminada. Esta política debe inhabilitarse en tu dispositivo para que no entre en conflicto con la política automotriz prevista en
CarBluetoothService. Si bien la superposición del producto Car debería encargarse de esto, puedes inhabilitar la política del teléfono en una
superposición de recursos configurando enable_phone_policy
en false
en MAXIMUM_CONNECTED_DEVICES
en
/packages/apps/Bluetooth/res/values/config.xml
.
Usa la política predeterminada para automóviles
CarBluetoothService mantiene los permisos del perfil predeterminado. La lista de dispositivos conocidos y sus prioridades de reconexión de perfil se encuentra en service/src/com/android/car/BluetoothProfileDeviceManager.java
.
Además, la política de administración de conexiones Bluetooth se puede encontrar en
service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
. De forma predeterminada, esta política define las instancias en las que Bluetooth debe conectarse a dispositivos vinculados y desconectarse de ellos. También administra los casos específicos del automóvil para determinar cuándo se debe encender y apagar el adaptador.
Crea tu propia política personalizada de administración de conexiones automotrices
Si la política predeterminada para automóviles no satisface tus necesidades, también puedes inhabilitarla y usar tu propia política personalizada. Como mínimo, tu política personalizada es responsable de determinar cuándo habilitar y cuándo inhabilitar el adaptador Bluetooth, así como cuándo conectar dispositivos. Es posible usar una variedad de eventos para habilitar o inhabilitar el adaptador de Bluetooth y para iniciar conexiones de dispositivos, incluidos los eventos debidos a cambios en propiedades específicas del automóvil.
Inhabilita la política predeterminada para automóviles
Primero, para usar una política personalizada, se debe inhabilitar la política predeterminada para automóviles estableciendo useDefaultBluetoothConnectionPolicy
en false
en una superposición de recursos.
Este recurso se define originalmente como parte de MAXIMUM_CONNECTED_DEVICES
en
packages/services/Car/service/res/values/config.xml
.
Cómo habilitar e inhabilitar el adaptador Bluetooth
Una de las funciones principales de tu política es activar y desactivar el adaptador de Bluetooth en los momentos adecuados. Puedes usar las APIs del framework de BluetoothAdapter.enable()
y BluetoothAdapter.disable()
para habilitar y, luego, inhabilitar el adaptador.
Estas llamadas deben respetar el estado persistente que el usuario seleccionó a través de la configuración o cualquier otro medio. Una forma de hacerlo 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 does nothing if the adapter // is already off, keeping the existing saved desired state for next reboot. bluetoothAdapter.disable(false); }
Determina cuándo activar y desactivar el adaptador Bluetooth
Con tu política personalizada, puedes determinar libremente qué eventos indican los mejores momentos para habilitar y, luego, inhabilitar el adaptador. Una forma de hacerlo es usar los estados de energía MAXIMUM_CONNECTED_DEVICES
en 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 cuándo conectar los dispositivos
Del mismo modo, cuando determinas los eventos que deberían activar las conexiones de dispositivos para que comiencen,
CarBluetoothManager proporciona la llamada a la API de connectDevices()
que
procede a conectar dispositivos según las listas de prioridad definidas para cada perfil de Bluetooth.
Un ejemplo de cuándo podrías 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 app's context Car car = Car.createCar(mContext); CarBluetoothManager carBluetoothManager = (CarBluetoothManager) car.getCarManager(Car.BLUETOOTH_SERVICE); carBluetoothManager.connectDevices(); } } } }
Verifica la administración de la conexión del automóvil
La forma más sencilla de verificar el comportamiento de tu política de conexión es habilitar Bluetooth en el IVI y validar que se conecte automáticamente a los dispositivos correctos en el orden adecuado. Puedes activar o desactivar el adaptador Bluetooth a través de la IU de configuración o con los siguientes comandos de 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, el resultado del siguiente comando se puede usar para ver información de depuración relacionada con las conexiones Bluetooth:
adb shell dumpsys car_service
Por último, si creaste tu propia política para automóviles, verificar cualquier comportamiento de conexión personalizado requiere controlar los eventos que elegiste para activar las conexiones de dispositivos.
Perfiles de Bluetooth para automóviles
En Android, el IVI puede admitir varios dispositivos conectados simultáneamente a través de Bluetooth. Los servicios telefónicos Bluetooth multidispositivo permiten a los usuarios conectar dispositivos separados de forma simultánea, como un teléfono personal y un teléfono de trabajo, y realizar llamadas con manos libres desde cualquiera de los dispositivos.
Cada perfil de Bluetooth individual aplica los límites de conexión, por lo general, dentro de la implementación del servicio de perfil en sí. De forma predeterminada, CarBluetoothService no emite ningún juicio adicional sobre la cantidad máxima de dispositivos conectados permitidos.
Perfil de manos libres
El perfil de manos libres (HFP) de Bluetooth permite que el vehículo realice y reciba llamadas telefónicas a través de un dispositivo remoto conectado. Cada conexión de dispositivo registra una cuenta de teléfono independiente con TelecomManager, que anuncia cualquier cuenta de teléfono disponible para las apps del IVI.
El IVI puede conectarse a varios dispositivos a través de HFP. MAX_STATE_MACHINES_POSSIBLE
MAXIMUM_CONNECTED_DEVICES
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 app de Teléfono
interactúa con el objeto HfpClientConnection
para administrar las funciones
de llamadas, como aceptar una llamada o colgar.
Cabe destacar que la app de Teléfono predeterminada no admite varios dispositivos HFP conectados simultáneamente. Para implementar el HFP multidispositivo, se requiere personalización
para permitir que los usuarios seleccionen qué cuenta del dispositivo usar cuando realicen una llamada. Luego, la app llama a telecomManager.placeCall
con la cuenta correcta. También debes
verificar que otras funciones multidispositivo también funcionen según lo previsto.
Cómo verificar el HFP multidispositivo
Para verificar que la conectividad multidispositivo funcione correctamente a través de Bluetooth, haz lo siguiente:
- Conecta un dispositivo al IVI a través de Bluetooth y transmite audio desde el dispositivo.
- Conecta dos teléfonos al IVI por Bluetooth.
- Elige un teléfono. Realizar una llamada saliente directamente desde el teléfono
y realizar una llamada saliente con el IVI
- En ambos casos, verifica que se pause el audio transmitido y que el audio del teléfono se reproduzca a través de las bocinas conectadas al IVI.
- Con el mismo teléfono, recibe una llamada entrante directamente en el teléfono y recibe una llamada entrante con el IVI.
- En ambos casos, verifica que se pause el audio de transmisión y que el audio del teléfono se reproduzca a través de las bocinas conectadas al IVI.
- Repite 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 de iniciar una llamada de emergencia desde el IVI, incluidas las siguientes:
- Solución de eCall independiente
- Solución de eCall integrada en el IVI
- Usar un teléfono Bluetooth conectado cuando no hay un sistema integrado disponible
Cómo conectar una llamada de emergencia
Si bien el equipo de 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, lo que también tiene el beneficio de introducir opciones de accesibilidad para las llamadas de emergencia. Para obtener más información, consulta Cómo compilar una app de llamadas.
A continuación, se muestra un ejemplo de cómo establecer un ConnectionService 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.registerPhoneAccount(account); mTelecomManager.enablePhoneAccount(account.getAccountHandle(), true); } }
Cómo habilitar el Bluetooth para las llamadas de emergencia
Llamar a emergencias antes de Android 10 implicaba marcar directamente desde un teléfono y usar equipos especiales si estaban disponibles (por ejemplo, activación automática al detectar peligro o una acción del usuario). En Android 10 y versiones posteriores, el marcador del automóvil puede llamar directamente a un número de emergencia, siempre que este MAXIMUM_CONNECTED_DEVICES
esté 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>
Si implementas las llamadas de emergencia de esta manera, otras apps, como las de reconocimiento de voz, también podrán llamar a un número de emergencia.
Perfil de acceso a la agenda telefónica
El perfil de acceso a la agenda telefónica (PBAP) de Bluetooth descarga los contactos y el historial de llamadas de un dispositivo remoto conectado. PBAP mantiene una lista agregada de contactos en la que se pueden realizar búsquedas y que se actualiza con la máquina de estados del cliente de PBAP. Cada dispositivo conectado interactúa con una máquina de estados del cliente de PBAP independiente, lo que hace que los contactos se asocien con el dispositivo adecuado cuando se realiza una llamada.
PBAP es unidireccional y, por lo tanto, requiere que el IVI cree instancias de conexiones a cualquier MAXIMUM_CONNECTED_DEVICES
en
PbapClientService
define la cantidad máxima de conexiones de dispositivos PBAP simultáneas permitidas con el IVI. El cliente de PBAP almacena los contactos de cada dispositivo conectado en el
proveedor de contactos, al que una app puede acceder para obtener la agenda 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 que se pueda establecer la conexión. Cuando un cliente de PBAP se desconecta, la base de datos interna quita todos los contactos y el historial de llamadas asociados con el dispositivo conectado anteriormente.
Perfil de acceso a mensajes
El perfil de acceso a mensajes (MAP) de Bluetooth 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 de forma local en el IVI. En cambio, cada vez que el dispositivo remoto conectado recibe un mensaje, el IVI lo recibe y analiza, y luego transmite su contenido en una instancia de Intent, que una app puede recibir.
Para conectarse a un dispositivo móvil con el objetivo de enviar y recibir
mensajes, el IVI debe iniciar la conexión MAP.
MAXIMUM_CONNECTED_DEVICES
en
MapClientService
define la cantidad máxima de conexiones simultáneas de dispositivos MAP permitidas con el IVI. El IVI y el dispositivo móvil deben autorizar cada conexión antes de que se puedan transferir mensajes.
Perfil de distribución de audio avanzado
El perfil de distribución de audio avanzado (A2DP) de Bluetooth permite que el vehículo reciba flujos de audio de un dispositivo remoto conectado.
A diferencia de otros perfiles, la cantidad máxima de dispositivos A2DP conectados se aplica en la pila nativa y no en Java. Actualmente, el valor está codificado como 1
con la variable kDefaultMaxConnectedAudioDevices
en
packages/modules/Bluetooth/system/btif/src/btif_av.cc
.
Perfil de control remoto de audio y video
El perfil de control remoto de audio/video (AVRCP) de Bluetooth permite que el vehículo controle y explore 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 explorar un reproductor multimedia específico en un teléfono Android a través de AVRCP, la app de música en el teléfono debe proporcionar un
MediaBrowserService
y permitir el acceso de com.android.bluetooth
a ese servicio.
Cómo crear un servicio de navegador multimedia explica cómo hacerlo en detalle.