Bluetooth

Android обеспечивает полноценную реализацию Bluetooth с поддержкой множества распространённых автомобильных профилей Bluetooth. Кроме того, реализовано множество улучшений, повышающих производительность и удобство работы с другими устройствами и сервисами.

Управление Bluetooth-подключением

В Android служба CarBluetoothService поддерживает Bluetooth-устройства текущего пользователя и списки приоритетов для каждого профиля подключения к IVI. Устройства подключаются к профилям в определённом порядке приоритета. Время включения, отключения и подключения устройств к профилю определяется политикой подключения по умолчанию, которую при необходимости можно переопределить с помощью наложения ресурсов .

Настройка управления автомобильными подключениями

Отключить политику телефона по умолчанию

Стек Bluetooth Android поддерживает политику подключения для телефонов, которая включена по умолчанию. Эту политику необходимо отключить на устройстве, чтобы она не конфликтовала с автомобильной политикой в ​​CarBluetoothService . Хотя оверлей продукта Car должен выполнять эту функцию автоматически, вы можете отключить телефонную политику в оверлее ресурсов , установив enable_phone_policy в значение false в параметре MAXIMUM_CONNECTED_DEVICES в /packages/apps/Bluetooth/res/values/config.xml .

Использовать автомобильную политику по умолчанию

CarBluetoothService сохраняет разрешения профиля по умолчанию. Список известных устройств и приоритеты повторного подключения их профилей находятся в service/src/com/android/car/BluetoothProfileDeviceManager.java .

Политику управления Bluetooth-подключениями можно найти в service/src/com/android/car/BluetoothDeviceConnectionPolicy.java . По умолчанию эта политика определяет случаи, когда Bluetooth должен подключаться к связанным устройствам и отключаться от них. Она также управляет специфическими для автомобиля ситуациями включения и выключения адаптера.

Создайте собственную политику управления автомобильными подключениями

Если политика автомобиля по умолчанию недостаточна для ваших нужд, её можно отключить, используя собственную политику. Ваша политика, как минимум, отвечает за определение времени включения и выключения адаптера Bluetooth, а также времени подключения устройств. Для включения/выключения адаптера Bluetooth и инициирования подключений устройств можно использовать различные события, включая события, связанные с изменением определённых характеристик автомобиля.

Отключить автомобильную политику по умолчанию

Во-первых, чтобы использовать пользовательскую политику, необходимо отключить автомобильную политику по умолчанию, установив параметр useDefaultBluetoothConnectionPolicy в false в наложении ресурсов . Этот ресурс изначально определен как часть MAXIMUM_CONNECTED_DEVICES в packages/services/Car/service/res/values/config.xml .

Включение и выключение адаптера Bluetooth

Одна из основных функций вашей политики — включение и выключение адаптера Bluetooth в нужное время. Для включения и выключения адаптера можно использовать API фреймворка BluetoothAdapter.enable() и BluetoothAdapter.disable() . Эти вызовы должны учитывать сохраненное состояние, выбранное пользователем в настройках или другими способами. Один из способов сделать это:

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

Определите, когда следует включать и выключать адаптер Bluetooth.

С помощью собственной политики вы можете свободно определять, какие события указывают на наилучшее время включения и выключения адаптера. Один из способов сделать это — использовать состояния питания MAXIMUM_CONNECTED_DEVICES в 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;
        }
    }
};

Определите, когда подключать устройства

Аналогичным образом, когда вы определяете события, которые должны инициировать начало подключения устройств, CarBluetoothManager обеспечивает вызов API connectDevices() , который приступает к подключению устройств на основе списков приоритетов, определенных для каждого профиля Bluetooth.

Одним из примеров того, когда вам может понадобиться это сделать, является включение адаптера 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();
            }
        }
    }
}

Проверка управления автомобильными соединениями

