Bluetooth

‫Android מספקת הטמעה מלאה של Bluetoothעם תמיכה בפרופילים נפוצים רבים של Bluetooth ברכב. בנוסף, יש הרבה שיפורים שמשפרים את הביצועים ואת חוויית השימוש במכשירים ובשירותים אחרים.

ניהול חיבור Bluetooth

ב-Android, ‏ CarBluetoothService שומר את מכשירי ה-Bluetooth של המשתמש הנוכחי ואת רשימות העדיפות לכל חיבור פרופיל ל-IVI. המכשירים מחוברים לפרופילים לפי סדר עדיפות מוגדר. ההחלטה מתי להפעיל, להשבית ולחבר מכשירים לפרופיל מתבססת על מדיניות חיבור שמוגדרת כברירת מחדל, שאפשר לבטל אותה באמצעות שכבת משאבים, אם רוצים.

הגדרת ניהול חיבורים לרכב

השבתה של מדיניות ברירת המחדל לטלפון

מערכת Android Bluetooth שומרת על מדיניות חיבור לטלפונים שמופעלת כברירת מחדל. צריך להשבית את המדיניות הזו במכשיר כדי שלא תהיה התנגשות בינה לבין מדיניות הרכב המיועדת ב- 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, וגם מתי לחבר מכשירים. אפשר להשתמש במגוון אירועים כדי להפעיל או להשבית את מתאם ה-Bluetooth וכדי ליזום חיבורים למכשיר, כולל אירועים שנובעים משינויים במאפיינים ספציפיים של הרכב.

השבתת מדיניות ברירת המחדל לרכב

קודם כל, כדי להשתמש במדיניות מותאמת אישית, צריך להשבית את מדיניות ברירת המחדל לרכב על ידי הגדרת useDefaultBluetoothConnectionPolicy ל-false ב שכבת משאבים. המשאב הזה מוגדר במקור כחלק מ-MAXIMUM_CONNECTED_DEVICES ב- packages/services/Car/service/res/values/config.xml.

הפעלה והשבתה של מתאם Bluetooth

אחת מהפונקציות העיקריות של המדיניות היא להפעיל ולהשבית את מתאם ה-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 דרך ממשק המשתמש של ההגדרות, או באמצעות הפקודות הבאות של 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 לא קובע הגבלות נוספות על המספר המקסימלי של מכשירים מחוברים שמותרים.

פרופיל לדיבורית

פרופיל הדיבורית (HFP) של Bluetooth מאפשר לרכב לבצע ולקבל שיחות טלפון באמצעות מכשיר מרוחק מחובר. כל חיבור של מכשיר רושם חשבון טלפון נפרד ב- TelecomManager, שמפרסם את כל חשבונות הטלפון הזמינים לאפליקציות IVI.

מערכת ה-IVI יכולה להתחבר לכמה מכשירים באמצעות HFP. MAX_STATE_MACHINES_POSSIBLE MAXIMUM_CONNECTED_DEVICES ב- HeadsetClientService מגדיר את המספר המקסימלי של חיבורי HFP בו-זמניים.

כשמשתמש מתקשר או מקבל שיחה במכשיר, נוצר אובייקט HfpClientConnection בחשבון הטלפון המתאים. אפליקציית חייגן יוצרת אינטראקציה עם האובייקט HfpClientConnection כדי לנהל תכונות של שיחות, כמו מענה לשיחה או ניתוק השיחה.

חשוב לציין שאפליקציית חייגן ברירת המחדל לא תומכת במספר מכשירי HFP שמחוברים בו-זמנית. כדי להטמיע HFP בכמה מכשירים, צריך לבצע התאמה אישית כדי לאפשר למשתמשים לבחור באיזה חשבון במכשיר להשתמש כשהם מתקשרים. האפליקציה מתקשרת אל telecomManager.placeCall עם החשבון הנכון. צריך גם לוודא שפונקציות אחרות של שימוש בכמה מכשירים פועלות כמו שצריך.

אימות של HFP בכמה מכשירים

כדי לוודא שהקישור בין כמה מכשירים פועל בצורה תקינה באמצעות Bluetooth:

  1. באמצעות Bluetooth, מחברים מכשיר למערכת המידע והבידור ומפעילים סטרימינג של אודיו מהמכשיר.
  2. מחברים שני טלפונים למערכת המידע והבידור באמצעות Bluetooth.
  3. בוחרים טלפון אחד. להתקשר ישירות מהטלפון, ולהתקשר באמצעות מערכת המידע והבידור.
    1. בשני המקרים, מוודאים שההזרמה של האודיו מושהית והאודיו של הטלפון מושמע ברמקולים המחוברים של מערכת ה-IVI.
  4. באותו טלפון, מקבלים שיחה נכנסת ישירות בטלפון, וגם מקבלים שיחה נכנסת באמצעות מערכת המידע והבידור.
    1. בשני המקרים, מוודאים שהסטרימינג של האודיו מושהה והאודיו של הטלפון מושמע ברמקולים המחוברים של מערכת ה-IVI.
  5. חוזרים על שלבים 3 ו-4 עם הטלפון המחובר השני.

