التفاصيل الفنية

يقدّم هذا القسم تفاصيل فنية خاصة بالتطبيق المرجعي Control Center.

مركز التحكّم هو تطبيق غير مجمَّع ومميّز وموقَّع من النظام ويتطلّب الحد الأدنى من إصدار حزمة تطوير البرامج (SDK) وهو 35 (الإصدار V من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 35)). يجب تثبيت التطبيق في system/priv-app لاستخدام System APIs. لقراءة معلومات الوسائط، يجب أن يكون التطبيق موقّعًا على مستوى النظام الأساسي. يمكنك تحديث التطبيق عبر شبكة غير سلكية (OTA).

خدمة تُشغَّل في الخلفية

يعتمد تطبيق "مركز التحكّم" على خدمة تُشغَّل في الخلفية لتوفير وظائفه. يتم بدء Control Center Service في حالة user-post-unlocked ضمن دورة حياة المستخدم من خلال Vendor ServiceController. يجب أن يكون "مركز التحكّم" نشطًا دائمًا وأن يتواصل في الخلفية، ولا يمكن أن يعتمد التطبيق على فتح المستخدم له.

يتصل تطبيق "Control Center Service" ويتواصل مع نُسخ أخرى منه في مناطق الركاب الأخرى باستخدام Communication API. يُعدّ الاطّلاع على دليل الدمج أمرًا ضروريًا لفهم كيفية إنشاء الاتصالات وإرسال البيانات واستلامها من خلال مثيلات "مركز التحكّم" على كل جهاز مستخدم.

مخطّط يوضّح بدء خدمة "مركز التحكّم" من خلال Vendor ServiceController
الشكل 5. بدأت خدمة "مركز التحكّم" من خلال Vendor ServiceController.

التواصل

بعد الاتصال، يتواصل Control Center Service مع عناصر protobuf تنقل المعلومات. لنقل protobuf إلى منطقة أخرى يشغلها شخص آخر باستخدام Communication APIs، يتم تحويل protobuf إلى byte array، ويتم إنشاء payload object، ويتم إرسال Payload من خلال CarOccupantConnectionManager#sendPayload.

message ControlCenterPayload {
    required Type messageType = 1;
    // ...
    enum Type {
       MEDIA_STATUS = 0;
       MEDIA_COMMAND = 1;
       INPUT_LOCK_COMMAND = 2;
       INPUT_LOCK_SUCCESSFUL = 3;
       CANCEL_AUDIO_REQUEST = 4;
       MIRRORING_REQUEST_RECEIVER_DECISION = 5;
       MIRRORING_SESSION_ENDED = 6;
    }
}

private fun parsePayload(
    senderZone: OccupantZoneInfo,
    payload: Payload
) {
     val parsedPayload =
         ControlCenterPayload.parseFrom(payload.bytes)
             when (parsedPayload.messageType) {
                 ControlCenterPayload.Type.MEDIA_STATUS -> {
                     // logic here
                 }
             }
             //…
}

البيانات

يتم تخزين معلومات حول مناطق الإشغال في "مركز التحكّم" على شكل عناصر OccupantZoneData. يتم إرسال التغييرات التي يتم إجراؤها على OccupantZoneData المحلي إلى مثيلات "مركز التحكّم" الأخرى من خلال Comms API.

عند تحليل Payload المستلَمة، يتم تمرير البيانات التي تم تحليلها إلى OccupantZoneStateRepository المحلية، والتي بدورها تُعلم طرق العرض بالتغيير. يتم تمرير معظم البيانات بين الفئات باستخدام Kotlin flows on Android.

التعامل مع طلبات تشغيل الصوت من مكبّرات الصوت في المقصورة

لكي يتمكّن السائق دائمًا من تلقّي طلبات من الركاب لتشغيل الصوت عبر مكبّرات الصوت في المقصورة، يسجّل Control Center ServicePrimary ZoneMedia Audio RequestCallback عند إنشائه.

يتم إعلام دالة الرجوع بشأن المكالمات الواردة إلى CarAudioManager#requestMediaAudioOnPrimaryZone. يتعامل برنامج التشغيل Control Center Service مع الطلبات من خلال إنشاء إشعار عائم (HUN) يمكن قبوله أو رفضه من خلال CarAudioManager#allowMediaAudioOnPrimaryZone(boolean).

مشاهدة فيديو مع شاشات أخرى

تعمل ميزة "المشاهدة مع الآخرين" بفضل Task Mirroring APIs في CarActivityManager. تبحث الخدمة TaskMirroringManager أولاً عن حزمة تطبيق MediaSession قيد التشغيل في CarActivityManager#getVisibleTasks، ثم تنشئ VirtualDisplay وتنقل المهمة المرئية إلى هذا العرض من خلال CarActivityManager#moveRootTaskToDisplay.

يعرض هذا الرمز المميز IBinder الذي يمكن أن تستخدمه MirroredSurfaceView في تنسيق لعرض المهمة من خلال MirroredSurfaceView#mirrorSurface. مرّر العنصر Communication API Payload الرمز المميّز إلى مناطق أخرى مشغولة.

