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 . Приложение «Набор номера» взаимодействует с объектом HfpClientConnection для управления функциями вызова, такими как прием или завершение вызова.

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

Проверка HFP на нескольких устройствах

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

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

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

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

  • Автономное решение eCall
  • Решение eCall интегрировано в IVI
  • Использование телефона с поддержкой Bluetooth в отсутствие встроенной системы Bluetooth.

Соедините экстренный вызов

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

Вот пример того, как установить аварийную службу подключения :

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 был доступен для просмотра через IVI по протоколу AVRCP, медиаприложение на телефоне должно предоставлять MediaBrowserService и разрешать доступ к этому сервису com.android.bluetooth . В руководстве по созданию службы просмотра медиафайлов подробно описано, как это сделать.