उपयोगकर्ता की प्राथमिकताओं के आर्किटेक्चर और लागू करने की गाइड

इस पेज पर, SDV User Preferences सिस्टम के आर्किटेक्चर के बारे में जानकारी दी गई है. साथ ही, इसमें उपयोगकर्ता के कंट्रोल वाली सेवा और क्लाइंट को लागू करने के निर्देश भी दिए गए हैं.

आर्किटेक्चर की खास जानकारी

User Preferences सिस्टम, उपयोगकर्ता की सेटिंग को सेव करने और मैनेज करने की सुविधा को, उन सेटिंग को लागू करने और उन पर पाबंदी लगाने की सुविधा से अलग करता है. आर्किटेक्चर से जुड़े अहम शब्दों के बारे में यहां बताया गया है:

सुविधाब्यौराभूमिकाज़िम्मेदारी
उपयोगकर्ता के कंट्रोल वाली सेवा यह SDV सेवा का एक स्टैंडर्ड बंडल है, जो किसी खास डोमेन को मैनेज करता है. उदाहरण के लिए, एचवीएसी, कार की सीटें, ऑडियो यह हार्डवेयर या सबसिस्टम की क्षमताओं और पाबंदियों की मौजूदा स्थिति के बारे में जानकारी देता है.
  • रजिस्ट्रेशन: यह उपयोगकर्ता की प्राथमिकताओं को मैनेज करने वाले एजेंट को, उन सेटिंग के बारे में जानकारी देता है जिन्हें वह मैनेज कर सकता है. जैसे, मेटाडेटा, डिफ़ॉल्ट वैल्यू, पाबंदियां.
  • लागू करना और स्वायत्तता: यह सेटिंग में बदलाव करने के अनुरोध स्वीकार करता है. साथ ही, मौजूदा स्थिति और सुरक्षा के नियमों के हिसाब से उनकी पुष्टि करता है और उन्हें हार्डवेयर पर लागू करता है. यह पूरी तरह से स्वायत्त है और यह तय करता है कि सेटिंग में किया गया बदलाव स्वीकार किया जाएगा या नहीं.
उपयोगकर्ता की प्राथमिकताओं को मैनेज करने वाला एजेंट यह मुख्य ऑर्केस्ट्रेटर है यह एक जगह पर स्टोरेज, उपयोगकर्ता प्रोफ़ाइल मैनेजमेंट, और सूचना हब की सुविधा देता है.
  • स्टोरेज: यह हर उपयोगकर्ता (जैसे, ड्राइवर, यात्री) के लिए सेटिंग सेव करता है.
  • राउटिंग: यह क्लाइंट (जैसे, ह्यूमन मशीन इंटरफ़ेस (एचएमआई)) से मिले, सेटिंग में बदलाव करने के अनुरोधों को, उपयोगकर्ता के कंट्रोल वाली सही सेवा तक पहुंचाता है.
  • सूचनाएं: यह ChangeNotifier इंटरफ़ेस का इस्तेमाल करके, दिलचस्पी रखने वाले पक्षों (व्यू या एचएमआई) को बदलावों के बारे में सूचनाएं ब्रॉडकास्ट करता है.
  • उपयोगकर्ता मैनेजमेंट: यह उपयोगकर्ता स्विच करने और रजिस्टर की गई सभी सेवाओं पर, सही और सेव की गई स्थिति लागू करने की प्रोसेस को मैनेज करता है.
User Preferences क्लाइंट यह एक ऐसा ऐप्लिकेशन या सेवा है जो यूज़र इंटरफ़ेस उपलब्ध कराती है. उदाहरण के लिए, एचएमआई वाला कोई IVI ऐप्लिकेशन या कोई अन्य लॉजिक जिसे उपयोगकर्ता की प्राथमिकताओं के साथ इंटरैक्ट करना होता है यह उपयोगकर्ताओं के साथ इंटरैक्ट करता है, सेटिंग दिखाता है, और बदलाव के अनुरोध शुरू करता है.
  • डिसप्ले: यह उपयोगकर्ता को मौजूदा सेटिंग और पाबंदियां दिखाता है.
  • बदलाव का अनुरोध: यह उपयोगकर्ता की शुरू की गई सेटिंग में किए गए बदलावों को, उपयोगकर्ता की प्राथमिकताओं को मैनेज करने वाले एजेंट को भेजता है.
  • सूचनाएं पाना: यह सेटिंग के रीयल-टाइम अपडेट के लिए सदस्यता लेता है और उन पर प्रतिक्रिया करता है.