Самый простой способ проверить работу политики подключения — включить Bluetooth на вашем IVI и убедиться, что он автоматически подключается к нужным устройствам в правильном порядке. Вы можете включить или отключить Bluetooth-адаптер через интерфейс настроек или с помощью следующих команд 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

Кроме того, вывод следующей команды можно использовать для просмотра отладочной информации, связанной с соединениями Bluetooth:

adb shell dumpsys car_service

Наконец, если вы создали собственную автомобильную политику, проверка любого пользовательского поведения подключения потребует управления событиями, которые вы выбрали для запуска подключений устройств.

Автомобильные профили Bluetooth

В Android IVI поддерживает одновременное подключение нескольких устройств по Bluetooth. Многофункциональные Bluetooth-сервисы позволяют пользователям одновременно подключать разные устройства, например, личный и рабочий, и совершать звонки без помощи рук с любого из них.

Ограничения на количество подключений устанавливаются каждым отдельным профилем Bluetooth, обычно в рамках реализации самой службы профилей. По умолчанию CarBluetoothService не оценивает максимальное количество подключенных устройств.

Профиль громкой связи

Профиль Bluetooth Hands-Free (HFP) позволяет автомобилю совершать и принимать телефонные звонки через подключенное удаленное устройство. Каждое подключение устройства регистрирует отдельную учетную запись телефона в TelecomManager , который сообщает приложениям IVI о всех доступных учетных записях телефона.

IVI может подключаться к нескольким устройствам через HFP. MAX_STATE_MACHINES_POSSIBLE MAXIMUM_CONNECTED_DEVICES в HeadsetClientService определяет максимальное количество одновременных подключений HFP.

Когда пользователь совершает или принимает телефонный звонок с устройства, соответствующая учётная запись телефона создаёт объект HfpClientConnection . Приложение Dialer взаимодействует с объектом HfpClientConnection для управления функциями вызова, такими как приём вызова или завершение вызова.

Обратите внимание, что приложение Dialer по умолчанию не поддерживает несколько одновременно подключенных устройств HFP. Для реализации HFP на нескольких устройствах требуется настройка, позволяющая пользователям выбирать, какую учетную запись устройства использовать при совершении вызова. Затем приложение вызывает telecomManager.placeCall с указанием правильной учетной записи. Необходимо убедиться, что другие функции работы с несколькими устройствами также работают должным образом.

Проверка многофункционального HFP-устройства

Чтобы проверить корректность работы подключения нескольких устройств по Bluetooth:

  1. Используя Bluetooth, подключите устройство к IVI и транслируйте аудио с устройства.
  2. Подключите два телефона к IVI по Bluetooth.
  3. Выберите один телефон. Совершите исходящий звонок прямо с телефона или через IVI.
    1. В обоих случаях убедитесь, что потоковая передача звука приостанавливается, а звук с телефона воспроизводится через подключенные динамики IVI.
  4. Используя один и тот же телефон, примите входящий звонок непосредственно на телефоне и примите входящий звонок с помощью IVI.
    1. В обоих случаях убедитесь, что потоковая передача звука приостанавливается, а звук телефона воспроизводится через подключенные IVI динамики.
  5. Повторите шаги 3 и 4 с другим подключенным телефоном.

Экстренный вызов

Возможность совершать экстренные вызовы — важный аспект телефонии и Bluetooth в автомобиле. Существует несколько способов инициировать экстренный вызов с помощью IVI, включая:

  • Автономное решение для электронных звонков
  • Решение eCall интегрировано в IVI
  • Использование подключенного Bluetooth-телефона при отсутствии встроенной системы

Подключите экстренный вызов

Хотя оборудование eCall критически важно для безопасности, в настоящее время оно не интегрировано в Android. Можно использовать ConnectionService для предоставления функций экстренных вызовов через Android, что также позволяет реализовать специальные возможности для экстренных вызовов. Подробнее см. в статье «Создание приложения для экстренных вызовов» .

