Bluetooth

Android cung cấp triển khai Bluetooth đầy đủ với sự hỗ trợ cho nhiều cấu hình Bluetooth phổ biến trên ô tô. Ngoài ra còn có nhiều cải tiến giúp cải thiện hiệu suất và trải nghiệm với các thiết bị và dịch vụ khác.

Quản lý kết nối Bluetooth

Trong Android, CarBluetoothService duy trì danh sách ưu tiên và thiết bị Bluetooth của người dùng hiện tại cho từng kết nối cấu hình với IVI. Các thiết bị được kết nối với hồ sơ theo thứ tự ưu tiên xác định. Thời điểm bật, tắt và kết nối thiết bị với cấu hình được điều khiển bởi chính sách kết nối mặc định có thể được ghi đè bằng cách sử dụng lớp phủ tài nguyên , nếu muốn.

Cấu hình quản lý kết nối ô tô

Tắt chính sách điện thoại mặc định

Ngăn xếp Android Bluetooth duy trì chính sách kết nối cho điện thoại được bật theo mặc định. Chính sách này phải được tắt trên thiết bị của bạn để không xung đột với chính sách dự kiến ​​dành cho ô tô trong CarBluetoothService . Mặc dù lớp phủ Sản phẩm ô tô sẽ giải quyết vấn đề này cho bạn nhưng bạn có thể tắt chính sách điện thoại trong lớp phủ tài nguyên bằng cách đặt enable_phone_policy thành false trong MAXIMUM_CONNECTED_DEVICES trong /packages/apps/Bluetooth/res/values/config.xml .

Sử dụng chính sách ô tô mặc định

CarBluetoothService duy trì các quyền hồ sơ mặc định. Danh sách các thiết bị đã biết và mức độ ưu tiên kết nối lại hồ sơ của chúng nằm trong service/src/com/android/car/BluetoothProfileDeviceManager.java .

Ngoài ra, bạn có thể tìm thấy chính sách quản lý kết nối Bluetooth trong service/src/com/android/car/BluetoothDeviceConnectionPolicy.java . Theo mặc định, chính sách này xác định các trường hợp Bluetooth sẽ kết nối và ngắt kết nối khỏi các thiết bị được liên kết. Nó cũng quản lý các trường hợp dành riêng cho ô tô về thời điểm nên bật và tắt bộ chuyển đổi.

Tạo chính sách quản lý kết nối ô tô tùy chỉnh của riêng bạn

Nếu chính sách ô tô mặc định không đủ cho nhu cầu của bạn, nó cũng có thể bị vô hiệu hóa theo chính sách tùy chỉnh của riêng bạn. Chính sách tùy chỉnh của bạn ít nhất chịu trách nhiệm xác định thời điểm bật và tắt bộ điều hợp Bluetooth cũng như thời điểm kết nối thiết bị. Có thể sử dụng nhiều sự kiện khác nhau để bật/tắt bộ điều hợp Bluetooth và bắt đầu kết nối thiết bị, bao gồm các sự kiện do thay đổi các thuộc tính cụ thể của ô tô.

Vô hiệu hóa chính sách ô tô mặc định

Trước tiên, để sử dụng chính sách tùy chỉnh, chính sách ô tô mặc định phải được tắt bằng cách đặt useDefaultBluetoothConnectionPolicy thành false trong lớp phủ tài nguyên . Tài nguyên này ban đầu được xác định là một phần của MAXIMUM_CONNECTED_DEVICES trong packages/services/Car/service/res/values/config.xml .

Bật và tắt bộ điều hợp Bluetooth

Một trong những chức năng cốt lõi trong chính sách của bạn là bật và tắt bộ điều hợp Bluetooth vào những thời điểm thích hợp. Bạn có thể sử dụng API khung BluetoothAdapter.enable()BluetoothAdapter.disable() để bật và tắt bộ điều hợp. Các cuộc gọi này phải tôn trọng trạng thái liên tục mà người dùng đã chọn thông qua Cài đặt hoặc bất kỳ phương tiện nào khác. Một cách để làm điều này là như sau:

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

Xác định thời điểm bật và tắt bộ chuyển đổi Bluetooth

Với chính sách tùy chỉnh của mình, bạn có thể tự do xác định sự kiện nào cho biết thời điểm tốt nhất để bật và tắt bộ điều hợp. Một cách như vậy để thực hiện việc này là sử dụng trạng thái nguồn MAXIMUM_CONNECTED_DEVICES trong 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;
        }
    }
};

Xác định thời điểm kết nối thiết bị

Tương tự, khi bạn xác định các sự kiện sẽ kích hoạt kết nối thiết bị để bắt đầu, CarBluetoothManager sẽ cung cấp lệnh gọi API connectDevices() để tiến hành kết nối các thiết bị dựa trên danh sách ưu tiên được xác định cho từng cấu hình Bluetooth.

Một ví dụ về thời điểm bạn có thể muốn thực hiện việc này là bất cứ khi nào bộ điều hợp Bluetooth bật:

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

Xác minh quản lý kết nối ô tô

