บลูทูธ

Android นำเสนอ การใช้งาน Bluetooth เต็มรูปแบบ พร้อมรองรับโปรไฟล์ Bluetooth ในรถยนต์ทั่วไปหลายโปรไฟล์ นอกจากนี้ยังมีการปรับปรุงมากมายที่ช่วยปรับปรุงประสิทธิภาพและประสบการณ์การใช้งานกับอุปกรณ์และบริการอื่นๆ

การจัดการการเชื่อมต่อบลูทูธ

ภายใน Android CarBluetoothService จะรักษาอุปกรณ์ Bluetooth ของผู้ใช้ปัจจุบันและรายการลำดับความสำคัญสำหรับการเชื่อมต่อแต่ละโปรไฟล์กับ IVI อุปกรณ์เชื่อมต่อกับส่วนกำหนดค่าตามลำดับความสำคัญที่กำหนด เมื่อใดที่ควรเปิดใช้งาน ปิดใช้งาน และเชื่อมต่ออุปกรณ์กับโปรไฟล์จะขับเคลื่อนโดยนโยบายการเชื่อมต่อเริ่มต้นที่สามารถแทนที่ได้ด้วยการใช้ การซ้อนทับทรัพยากร หากต้องการ

กำหนดค่าการจัดการการเชื่อมต่อยานยนต์

ปิดใช้งานนโยบายโทรศัพท์เริ่มต้น

สแตกบลูทูธของ Android จะรักษานโยบายการเชื่อมต่อสำหรับโทรศัพท์ที่เปิดใช้งานตามค่าเริ่มต้น จะต้องปิดการใช้งานนโยบายนี้บนอุปกรณ์ของคุณเพื่อไม่ให้ขัดแย้งกับนโยบายด้านยานยนต์ที่ต้องการใน CarBluetoothService แม้ว่าการซ้อนทับผลิตภัณฑ์ Car ควรดูแลเรื่องนี้ให้กับคุณ คุณสามารถปิดใช้งานนโยบายโทรศัพท์ใน การซ้อนทับทรัพยากรได้ โดยตั้ง enable_phone_policy เป็น false ใน MAXIMUM_CONNECTED_DEVICES ใน /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 และเพื่อเริ่มต้นการเชื่อมต่ออุปกรณ์ รวมถึงเหตุการณ์ที่เกิดจากการเปลี่ยนแปลงคุณสมบัติเฉพาะของรถ

ปิดการใช้งานนโยบายยานยนต์เริ่มต้น

ขั้นแรก หากต้องการใช้นโยบายที่กำหนดเอง จะต้องปิดใช้งานนโยบายยานยนต์เริ่มต้นโดยตั้งค่า useDefaultBluetoothConnectionPolicy เป็น false ใน ทรัพยากรซ้อนทับ รีซอร์สนี้เดิมถูกกำหนดให้เป็นส่วนหนึ่งของ MAXIMUM_CONNECTED_DEVICES ใน packages/services/Car/service/res/values/config.xml

เปิดใช้งานและปิดใช้งานอะแดปเตอร์ 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 does nothing if the adapter
    // is already off, keeping the existing saved desired state for next reboot.
    bluetoothAdapter.disable(false);
}

กำหนดเวลาเปิดและปิดอะแดปเตอร์ Bluetooth

ด้วยนโยบายที่กำหนดเองของคุณ คุณจะมีอิสระในการพิจารณาว่าเหตุการณ์ใดระบุเวลาที่ดีที่สุดในการเปิดใช้งานและปิดใช้งานอะแดปเตอร์ วิธีหนึ่งในการทำเช่นนี้คือการใช้สถานะพลังงาน MAXIMUM_CONNECTED_DEVICES ใน 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;
        }
    }
};

กำหนดเวลาที่จะเชื่อมต่ออุปกรณ์

ในทำนองเดียวกัน เมื่อคุณกำหนดเหตุการณ์ที่ควรทริกเกอร์การเชื่อมต่ออุปกรณ์เพื่อเริ่มต้น 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 app's context
                Car car = Car.createCar(mContext);
                CarBluetoothManager carBluetoothManager =
                        (CarBluetoothManager) car.getCarManager(Car.BLUETOOTH_SERVICE);
                carBluetoothManager.connectDevices();
            }
        }
    }
}

ตรวจสอบการจัดการการเชื่อมต่อยานยนต์

