Bluetooth

Android cung cấp một bản triển khai Bluetooth đầy đủvới hỗ trợ nhiều cấu hình Bluetooth phổ biến trong ô tô. Ngoài ra, còn có nhiều điểm cải tiến giúp nâng cao 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ì các thiết bị Bluetooth và danh sách ưu tiên 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 cấu hình 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 một cấu hình được điều khiển bởi chính sách kết nối mặc định. Bạn có thể ghi đè chính sách này bằng cách sử dụng lớp phủ tài nguyên nếu muốn.

Định cấu hình tính năng quản lý kết nối ô tô

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

Ngăn xếp Bluetooth của Android duy trì một chính sách kết nối cho điện thoại được bật theo mặc định. Bạn phải tắt chính sách này trên thiết bị để chính sách này không xung đột với chính sách ô tô dự kiến trong CarBluetoothService. Mặc dù lớp phủ sản phẩm Ô tô sẽ xử lý việc này cho bạn, bạn có thể tắt chính sách cho đ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 mặc định của cấu hình. Danh sách các thiết bị đã biết và mức độ ưu tiên kết nối lại cấu hình của các thiết bị đó 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 mà Bluetooth sẽ kết nối và ngắt kết nối với các thiết bị đã liên kết. Chính sách này cũng quản lý các trường hợp cụ thể của ô tô khi bộ chuyển đổi cần được bật và tắt.

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

Nếu chính sách ô tô mặc định không đáp ứng đủ nhu cầu của bạn, thì bạn cũng có thể tắt chính sách này để sử dụng chính sách tuỳ chỉnh của riêng mình. Chính sách tuỳ chỉnh của bạn phải chịu trách nhiệm xác định thời điểm bật và tắt bộ chuyển đổi Bluetooth, cũng như thời điểm kết nối thiết bị. Bạn có thể sử dụng nhiều sự kiện để bật/tắt bộ chuyển đổi Bluetooth và bắt đầu kết nối thiết bị, bao gồm cả các sự kiện do thay đổi trong các thuộc tính cụ thể của ô tô.

Tắt chính sách ô tô mặc định

Trước tiên, để sử dụng chính sách tuỳ chỉnh, bạn phải tắt chính sách ô tô mặc định bằng cách đặt useDefaultBluetoothConnectionPolicy thành false trong một 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ộ chuyển đổi Bluetooth

Một trong những chức năng cốt lõi của chính sách là bật và tắt bộ chuyển đổi Bluetooth vào thời điểm thích hợp. Bạn có thể sử dụng các API khung BluetoothAdapter.enable()BluetoothAdapter.disable() để bật và tắt bộ chuyển đổi. Các lệnh gọi này phải tuân theo trạng thái được duy trì mà người dùng đã chọn thông qua phần Cài đặt hoặc bất kỳ phương tiện nào khác. Bạn có thể thực hiện việc này theo một trong những cách 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 tuỳ chỉnh, bạn có thể tự do xác định những sự kiện cho biết thời điểm tốt nhất để bật và tắt bộ chuyển đổi. Một trong những cách để thực hiện việc này là sử dụng các 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 quá trình bắt đầu kết nối thiết bị, CarBluetoothManager sẽ cung cấp lệnh gọi API connectDevices() đó tiến hành kết nối 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ộ chuyển đổi 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 tính năng 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 là bật Bluetooth trên IVI và xác thực rằng chính sách này tự động kết nối với các thiết bị chính xác theo đúng thứ tự. Bạn có thể bật/tắt bộ chuyển đổi 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, bạn có thể sử dụng kết quả của lệnh sau để 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 tuỳ chỉnh đều yêu cầu bạn phải 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. Các dịch vụ điện thoại Bluetooth nhiều thiết bị cho phép người dùng kết nối các thiết bị riêng biệt đồng thời, chẳng hạn như điện thoại cá nhân và điện thoại công việc, đồng thời thực hiện cuộc gọi rảnh tay từ một trong hai thiết bị.

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

Cấu hình rảnh tay

Cấu hình rảnh tay Bluetooth (HFP) cho phép xe thực hiện và nhận 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 các ứ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 tối đa kết nối HFP đồng thời.

Khi người dùng thực hiện hoặc nhận cuộc gọi điện thoạ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.