Cách dễ nhất để xác minh hành vi của chính sách kết nối của bạn là bật Bluetooth trên IVI của bạn và xác thực rằng nó tự động kết nối với đúng thiết bị theo thứ tự thích hợp. Bạn có thể chuyển đổi bộ điều hợp Bluetooth thông qua giao diện người dùng cài đặt hoặc bằng các lệnh adb sau:

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

Ngoài ra, đầu ra của lệnh sau có thể được sử dụng để xem thông tin gỡ lỗi liên quan đến kết nối Bluetooth:

adb shell dumpsys car_service

Cuối cùng, nếu bạn đã xây dựng chính sách ô tô của riêng mình thì việc xác minh mọi hành vi kết nối tùy chỉnh đều yêu cầu kiểm soát các sự kiện mà bạn đã chọn để kích hoạt kết nối thiết bị.

Cấu hình Bluetooth ô tô

Trong Android, IVI có thể hỗ trợ nhiều thiết bị được kết nối đồng thời qua Bluetooth. Dịch vụ điện thoại Bluetooth đa thiết bị cho phép người dùng kết nối đồng thời các thiết bị riêng biệt, chẳng hạn như điện thoại cá nhân và điện thoại cơ quan, đồng thời thực hiện cuộc gọi rảnh tay từ một trong hai thiết bị.

Giới hạn kết nối được thực thi bởi từng cấu hình Bluetooth riêng lẻ, thường là trong quá trình triển khai chính dịch vụ cấu hình đó. Theo mặc định, CarBluetoothService không đưa ra phán quyết nào thêm về số lượng thiết bị được kết nối tối đa được phép.

Hồ sơ rảnh tay

Cấu hình rảnh tay Bluetooth (HFP) cho phép xe thực hiện và nhận các cuộc gọi điện thoại thông qua một thiết bị từ xa được kết nối. Mỗi kết nối thiết bị sẽ đăng ký một tài khoản điện thoại riêng với TelecomManager , tài khoản này sẽ quảng cáo mọi tài khoản điện thoại có sẵn cho ứng dụng IVI.

IVI có thể kết nối với nhiều thiết bị thông qua HFP. MAX_STATE_MACHINES_POSSIBLE MAXIMUM_CONNECTED_DEVICES trong HeadsetClientService xác định số lượng kết nối HFP đồng thời tối đa.

Khi người dùng thực hiện hoặc nhận cuộc gọi từ một thiết bị, tài khoản điện thoại tương ứng sẽ tạo một đối tượng HfpClientConnection . Ứng dụng Trình quay số tương tác với đối tượng HfpClientConnection để quản lý các tính năng cuộc gọi, chẳng hạn như chấp nhận cuộc gọi hoặc gác máy.

Cần lưu ý rằng ứng dụng Trình quay số mặc định không hỗ trợ nhiều thiết bị HFP được kết nối đồng thời. Để triển khai HFP trên nhiều thiết bị, cần phải tùy chỉnh để cho phép người dùng chọn tài khoản thiết bị nào sẽ sử dụng khi thực hiện cuộc gọi. Sau đó, ứng dụng sẽ gọi telecomManager.placeCall bằng đúng tài khoản. Bạn cần xác minh rằng chức năng đa thiết bị khác cũng hoạt động như dự định.

Xác minh HFP đa thiết bị

Để kiểm tra xem kết nối nhiều thiết bị có hoạt động bình thường qua Bluetooth hay không:

  1. Sử dụng Bluetooth, kết nối thiết bị với IVI và truyền phát âm thanh từ thiết bị.
  2. Kết nối hai điện thoại với IVI qua Bluetooth.
  3. Chọn một chiếc điện thoại. Thực hiện cuộc gọi đi trực tiếp từ điện thoại và thực hiện cuộc gọi đi bằng IVI.
    1. Cả hai lần, hãy xác minh các lần tạm dừng âm thanh phát trực tuyến và âm thanh điện thoại phát qua loa được kết nối IVI.
  4. Sử dụng cùng một điện thoại, nhận cuộc gọi đến trực tiếp trên điện thoại và nhận cuộc gọi đến bằng IVI.
    1. Cả hai lần, hãy xác minh việc tạm dừng âm thanh phát trực tuyến và âm thanh điện thoại phát qua loa được kết nối IVI.
  5. Lặp lại bước 3 và 4 với điện thoại được kết nối khác.

Gọi khẩn cấp

Khả năng thực hiện cuộc gọi khẩn cấp là một khía cạnh quan trọng của chức năng điện thoại và Bluetooth trên ô tô. Có một số cách có thể bắt đầu cuộc gọi khẩn cấp từ IVI, bao gồm:

  • Giải pháp eCall độc lập
  • Giải pháp eCall tích hợp vào IVI
  • Dựa vào điện thoại Bluetooth được kết nối khi không có hệ thống tích hợp sẵn

Kết nối cuộc gọi khẩn cấp

