Bluetooth

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

Управление Bluetooth-соединением

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

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

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

Стек Android Bluetooth поддерживает политику подключения для телефонов, которая включена по умолчанию. Эта политика должна быть отключена на вашем устройстве, чтобы она не конфликтовала с предполагаемой автомобильной политикой в ​​CarBluetoothService . Хотя наложение продукта Car должно позаботиться об этом за вас, вы можете отключить политику телефона в наложении ресурсов , установив для enable_phone_policy значение false в /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 в наложении ресурсов . Этот ресурс изначально определен как часть 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 will do nothing if the adapter
    // is already off, keeping the existing saved desired state for next reboot.
    bluetoothAdapter.disable(false);
}

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

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

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

Точно так же, как только вы определили события, которые должны инициировать начало подключения устройств, 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 application’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 в 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.registerPhoneAcccount(account);
        mTelecomManager.enablePhoneAccount(account.getAccountHandle(), true);
    }
}

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

Вызов экстренной помощи до Android 10 включал прямой набор номера с телефона и вызов специального оборудования, если оно было доступно (например, автозапуск при обнаружении опасности или действия пользователя). Начиная с Android 10 номеронабиратель в автомобиле может напрямую вызывать экстренный номер, если этот код содержится в 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>

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

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

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

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

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

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

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

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

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

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

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

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

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

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