بلوتوث

اندروید یک پیاده‌سازی کامل بلوتوث را با پشتیبانی از بسیاری از پروفایل‌های بلوتوث رایج در خودرو ارائه می‌کند. همچنین پیشرفت های زیادی وجود دارد که عملکرد و تجربه را با دستگاه ها و خدمات دیگر بهبود می بخشد.

مدیریت اتصال بلوتوث

در Android، CarBluetoothService دستگاه‌های بلوتوث کاربر فعلی و لیست‌های اولویت را برای هر اتصال نمایه به IVI حفظ می‌کند. دستگاه ها با یک اولویت مشخص به پروفایل ها متصل می شوند. زمان فعال کردن، غیرفعال کردن و اتصال دستگاه‌ها به یک نمایه توسط یک خط‌مشی اتصال پیش‌فرض هدایت می‌شود که در صورت تمایل می‌توان با استفاده از یک پوشش منبع لغو شود.

پیکربندی مدیریت اتصال خودرو

خط مشی پیش فرض تلفن را غیرفعال کنید

پشته بلوتوث Android یک خط مشی اتصال را برای تلفن ها حفظ می کند که به طور پیش فرض فعال است. این خط‌مشی باید در دستگاه شما غیرفعال شود تا با خط‌مشی خودرو مورد نظر در CarBluetoothService مغایرت نداشته باشد. در حالی که پوشش محصول خودرو باید از این موضوع برای شما مراقبت کند، می‌توانید با تنظیم 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 فراخوانی API connectDevices() را ارائه می دهد که بر اساس لیست های اولویت تعریف شده برای هر نمایه بلوتوث به اتصال دستگاه ها ادامه می دهد.

یکی از مواردی که ممکن است بخواهید این کار را انجام دهید، زمانی است که آداپتور بلوتوث روشن می شود:

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

در نهایت، اگر خط‌مشی خودرویی خود را ایجاد کرده‌اید، تأیید هرگونه رفتار اتصال سفارشی مستلزم کنترل رویدادهایی است که برای راه‌اندازی اتصالات دستگاه انتخاب کرده‌اید.

پروفایل های بلوتوث خودرو

در اندروید، IVI می تواند چندین دستگاه را که به طور همزمان از طریق بلوتوث متصل هستند پشتیبانی کند. خدمات تلفن بلوتوث چند دستگاهی به کاربران این امکان را می‌دهد که به طور همزمان دستگاه‌های جداگانه‌ای مانند تلفن شخصی و تلفن محل کار را متصل کرده و از هر دستگاه به صورت هندزفری تماس بگیرند.

محدودیت‌های اتصال توسط هر پروفایل بلوتوث جداگانه اعمال می‌شود، معمولاً در اجرای خود سرویس نمایه. به طور پیش فرض، CarBluetoothService هیچ قضاوت دیگری در مورد حداکثر تعداد مجاز دستگاه های متصل انجام نمی دهد.

نمایه هندزفری

نمایه هندزفری بلوتوث (HFP) به وسیله نقلیه امکان برقراری و دریافت تماس های تلفنی از طریق یک دستگاه از راه دور متصل را می دهد. هر اتصال دستگاه یک حساب تلفن جداگانه را با TelecomManager ثبت می کند، که هر حساب تلفن موجود را در برنامه های IVI تبلیغ می کند.

IVI می تواند از طریق HFP به چندین دستگاه متصل شود. MAX_STATE_MACHINES_POSSIBLE MAXIMUM_CONNECTED_DEVICES در HeadsetClientService حداکثر تعداد اتصالات HFP همزمان را تعیین می کند.

هنگامی که یک کاربر از یک دستگاه تماس تلفنی برقرار می کند یا دریافت می کند، حساب تلفن مربوطه یک شی HfpClientConnection ایجاد می کند. برنامه Dialer با شی HfpClientConnection تعامل می کند تا ویژگی های تماس را مدیریت کند، مانند پذیرش تماس یا قطع کردن تماس.

لازم به ذکر است که برنامه پیش‌فرض Dialer از چندین دستگاه HFP متصل به‌طور همزمان پشتیبانی نمی‌کند. به منظور اجرای HFP چند دستگاهی، سفارشی‌سازی لازم است تا به کاربران اجازه دهد هنگام برقراری تماس از کدام حساب دستگاه استفاده کنند. سپس برنامه با حساب درست با telecomManager.placeCall تماس می گیرد. باید تأیید کنید که سایر عملکردهای چند دستگاهی نیز همانطور که در نظر گرفته شده است کار می کنند.

بررسی HFP چند دستگاهی