Вот пример того, как организовать экстренную службу 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);
    }
}

Включить Bluetooth для экстренных вызовов

До Android 10 вызов экстренных служб осуществлялся путём прямого набора номера с телефона и активации специального оборудования, если оно доступно (например, автоматического срабатывания при обнаружении опасности или действии пользователя). В Android 10 и более поздних версиях автомобильный номеронабиратель может напрямую вызывать экстренные службы, при условии, что в файле apps/Bluetooth/res/values/config.xml указано следующее MAXIMUM_CONNECTED_DEVICES :

<!-- For supporting emergency call through the hfp client connection service --> <bool name=”hfp_client_connection_service_support_emergency_call”>true</bool>

Реализуя функцию экстренного вызова таким образом, другие приложения, например, распознавание голоса, также могут вызвать номер экстренной службы.

Профиль доступа к телефонной книге

Профиль доступа к телефонной книге Bluetooth (PBAP) загружает контакты и историю вызовов с подключенного удаленного устройства. PBAP поддерживает агрегированный список контактов с возможностью поиска, который обновляется клиентским конечным автоматом PBAP. Каждое подключенное устройство взаимодействует с отдельным клиентским конечным автоматом PBAP, что приводит к привязке контактов к соответствующему устройству при совершении вызова.

PBAP является однонаправленным и поэтому требует от IVI создания подключений к любым MAXIMUM_CONNECTED_DEVICES в PbapClientService , который определяет максимальное количество одновременных подключений устройств PBAP, разрешенных для IVI. Клиент PBAP хранит контакты для каждого подключенного устройства в поставщике контактов , к которому приложение может получить доступ для создания телефонной книги каждого устройства.

Кроме того, для установки соединения профиль должен быть авторизован как IVI, так и мобильным устройством. При отключении PBAP-клиента внутренняя база данных удаляет все контакты и историю вызовов, связанные с ранее подключенным устройством.

Профиль доступа к сообщениям

Профиль доступа к сообщениям Bluetooth (MAP) позволяет автомобилю отправлять и получать SMS-сообщения через подключенное удаленное устройство. В настоящее время сообщения не хранятся локально в IVI. Вместо этого, когда подключенное удаленное устройство получает сообщение, IVI получает и анализирует его, а затем передает его содержимое в экземпляре Intent , который затем может быть получен приложением.

Для подключения к мобильному устройству для отправки и получения сообщений IVI должен инициировать MAP-соединение. MAXIMUM_CONNECTED_DEVICES в MapClientService определяет максимальное количество одновременных подключений MAP-устройств, разрешенных к IVI. Каждое соединение должно быть авторизовано IVI и мобильным устройством, прежде чем сообщения будут переданы.

Расширенный профиль распространения звука

Профиль расширенного распространения звука Bluetooth (A2DP) позволяет автомобилю принимать аудиопотоки с подключенного удаленного устройства.

В отличие от других профилей, максимальное количество подключенных устройств A2DP задаётся в собственном стеке, а не в Java. В настоящее время значение жёстко задано равным 1 с помощью переменной kDefaultMaxConnectedAudioDevices в packages/modules/Bluetooth/system/btif/src/btif_av.cc .

Профиль дистанционного управления аудио/видео

Профиль дистанционного управления аудио/видео Bluetooth (AVRCP) позволяет автомобилю управлять медиаплеерами и просматривать их на подключенном удалённом устройстве. Поскольку IVI выполняет роль контроллера AVRCP, любые активируемые элементы управления, влияющие на воспроизведение звука, требуют подключения A2DP к целевому устройству.

Чтобы медиаплеер на Android-смартфоне был доступен для просмотра через AVRCP через IVI, медиаприложение на телефоне должно предоставлять службу MediaBrowserService и разрешать доступ к ней com.android.bluetooth . В статье «Создание службы медиабраузера» подробно объясняется, как это сделать.