उपयोगकर्ता के कंट्रोल वाली सेवा लागू करना

उपयोगकर्ता की प्राथमिकताओं को मैनेज करने वाले एजेंट को यह बताने के लिए कि कौनसी कुंजियां मौजूद हैं, उनका डेटा टाइप, डिफ़ॉल्ट वैल्यू, और पाबंदियां (जैसे, कम से कम और ज़्यादा से ज़्यादा वैल्यू), आपकी सेवा के बंडल को UserPreferencesRegistryService इंटरफ़ेस के साथ इंटरैक्ट करना होगा. जब आपकी सेवा शुरू होती है, तो उसे उन सेटिंग को रजिस्टर करना होगा जिन्हें वह मैनेज कर सकती है. जब कोई उपयोगकर्ता किसी सेटिंग में बदलाव करने की कोशिश करता है (या उपयोगकर्ता स्विच करते समय), तो एजेंट आपकी सेवा पर RequestSettingsChange को कॉल करता है.

उपयोगकर्ता की प्राथमिकताओं (और एचएमआई वाले उपयोगकर्ता) को अपनी सेवा कंट्रोल करने की अनुमति देने के लिए, इस सेक्शन में दिया गया तरीका अपनाएं.

  1. वीएसआईडीएल फ़ाइल में सेवा इंटरफ़ेस तय करें:

    • सर्वर के तौर पर, com.sdv.google.user_preferences.user_controllable.UserControllableService लागू करें. इससे एजेंट, आपको बदलाव के अनुरोध भेज सकेगा.
    • क्लाइंट के तौर पर, com.sdv.google.user_preferences.UserPreferencesRegistryService का इस्तेमाल करें. इससे स्टार्टअप पर आपकी सेटिंग रजिस्टर हो जाती हैं.

    यहां दिए गए उदाहरण में, उपयोगकर्ता के कंट्रोल वाली सेवा के लिए service_bundle.vsidl दिखाया गया है:

    service_bundle {
        name: "MyFeatureService"
        server {
            service: "com.sdv.google.user_preferences.user_controllable.UserControllableService"
        }
        client {
            service: "com.sdv.google.user_preferences.UserPreferencesRegistryService"
        }
    }
    
  2. कुंजी प्रोटो user_preferences_registry_service.proto में, स्टार्टअप पर सेटिंग रजिस्टर करें:

    1. UserPreferencesRegistryService से कनेक्ट करें.
    2. RegisterSettingsRequest का कोई इंस्टेंस बनाएं.
    3. SettingsGroup (सेटिंग का लॉजिकल कलेक्शन) का कोई इंस्टेंस तय करें.
    4. हर सेटिंग के लिए, यह तय करें:

      *   **Key:** Unique string ID (for example, `TEMPERATURE`)
      *   **Kind:** `PER_USER` (stored per user profile) or `SHARED`
          (global)
      *   **Default value:** Initial value if no user preference exists
      *   **Constraints:** (optional) Validation rules (for example, Min
          16, Max 32 for HVAC).
      
    5. RegisterSettings() को कॉल करें.

    यहां दिया गया उदाहरण, रस्ट में है:

    let temperature_setting = SettingDefinition {
        name: "TEMPERATURE".to_string(),
        kind: SettingKind::PER_USER.into(),
        default_value: Value::Int64(22), // Default 22 degrees
        constraint: Some(Constraints::Int64Constraints(Int64Constraints {
            min_value: Some(16),
            max_value: Some(32),
            ..Default::default()
        })),
        ..Default::default()
    };
    
    registry_client.RegisterSettings(&RegisterSettingsRequest {
        group_name: "HVAC".to_string(),
        version: "1.0".to_string(),
        settings_definitions: vec![temperature_setting],
    }).await?;
    
  3. user_controllable_service.proto में, सेटिंग में बदलाव के अनुरोधों को हैंडल करें:

    1. RequestSettingsChange आरपीसी लागू करें.
    2. पुष्टि करें कि अनुरोध की गई वैल्यू, मौजूदा कॉन्टेक्स्ट में मान्य हैं या नहीं. उदाहरण के लिए, अगर हार्डवेयर तैयार है.
    3. बदलाव लागू करने के लिए, खास लॉजिक लागू करें. उदाहरण के लिए, सीट को घुमाना, पंखे की स्पीड बदलना.
    4. RequestSettingsChangeResponse में, लागू की गई वैल्यू लौटाएं:
    5. अगर आपने बदलाव स्वीकार कर लिया है, तो नई वैल्यू लौटाएं.
    6. अगर आपने वैल्यू को अस्वीकार कर दिया है या उसे सीमित कर दिया है, तो वह वैल्यू लौटाएं जिसे आपने सेट किया है (या बनाए रखा है).

    यहां दिया गया उदाहरण, रस्ट में है:

    async fn RequestSettingsChange(
        &self,
        _caller_id: ServiceFqin,
        request: &RequestSettingsChangeRequest
    ) -> SdvResult<RequestSettingsChangeResponse> {
        let mut applied_settings = Vec::new();
    
        for setting in &request.settings {
            if self.hardware.set_value(setting.key, setting.value).is_ok() {
                // Change accepted
                applied_settings.push(setting.clone());
            } else {
                // Change rejected, return current actual value
                let current_val = self.hardware.get_value(setting.key);
                applied_settings.push(create_setting(setting.key, current_val));
            }
        }
    
        Ok(RequestSettingsChangeResponse {
            settings: applied_settings,
        })
    }
    
  4. अपने सबसिस्टम को साफ़ स्थिति में वापस लाने के लिए, FactoryReset आरपीसी लागू करें:

    1. सभी सेटिंग को उनकी डिफ़ॉल्ट वैल्यू पर रीसेट करें. ये वैल्यू, आपके कोड कॉन्फ़िगरेशन में तय की जाती हैं.
    2. रजिस्ट्री सेवा पर UpdateSettings को कॉल करें, ताकि एजेंट को यह बताया जा सके कि वैल्यू में बाहरी तौर पर बदलाव किया गया है. यह बदलाव, रीसेट की वजह से हुआ है, न कि उपयोगकर्ता के अनुरोध की वजह से.

