Bluetooth

Android cung cấp tính năng triển khai Bluetooth đầy đủ với khả năng hỗ trợ nhiều hồ sơ Bluetooth phổ biến trong ô tô. Ngoài ra, còn có nhiều tính năng nâng cao 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ì các thiết bị Bluetooth và danh sách ưu tiên của người dùng hiện tại cho mỗi 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 khiển bằng 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 về điện thoại

Ngăn xếp Bluetooth của Android duy trì chính sách kết nối cho các đ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ị để không xung đột với chính sách dành cho ô tô trong CarBluetoothService. Mặc dù lớp phủ sản phẩm Ô tô sẽ xử lý vấn đề 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 về ô tô

CarBluetoothService duy trì các quyền mặc định đối với hồ sơ. Danh sách 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 sẽ kết nối và ngắt kết nối với các thiết bị đã liên kết. Trình quản lý này cũng quản lý các trường hợp dành riêng cho ô tô về thời điểm bật và tắt bộ chuyển đổi.

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 mặc định dành cho ngành ô 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 đó để 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, 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 ô tô cụ thể.

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

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 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 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 ổn định 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. Bạn có thể thực hiện việc này theo 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 trình chuyển đổi. Một cách để thực hiện việc này là sử dụng trạng thái nguồn điệ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 việc 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 các thiết bị dựa trên danh sách mức độ ưu tiên được xác định cho từng hồ sơ Bluetooth.

Ví dụ về trường hợp bạn có thể muốn làm 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 đúng thiết bị theo thứ tự thích hợp. 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 kết quả 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 đã tạo chính sách dành cho ô 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 sẽ yêu cầu bạn 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 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 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 theo 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 đánh giá nào 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 cuộc gọi điện thoại qua một thiết bị từ xa đã 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 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 đ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 gọi, chẳng hạn như chấp nhận cuộc gọi hoặc cúp 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 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ị sẽ sử dụng khi gọi điện. 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 các chức năng đa thiết bị khác cũng 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. Sử dụng Bluetooth để kết nối một thiết bị với IVI và truyền trực tuyến â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 đ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 âm thanh phát trực tuyến tạm dừng và âm thanh điện thoại phát qua loa đã 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. Cả hai lần, hãy xác minh âm thanh phát trực tuyến tạm dừng và âm thanh điện thoại phát qua loa đã 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 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 rất quan trọng đối với sự an toàn, nhưng thiết bị này hiện chưa đượ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. Điều này cũng có lợi ích là giới thiệu các tuỳ 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 Xây dựng ứng dụng gọi điện.

Dưới đâ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 cho cuộc gọi khẩn cấp

Tính năng 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 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ố trong ô 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 có 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 số khẩn cấp.

Hồ sơ truy cập danh bạ

Cấu hình truy cập danh bạ qua Bluetooth (PBAP) sẽ tải danh bạ và nhật ký cuộc gọi xuống từ một thiết bị từ xa đã 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ằng máy trạng thái ứng dụng PBAP. Mỗi thiết bị đượ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 liên kết danh bạ 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 tạo bản sao các kết nối đến 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 PBAP lưu trữ danh bạ cho từng thiết bị được kết nối trong Trình cung cấp danh bạ. Sau đó, ứng dụng có thể truy cập vào ứng dụng này để lấy danh bạ điện thoại 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 hồ sơ để 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ả 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 thư

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

Để kết nối với một thiết bị di động nhằm mục đích gửi và nhận thông báo, IVI phải bắt đầu 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 uỷ quyền 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 (A2DP) của Bluetooth cho phép xe nhận các luồng âm thanh từ một thiết bị từ xa đã kết nối.

Không giống như các hồ sơ 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ị này hiện được mã hoá 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 kiểm soát và duyệt qua trình phát nội dung nghe nhìn trên thiết bị từ xa đã 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ị mục tiêu.

Để IVI có thể duyệt qua 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ụ đó. 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.