Mặc dù thiết bị eCall rất quan trọng về mặt an toàn nhưng hiện tại nó chưa được tích hợp vào Android. Có thể sử dụng ConnectionService để hiển thị các tính năng gọi khẩn cấp thông qua Android, tính năng này cũng có lợi ích là giới thiệu các tùy chọn trợ năng cho các cuộc gọi khẩn cấp. Để tìm hiểu thêm, hãy xem Xây dựng ứng dụng gọi điện .

Dưới đây là ví dụ về cách thiết lập ConnectionService khẩn cấp:

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

Bật Bluetooth cho các cuộc gọi khẩn cấp

Gọi khẩn cấp trước Android 10 bao gồm quay số trực tiếp từ điện thoại và gọi thiết bị đặc biệt nếu có (ví dụ: tự động kích hoạt khi phát hiện nguy hiểm hoặc hành động của người dùng). Trong Android 10 trở lên, Trình quay số trong ô tô có thể gọi trực tiếp đến số khẩn cấp, miễn là MAXIMUM_CONNECTED_DEVICES này trong 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>

Bằng cách triển khai tính năng gọi khẩn cấp theo cách này, các ứng dụng khác, chẳng hạn như nhận dạng giọng nói, cũng có thể gọi đến số khẩn cấp.

Hồ sơ truy cập danh bạ điện thoại

Cấu hình truy cập danh bạ Bluetooth (PBAP) tải xuống danh bạ và lịch sử cuộc gọi từ thiết bị từ xa được kết nối. PBAP duy trì một danh sách liên hệ tổng hợp, có thể tìm kiếm được cập nhật bởi máy trạng thái máy khách PBAP. Mỗi thiết bị được kết nối sẽ tương tác với một máy trạng thái máy khách PBAP riêng biệt, dẫn đến các liên hệ được liên kết với thiết bị phù hợp khi thực hiện cuộc gọi.

PBAP là một chiều và do đó yêu cầu IVI khởi tạo kết nối với bất kỳ MAXIMUM_CONNECTED_DEVICES nào trong PbapClientService xác định số lượng kết nối thiết bị PBAP đồng thời tối đa được phép với IVI. Ứng dụng khách PBAP lưu trữ danh bạ cho từng thiết bị được kết nối trong Nhà cung cấp Danh bạ , sau đó ứng dụng có thể truy cập để lấy danh bạ cho từng thiết bị.

Ngoài ra, kết nối hồ sơ phải được cả IVI và thiết bị di động cho phép để thực hiện kết nối. Khi máy khách PBAP ngắt kết nối, cơ sở dữ liệu nội bộ sẽ xóa tất cả danh bạ và lịch sử cuộc gọi được liên kết với thiết bị đã kết nối trước đó.

Hồ sơ truy cập tin nhắn

Cấu hình truy cập tin nhắn Bluetooth (MAP) cho phép xe gửi và nhận tin nhắn SMS thông qua thiết bị từ xa được kết nối. Hiện tại, tin nhắn không được lưu trữ cục bộ trên IVI. Thay vào đó, bất cứ khi nào thiết bị từ xa được kết nối nhận được tin nhắn, IVI sẽ nhận và phân tích tin nhắn cũng như phát nội dung của nó trong một phiên bản Intent mà sau đó ứng dụng có thể nhận được.

Để kết nối với thiết bị di động nhằm mục đích gửi và nhận tin nhắn, IVI phải khởi tạo kết nối MAP. MAXIMUM_CONNECTED_DEVICES trong MapClientService xác định số lượng kết nối thiết bị MAP đồng thời tối đa được phép với IVI. Mỗi kết nối phải được IVI và thiết bị di động cho phép trước khi có thể chuyển tin nhắn.

Cấu hình phân phối âm thanh nâng cao

Cấu hình phân phối âm thanh nâng cao Bluetooth (A2DP) cho phép xe nhận luồng âm thanh từ thiết bị từ xa được kết nối.

Không giống như các cấu hình khác, số lượng thiết bị A2DP được kết nối tối đa được thực thi trong ngăn xếp gốc chứ không phải trong Java. Giá trị hiện được mã hóa cứng thành 1 bằng cách sử dụng biến kDefaultMaxConnectedAudioDevices trong packages/modules/Bluetooth/system/btif/src/btif_av.cc .

Cấu hình điều khiển từ xa âm thanh/video

Cấu hình điều khiển từ xa âm thanh/video Bluetooth (AVRCP) cho phép xe điều khiển và duyệt các trình phát đa phương tiện trên thiết bị từ xa được kết nối. Vì IVI đóng vai trò là bộ điều khiển AVRCP nên mọi điều khiển được kích hoạt ảnh hưởng đến việc phát lại âm thanh đều dựa vào kết nối A2DP với thiết bị đích.

Để IVI có thể duyệt một trình phát phương tiện cụ thể trên điện thoại Android qua AVRCP, ứng dụng phương tiện trên điện thoại phải cung cấp MediaBrowserService và cho phép truy cập com.android.bluetooth vào dịch vụ đó. Xây dựng dịch vụ trình duyệt phương tiện sẽ giải thích cách thực hiện việc này một cách chi tiết.