पिछले वर्शन के साथ काम करने की सुविधा और स्कीमा का विकास

उपयोगकर्ता के कंट्रोल वाली सेवा से तय की गई सेटिंग का स्कीमा, सार्वजनिक इंटरफ़ेस माना जाता है. इस इंटरफ़ेस का इस्तेमाल, उपयोगकर्ता की प्राथमिकताओं को मैनेज करने वाला एजेंट और अलग-अलग क्लाइंट (जैसे, एचएमआई) करते हैं. इनके रिलीज़ शेड्यूल अलग-अलग हो सकते हैं. इसलिए, सिस्टम की अस्थिरता और क्लाइंट के काम न करने की समस्या से बचने के लिए, पिछले वर्शन के साथ काम करने की सुविधा को बनाए रखना ज़रूरी है.

कंपैटिबल बदलाव

उपयोगकर्ता के कंट्रोल वाली सेवा को, अपनी सेटिंग के स्कीमा में सिर्फ़ कंपैटिबल बदलाव करने चाहिए. इन बदलावों से यह पक्का होता है कि पुराने क्लाइंट, अपडेट के बिना भी सही तरीके से काम करते रहें:

  • कोई नई, ज़रूरी नहीं वाली सेटिंग जोड़ें. इसकी डिफ़ॉल्ट वैल्यू सही होनी चाहिए:

    • यह सेटिंग ज़रूरी नहीं है. इसलिए, सेवा के अलग-अलग वर्शन के साथ काम करने के लिए, क्लाइंट को इसकी मौजूदगी की जांच करनी होगी.
    • अगर क्लाइंट को अपडेट नहीं किया गया है, तो वे इस सेटिंग को अनदेखा कर देते हैं.
    • अगर नई सेटिंग के लिए उपयोगकर्ता की कोई प्राथमिकता मौजूद नहीं है, तो एजेंट, दी गई डिफ़ॉल्ट वैल्यू का इस्तेमाल करता है.

इनकंपैटिबल बदलाव

