Bluetooth

Android cung cấp một chế độ triển khai Bluetooth đầy đủ với khả năng 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 hồ sơ 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 một hồ sơ được điều chỉnh theo 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 trên ô tô

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

Ngăn xếp Bluetooth 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 dự kiến dành cho ô tô trong CarBluetoothService. Mặc dù lớp phủ Sản phẩm ô tô sẽ xử lý việc này cho bạn, nhưng bạn có thể tắt chính sách về đ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 mặc định cho ô tô

CarBluetoothService duy trì các quyền mặc định đối với hồ sơ. 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 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 Bluetooth nên kết nối và ngắt kết nối với các thiết bị đã liên kết. Ngoài ra, lớp này còn 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 tuỳ chỉnh của riêng bạn cho ô tô

Nếu chính sách mặc định về ô tô không đáp ứng được nhu cầu của bạn, 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, tối thiểu, 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 các 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 những thay đổi về các thuộc tính cụ thể của ô tô.

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

Trước tiên, để sử dụng một chính sách tuỳ chỉnh, bạn phải tắt chính sách mặc định về ô tô 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ể 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 tôn trọng 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 thức nào khác. Sau đây là một cách để thực hiện việc này:

/**
 * 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 thích hợp nhất để bật và tắt bộ chuyển đổi. Một 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 những sự kiện sẽ kích hoạt các kết nối thiết bị để bắt đầu, CarBluetoothManager sẽ cung cấp lệnh gọi API connectDevices(). Lệnh gọi này sẽ 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 hồ sơ Bluetooth.

Một ví dụ về trường hợp 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 hoạt động quản lý kết nối trên ô 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 IVI tự động kết nối với các thiết bị phù hợp 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ể dùng đầu ra của lệnh sau để xem thông tin gỡ lỗi liên quan đến các 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 riêng về ô tô, 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 kiểm soát những sự kiện mà bạn đã chọn để kích hoạt các kết nối thiết bị.

Cấu hình Bluetooth cho ô tô

Trong Android, IVI có thể hỗ trợ nhiều thiết bị kết nối đồng thời qua Bluetooth. Dịch vụ điện thoại Bluetooth trên nhiều 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ô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ị.

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

Hồ sơ rảnh tay

Cấu hình rảnh tay (HFP) của Bluetooth 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 biệt với TelecomManager, tài khoản này sẽ thông bá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 các 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 trên 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 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 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ị, 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 dùng khi gọi điện. 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 trên nhiều thiết bị

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

  1. Kết nối một thiết bị với IVI bằng Bluetooth và phát trực tuyến âm thanh từ thiết bị đó.
  2. Kết nối 2 điện thoại với hệ thống 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. Trong cả hai lần, hãy xác minh rằng âm thanh phát trực tuyến tạm dừng và âm thanh trên đ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 phát trực tiếp tạm dừng và âm thanh điện thoại 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 đã kết nối còn lại.

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 đã 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 là thiết bị quan trọng đối với sự an toàn, nhưng hiện tại thiết bị này chưa được tích hợp vào Android. Bạn có thể dùng ConnectionService để cung cấp các tính năng gọi khẩn cấp thông qua Android. Điều 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 phần Tạo ứng dụng gọi điện.

Sau đây là ví dụ về cách thiết lập một 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 để thực hiện cuộc gọi khẩn cấp

Việc gọi khẩn cấp trước Android 10 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). Trên Android 10 trở lên, Trình quay số trên ô tô có thể gọi trực tiếp đến số điện thoại 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.

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

Cấu hình truy cập danh bạ qua 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 được gồm các địa chỉ liên hệ do máy trạng thái của ứng dụng PBAP cập nhật. Mỗi thiết bị được kết nối tương tác với một máy trạng thái riêng của ứng dụng PBAP, dẫn đến việc danh bạ đượ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 đó, IVI phải khởi tạo các kết nối với mọi MAXIMUM_CONNECTED_DEVICES trong PbapClientService xác định số lượng tối đa các kết nối đồng thời của thiết bị PBAP được phép với IVI. Ứng dụng PBAP lưu trữ danh bạ của từng thiết bị được kết nối trong Contacts Provider (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ạ của 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 hồ sơ thì mới có thể kết nối. Khi một ứng dụng PBAP ngắt kết nối, cơ sở dữ liệu nội bộ sẽ xoá tất cả danh bạ và nhật ký cuộc gọi 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 (MAP) qua Bluetooth 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, các 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 một thông báo, IVI sẽ nhận và phân tích thông báo đó, đồng thời phát nội dung của thông báo trong một thực thể Intent. Sau đó, một ứng dụng có thể nhận được thông báo 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 các kết nối đồng thời của thiết bị MAP được phép với IVI. IVI và thiết bị di động phải cho phép từng kết nối thì mới có thể truyề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 (A2DP) của Bluetooth cho phép xe nhận các 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 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ã 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 (AVRCP) qua Bluetooth cho phép xe điều khiển và duyệt trình phát nội dung nghe nhìn trên một thiết bị từ xa được kết nối. Vì IVI đóng vai trò là một 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ị mục tiêu.

Để IVI có thể duyệt một trình phát nội dung nghe nhìn cụ thể trên điện thoại Android thông qua AVRCP, ứng dụng đ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ụ đó. 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.