Xin 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 nhiều thiết bị, bạn cần tuỳ chỉnh để cho phép người dùng chọn tài khoản thiết bị cần sử dụng khi thực hiện cuộc gọi. Sau đó, ứng dụng sẽ gọi telecomManager.placeCall bằng tài khoản chính xác. Bạn cũng cần xác minh rằng các chức năng khác trên nhiều thiết bị hoạt động như dự kiến.

Xác minh HFP nhiều thiết bị

Cách kiểm tra để đảm bảo rằng tính năng kết nối nhiều thiết bị hoạt động đúng cách qua Bluetooth:

  1. Sử dụng Bluetooth, kết nối một thiết bị với IVI và truyền phát âm thanh từ thiết bị đó.
  2. Kết nối 2 điện thoại với IVI qua Bluetooth.
  3. Chọn một đ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. Trong cả hai lần, hãy xác minh rằng âm thanh được truyền phát sẽ tạm dừng và âm thanh điện thoại phát qua loa được kết nối vớ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. Trong cả hai lần, hãy xác minh rằng âm thanh được truyền phát sẽ tạm dừng và âm thanh điện thoại sẽ phát qua loa được kết nối vớ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 các chức năng điện thoại và Bluetooth trong ô tô. Có một số cách để 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 được 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

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

Mặc dù thiết bị eCall rất quan trọng đối với sự an toàn, nhưng thiết bị này hiện không được tích hợp vào Android. Bạn 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 mang lại lợi ích là giới thiệu các lựa chọn hỗ trợ tiếp cận cho cuộc gọi khẩn cấp. Để tìm hiểu thêm, hãy xem bài viết 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 cuộc gọi khẩn cấp

Trước Android 10, việc gọi khẩn cấp liên quan đến việc 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 thấy 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ể trực tiếp gọi một 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ư ứng dụng nhận dạng giọng nói, cũng có thể gọi một số khẩn cấp.

Cấu hình truy cập danh bạ

Cấu hình truy cập danh bạ Bluetooth (PBAP) tải danh bạ và nhật ký cuộc gọi xuống từ một thiết bị từ xa được kết nối. PBAP duy trì một danh sách tổng hợp, có thể tìm kiếm gồm các địa chỉ liên hệ được cập nhật bởi máy trạng thái ứng dụng PBAP. Mỗi thiết bị thông minh được kết nối tương tác với một máy trạng thái ứng dụng PBAP riêng biệt, dẫn đến việc các địa chỉ liên hệ được liên kết với thiết bị thích 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 mọi MAXIMUM_CONNECTED_DEVICES trong PbapClientService xác định số lượng tối đa kết nối thiết bị PBAP đồng thời được phép với IVI. Ứng dụng PBAP lưu trữ các địa chỉ liên hệ cho từng thiết bị thông minh được kết nối trong Trình cung cấp danh bạ. Sau đó, một ứng dụng có thể truy cập vào trình cung cấp này để lấy danh bạ cho từng thiết bị.

Ngoài ra, cả IVI và thiết bị di động đều phải cho phép kết nối cấu hình thì mới có thể kết nối. Khi ứng dụng PBAP ngắt kết nối, cơ sở dữ liệu nội bộ sẽ xoá tất cả địa chỉ liên hệ và nhật ký cuộc gọi được liên kết với thiết bị thông minh đã kết nối trước đó.

Cấu hình 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 một 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 nhận và phân tích tin nhắn, đồng thời truyền nội dung của tin nhắn đó trong một thực thể Ý định. Sau đó, một ứng dụng có thể nhận được thực thể này.

Để 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 bắt đầu kết nối MAP. MAXIMUM_CONNECTED_DEVICES trong MapClientService xác định số lượng tối đa kết nối thiết bị MAP đồng thời đượ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 thì mới 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ừ mộ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 tối đa thiết bị A2DP được kết nối sẽ được thực thi trong ngăn xếp gốc chứ không phải trong Java. Giá trị này hiện được mã hoá cứng thành 1 bằ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 trình phát nội dung đa phương tiện trên một 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 chế độ điều khiển được kích hoạt ảnh hưởng đến việc phát âm thanh đều dựa vào kết nối A2DP với thiết bị đích.

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