इन बदलावों को ब्रेक करने वाला माना जाता है. साथ ही, इन्हें करने की अनुमति नहीं होती, क्योंकि इनसे पुराने क्लाइंट तुरंत काम करना बंद कर देते हैं:

  • किसी मौजूदा सेटिंग को हटाना.

  • किसी मौजूदा सेटिंग के मतलब, यूनिट या डेटा टाइप में बदलाव करना. उदाहरण के लिए, सेल्सियस में तापमान दिखाने वाले किसी इंटिजर को, पास्कल में प्रेशर दिखाने वाले फ़्लोट में बदलना.

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

ज़रूरी ब्रेक करने वाले बदलावों को हैंडल करना

अगर ब्रेक करने वाला कोई बदलाव करना ज़रूरी है, तो सेवा को मौजूदा सेटिंग में बदलाव नहीं करना चाहिए. कंपैटबिलिटी बनाए रखते हुए, इस बदलाव को मैनेज करने का तरीका मुख्य तौर पर, उपयोगकर्ता के कंट्रोल वाली सेवा के लॉजिक में मौजूद होता है:

  1. नई डेफ़िनिशन, कुंजी या यूनिट के साथ कोई नई सेटिंग बनाएं.
  2. कंपैटबिलिटी के लिए रजिस्टर करके, मौजूदा सेटिंग को बंद करें. नए क्लाइंट डेवलप करते समय, इस नई सेटिंग का इस्तेमाल करें.
  3. नए क्लाइंट को, उपयोगकर्ता के कंट्रोल वाली सेवा के कारोबार के लॉजिक में कंपैटबिलिटी लॉजिक लागू करने की सलाह दें.

सेवा के RequestSettingsChange को लागू करने से यह पक्का होना चाहिए कि किसी एक सेटिंग में किया गया बदलाव, उसकी बंद की गई सेटिंग में दिखे. साथ ही, बंद की गई सेटिंग में किया गया बदलाव, सेटिंग में दिखे.

कंपैटबिलिटी लॉजिक का उदाहरण:

  1. कोई सेवा, पुरानी सेटिंग TEMPERATURE_C (सेल्सियस) को बंद करती है और TEMPERATURE_K (केल्विन) को लॉन्च करती है.

  2. जब एजेंट, नई सेटिंग को अपडेट करने का अनुरोध भेजता है, तो:

    • सेवा को TEMPERATURE_K (उदाहरण के लिए, 295.15 K) के लिए अनुरोध मिलता है.

    • सेवा का लॉजिक इसे सेल्सियस (22°C) में बदलता है. साथ ही, लेगसी क्लाइंट के लिए अनुकूलता बनाए रखने के लिए, दोनों वैल्यू को अंदरूनी तौर पर अपडेट और सेव करता है.

  3. जब एजेंट, पुराने क्लाइंट से बंद की गई सेटिंग के लिए अनुरोध भेजता है, तो:

    • सेवा को TEMPERATURE_C (उदाहरण के लिए, 24°C) के लिए अनुरोध मिलता है.
    • सेवा इसे केल्विन (297.15 K) में बदलती है. साथ ही, दोनों वैल्यू को अंदरूनी तौर पर अपडेट और सेव करती है.

इस डुअल-राइट रणनीति से यह पक्का होता है कि सभी क्लाइंट, अपने रिलीज़ शेड्यूल के बावजूद, एक जैसा और सटीक डेटा पढ़ें. इससे, बाहरी रिलीज़ में अंतर की वजह से होने वाली समस्याओं से बचा जा सकता है.

क्लाइंट लागू करना