برای بررسی اینکه اتصال چند دستگاه به درستی از طریق بلوتوث کار می کند:

  1. با استفاده از بلوتوث، یک دستگاه را به IVI متصل کنید و صدا را از دستگاه پخش کنید.
  2. دو گوشی را از طریق بلوتوث به IVI وصل کنید.
  3. یک گوشی انتخاب کنید تماس خروجی را مستقیماً از تلفن برقرار کنید و با استفاده از IVI یک تماس خروجی برقرار کنید.
    1. هر دو بار، بررسی کنید که صدای پخش شده متوقف شود و صدای تلفن از طریق بلندگوهای متصل IVI پخش شود.
  4. با استفاده از همان تلفن، تماس ورودی را مستقیماً روی تلفن دریافت کنید و تماس ورودی را با استفاده از IVI دریافت کنید.
    1. هر دو بار، بررسی کنید که جریان صدای مکث می کند و صدای تلفن از طریق بلندگوهای متصل IVI پخش می شود.
  5. مراحل 3 و 4 را با تلفن متصل دیگر تکرار کنید.

تماس اضطراری

توانایی برقراری تماس های اضطراری جنبه مهمی از عملکردهای تلفن و بلوتوث در خودرو است. راه‌های مختلفی برای برقراری تماس اضطراری از IVI وجود دارد، از جمله:

  • راه حل مستقل eCall
  • راه حل eCall یکپارچه در IVI
  • وقتی هیچ سیستم داخلی در دسترس نیست، به تلفن بلوتوث متصل تکیه کنید

تماس اضطراری را وصل کنید

در حالی که تجهیزات eCall از نظر ایمنی بسیار مهم هستند، در حال حاضر در اندروید ادغام نشده اند. این امکان وجود دارد که از 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 مخاطبین را برای هر دستگاه متصل در Contacts Provider ذخیره می کند که سپس توسط یک برنامه برای استخراج دفترچه تلفن برای هر دستگاه قابل دسترسی است.

علاوه بر این، اتصال پروفایل باید توسط IVI و دستگاه تلفن همراه مجاز باشد تا بتوان اتصال برقرار شود. هنگامی که یک کلاینت PBAP قطع می شود، پایگاه داده داخلی همه مخاطبین و تاریخچه تماس مرتبط با دستگاه قبلاً متصل شده را حذف می کند.

نمایه دسترسی به پیام

نمایه دسترسی به پیام بلوتوث (MAP) به خودرو امکان می دهد پیام های SMS را از طریق یک دستگاه راه دور متصل ارسال و دریافت کند. در حال حاضر، پیام ها به صورت محلی در IVI ذخیره نمی شوند. در عوض، هر زمان که دستگاه راه دور متصل پیامی را دریافت کرد، IVI پیام را دریافت و تجزیه می‌کند و محتوای آن را در یک نمونه Intent پخش می‌کند، که سپس می‌تواند توسط یک برنامه دریافت شود.

برای اتصال به یک دستگاه تلفن همراه به منظور ارسال و دریافت پیام، IVI باید اتصال MAP را آغاز کند. MAXIMUM_CONNECTED_DEVICES در MapClientService حداکثر تعداد اتصالات همزمان دستگاه MAP مجاز با IVI را تعیین می کند. هر اتصال باید توسط IVI و دستگاه تلفن همراه قبل از انتقال پیام مجاز باشد.

نمایه توزیع صوتی پیشرفته

نمایه توزیع صوتی پیشرفته بلوتوث (A2DP) به خودرو امکان می دهد جریان های صوتی را از یک دستگاه راه دور متصل دریافت کند.

برخلاف سایر پروفایل ها، حداکثر تعداد دستگاه های A2DP متصل در پشته بومی و نه در جاوا اعمال می شود. مقدار در حال حاضر با استفاده از متغیر kDefaultMaxConnectedAudioDevices در packages/modules/Bluetooth/system/btif/src/btif_av.cc به 1 تبدیل شده است.

نمایه کنترل از راه دور صوتی/تصویری

نمایه کنترل از راه دور صوتی/تصویری بلوتوث (AVRCP) به وسیله نقلیه اجازه می دهد تا پخش کننده های رسانه را روی یک دستگاه از راه دور متصل کنترل و مرور کند. از آنجایی که IVI نقش یک کنترل‌کننده AVRCP را بازی می‌کند، هر کنترل فعالی که بر پخش صدا تأثیر می‌گذارد به اتصال A2DP به دستگاه هدف بستگی دارد.

برای اینکه یک پخش کننده رسانه خاص در تلفن Android قابل مرور توسط IVI از طریق AVRCP باشد، برنامه رسانه روی تلفن باید یک MediaBrowserService ارائه دهد و به com.android.bluetooth اجازه دسترسی به آن سرویس را بدهد. ساخت یک سرویس مرورگر رسانه نحوه انجام این کار را با جزئیات توضیح می دهد.