วิธีที่ง่ายที่สุดในการตรวจสอบพฤติกรรมของนโยบายการเชื่อมต่อของคุณคือการเปิดใช้งาน Bluetooth บน IVI ของคุณ และตรวจสอบว่าบลูทูธเชื่อมต่อกับอุปกรณ์ที่ถูกต้องตามลำดับที่เหมาะสมโดยอัตโนมัติ คุณสามารถสลับอะแดปเตอร์ Bluetooth ผ่าน UI การตั้งค่า หรือด้วยคำสั่ง 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 (HFP) ช่วยให้รถสามารถโทรออกและรับสายโทรศัพท์ผ่านอุปกรณ์ระยะไกลที่เชื่อมต่อได้ การเชื่อมต่ออุปกรณ์แต่ละรายการจะลงทะเบียนบัญชีโทรศัพท์แยกต่างหากกับ TelecomManager ซึ่งจะโฆษณาบัญชีโทรศัพท์ใดๆ ที่มีอยู่ไปยังแอป IVI

IVI สามารถเชื่อมต่อกับอุปกรณ์หลายเครื่องผ่าน HFP MAX_STATE_MACHINES_POSSIBLE MAXIMUM_CONNECTED_DEVICES ใน HeadsetClientService กำหนดจำนวนสูงสุดของการเชื่อมต่อ HFP พร้อมกัน

เมื่อผู้ใช้โทรออกหรือรับสายจากอุปกรณ์ บัญชีโทรศัพท์ที่เกี่ยวข้องจะสร้างออบเจ็กต์ HfpClientConnection แอป Dialer โต้ตอบกับออบเจ็กต์ HfpClientConnection เพื่อจัดการคุณสมบัติการโทร เช่น การรับสายหรือการวางสาย

ควรสังเกตว่าแอป Dialer เริ่มต้นไม่รองรับอุปกรณ์ HFP ที่เชื่อมต่อพร้อมกันหลายเครื่อง เพื่อใช้งาน HFP แบบหลายอุปกรณ์ จำเป็นต้องมีการปรับแต่งเพื่อให้ผู้ใช้เลือกบัญชีอุปกรณ์ที่จะใช้เมื่อทำการโทร จากนั้นแอปจะเรียก telecomManager.placeCall ด้วยบัญชีที่ถูกต้อง คุณต้องตรวจสอบว่าฟังก์ชันการทำงานหลายอุปกรณ์อื่นๆ ทำงานตามที่ตั้งใจไว้เช่นกัน

ตรวจสอบ HFP หลายอุปกรณ์

วิธีตรวจสอบว่าการเชื่อมต่อหลายอุปกรณ์ทำงานอย่างถูกต้องผ่าน Bluetooth:

  1. ใช้บลูทูธ เชื่อมต่ออุปกรณ์กับ IVI และสตรีมเสียงจากอุปกรณ์
  2. เชื่อมต่อโทรศัพท์สองเครื่องเข้ากับ IVI ผ่าน Bluetooth
  3. เลือกโทรศัพท์หนึ่งเครื่อง โทรออกโดยตรงจากโทรศัพท์ และโทรออกโดยใช้ IVI
    1. ทั้งสองครั้ง ให้ตรวจสอบการหยุดชั่วคราวของเสียงที่สตรีมและเสียงของโทรศัพท์เล่นผ่านลำโพงที่เชื่อมต่อด้วย IVI
  4. ใช้โทรศัพท์เครื่องเดียวกัน รับสายเรียกเข้าทางโทรศัพท์โดยตรง และรับสายเรียกเข้าโดยใช้ IVI
    1. ทั้งสองครั้ง ให้ตรวจสอบว่าการสตรีมเสียงหยุดชั่วคราวและเสียงของโทรศัพท์เล่นผ่านลำโพงที่เชื่อมต่อ IVI
  5. ทำซ้ำขั้นตอนที่ 3 และ 4 กับโทรศัพท์เครื่องอื่นที่เชื่อมต่ออยู่

โทรฉุกเฉิน

ความสามารถในการโทรฉุกเฉินเป็นส่วนสำคัญของฟังก์ชันโทรศัพท์และบลูทูธในรถยนต์ มีหลายวิธีในการโทรฉุกเฉินจาก IVI ได้แก่:

  • โซลูชัน eCall แบบสแตนด์อโลน
  • โซลูชัน 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.registerPhoneAccount(account);
        mTelecomManager.enablePhoneAccount(account.getAccountHandle(), true);
    }
}

เปิดใช้งานบลูทูธสำหรับการโทรฉุกเฉิน

