بلوتوث

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

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

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

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

غیرفعال کردن سیاست پیش‌فرض تلفن

پشته بلوتوث اندروید یک سیاست اتصال برای تلفن‌ها دارد که به طور پیش‌فرض فعال است. این سیاست باید در دستگاه شما غیرفعال شود تا با سیاست خودرو در نظر گرفته شده در 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 در یک resource overlay غیرفعال کرد. این منبع در ابتدا به عنوان بخشی از 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 و تأیید اتصال خودکار آن به دستگاه‌های صحیح با ترتیب مناسب است. می‌توانید آداپتور بلوتوث را از طریق رابط کاربری تنظیمات یا با دستورات 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 تعامل می‌کند تا ویژگی‌های تماس، مانند پذیرش تماس یا قطع تماس را مدیریت کند.

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

تأیید HFP چند دستگاهی

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

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

تماس اضطراری

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

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

اتصال تماس اضطراری

اگرچه تجهیزات eCall از نظر ایمنی بسیار مهم هستند، اما در حال حاضر با اندروید یکپارچه نشده‌اند. می‌توان از ConnectionService برای نمایش ویژگی‌های تماس اضطراری از طریق اندروید استفاده کرد که این امر همچنین مزیت معرفی گزینه‌های دسترسی برای تماس‌های اضطراری را دارد. برای کسب اطلاعات بیشتر، به بخش «ساخت یک برنامه تماس» مراجعه کنید.

در اینجا مثالی از نحوه ایجاد یک 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);
    }
}

فعال کردن بلوتوث برای تماس‌های اضطراری

تماس با اورژانس قبل از اندروید ۱۰ شامل شماره‌گیری مستقیم از تلفن و فراخوانی تجهیزات ویژه در صورت وجود (به عنوان مثال، فعال شدن خودکار پس از تشخیص خطر یا اقدام کاربر) بود. در اندروید ۱۰ و بالاتر، شماره‌گیر داخل خودرو می‌تواند مستقیماً با شماره اضطراری تماس بگیرد، البته با ارائه این 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) به خودرو اجازه می‌دهد تا از طریق یک دستگاه کنترل از راه دور متصل، پیامک ارسال و دریافت کند. در حال حاضر، پیام‌ها به صورت محلی در IVI ذخیره نمی‌شوند. در عوض، هر زمان که دستگاه کنترل از راه دور متصل، پیامی دریافت کند، IVI پیام را دریافت و تجزیه کرده و محتوای آن را در یک Intent instance پخش می‌کند که سپس می‌تواند توسط یک برنامه دریافت شود.

برای اتصال به یک دستگاه تلفن همراه به منظور ارسال و دریافت پیام، 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 به دستگاه هدف متکی است.

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