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

يقدّم هذا القسم تفاصيل فنية خاصة بالتطبيق المرجعي 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;.
الشكل 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)
       }
   }
...

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

بما أنّ &quot;مركز التحكّم&quot; هو تطبيق نظام وموقّع من المنصة بسبب استخدام أذونات التوقيع فقط، يجب أن يكون &quot;مركز التحكّم&quot; مثبّتًا مسبقًا على الجهاز ويمكن تحديثه عبر الهواء فقط، على غرار تطبيق وسائط السيارة.

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

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

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

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