การโทรหาหมายเลขฉุกเฉินก่อน Android 10 เกี่ยวข้องกับการโทรโดยตรงจากโทรศัพท์และเรียกใช้อุปกรณ์พิเศษ หากมี (เช่น ทริกเกอร์อัตโนมัติเมื่อตรวจพบอันตรายหรือการกระทำของผู้ใช้) ใน Android 10 ขึ้นไป ตัวเรียกเลขหมายในรถยนต์สามารถโทรไปยังหมายเลขฉุกเฉินได้โดยตรง โดยมีเงื่อนไข MAXIMUM_CONNECTED_DEVICES นี้ใน 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_CONNECTED_DEVICES ใดๆ ใน PbapClientService กำหนดจำนวนสูงสุดของการเชื่อมต่ออุปกรณ์ PBAP พร้อมกันที่อนุญาตกับ IVI ไคลเอ็นต์ PBAP จะจัดเก็บรายชื่อติดต่อสำหรับอุปกรณ์แต่ละเครื่องที่เชื่อมต่อไว้ใน ผู้ให้บริการรายชื่อติดต่อ ซึ่งจากนั้นแอปจะสามารถเข้าถึงได้ เพื่อรับสมุดโทรศัพท์สำหรับแต่ละอุปกรณ์

นอกจากนี้ การเชื่อมต่อโปรไฟล์ต้องได้รับอนุญาตจากทั้ง IVI และอุปกรณ์มือถือจึงจะทำการเชื่อมต่อได้ เมื่อไคลเอนต์ PBAP ยกเลิกการเชื่อมต่อ ฐานข้อมูลภายในจะลบผู้ติดต่อและประวัติการโทรทั้งหมดที่เกี่ยวข้องกับอุปกรณ์ที่เชื่อมต่อก่อนหน้านี้

โปรไฟล์การเข้าถึงข้อความ

โปรไฟล์การเข้าถึงข้อความ Bluetooth (MAP) ช่วยให้รถสามารถส่งและรับข้อความ SMS ผ่านอุปกรณ์ระยะไกลที่เชื่อมต่อได้ ในปัจจุบัน ข้อความจะไม่ถูกจัดเก็บไว้ใน IVI เมื่อใดก็ตามที่อุปกรณ์ระยะไกลที่เชื่อมต่อได้รับข้อความ IVI จะได้รับและแยกวิเคราะห์ข้อความและเผยแพร่เนื้อหาในอินสแตนซ์ Intent ซึ่งแอปสามารถรับได้

ในการเชื่อมต่อกับอุปกรณ์เคลื่อนที่เพื่อวัตถุประสงค์ในการส่งและรับข้อความ IVI จะต้องเริ่มต้นการเชื่อมต่อ MAP MAXIMUM_CONNECTED_DEVICES ใน MapClientService กำหนดจำนวนสูงสุดของการเชื่อมต่ออุปกรณ์ MAP พร้อมกันที่อนุญาตกับ IVI การเชื่อมต่อแต่ละครั้งจะต้องได้รับอนุญาตจาก IVI และอุปกรณ์มือถือก่อนจึงจะสามารถถ่ายโอนข้อความได้

โปรไฟล์การกระจายเสียงขั้นสูง

โปรไฟล์การกระจายเสียงขั้นสูง Bluetooth (A2DP) ช่วยให้รถสามารถรับสตรีมเสียงจากอุปกรณ์ระยะไกลที่เชื่อมต่อได้

ไม่เหมือนกับโปรไฟล์อื่นๆ จำนวนสูงสุดของอุปกรณ์ A2DP ที่เชื่อมต่อจะบังคับใช้ในเนทีฟสแต็ก ไม่ใช่ใน Java ขณะนี้ค่าได้รับการฮาร์ดโค้ดเป็น 1 โดยใช้ตัวแปร kDefaultMaxConnectedAudioDevices ใน packages/modules/Bluetooth/system/btif/src/btif_av.cc

โปรไฟล์การควบคุมระยะไกลเสียง/วิดีโอ

โปรไฟล์การควบคุมระยะไกลเสียง/วิดีโอ Bluetooth (AVRCP) ช่วยให้รถสามารถควบคุมและเรียกดูเครื่องเล่นมีเดียบนอุปกรณ์ระยะไกลที่เชื่อมต่อได้ เนื่องจาก IVI มีบทบาทเป็นตัวควบคุม AVRCP การควบคุมที่ทริกเกอร์ซึ่งส่งผลต่อการเล่นเสียงจึงต้องอาศัยการเชื่อมต่อ A2DP กับอุปกรณ์เป้าหมาย

เพื่อให้เครื่องเล่นสื่อเฉพาะบนโทรศัพท์ Android สามารถเรียกดูได้โดย IVI ผ่าน AVRCP แอปสื่อบนโทรศัพท์จะต้องจัดเตรียม MediaBrowserService และอนุญาตให้ com.android.bluetooth เข้าถึงบริการนั้น การสร้างบริการเบราว์เซอร์สื่อ จะอธิบายวิธีดำเนินการโดยละเอียด