उपयोगकर्ता की प्राथमिकताओं को मैनेज करने वाले एजेंट के साथ इंटरैक्ट करने वाला क्लाइंट (उदाहरण के लिए, एचएमआई) लागू करने के लिए:

  1. उपयोगकर्ता की प्राथमिकताओं के खास इंटरफ़ेस के साथ इंटरैक्ट करने के लिए, अपने क्लाइंट सेवा का बंडल तय करें. अपनी वीएसआईडीएल फ़ाइल में:

    • सर्वर के तौर पर, com.sdv.google.user_preferences.view.ChangeNotifier लागू करें, ताकि एजेंट आपके क्लाइंट को सेटिंग में किए गए बदलावों के बारे में रीयल-टाइम में सूचनाएं भेज सके.
    • क्लाइंट के तौर पर, सेटिंग में बदलाव का अनुरोध करने और अपडेट के लिए सदस्यता लेने के लिए, com.sdv.google.user_preferences.UserPreferencesManagementService का इस्तेमाल करें.
    • क्लाइंट के तौर पर, उपयोगकर्ता प्रोफ़ाइल मैनेज करने के लिए, com.sdv.google.user_preferences.UserPreferencesAdminService का इस्तेमाल करें. उदाहरण के लिए, बनाना, चुनना, मिटाना, फ़ैक्ट्री रीसेट करना.

    यहां दिए गए उदाहरण में, किसी क्लाइंट के लिए service_bundle.vsidl फ़ाइल दिखाई गई है:

    service_bundle {
        name: "MyHmiClient"
        server {
            service: "com.sdv.google.user_preferences.view.ChangeNotifier"
        }
        client {
            service: "com.sdv.google.user_preferences.UserPreferencesManagementService"
        }
        client {
            service: "com.sdv.google.user_preferences.UserPreferencesAdminService"
        }
    }
    

    इसके मुताबिक, अनुमति की नीतियां जोड़ें. उपयोगकर्ता की प्राथमिकताओं को मैनेज करने वाले एजेंट के लिए, तय किए गए सर्वर के लिए कोई क्लाइंट बनाएं. उदाहरण के लिए:

    server {
        service: "com.sdv.google.user_preferences.view.ChangeNotifier"
        allow_all_channels: true
    }
    client {
        service: "com.sdv.google.user_preferences.UserPreferencesManagementService"
        allow_all_channels: true
    }
    client {
        service: "com.sdv.google.user_preferences.UserPreferencesAdminService"
        allow_all_channels: true
    }
    
  2. UserPreferencesManagementService में, अनुरोध सेटिंग में बदलाव किया जा सकता है:

    1. UserPreferencesManagementService से कनेक्ट करें.
    2. RequestSettingsChangeRequest का कोई इंस्टेंस बनाएं. इसमें SettingsGroupId और मनचाही सेटिंग तय करें.
    3. ज़रूरी नहीं. ChangePersistencePolicy को PERSISTENT_CHANGE (डिफ़ॉल्ट) या NON_PERSISTENT_CHANGE पर सेट करें.
    4. RequestSettingsChange() को कॉल करें.

    यहां दिया गया उदाहरण, रस्ट में है:

    management_client.RequestSettingsChange(&RequestSettingsChangeRequest {
        settings_group_id: Some(SettingsGroupId {
            service_fqin: hvac_service_fqin.to_string(),
            name: "HVAC".to_string(),
            ..Default::default()
        }).into(),
        settings: vec![Setting {
            key: "TEMPERATURE".to_string(),
            value: Some(Value::Int64(24)),
            ..Default::default()
        }],
        change_persistence_policy: ChangePersistencePolicy::PERSISTENT_CHANGE.into(),
        ..Default::default()
    }).await?;
    
  3. user_preferences_management_service.proto और change_notifier.proto की मदद से, सेटिंग में किए गए बदलावों के लिए सदस्यता लें:

    1. अपने सेवा बंडल में, ChangeNotifier इंटरफ़ेस से OnSettingsChange आरपीसी लागू करें. जब कोई बदलाव होता है, तो उपयोगकर्ता की प्राथमिकताओं को मैनेज करने वाला एजेंट इस तरीके को लागू करता है.
    2. UserPreferencesManagementService से कनेक्ट करें.
    3. SubscribeToSettingsChangeAndGetSettingsRequest बनाएं. इसमें वह SettingsGroupId तय करें जिसे आपको मॉनिटर करना है.
    4. सेटिंग की स्थिति दिखाने और फिर अपने OnSettingsChange को लागू करने के ज़रिए, आने वाले समय में अपडेट भेजने के लिए, SubscribeToSettingsChangeAndGetSettings() को कॉल करें.

    ChangeNotifier इंटरफ़ेस को लागू करने का यह उदाहरण, रस्ट में है:

    #[async_trait]
    impl ChangeNotifier for MyHmiServiceImpl {
        async fn OnSettingsChange(
            &self,
            _caller_id: ServiceFqin,
            request: &OnSettingsChangeRequest,
        ) -> SdvResult<OnSettingsChangeResponse> {
            // Process the active_settings, pending_changes, and persisted_settings
            // Update your UI or internal state accordingly.
            info!("Received settings change for group: {}", request.settings_group_id.name);
            // ...
            Ok(OnSettingsChangeResponse::new())
        }
    }
    

    सदस्यता लेने का यह उदाहरण, रस्ट में है:

    management_client.SubscribeToSettingsChangeAndGetSettings(&SubscribeToSettingsChangeAndGetSettingsRequest {
        settings_group_id: Some(SettingsGroupId {
            service_fqin: hvac_service_fqin.to_string(),
            name: "HVAC".to_string(),
            ..Default::default()
        }).into(),
        ..Default::default()
    }).await?;
    
  4. ज़रूरी नहीं: उपयोगकर्ता प्रोफ़ाइल मैनेज करने वाले क्लाइंट (उदाहरण के लिए, सेटिंग का कोई खास ऐप्लिकेशन), एडमिन सेवा के साथ इंटरैक्ट करने के लिए, user_preferences_admin_service.proto का इस्तेमाल कर सकते हैं:

    1. UserPreferencesAdminService से कनेक्ट करें.
    2. उपयोगकर्ता प्रोफ़ाइल मैनेज करने के लिए, CreateUser, SelectUser, DeleteUser, FactoryReset, और ListUsers जैसे आरपीसी का इस्तेमाल करें.

    उपयोगकर्ता बनाने का यह उदाहरण, रस्ट में है:

    admin_service_client.CreateUser(&CreateUserRequest {
        user: Some(User {
            id: 1,
            flags: UserFlags::DRIVER.value(),
            ..Default::default()
        }).into(),
        ..Default::default()
    }).await?;
    
  5. user_preferences_admin_service.proto की मदद से, एडमिन सेवा के ज़रिए उपलब्ध सेटिंग और उपयोगकर्ताओं के बारे में जानें:

    1. UserPreferencesAdminService पर ListUsers() को कॉल करके, रजिस्टर किए गए सभी उपयोगकर्ताओं की सूची पाएं.
    2. UserPreferencesAdminService पर GetUserSettings(user_id) को कॉल करके, किसी खास उपयोगकर्ता के लिए सेटिंग पाएं.

    उपयोगकर्ताओं की सूची पाने और सेटिंग पाने का यह उदाहरण, रस्ट में है:

    // List all users
    let list_users_response = admin_service_client.ListUsers(&ListUsersRequest::new()).await?;
    info!("Available users: {:?}", list_users_response.users);
    
    // Get settings for a specific user (for example, user with ID 1)
    if let Some(user_id) = list_users_response.users.first().map(|u| u.id) {
        let get_settings_response = admin_service_client.GetUserSettings(&GetUserSettingsRequest {
            user_id,
            ..Default::default()
        }).await?;
        info!("Settings for user {}: {:?}", user_id, get_settings_response.groups);
    }
    

