บลูทูธ

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

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

ใน Android CarBluetoothService จะดูแลอุปกรณ์บลูทูธและรายการลำดับความสำคัญของ ผู้ใช้ปัจจุบันสำหรับการเชื่อมต่อโปรไฟล์แต่ละรายการกับ 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

นอกจากนี้ คุณยังดูนโยบายการจัดการการเชื่อมต่อบลูทูธได้ใน service/src/com/android/car/BluetoothDeviceConnectionPolicy.java โดยค่าเริ่มต้น นโยบายนี้จะกำหนดอินสแตนซ์เมื่อบลูทูธควรเชื่อมต่อและยกเลิกการเชื่อมต่อกับอุปกรณ์ที่จับคู่ นอกจากนี้ ยังจัดการกรณีเฉพาะของรถยนต์เมื่อควรเปิดและปิดอะแดปเตอร์ด้วย

สร้างนโยบายการจัดการการเชื่อมต่อยานยนต์ที่กำหนดเอง

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

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

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

เปิดและปิดใช้งานอะแดปเตอร์บลูทูธ

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

กำหนดเวลาเปิดและปิดอะแดปเตอร์บลูทูธ

นโยบายที่กำหนดเองช่วยให้คุณกำหนดได้อย่างอิสระว่าเหตุการณ์ใดที่บ่งบอกถึงช่วงเวลาที่ดีที่สุดในการ เปิดและปิดใช้อะแดปเตอร์ วิธีหนึ่งในการทำเช่นนี้คือการใช้สถานะพลังงาน 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 จะให้connectDevices()การเรียก API ที่ ดำเนินการต่อเพื่อเชื่อมต่ออุปกรณ์ตามรายการลำดับความสำคัญที่กำหนดไว้สำหรับโปรไฟล์บลูทูธแต่ละรายการ

ตัวอย่างกรณีที่คุณอาจต้องการทำเช่นนี้คือเมื่อใดก็ตามที่อะแดปเตอร์บลูทูธเปิดอยู่

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

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

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

นอกจากนี้ คุณยังใช้เอาต์พุตของคำสั่งต่อไปนี้เพื่อดูข้อมูลการแก้ไขข้อบกพร่อง ที่เกี่ยวข้องกับการเชื่อมต่อบลูทูธได้ด้วย

adb shell dumpsys car_service

สุดท้าย หากคุณสร้างนโยบายยานยนต์ของคุณเอง การยืนยันลักษณะการเชื่อมต่อที่กำหนดเอง ต้องควบคุมเหตุการณ์ที่คุณเลือกเพื่อทริกเกอร์การเชื่อมต่ออุปกรณ์

โปรไฟล์บลูทูธสำหรับยานยนต์

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

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

Hands-Free Profile

โปรไฟล์แฮนด์ฟรีบลูทูธ (HFP) ช่วยให้ยานพาหนะโทรออกและรับสาย โทรศัพท์ผ่านอุปกรณ์ระยะไกลที่เชื่อมต่อได้ การเชื่อมต่ออุปกรณ์แต่ละครั้งจะลงทะเบียนบัญชีโทรศัพท์แยกต่างหากกับ TelecomManager ซึ่งจะโฆษณาบัญชีโทรศัพท์ที่มีอยู่ให้กับแอป IVI

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

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

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

ยืนยัน HFP แบบหลายอุปกรณ์

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

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

การโทรหาหมายเลขฉุกเฉิน

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

  • โซลูชัน eCall แบบสแตนด์อโลน
  • โซลูชัน eCall ที่ผสานรวมเข้ากับ IVI
  • การใช้โทรศัพท์ที่เชื่อมต่อบลูทูธเมื่อไม่มีระบบในตัว

ต่อสายการโทรฉุกเฉิน

แม้ว่าอุปกรณ์ 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>

การใช้การโทรฉุกเฉินในลักษณะนี้จะช่วยให้แอปอื่นๆ เช่น การจดจำเสียง สามารถโทรไปยังหมายเลขฉุกเฉินได้ด้วย

โปรไฟล์การเข้าถึงสมุดโทรศัพท์

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

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

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

Message Access Profile

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

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

Advanced Audio Distribution Profile

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

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

Audio/video Remote Control Profile

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

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