שיחות חירום

היכולת להתקשר לשירותי חירום היא היבט חשוב של פונקציות הטלפוניה וה-Bluetooth ברכב. יש כמה דרכים ליזום שיחת חירום ממערכת IVI, כולל:

  • פתרון עצמאי של eCall
  • פתרון eCall משולב במערכת IVI
  • להסתמך על טלפון שמחובר באמצעות Bluetooth כשאין מערכת מובנית זמינה

חיבור שיחת חירום

ציוד לשיחות חירום אוטומטיות הוא קריטי לבטיחות, אבל הוא לא משולב כרגע ב-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);
    }
}

הפעלת Bluetooth לשיחות חירום

כדי להתקשר לשירותי חירום בגרסאות Android 9 ומטה, צריך לחייג ישירות מהטלפון ולהפעיל ציוד מיוחד אם הוא זמין (לדוגמה, הפעלה אוטומטית כשמזוהה סכנה או פעולת משתמש). ב-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) ב-Bluetooth מוריד אנשי קשר והיסטוריית שיחות ממכשיר מרוחק מחובר. פרופיל PBAP שומר רשימה מצטברת של אנשי קשר שאפשר לחפש בה, והיא מתעדכנת על ידי מכונת המצבים של לקוח PBAP. כל מכשיר מחובר מקיים אינטראקציה עם מכונת מצבים נפרדת של לקוח PBAP, וכתוצאה מכך אנשי הקשר משויכים למכשיר המתאים כשמבצעים שיחה.

פרופיל PBAP הוא חד-כיווני, ולכן מערכת ה-IVI צריכה ליצור מופעים של חיבורים לכל MAXIMUM_CONNECTED_DEVICES ב- PbapClientService. הפרופיל מגדיר את המספר המקסימלי של חיבורי מכשיר PBAP בו-זמניים שמותרים במערכת ה-IVI. לקוח PBAP מאחסן את אנשי הקשר של כל מכשיר מחובר ב ספק אנשי הקשר, שאפליקציה יכולה לגשת אליו כדי ליצור את ספר הטלפונים של כל מכשיר.

בנוסף, כדי ליצור חיבור, גם מערכת ה-IVI וגם המכשיר הנייד צריכים לאשר את חיבור הפרופיל. כשלקוח PBAP מתנתק, מסד הנתונים הפנימי מסיר את כל אנשי הקשר ואת היסטוריית השיחות שמשויכים למכשיר שהיה מחובר קודם.

פרופיל גישה להודעות

פרופיל הגישה להודעות (MAP) של Bluetooth מאפשר לרכב לשלוח ולקבל הודעות SMS באמצעות מכשיר מרוחק מחובר. בשלב הזה, ההודעות לא מאוחסנות באופן מקומי במערכת המידע והבידור. במקום זאת, בכל פעם שמכשיר מרוחק מחובר מקבל הודעה, מערכת ה-IVI מקבלת את ההודעה, מנתחת אותה ומשדרת את התוכן שלה במופע Intent, שאפליקציה יכולה לקבל.

כדי להתחבר למכשיר נייד לצורך שליחה וקבלה של הודעות, מערכת ה-IVI צריכה ליזום את חיבור ה-MAP. ‫MAXIMUM_CONNECTED_DEVICES ב- MapClientService מגדיר את המספר המקסימלי של חיבורים בו-זמניים של מכשיר MAP שמותרים עם מערכת ה-IVI. לפני העברת ההודעות, צריך לקבל אישור לכל חיבור ממערכת ה-IVI ומהמכשיר הנייד.

Advanced Audio Distribution Profile

פרופיל מתקדם להפצת אודיו (A2DP) ב-Bluetooth מאפשר לרכב לקבל זרמי אודיו ממכשיר מרוחק מחובר.

בניגוד לפרופילים אחרים, המספר המקסימלי של מכשירי A2DP שמחוברים נאכף במערך המקורי ולא ב-Java. הערך מוטמע כרגע בקידוד 1 באמצעות המשתנה kDefaultMaxConnectedAudioDevices ב- packages/modules/Bluetooth/system/btif/src/btif_av.cc.

Audio/video Remote Control Profile

פרופיל השלט הרחוק לאודיו/וידאו (AVRCP) של Bluetooth מאפשר לרכב לשלוט בנגני מדיה במכשיר מרוחק מחובר ולעיין בהם. מערכת ה-IVI פועלת כבקר AVRCP, ולכן כל אמצעי בקרה שמופעלים ומשפיעים על הפעלת האודיו מסתמכים על חיבור A2DP למכשיר היעד.

כדי שאפשר יהיה לעיין בנגן מדיה ספציפי בטלפון Android באמצעות AVRCP דרך מערכת IVI, אפליקציית המדיה בטלפון צריכה לספק MediaBrowserService ולאפשר גישה של com.android.bluetooth לשירות הזה. במאמר בנושא יצירת שירות לדפדוף במדיה מוסבר איך עושים את זה בפירוט.