फ़्लो की खास जानकारी

  1. क्लाइंट शुरू होता है और एजेंट की मैनेजमेंट और एडमिन सेवाओं से कनेक्ट होता है.
  2. क्लाइंट, सेटिंग ग्रुप ढूंढता है और उनके लिए सदस्यता लेता है. साथ ही, शुरुआती स्थिति दिखाता है.
  3. क्लाइंट, एजेंट को RequestSettingsChange भेजता है.
  4. एजेंट, क्लाइंट को अपडेट की गई सेटिंग और स्थिति के साथ OnSettingsChange सूचना भेजता है.

काम करने वाले पूरे उदाहरण के लिए, @samples/user_preferences/v1/ में मौजूद HMIService देखें.

एजेंट लागू करना

ऑर्केस्ट्रेटर से लॉन्च किया गया सेवा बंडल, उपयोगकर्ता की प्राथमिकताओं को मैनेज करने वाले एजेंट को लागू करता है. सुविधा के लिए, रेफ़रंस के तौर पर एक उदाहरण दिया गया है.

इसके अलावा, एजेंट के लिए सेवा बंडल user_preferences_sample.vsidl की यह फ़ाइल दी गई है:

package: "com.sdv.oem.user_preferences"

service_bundle {
    name: "UserPreferencesServiceBundle"
    server {
        service: "com.sdv.google.user_preferences.UserPreferencesAdminService"
    }
    server {
        service: "com.sdv.google.user_preferences.UserPreferencesManagementService"
    }
    server {
        service: "com.sdv.google.user_preferences.UserPreferencesRegistryService"
    }
    client {
        service: "com.sdv.google.user_preferences.view.ChangeNotifier"
    }
    client {
        service: "com.sdv.google.user_preferences.user_controllable.UserControllableService"
    }
}

