तकनीकी जानकारी

इस सेक्शन में, Control Center रेफ़रंस ऐप्लिकेशन से जुड़ी तकनीकी जानकारी दी गई है.

Control Center, सिस्टम के ज़रिए साइन किया गया एक ऐसा ऐप्लिकेशन है जो बंडल नहीं किया गया है और जिसे खास अधिकार मिले हुए हैं. इसके लिए, कम से कम एसडीके वर्शन 35 (Android V (एपीआई लेवल 35)) की ज़रूरत होती है. System APIs का इस्तेमाल करने के लिए, ऐप्लिकेशन को system/priv-app में इंस्टॉल किया गया है. मीडिया की जानकारी पढ़ने के लिए, ऐप्लिकेशन को प्लैटफ़ॉर्म के हिसाब से साइन किया जाना चाहिए. ऐप्लिकेशन को ओवर-द-एयर (OTA) अपडेट किया जा सकता है.

बैकग्राउंड में चलने वाली सेवा

Control Center ऐप्लिकेशन, बैकग्राउंड सेवा पर निर्भर करता है. Control Center Service को Vendor ServiceController ने उपयोगकर्ता के लाइफ़साइकल में user-post-unlocked स्थिति में शुरू किया है. Control Center हमेशा चालू रहना चाहिए और बैकग्राउंड में काम करना चाहिए. ऐप्लिकेशन को इस बात पर भरोसा नहीं करना चाहिए कि उपयोगकर्ता ने ऐप्लिकेशन खोला है.

Control Center Service, Communication API का इस्तेमाल करके, कार के दूसरे ऑक्यूपंट ज़ोन में मौजूद अपने अन्य इंस्टेंस से कनेक्ट होता है और उनसे इंटरैक्ट करता है. इंटिग्रेशन गाइड को पढ़ना ज़रूरी है. इससे यह समझने में मदद मिलती है कि हर उपयोगकर्ता के डिवाइस पर Control Center के इंस्टेंस, कनेक्शन कैसे बनाते हैं और डेटा कैसे भेजते और पाते हैं.

इस डायग्राम में, वेंडर के ServiceController की मदद से Control Center Service को शुरू होते हुए दिखाया गया है.
पांचवीं इमेज. Control Center Service को Vendor ServiceController ने शुरू किया है.

कम्यूनिकेशन

कनेक्ट होने के बाद, Control Center Service, protobuf से कम्यूनिकेट करता है. 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
                 }
             }
             //…
}

डेटा

ऑक्यूपेंट ज़ोन की जानकारी, Control Center में OccupantZoneData ऑब्जेक्ट के तौर पर सेव की जाती है. स्थानीय OccupantZoneData में किए गए बदलावों को Comms API के ज़रिए, Control Center के अन्य इंस्टेंस को भेजा जाता है.

जब मिले हुए Payload को पार्स किया जाता है, तो पार्स किए गए डेटा को लोकल OccupantZoneStateRepository में पास किया जाता है. इसके बाद, यह व्यू को बदलाव की सूचना देता है. ज़्यादातर डेटा को क्लास के बीच Kotlin flows on Android की मदद से पास किया जाता है.

केबिन स्पीकर पर ऑडियो के लिए किए गए अनुरोधों को मैनेज करना

इसलिए, जब ड्राइवर का Control Center Service Primary ZoneMedia Audio RequestCallback रजिस्टर करता है, तब ड्राइवर को हमेशा यात्रियों के केबिन स्पीकर पर ऑडियो चलाने के अनुरोध मिल सकते हैं.

कॉलबैक को CarAudioManager#requestMediaAudioOnPrimaryZone पर किए गए कॉल की सूचना दी जाती है. ड्राइवर का Control Center Service, अनुरोधों को मैनेज करता है. इसके लिए, वह एक सूचना (एचयूएन) बनाता है. इसे CarAudioManager#allowMediaAudioOnPrimaryZone(boolean) के ज़रिए स्वीकार या अस्वीकार किया जा सकता है.

अन्य स्क्रीन पर किसी वीडियो को एक साथ देखना

CarActivityManager में Task Mirroring APIs की वजह से, लोगों के साथ मिलकर वीडियो देखने की सुविधा काम करती है. TaskMirroringManager सबसे पहले, CarActivityManager#getVisibleTasks में चल रहे MediaSession ऐप्लिकेशन के पैकेज को खोजता है. इसके बाद, VirtualDisplay बनाता है और CarActivityManager#moveRootTaskToDisplay के ज़रिए दिखने वाले टास्क को इस डिसप्ले पर ले जाता है.

इससे एक IBinder टोकन मिलता है. MirroredSurfaceView इसका इस्तेमाल लेआउट में कर सकता है, ताकि MirroredSurfaceView#mirrorSurface के ज़रिए टास्क दिखाया जा सके. Communication API Payload ऑब्जेक्ट ने टोकन को अन्य ऑक्यूपेंट ज़ोन में पास कर दिया है.

उन ऑक्यूपेंट ज़ोन में मौजूद हर Control Center इंस्टेंस, Mirroring activity लॉन्च करता है. साथ ही, उस टोकन का इस्तेमाल करके MirroredSurfaceView में डेटा भरता है.

किसी टास्क को दूसरी स्क्रीन पर दिखाने के लिए, मिररिंग टोकन का फ़्लो.
छठी इमेज. टोकन फ़्लो को मिरर करें.