يتم تشغيل كل مثيل من "لوحة التحكّم" في مناطق الإشغال هذه باستخدام Mirroring activity ويستخدم هذا الرمز المميز لتعبئة MirroredSurfaceView.

مخطّط انسيابي لرمز مميّز لعكس الشاشة من أجل عرض مهمة على شاشة أخرى
الشكل 6. عرض مسار الرموز المميزة

واجهات برمجة التطبيقات لعكس المهام

يستخدم "مركز التحكّم" واجهات برمجة التطبيقات التالية لعكس المهام:

CarActivityManager#getVisibleTasks(int displayId)
<ActivityManager.RunningTaskInfo> طلب عرض اسم المُرسِل.

CarActivityManager#moveRootTaskToDisplay(int virtualDisplayId)
ينقل هذا الخيار المهمة المرئية المحدّدة إلى شاشة عرض افتراضية تم إنشاؤها.

CarActivityManager#createTaskMirroringToken(int taskId)
تنشئ هذه السمة مهمة لعكس الرمز المميز IBinder ويجب استدعاؤها بعد نقل المهمة إلى الشاشة الافتراضية.

MirroredSurfaceView#mirrorSurface(IBinder token)
عنصر عرض مخصّص يستخدم الرمز المميز لعرض محتوى الشاشة الافتراضية.

القيود المفروضة على ميزة "عكس المهام" في "مركز التحكّم"

لا يتيح "مركز التحكّم" عرض المهام على شاشة أخرى إلا لتطبيقات MediaSession. ومع ذلك، يمكن لواجهة برمجة التطبيقات أن تعكس أي مهمة. يتم إنشاء الشاشة الافتراضية باستخدام أبعاد شاشة العرض الخاصة بالجهاز المرسِل. إذا كانت شاشة جهاز الاستقبال تستخدم دقة أبعاد مختلفة، ستظهر الشاشة الافتراضية في منتصف الشاشة.

المهام المرئية على السطح

يوسّع &quot;مركز التحكّم&quot; إطار Theme.CarUi.NoToolbar ليصبح نافذة شفافة. وهذا يعني أنّه عند فتح &quot;مركز التحكّم&quot; فوق مهمة، يتم عرض المهمة في CarActivityManager#getVisibleTasks، ما يتيح عرضها على شاشة أخرى.

تلقّي معلومات حول عرض المحتوى على شاشة أخرى

يُعلم "مركز التحكّم" التطبيقات الأخرى بجلسات النسخ المطابق. لتلقّي التحديثات، يجب أن تربط التطبيقات Control Center Service وأن ترسل فئة Handler كعميل يتلقّى Messages من Control Center Service ويتعامل معه.

يمكن لتطبيقات العميل تلقّي اسم حزمة التطبيق الذي يتم عرضه على الشاشة وإطلاق intent URI للنشاط في &quot;مركز التحكّم&quot; الذي يستضيف التطبيق المعروض على الشاشة باستخدام المفاتيح التالية:

  • _config_msg_mirroring_pkg_name_key_
  • _config_msg_mirroring_redirect_uri_key_

يجب أن تكون هذه الإعدادات متوفّرة في موارد تطبيق العميل وفي موارد &quot;مركز التحكّم&quot;.

تتلقّى تطبيقات العميل معلومات النسخ المطابق من &quot;مركز التحكّم&quot;.
الشكل 7. تلقّي معلومات النسخ المطابق من "مركز التحكّم"

مركز التحكّم في تصحيح الأخطاء

يتعامل صف Logger مع سجلّات "مركز التحكّم" التي يمكن ضبطها لفرض السجلّات.

class Logger(cls: Class<*>) {

   companion object {
       private const val FORCE_LOGS = false
   }

   private val tag: String

   init {
       tag = cls.simpleName
   }

   fun v(message: String) {
       if (Log.isLoggable(tag, Log.VERBOSE) || FORCE_LOGS) {
           Log.v(tag, message)
       }
   }
...

تطبيقات النظام وإمكانية التحديث

بما أنّ "مركز التحكّم" هو تطبيق نظام وموقّع من المنصة بسبب استخدام أذونات التوقيع فقط، يجب أن يكون "مركز التحكّم" مثبّتًا مسبقًا على الجهاز ولا يمكن تحديثه إلا عبر الهواء (OTA)، تمامًا مثل تطبيق وسائط السيارة.

إنشاء "مركز التحكّم" من المصدر

للحصول على رمز مصدر "مركز التحكّم"، يُرجى الاطّلاع على دمج التطبيقات غير المجمَّعة.

خصوصية المستخدم عند استخدام شاشات متعددة

يتيح "مركز التحكّم" لجميع ركاب السيارة عرض معلومات الوسائط على جميع شاشات العرض. تنصحك Google بإدراج إشعار خصوصية غير حاصِر لإعلام المستخدمين. تنصحك Google بإجراء ذلك على مستوى النظام عند تسجيل الدخول إلى شاشة.