लागू करने के लिए, जनरेट किए गए मिडलवेयर का इस्तेमाल किया जा सकता है. साथ ही, इसे rust_ffi_shared में कंपाइल किया जाना चाहिए. इसे, उपयोगकर्ता की प्राथमिकताओं को मैनेज करने वाले एजेंट को लागू करने वाले सेवा बंडल से रेफ़र किया जाता है:

sdv_service_bundle_metadata {
  # This name must match the agent's Bundle Name
  name: "UserPreferencesServiceBundle"
  version_number: 1
  version_name: "1"

  native_library_path: "lib64/<USER-PREFERENCES-FFI-LIB>.so"

  orchestration_config_path: "etc/user_preferences_service_bundle/<USER-PREFERENCES-ORCHESTRATION>.textproto"

  authorization_policy_path: "etc/user_preferences_service_bundle/permissions.textproto"
}

क्लाइंट की अनुमति की नीति .textproto फ़ाइल के लिए, ज़रूरी अनुमतियां चाहिए:

client {
    service: "com.sdv.google.user_preferences.UserPreferencesManagementService"
    allow_all_channels: true
}

client {
    service: "com.sdv.google.user_preferences.UserPreferencesRegistryService"
    allow_all_channels: true
}

client {
    service: "com.sdv.google.user_preferences.UserPreferencesAdminService"
    allow_all_channels: true
}

अहम जानकारी: मुख्य सिद्धांत

इस सेक्शन में, कुछ अहम सिद्धांतों के बारे में बताया गया है.

उपयोगकर्ता

गाड़ी का हर उपयोगकर्ता (User क्लास), एक खाता बना सकता है. इसमें वह अपनी प्राथमिकताएं सेव कर सकता है. User Preferences, सिर्फ़ गाड़ी के ड्राइवरों के लिए खाते बनाने की सुविधा देता है. मेहमान ड्राइवर, अस्थायी खाते बना सकते हैं. ये खाते, एक बार इस्तेमाल करने के बाद अपने-आप मिट जाते हैं.

message User {
  // Required.
  // A unique ID for the user.
  int32 id = 1;

  // Bit flags that define properties of user. Integer values have to be powers of 2 as they are used as
  // a bit mask.
  enum UserFlags {
    // Due to Protobuff requirement to have the first enum option set to 0,
    // Assign 0 to an unused flag
    UNSET = 0x0;
    // Marks the user as vehicle driver
    DRIVER = 0x01;
    // Ephemeral users have non-persistent state, once another user is selected
    // the profile is deleted automatically
    EPHEMERAL = 0x02;
  }

  // Required.
  // Bitmask for the user flags defined above
  int32 flags = 2;
}

सेटिंग ग्रुप

सेटिंग ग्रुप (SettingsGroup क्लास), मिलती-जुलती सेटिंग को व्यवस्थित और मैनेज करते हैं. गाड़ी में कॉन्फ़िगर किए जा सकने वाले हर कॉम्पोनेंट की सेटिंग, ग्रुप के तौर पर तय की जाती हैं. इनमें, की-वैल्यू पेयर के तौर पर दिखाई जाने वाली सेटिंग की सूची शामिल होती है. उदाहरण के लिए, इलेक्ट्रिक सीटों वाली गाड़ियां, ड्राइवर की सीट के लिए एक सेटिंग ग्रुप और सामने वाली पैसेंजर सीट के लिए दूसरा सेटिंग ग्रुप तय कर सकती हैं. इन दोनों ग्रुप में, एक ही नाम वाली सेटिंग शामिल होती हैं.

message SettingsGroup {
  // Required.
  // The identifier for this group.
  SettingsGroupId id = 1;

  // Required.
  // The version number of schema used by this setting group.
  string version = 2;

  // Required.
  // The list of settings within the setting group.
  repeated Setting settings = 3;
}

सेटिंग

सेटिंग, मैसेज (Setting क्लास), SettingsGroup में मौजूद किसी एक सेटिंग को दिखाता है. इस मैसेज में एक कुंजी शामिल होती है, जो सेटिंग का नाम होती है. साथ ही, एक वैल्यू होती है, जो कई तरह की हो सकती है.