टास्क मिरर करने वाले एपीआई

Control Center, टास्क मिररिंग के लिए इन एपीआई का इस्तेमाल करता है:

CarActivityManager#getVisibleTasks(int displayId)
<ActivityManager.RunningTaskInfo> ने भेजने वाले का डिसप्ले नेम पाने के लिए कॉल किया.

CarActivityManager#moveRootTaskToDisplay(int virtualDisplayId)
इससे चुनी गई दिखने वाली टास्क को बनाए गए वर्चुअल डिसप्ले पर ले जाया जाता है.

CarActivityManager#createTaskMirroringToken(int taskId)
यह IBinder टोकन को मिरर करने के लिए एक टास्क बनाता है. इसे तब कॉल किया जाना चाहिए, जब टास्क को वर्चुअल डिसप्ले पर ले जाया गया हो.

MirroredSurfaceView#mirrorSurface(IBinder token)
कस्टम व्यू ऑब्जेक्ट, जो टोकन का इस्तेमाल करके |वर्चुअल डिसप्ले का कॉन्टेंट दिखाता है.

Control Center में टास्क मिररिंग की सुविधा की सीमाएं

कंट्रोल सेंटर, सिर्फ़ MediaSession ऐप्लिकेशन के लिए टास्क मिररिंग की सुविधा देता है. हालांकि, एपीआई किसी भी टास्क को मिरर कर सकता है. वर्चुअल डिसप्ले, भेजने वाले के डिसप्ले के डाइमेंशन के हिसाब से बनाया जाता है. अगर रिसीवर के डिसप्ले में अलग-अलग रिज़ॉल्यूशन और डाइमेंशन का इस्तेमाल किया जाता है, तो वर्चुअल डिसप्ले स्क्रीन के बीच में दिखता है.

ऐसे टास्क जो सर्फ़ेस पर दिखते हैं

कंट्रोल सेंटर, चेसिस Theme.CarUi.NoToolbar को बढ़ाकर एक पारदर्शी विंडो बनाता है. इसका मतलब है कि जब किसी टास्क के ऊपर कंट्रोल सेंटर खोला जाता है, तो टास्क को CarActivityManager#getVisibleTasks में वापस भेज दिया जाता है. इससे टास्क को मिरर किया जा सकता है.

स्क्रीन मिररिंग की जानकारी पाना

कंट्रोल सेंटर, स्क्रीन मिरर करने के सेशन के बारे में अन्य ऐप्लिकेशन को सूचना देता है. अपडेट पाने के लिए, ऐप्लिकेशन को Control Center Service से बाइंड करना होगा. साथ ही, Handler क्लास को क्लाइंट के तौर पर भेजना होगा. यह क्लास, Control Center Service से Messages को पाने और मैनेज करने का काम करती है.

क्लाइंट ऐप्लिकेशन, मिरर किए गए ऐप्लिकेशन का पैकेज नाम पा सकते हैं. साथ ही, इन कुंजियों के साथ मिरर किए गए ऐप्लिकेशन को होस्ट करने वाले Control Center में गतिविधि के लिए intent URI लॉन्च कर सकते हैं:

  • _config_msg_mirroring_pkg_name_key_
  • _config_msg_mirroring_redirect_uri_key_

ये कॉन्फ़िगरेशन, क्लाइंट ऐप्लिकेशन के संसाधनों और Control Center के संसाधनों में मौजूद होने चाहिए.

क्लाइंट ऐप्लिकेशन को कंट्रोल सेंटर से मिररिंग की जानकारी मिलती है.
सातवीं इमेज. Control Center से स्क्रीन मिरर करने की जानकारी पाएं.

डीबग कंट्रोल सेंटर

Logger क्लास, Control Center के लॉग को मैनेज करती है. इसे लॉग को फ़ोर्स करने के लिए कॉन्फ़िगर किया जा सकता है.

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)
       }
   }
...

सिस्टम ऐप्लिकेशन और उसे अपडेट करने की सुविधा

कंट्रोल सेंटर एक सिस्टम ऐप्लिकेशन है. साथ ही, सिग्नेचर-ओनली अनुमतियों का इस्तेमाल करने की वजह से, इसे प्लैटफ़ॉर्म से साइन किया गया है. इसलिए, कंट्रोल सेंटर को डिवाइस पर पहले से इंस्टॉल होना चाहिए. साथ ही, इसे सिर्फ़ ओटीए के ज़रिए अपडेट किया जा सकता है. यह कार मीडिया ऐप्लिकेशन की तरह ही है.

सोर्स से कंट्रोल सेंटर बनाना

Control Center का सोर्स कोड पाने के लिए, अनबंडल किए गए ऐप्लिकेशन इंटिग्रेट करना लेख पढ़ें.

मल्टी-डिसप्ले के साथ उपयोगकर्ता की निजता

Control Center की मदद से, कार में बैठे सभी लोग सभी डिसप्ले पर मीडिया की जानकारी देख सकते हैं. Google का सुझाव है कि उपयोगकर्ताओं को सूचना देने के लिए, बिना रुकावट वाला निजता नोटिस डालें. Google का सुझाव है कि आप ऐसा सिस्टम लेवल पर करें. ऐसा तब करें, जब आपने किसी डिसप्ले में साइन इन किया हो.