इस उदाहरण में दिखाया गया है कि किसी सेटिंग को कुंजी और वैल्यू के साथ कैसे दिखाया जाता है:

// A key value pair representing a setting within a UserControllableService SettingsGroup.
message Setting {
  // Required.
  // A name that uniquely identifies a setting within a SettingsGroup.
  string key = 1;

  // Required.
  // New value of the setting.
  oneof value {
    bool bool = 2;
    float float = 3;
    int32 int32 = 4;
    int64 int64 = 5;
    bytes blob = 6;
    int32 enum = 7;
  }
}

सेटिंग की डेफ़िनिशन

सेटिंग की डेफ़िनिशन (SettingDefinition क्लास), सेटिंग ग्रुप में मौजूद अलग-अलग सेटिंग के लिए टेंप्लेट के तौर पर काम करती हैं. इनमें सेटिंग की बुनियादी विशेषताएं तय की जाती हैं. जैसे, सेटिंग सभी उपयोगकर्ताओं के साथ शेयर की जाती है, हर उपयोगकर्ता के लिए अलग होती है या बाहरी तौर पर मैनेज की जाती है (पासथ्रू).

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

// The definition of a setting, along with its properties such as type and constraints
message SettingDefinition {
  // Required.
  SettingKind kind = 1;

  // Required.
  SettingWithConstraints setting_with_constraints = 2;
}

enum SettingKind {
  // A setting which is applied for all vehicle users.
  SHARED = 0;
  // Store the value of the setting for each vehicle user separately.
  PER_USER = 1;
  // UserControllableService is fully responsible for the storage of PASSTHROUGH setting.
  // User Preferences only notifies UserControllableService when the value is explicitly set by
  // user. User Preferences does not attempt to request changes based on user change or service
  // registration.
  PASSTHROUGH = 2;
};

message SettingWithConstraints {
  // Required
  Setting setting = 1;

  // Required.
  // Defines restrictions on the setting's value
  oneof constraints {
    FloatConstraints float_constraints = 2;
    Int32Constraints int32_constraints = 3;
    Int64Constraints int64_constraints = 4;
    EnumConstraints enum_constraints = 5;
  }
}

message Int32Constraints {
  // The minimum value that a setting can have.
  optional int32 min_value = 1;
  // The maximum value that a setting can have.
  optional int32 max_value = 2;
  // The step by which a setting's value can be increased or decreased.
  optional int32 step = 3;
}

message Int64Constraints {
  // The minimum value that a setting can have.
  optional int64 min_value = 1;
  // The maximum value that a setting can have.
  optional int64 max_value = 2;
  // The step by which a setting's value can be increased or decreased.
  optional int64 step = 3;
}

message FloatConstraints {
  // The minimum value that a setting can have.
  optional float min_value = 1;
  // The maximum value that a setting can have.
  optional float max_value = 2;
  // The step by which a setting's value can be increased or decreased.
  optional float step = 3;
}

message EnumConstraints {
  // Required.
  // List of unique values sorted in ascending order.
  repeated int32 possible_values = 1;
}

जब कोई उपयोगकर्ता सेटिंग अपडेट करता है, तब होने वाले इवेंट का क्रम

इस उदाहरण में, जब कोई उपयोगकर्ता Android Automotive OS (AAOS) में मौजूद इन-व्हीकल इंफ़ोटेनमेंट (IVI) का इस्तेमाल करके, कोई सेटिंग अपडेट करता है, तब होने वाले इवेंट का क्रम दिखाया गया है:

उपयोगकर्ता के सेटिंग बदलने पर होने वाले इवेंट

पहली इमेज. जब कोई उपयोगकर्ता सेटिंग में बदलाव करता है, तब होने वाले इवेंट.

जब कोई गाड़ी स्टार्ट होती है, तब होने वाले इवेंट का क्रम

इस उदाहरण में दिखाया गया है कि जब कोई गाड़ी स्टार्ट होती है, तब SDV User Preferences, उपयोगकर्ता की पसंदीदा सेटिंग कैसे लागू करता है:

वाहन के चालू होने पर होने वाले इवेंट

दूसरी इमेज. जब कोई गाड़ी स्टार्ट होती है, तब होने वाले इवेंट.