ऑर्केस्ट्रेटर एक लोकल एसडीवी एजेंट होता है. यह हर वर्चुअल मशीन (वीएम) पर काम करता है. यह एक ऐसा तरीका उपलब्ध कराता है जिससे यह कंट्रोल किया जा सकता है कि सर्विस बंडल कब बनाए जाने चाहिए, कब शुरू किए जाने चाहिए, कब बंद किए जाने चाहिए या कब हटाए जाने चाहिए. ऐसा ऑर्केस्ट्रेशन कॉन्फ़िगरेशन के ज़रिए किया जाता है. इसमें नियमों का एक सेट तय किया जाता है. इससे यह तय होता है कि सर्विस बंडल इंस्टेंस पर कार्रवाइयां कब और कैसे की जाएंगी. ये नियम, वाहन, पावर, और कस्टम मोड पर आधारित होते हैं.
ऑर्केस्ट्रेटर को कॉन्फ़िगरेशन एपीईएक्स में या हर वीएम के हिसाब से कॉन्फ़िगरेशन के ज़रिए कॉन्फ़िगर किया जा सकता है. यह डिस्ट्रिब्यूटेड कॉन्फ़िगरेशन सिस्टम, सर्विस बंडल के हर हिस्से को सर्विस बंडल रजिस्ट्री के ज़रिए अलग-अलग अपडेट करने की सुविधा देता है. इसके बारे में यहां बताया गया है.
पहली इमेज. ऑर्केस्ट्रेटर के कॉन्फ़िगरेशन का डायग्राम.
वाहन से अलग कॉन्फ़िगरेशन, ओईएम या वाहन के हिसाब से नहीं बदलते. हर ओईएम के सभी वाहनों पर कॉन्फ़िगरेशन एक जैसा रहता है. हालांकि, ओईएम के हिसाब से अलग-अलग वाहनों के लिए, वाहन के हिसाब से कॉन्फ़िगरेशन अलग-अलग हो सकते हैं. ऐसा हो सकता है कि किसी ओईएम के बनाए गए सभी वाहनों के लिए कॉन्फ़िगरेशन एक जैसा हो.
कॉन्फ़िगरेशन एपीएक्स
रन टाइम पर, Orchestrator, सेवा बंडल रजिस्ट्री पर जाता है. इससे वह हर सेवा बंडल के लिए एसडीवी ऑर्केस्ट्रेशन को फ़ेच करता है. साथ ही, हर कॉन्फ़िगरेशन को लोड और पार्स करता है. ज़्यादा जानने के लिए, ऑर्केस्ट्रेशन मेटाडेटा देखें.
हर वीएम के लिए कॉन्फ़िगरेशन
ऑर्केस्ट्रेटर शुरू होने पर, यह वीएम कॉन्फ़िगरेशन को लोड और पार्स करता है. हालांकि, ऐसा सिर्फ़ तब होता है, जब वीएम कॉन्फ़िगरेशन मौजूद हो. इस कॉन्फ़िगरेशन फ़ाइल का पूरा पाथ, सिस्टम प्रॉपर्टी persist.sdv.orchestrator_config_path और ro.boot.sdv.orchestrator_config_path के ज़रिए तय किया जाता है.
सिस्टम, बूट के समय वीएम कॉन्फ़िगरेशन फ़ाइल के पाथ का पता लगाता है. इसके लिए, वह इस क्रम का इस्तेमाल करता है:
सिस्टम,
persist.sdv.orchestrator_config_pathप्रॉपर्टी की जांच करता है. अगर इसकी कोई वैल्यू है, तो उस पाथ का इस्तेमाल किया जाता है. यह वैल्यू, रीबूट करने पर भी बनी रहती है या इसे रन टाइम पर सेट किया जाता है.अगर
persist.sdv.orchestrator_config_pathखाली है, तो सिस्टमro.boot.sdv.orchestrator_config_pathप्रॉपर्टी की जांच करता है. अगरro.boot.sdvप्रॉपर्टी की कोई वैल्यू है, तो उस पाथ को persist प्रॉपर्टी में कॉपी कर दिया जाता है. साथ ही, इसका इस्तेमाल मौजूदा बूट और आने वाले समय के सभी बूट के लिए किया जाता है. हालांकि, इसे बदला जा सकता है.
persist.sdv.orchestrator_config_path
persist.sdv.orchestrator_config_path, SDV Orchestrator एजेंट की मुख्य प्रॉपर्टी है. इसका इस्तेमाल, कॉन्फ़िगरेशन फ़ाइल का पाथ पाने के लिए किया जाता है. यह एक
स्थायी प्रॉपर्टी है. इसका मतलब है कि डिवाइस रीबूट होने पर भी इसकी वैल्यू सेव रहती है. रन टाइम पर वैल्यू बदली जा सकती है. यह टेस्टिंग या खास स्थितियों (उदाहरण के लिए, एंड-टू-एंड टेस्ट) के लिए फ़ायदेमंद है.
setprop कमांड का इस्तेमाल करके, रन टाइम पर वैल्यू सेट की जा सकती है. साथ ही, मेकफ़ाइल (.mk एक्सटेंशन के साथ) या .rc एक्सटेंशन वाली रिसॉर्स स्क्रिप्ट फ़ाइल का इस्तेमाल करके, बिल्ड टाइम पर वैल्यू सेट की जा सकती है.
रन टाइम पर प्रॉपर्टी सेट करना
रन टाइम पर प्रॉपर्टी सेट करने से, टेस्टिंग या कुछ समय के लिए बदलाव करने में मदद मिलती है. ऐसा इसलिए, क्योंकि वैल्यू को रीबूट करने पर भी सेव किया जाता है:
adb root
adb shell setprop persist.sdv.orchestrator_config_path {$path_to_file}.textproto
बिल्ड टाइम पर प्रॉपर्टी सेट करना
इस प्रॉपर्टी को अपने डिवाइस के बिल्ड कॉन्फ़िगरेशन के हिस्से के तौर पर सेट करने के लिए, अपने प्रॉडक्ट या बोर्ड के मेकफ़ाइल में एक लाइन जोड़ें. यह नई डिवाइस इमेज के लिए डिफ़ॉल्ट वैल्यू सेट करने का सबसे सही तरीका है.
# Add this line to a product's or device's .mk file
PRODUCT_PROPERTY_OVERRIDES += persist.sdv.orchestrator_config_path={$path_to_file}.textproto
इस प्रॉपर्टी को किसी रिसॉर्स स्क्रिप्ट फ़ाइल में भी सेट किया जा सकता है:
# Add this line to an .rc file
on {$property}
setprop persist.sdv.orchestrator_config_path {$path_to_file}.textproto
ro.boot.sdv.orchestrator_config_path
ro.boot.sdv.orchestrator_config_path बूट-टाइम की रीड-ओनली प्रॉपर्टी है. इसका इस्तेमाल persist.sdv.orchestrator_config_path प्रॉपर्टी के लिए शुरुआती वैल्यू देने के लिए किया जाता है. अगर सिस्टम बूट होने पर persist.sdv.orchestrator_config_path खाली है, तो ro.boot.sdv.orchestrator_config_path की वैल्यू इसमें कॉपी हो जाती है. persist.sdv.orchestrator_config_path सेट होने के बाद, बाद के बूट पर यह प्रॉपर्टी इसे नहीं बदलेगी.
bootconfig या कर्नल cmdline का इस्तेमाल करके, ro.boot.sdv.orchestrator_config_path सेट किया जा सकता है.
फ़ाइल फ़ॉर्मैट
ऑर्केस्ट्रेशन कॉन्फ़िगरेशन को .textproto फ़ॉर्मैट में तय करें. उदाहरण के लिए, स्ट्रक्चर्ड टेक्स्ट में, ताकि रन टाइम पर नए कॉन्फ़िगरेशन लोड किए जा सकें.
कॉन्फ़िगरेशन सिंटैक्स
इस सेक्शन में कॉन्फ़िगरेशन सिंटैक्स के बारे में बताया गया है.
सेवा बंडल
हर सेवा बंडल को Service bundle configuration के साथ तय किया जाना चाहिए. इससे Orchestrator में बंडल की पहचान होती है. साथ ही, इसका इस्तेमाल बंडल इंस्टेंस के लाइफ़साइकल को मैनेज करने के लिए किया जाता है. सेवा के बंडल के कॉन्फ़िगरेशन से यह तय होता है कि:
InstanceToGroupMappingकी मदद से, किसी ग्रुप में सेवा बंडल का एक इंस्टेंस शामिल किया जा सकता है. इससे एक ही सेवा बंडल के इंस्टेंस के बीच डिपेंडेंसी सेट की जा सकती है.InstancesStates, सेवा बंडल इंस्टेंस के लिए अलग-अलग स्थितियां तय करता है.InstancesStateConfigurationसे उस स्थिति (InstancesStatesसे) के बारे में पता चलता है जिस पर सेवा बंडल के इंस्टेंस को सेट किया जाना चाहिए. ऐसा तब होता है, जब शर्त का आकलनtrueके तौर पर किया जाता है.ServiceBundleConfigमें, किसी खास सेवा बंडल और उसके इंस्टेंस के बारे में जानकारी होती है. इसमें बंडल के लिए,InstanceToGroupMappingऔरInstancesStateConfigurationशामिल हैं.CustomModesसे, कस्टम मोड की सूची तय होती है. बंडल को इन मोड में पब्लिश करने की अनुमति होती है.CustomModesका इस्तेमाल, किसी अनधिकृत बंडल को कस्टम मोड की वैल्यू में बदलाव करने से रोकने के लिए किया जाता है. यह फ़ील्ड भरना ज़रूरी नहीं है, क्योंकि हो सकता है कि सेवा बंडल किसी कस्टम मोड में पब्लिश न हो. ज़्यादा जानने के लिए, कस्टम मोड देखें.
बंडल का ज़रूरी कॉन्फ़िगरेशन
बंडल कॉन्फ़िगरेशन में कम से कम ये एट्रिब्यूट शामिल होते हैं:
service_bundle_config {
package_name: "package_name"
service_bundle_name: "service_bundle_name"
instance: "instance_1"
instance: "instance_n"
}
इस एलान में, n सेवा बंडल के उन इंस्टेंस के बारे में बताया गया है जिनके FQIN ये हैं:
vm_name.package_name.service_bundle_name.instance_1
…
vm_name.package_name.service_bundle_name.instance_n
कॉन्फ़िगरेशन में वीएम का नाम साफ़ तौर पर नहीं बताया गया है. कॉन्फ़िगरेशन को हर वीएम के हिसाब से तय किया जाता है. इसलिए, वीएम का नाम हमेशा उस वीएम का नाम होता है जिस पर कॉन्फ़िगरेशन फ़ाइल डिप्लॉय की जाती है. साथ ही, यह नाम ऑर्केस्ट्रेशन एजेंट को पहले से पता होता है.
इंस्टेंस कॉन्फ़िगर करना
सेवा बंडल इंस्टेंस के बारे में जानकारी देने से कोई असर नहीं पड़ता. ऑर्केस्ट्रेटर से लागू किए जाने के लिए, इंस्टेंस कॉन्फ़िगर किए जाने चाहिए. उदाहरण के लिए, Orchestrator को यह जानकारी होनी चाहिए कि किसी इंस्टेंस को किन शर्तों (या वीएम या वाहन की स्थिति) के तहत चलाना है. उदाहरणों को कॉन्फ़िगर करने के लिए, कॉन्फ़िगरेशन की स्थितियां इन तरीकों से तय की जानी चाहिए:
condition, वीएम या वाहन की स्थिति के बारे में बताने वाला एक एक्सप्रेशन है. इसका आकलन किया जाना चाहिए.instances_states, हर इंस्टेंस के लिए राज्यों का एक सेट है. इसे तब लागू किया जाना चाहिए, जब शर्त का आकलनtrueके तौर पर किया गया हो.
ज़्यादा जानने के लिए, शर्तें देखें.
service_bundle_config {
package_name: "oem.package"
service_bundle_name: "OemApplication"
instance: "adaptive_light"
instance: "reserve_light"
state {
condition {
power_state: "ON"
}
instances_states {
started: "adaptive_light"
created: "reserve_light"
}
}
}
इंस्टेंस को ग्रुप से मैप करना
सेवा ग्रुप में शामिल करके, सेवा इंस्टेंस भी कॉन्फ़िगर किए जा सकते हैं. सर्विस बंडल के कॉन्फ़िगरेशन लेवल पर, ग्रुप में इंस्टेंस जोड़े जा सकते हैं. इसके बाद, वीएम कॉन्फ़िगरेशन लेवल पर ग्रुप कॉन्फ़िगर किए जा सकते हैं. ज़्यादा जानने के लिए, अगला सेक्शन और सेवा बंडल देखें.
service_bundle_config {
package_name: "oem.package"
service_bundle_name: "OemApplication"
instance: "fog_front_light"
instance: "fog_rear_light"
instance: "turn_signal_light"
instance: "light_flasher_display"
# Declare that fog_light contains fog_front_light and fog_rear_light.
group_mapping {
group: "fog_light"
instance: "fog_front_light"
instance: "fog_rear_light"
}
# Declare that flasher_light contains turn_signal_light and light_flasher_display.
group_mapping {
group: "flasher_light"
instance: "turn_signal_light"
instance: "light_flasher_display"
}
}
प्रोटो स्कीमा
यहां प्रोटो स्कीम का एक सैंपल दिया गया है:
// Service bundle configuration.
//
// Defines service bundle data, its instances and configuration for instances
// states depending on the state of the system
message ServiceBundleConfig {
// Required. Name of the service bundle.
string service_bundle_name = 1;
// Required. Package name of the service bundle.
string package_name = 2;
// Required. Service instances.
repeated string instance = 3;
// Configuration for instances states depending on the state of the system.
repeated InstancesStateConfiguration state = 4;
// Mapping of groups to their member service instances.
repeated InstanceToGroupMapping group_mapping = 5;
// Custom modes that this service bundle is allowed to set.
repeated string custom_mode = 6;
// Defines the retry policies for specific instances.
// If multiple mappings target the same instance, the one with the highest `max_retries`
// value takes precedence. This applies across all configuration files.
repeated InstanceToRetryMapping retry_mapping = 7;
}
// Mapping of instances to their retry configuration.
message InstanceToRetryMapping {
// Required.
//
// Name of the instances for which the given retry configuration is applied.
repeated string instance = 1;
// Required.
//
// The configuration that defines the restart and retry strategy for the instances.
RetryConfiguration retry_config = 2;
// Configuration for retry and restart.
// This configuration is applied after a failure on a transition or after the bundle instance
// has crashed. Upon a successful operation, the retry counter are reset to max_retries. This
// configuration can be applied to any service bundle, not only the monitored ones. If the
// configuration is not provided or none of the optional fields are filled, the default behavior
// stated is applied (the value from `ro.boot.sdv.orchestrator.recovery.max_retries`
// or zero if not set).
message RetryConfiguration {
// The number of times a retry/restart operation can be performed.
// Defines the number of times the Orchestrator retries a transition
// after a transient failure or after a bundle crash notification.
// This applies to creating, starting and destroying operations.
// The retry count resets to max_retries after a successful operation.
// If not set, the default configured value in the
// `ro.boot.sdv.orchestrator.recovery.max_retries` is used, or-if not set-
// it fallbacks to zero.
optional uint32 max_retries = 1;
}
}
// Mapping of groups to their member service instances.
message InstanceToGroupMapping {
// Required. Names of groups to which members are added.
//
// Group behavior is defined in VM configuration.
repeated string group = 1;
// Required. Names of instances to be included in the groups.
//
// Can reference only instance defined in the same config file.
repeated string instance = 2;
}
// Describes the state the service instances should be in after the state is executed.
//
// If there is no valid configuration for the instance in the specific system state, such instance is transitioned to the "destroyed" state.
//
// For the GroupsStates definition to be useful, at least one item should be present in any of the fields.
message InstancesStates {
// Names of the instances that must be in a "created" state.
repeated string created = 1;
// Names of the instances that must be in a "started" state, overrides "created" state.
repeated string started = 2;
// Names of the instances that must not run, overrides all other states.
repeated string destroyed = 3;
}
// Configuration for instances states depending on the state of the system.
message InstancesStateConfiguration {
// Condition for the system state under which the related instances states should be executed by Orchestrator.
//
// If omitted, the related instances states are always executed.
Condition condition = 1;
// Required. States of service bundle instances to be executed by Orchestrator if the condition is true.
InstancesStates instances_states = 2;
}
वीएम-लेवल का कॉन्फ़िगरेशन
वीएम कॉन्फ़िगरेशन की मदद से, ग्रुप मैपिंग और ग्रुप के लिए कॉन्फ़िगरेशन तय किया जा सकता है. इसका इस्तेमाल, वीएम लेवल पर सेवा बंडलों के बीच डिपेंडेंसी को मॉडल करने के लिए किया जाता है. इससे एक ही समय में कई सेवा बंडलों की स्थिति में बदलाव करने की सुविधा मिलती है. ग्रुप के सभी इंस्टेंस को तय की गई स्थिति में लाया जाता है.
ऑर्केस्ट्रेटर, इस बात की गारंटी नहीं देता कि स्थिति में बदलाव किस क्रम में लागू होगा. ऑर्केस्ट्रेटर, हर इंस्टेंस को दी गई स्थिति में प्रमोट करता है.
कॉन्फ़िगरेशन के किसी भी हिस्से में group नाम का इस्तेमाल करके, ग्रुप का एलान इंप्लिसिट तरीके से किया जाता है. उदाहरण के लिए, इंस्टेंस से ग्रुप मैपिंग, ग्रुप से ग्रुप मैपिंग, और ग्रुप कॉन्फ़िगरेशन की स्थितियां.
ग्रुप से ग्रुप की मैपिंग
ग्रुप में अन्य ग्रुप शामिल किए जा सकते हैं. group_1 में subgroup_2 शामिल है, यह एलान करके हम subgroup_2 में मौजूद सेवा के सभी इंस्टेंस को group_1 में जोड़ देते हैं.
उदाहरण के लिए:
# Declare that body contains fog_light and flasher_light.
group_mapping {
group: "body"
subgroup: "fog_light"
subgroup: "flasher_light"
}
किसी ग्रुप को कॉन्फ़िगर करना
किसी ग्रुप को घोषित करने से कोई फ़र्क़ नहीं पड़ता. ऑर्केस्ट्रेटर से एक्ज़ीक्यूट किए जाने के लिए, ग्रुप कॉन्फ़िगर किए जाने चाहिए. उदाहरण के लिए, ऑर्केस्ट्रेटर को यह जानकारी होनी चाहिए कि ग्रुप को किन शर्तों के तहत या वीएम या वाहन की किस स्थिति में चलाना है.
कॉन्फ़िगरेशन की स्थितियों का इस्तेमाल करके, ग्रुप को सेवा इंस्टेंस की तरह कॉन्फ़िगर किया जा सकता है. सिंटैक्स में सिर्फ़ यह अंतर है कि instances_states के बजाय groups_states का इस्तेमाल किया गया है:
state {
condition {
power_state: "ON"
}
groups_states {
started: "Body"
started: "Adas"
}
}
प्रोटो स्कीमा
यहां एक सैंपल प्रोटो स्कीमा दिया गया है:
// VM configuration.
//
// Defines group-to-group mappings and configuration for groups
// states depending on the state of the system.
//
// Configurations of service bundles can also be defined in VM configuration (as well as in a separate configuration file).
message VmConfig {
// Group to member groups mapping.
repeated GroupToGroupMapping group_mapping = 1;
// Configuration of group states.
repeated GroupsStateConfiguration state = 2;
// Required. We also allow to configure individual service bundles in the VM config, to simplify development and migration from the monolithic configuration.
repeated ServiceBundleConfig service_bundle_config = 3;
}
// Mapping of groups to their member groups.
message GroupToGroupMapping {
// Required. Names of groups to which members are added.
repeated string group = 1;
// Required. Names of member groups to be included in the groups.
repeated string subgroup = 2;
}
// Describes the state the service instance groups should be in after the state is executed.
//
// If group configuration is valid in a specific system state, the configured state is applied to
// all group members. After that, the normal service instance configuration rules still apply:
// - "destroyed" > "started" > "created" precedence
// - not configured means the instance should be moved to the default state
//
// For the GroupsStates definition to be useful, at least one item should be present in any of the fields.
message GroupsStates {
// Names of the groups that must be in a "created" state.
repeated string created = 1;
// Names of the groups that must be in a "started" state, overrides "created" state.
repeated string started = 2;
// Names of the groups that must not run, overrides all other states.
repeated string destroyed = 3;
}
// Configuration for group states depending on the state of the system.
message GroupsStateConfiguration {
// Condition for the system state under which the related group states should be executed by Orchestrator.
//
// If omitted, the related groups states are always executed.
Condition condition = 1;
// Required. States of service bundle groups to be executed by Orchestrator if the condition is true.
GroupsStates groups_states = 2;
}
कॉन्फ़िगरेशन की स्थितियां
कॉन्फ़िगरेशन की स्थितियां (स्टेट) यह तय करती हैं कि किसी सेवा के इंस्टेंस या ग्रुप को कब शुरू, बंद या डिस्ट्रॉय किया जाए. इसमें conditions और instances_states (बंडल कॉन्फ़िगरेशन) और groups_states (वीएम कॉन्फ़िगरेशन) शामिल हैं.
शर्तें
शर्तों की मदद से, मॉडल को बूलियन शर्त दी जाती है. इस शर्त के true होने पर, तय की गई इंस्टेंस की स्थिति लागू होती है. किसी शर्त में ये विशेषताएं होती हैं:
सपोर्ट किए गए सिग्नल के आधार पर, मनमाने तौर पर जटिल बूलियन एक्सप्रेशन (
andयाnotएक्सप्रेशन से बना). जैसे, पावर, वाहन, और कस्टम मोड.(ज़रूरी नहीं) शर्त के बिना कॉन्फ़िगरेशन की स्थिति हमेशा चालू रहती है. इसका मतलब है कि यह
trueके तौर पर काम करती है
इंस्टेंस और ग्रुप के स्टेटस
instances_states और groups_states में ये विशेषताएं होती हैं.
यह तय करें कि दिए गए इंस्टेंस या ग्रुप पर लागू करने के लिए, ऑर्केस्ट्रेशन एजेंट को किन स्थितियों की ज़रूरत है. हालांकि, यह ज़रूरी है कि स्थिति
activeहोग्रुप पर कोई स्थिति लागू करने पर, वह ग्रुप में मौजूद हर सेवा बंडल इंस्टेंस पर लागू होती है. इस स्थिति में इंस्टेंस कब लाए जाते हैं, इसके लिए कोई क्रम तय नहीं किया गया है.
ये राज्य शामिल हैं:
Service::on_startके बादstartedको कॉल किया जाता है.createdService::newको कॉल करने के बाद, लेकिनService::on_startको कॉल करने से पहले.या
Service::on_stopको कॉल करने के बाद, लेकिनService::dropको कॉल करने से पहले.
Service::dropके बादdestroyedको कॉल किया जाता है.
नियमों का सेट
कॉन्फ़िगरेशन की स्थिति, शर्त के आधार पर चालू या बंद हो सकती है. एक से ज़्यादा स्थितियां एक साथ चालू हो सकती हैं. जब ऑर्केस्ट्रेशन एजेंट को सिग्नल अपडेट मिलता है, तो सर्विस बंडल के लाइफ़साइकल में बदलाव करने से पहले, सभी कॉन्फ़िगरेशन स्टेटस का आकलन किया जाता है. सेवा के इंस्टेंस की स्थितियों का आकलन इन नियमों के मुताबिक किया जाता है:
जब सेवा के इंस्टेंस पर, ऐक्टिव स्टेट में से कोई भी लागू नहीं होती है, तो उसे बंद कर दिया जाता है.
जब एक या उससे ज़्यादा स्थितियां लागू होती हैं, तब यह प्राथमिकता लागू होती है:
destroyedको सबसे ज़्यादा प्राथमिकता दी जाती है.startedकोcreatedसे पहले प्राथमिकता दी जाती है.
प्रोटो स्कीमा
यहां एक सैंपल प्रोटो स्कीमा दिया गया है:
// A root boolean condition.
message Condition {
// Required.
oneof root {
// VPM power state condition.
string power_state = 1;
// VPM vehicle state condition.
string vehicle_state = 2;
// Custom mode state condition.
CustomState custom_state = 3;
// Negation of a nested condition.
Condition not = 4;
// Logical 'and' between conditions grouped in expression.
Expression and = 5;
// Logical 'or' between conditions grouped in expression.
Expression or = 6;
}
}
// Representation of Custom state condition.
//
// Custom mode(s) are defined by the OEM and are not standardized by the platform, in contrast with
// VPM modes (i.e. power and vehicle mode).
message CustomState {
// Custom mode being checked.
string mode = 1;
// State of the custom mode.
string state = 2;
}
// A set of conditions united under an 'and' or 'or' expression.
//
// Evaluation type ('and' or 'or') depends on the field in [Condition]/[Expression], where the
// expression is being used.
//
// At least one value in at least one of the fields is required.
message Expression {
// VPM power state condition.
repeated string power_state = 1;
// VPM vehicle state condition.
repeated string vehicle_state = 2;
// Custom mode state condition.
repeated CustomState custom_state = 3;
// Negation of a nested condition.
repeated Condition not = 4;
// Logical 'and' between conditions grouped in expression.
repeated Expression and = 5;
// Logical 'or' between conditions grouped in expression.
repeated Expression or = 6;
}
क्रैश होने के बाद ठीक होने और रीस्टार्ट करने की रणनीति
ऑर्केस्ट्रेटर, सर्विस बंडल क्रैश होने और लाइफ़साइकल ट्रांज़िशन फ़ेल होने की समस्याओं को हल करने के लिए, एक मज़बूत तरीका उपलब्ध कराता है. ऑर्केस्ट्रेटर के पास सेवा की स्थितियों की पूरी जानकारी होती है. साथ ही, यह मोड ट्रांज़िशन को मैनेज करता है. इसलिए, यह रीस्टार्ट करने और फिर से कोशिश करने की रणनीति को लागू करने के लिए सबसे सही कॉम्पोनेंट है. लाइफ़साइकल मैनेजर (एलएम), सेवा के बंडल क्रैश होने की जानकारी Orchestrator को देता है. इसके लिए, वह बाइंडर डेथ नोटिफ़िकेशन का इस्तेमाल करता है. एलएम को गैर-ज़रूरी बाइंडर कॉल से बचने के लिए, Orchestrator हर बंडल की पिछली स्थिति को कैश मेमोरी में सेव करता है. इससे कोई फ़र्क़ नहीं पड़ता कि बंडल की स्थिति सफल है या नहीं. अगर पिछली स्थिति, नई स्थिति के जैसी है, तो Orchestrator ट्रांज़िशन को फिर से लागू नहीं करता.
कॉन्फ़िगरेशन को फिर से आज़माएं
retry_mapping का इस्तेमाल करके, Orchestrator कॉन्फ़िगरेशन में हर इंस्टेंस के लिए, रीस्टार्ट करने और फिर से कोशिश करने की रणनीति तय की जा सकती है. अगर कॉन्फ़िगरेशन में max_retries सेट नहीं है, तो डिफ़ॉल्ट वैल्यू को ro.boot.sdv.orchestrator.recovery.max_retries सिस्टम प्रॉपर्टी से लिया जाता है. अगर इस प्रॉपर्टी को सेट नहीं किया जाता है, तो वैल्यू 0 पर वापस आ जाती है.
max_retries: इससे यह तय होता है कि Orchestrator, कुछ समय के लिए होने वाली गड़बड़ी या बंडल क्रैश होने की सूचना मिलने के बाद, कितनी बार ट्रांज़िशन करने की कोशिश करेगा. ऑपरेशन पूरा होने या नया मोड प्रोसेस होने के बाद, फिर से कोशिश करने की संख्याmax_retriesपर रीसेट हो जाती है. अगर एक से ज़्यादा मैपिंग, एक ही इंस्टेंस को टारगेट करती हैं, तो सबसे ज़्यादाmax_retriesवाली मैपिंग को प्राथमिकता दी जाती है.
कॉन्फ़िगरेशन का सैंपल
service_bundle_config {
package_name: "oem.package"
service_bundle_name: "OemApplication"
instance: "fog_front_light"
instance: "fog_rear_light"
# Defines the restart configuration mapping for specific instances.
retry_mapping {
instance: "fog_front_light"
instance: "fog_rear_light"
retry_config {
max_retries: 3
}
}
}
खाता वापस पाने से जुड़ी गतिविधि
ऑर्केस्ट्रेटर के रीस्टार्ट और फिर से कोशिश करने की सुविधा, कई तरह की गड़बड़ियों को आसानी से ठीक कर देती है:
- सामान्य ऑपरेशन क्रैश: अगर कोई सेवा बंडल चलते समय क्रैश हो जाता है, तो Orchestrator, रीस्टार्ट करने की रणनीति लागू करता है. साथ ही, बंडल को उसकी पिछली स्थिति में वापस लाने की कोशिश करता है. यह कोशिश, बंडल को रीस्टार्ट करने के लिए बची हुई कोशिशों के आधार पर की जाती है.
- मोड बदलने के दौरान क्रैश होना: अगर नया मोड लागू करते समय कोई बंडल क्रैश हो जाता है, तो रीस्टार्ट करने का अनुरोध कतार में लग जाता है और उसे बाद में प्रोसेस किया जाता है. अनुरोध प्रोसेस होने के बाद, Orchestrator यह देखता है कि इंस्टेंस की आखिरी स्थिति क्या थी. इसके बाद, वह सिर्फ़ तब रीस्टार्ट करता है, जब इंस्टेंस, अनुरोध की गई आखिरी स्थिति में न हो (पिछली मोड ट्रांज़िशन से).
- रिकवरी के दौरान नया मोड: अगर बंडल को रीस्टार्ट किया जा रहा है या वह रीस्टार्ट किए जाने वाले इंस्टेंस की सूची में है, तो Orchestrator को नए मोड पर ट्रांज़िशन करने का अनुरोध मिलने पर, वह चालू रिकवरी को रद्द कर देता है. नया मोड ट्रांज़िशन चालू हो जाता है और फिर से कोशिश करने की संख्या को रीसेट कर दिया जाता है, ताकि नए टारगेट स्टेट के लिए नए सिरे से कोशिश की जा सके.
Orchestrator, Lifecycle Manager से मिली अलग-अलग तरह की गड़बड़ियों के बीच अंतर करता है, ताकि फिर से कोशिश करने की रणनीति तय की जा सके:
- अस्थायी गड़बड़ियां (
SERVICE_NOT_FOUND,OPERATION_FAILED,INTERNAL_ERROR): Orchestrator, किसी खास क्लीनअप कार्रवाई के बिना ऑपरेशन को फिर से आज़माता है. - लगातार होने वाली गड़बड़ियां (
VALUE_CORRUPTED,INVALID_ARGUMENT): Orchestrator यह मान लेता है कि सेवा बंडल खराब हो गया है. इसलिए, यह सेवा इंस्टेंस को बंद करने की कोशिश करता है. इसके बाद, यह ऑपरेशन को फिर से शुरू करता है, ताकि यह पक्का किया जा सके कि सेवा को सही तरीके से रीस्टार्ट किया गया है. - स्थायी गड़बड़ियां (
PERMISSION_DENIED): इस तरह की गड़बड़ियों के ठीक होने पर, ऑपरेशन को फिर से शुरू नहीं किया जाता. साथ ही, बंडल को ऐसी स्थिति में माना जाता है जिसे ठीक नहीं किया जा सकता.
अगर लाइफ़साइकल मैनेजर क्रैश हो जाता है, तो सभी सेवा बंडल प्रोसेस बंद हो जाती हैं. असल स्थिति के बारे में जानकारी न होने की वजह से, Orchestrator हर इंस्टेंस को अमान्य कर देता है. साथ ही, हर इंस्टेंस को आखिरी बार अनुरोध की गई स्थिति में लाने के लिए, फिर से शुरू करने की रणनीति लागू करता है.
बार-बार क्रैश होने या काम न करने वाले बंडलों के लिए, रिकवरी के लूप को बार-बार होने से रोकने के लिए, फिर से कोशिश करने वाले काउंटर को सिर्फ़ तब max_retries पर रीसेट किया जाता है, जब लाइफ़साइकल ऑपरेशन पूरा हो जाता है या जब नए मोड में ट्रांज़िशन करने का अनुरोध किया जाता है. अगर किसी बंडल के लगातार अनुरोध पूरे नहीं होते हैं, तो वह फिर से अनुरोध करने की तय सीमा तक पहुंच जाता है. उदाहरण के लिए, ट्रांज़िशन पूरा न होने के बाद क्रैश हो जाना. ऐसे में, बंडल तब तक फिर से अनुरोध नहीं कर सकता, जब तक कि फिर से अनुरोध करने की सीमा रीसेट नहीं हो जाती.
सेहत की निगरानी करने वाले ऐप्लिकेशन को स्थिति की जानकारी देना
ऑर्केस्ट्रेटर, इंटरनल बाइंडर इंटरफ़ेस को दिखाता है. Health Monitor (HM) इस इंटरफ़ेस के साथ रजिस्टर करता है, ताकि उसे सभी सर्विस बंडल की स्थिति के बारे में लगातार अपडेट मिलते रहें. इस इंटरफ़ेस के ज़रिए, Orchestrator इन दोनों की रिपोर्ट देता है:
- लाइफ़साइकल की स्थिति: मौजूदा कॉन्फ़िगरेशन और चालू मोड के आधार पर, इंस्टेंस की स्थिति (जैसे, शुरू किया गया, बनाया गया या बंद किया गया).
- रिकवरी की स्थिति: इससे लाइफ़साइकल की तय की गई स्थिति तक पहुंचने का स्टेटस पता चलता है. इससे यह पता चलता है कि इंस्टेंस काम कर रहा है या नहीं. साथ ही, यह भी पता चलता है कि अगर इंस्टेंस काम नहीं कर रहा है, तो क्या उसे ठीक करने की कोशिश की जा रही है या कोशिशें पूरी होने के बाद भी वह ठीक नहीं हो पाया है.
यह जानकारी सभी इंस्टेंस के लिए रिपोर्ट की जाती है. इसमें वे इंस्टेंस भी शामिल हैं जिन्होंने हार्टबीट मॉनिटरिंग के लिए रजिस्टर नहीं किया है. HM इस जानकारी का इस्तेमाल, अपने एपीआई लागू करने के लिए करता है. इससे वीएम की स्थिति की जानकारी दी जा सकती है. इस बारे में ज़्यादा जानने के लिए, सेहत की निगरानी पर जाएँ.
उदाहरण
इस सेक्शन में, शर्तों के साथ स्थितियां कॉन्फ़िगर करने के उदाहरण दिए गए हैं.
बुनियादी सेवा का सैंपल
- इसमें कोई शर्त नहीं होती. इसलिए, यह हमेशा चालू रहता है.
- यह एक सेवा इंस्टेंस शुरू करता है.
state {
# Note: This state has no condition, hence its actions are valid throughout the lifetime of the program
instances_states { started: "ServiceBundleName" }
}
एचवीएसी ऐप्लिकेशन का सैंपल
शर्त:
custom_state != occupancy.OCCUPANCY_EMPTY || custom_state == preheat.PREHEAT_ONहोने पर चालू होती है.एचवीएसी से जुड़ी कई सेवाओं को
startedके तौर पर दिखाता है.
state {
condition {
or {
# I.e. when the vehicle is occupied (for example, by _DRIVER / _NON_DRIVER / _PET)
not {
custom_state {
mode: "occupancy"
state: "OCCUPANCY_EMPTY"
}
}
custom_state {
mode: "preheat"
state: "PREHEAT_ON"
}
}
}
# HVAC-related services
instances_states {
started: "HvacTemperatureCommand"
started: "TempSensorDriverZone"
started: "TempSensorPassengerZone"
started: "RefrigerantLoop"
}
}
बैटरी बचाने की सुविधा का सैंपल
शर्त:
custom_state == system_power.SYSTEM_POWER_LOW && custom_state == range_ext.RANGE_EXT_ONहोने पर चालू होती है.इस स्थिति को, बैटरी बचाने वाली स्थिति के तौर पर देखा जा सकता है.
यह कुकी, एचवीएसी से जुड़ी किसी सेवा के इंस्टेंस को
destroyedके तौर पर सेट करती है.इस उदाहरण में,
SYSTEM_POWER_LOWऔरRANGE_EXT_ONमोड चालू होने पर, एचवीएसी ऐप्लिकेशन,RefrigerantLoopसेवा इंस्टेंस के बिना चलता है:state { condition { and { custom_state { mode: "system_power" state: "SYSTEM_POWER_LOW" } custom_state { mode: "range_ext" state: "RANGE_EXT_ON" } } } # Disable services with high power consumption instances_states { destroyed: "RefrigerantLoop" } }
लाइफ़ ऑनबोर्ड सैंपल
शर्त: अगर
power_state == ON && vehicle_state == LIFE_ON_BOARDहै, तो चालू है.इस स्थिति को कार में कोई व्यक्ति मौजूद है और कार चालू है के तौर पर देखा जा सकता है.
यह कुकी, तापमान मापने वाले सेंसर को चालू के तौर पर सेट करती है.
जब कोई व्यक्ति कार में होता है, तो सुरक्षा के लिहाज़ से तापमान जैसी चीज़ों की निगरानी की जाती है.
state {
condition {
and {
power_state: "ON"
vehicle_state: "LIFE_ON_BOARD"
}
}
# Temperature monitoring services
instances_states {
started: "TempSensorDriverZone"
started: "TempSensorPassengerZone"
}
}
उदाहरण
इस सेक्शन में, पूरे उदाहरण दिए गए हैं. इनमें यह जानकारी शामिल है:
सेवा बंडल-लेवल का प्रोटो कॉन्फ़िगरेशन, जिसमें दो इंस्टेंस वाला सेवा बंडल शामिल है. इनमें से हर इंस्टेंस, ग्रुप का एक हिस्सा है
वीएम-लेवल का प्रोटो कॉन्फ़िगरेशन, जो मोड के आधार पर ग्रुप से इंटरैक्ट करने के लिए लॉजिक पेश करता है
सेवा के बंडल के लेवल का कॉन्फ़िगरेशन
# proto-file: //system/software_defined_vehicle/orchestration/distributed_config/src/protos/service_bundle_config.proto
# proto-message: ServiceBundleConfig
package_name: "oem.package"
service_bundle_name: "OemApplication"
instance: "fog_front_light"
instance: "fog_rear_light"
instance: "turn_signal_light"
custom_mode: "FOG"
custom_mode: "TURN"
group_mapping {
group: "fog_light"
instance: "fog_front_light"
instance: "fog_rear_light"
}
group_mapping {
group: "flasher_light"
instance: "turn_signal_light"
}
state {
condition {
power_state: "ON"
}
instances_states {
created: "turn_signal_light"
destroyed: "fog_front_light"
destroyed: "fog_rear_light"
}
}
वीएम-लेवल का कॉन्फ़िगरेशन
# proto-file: //system/software_defined_vehicle/orchestration/distributed_config/src/protos/vm_config.proto
# proto-message: VmConfig
group_mapping {
group: "lights"
subgroup: "fog_light"
subgroup: "flasher_light"
}
state {
condition {
custom_state {
mode: "FOG"
state: "ON"
}
}
groups_states {
started: "fog_light"
}
}
state {
condition {
custom_state {
mode: "TURN"
state: "RIGHT"
}
}
groups_states {
started: "flasher_light"
}
}
state {
condition {
vehicle_state: "SUSPEND_TO_RAM_ENTER"
}
groups_states {
created: "lights"
}
}
बंडल मैनेजमेंट के लिए पैरललिज़्म को कॉन्फ़िगर करना
ro.boot.sdv.max_bundles_management_threads सिस्टम प्रॉपर्टी, सर्विस बंडल के लाइफ़साइकल के दौरान परफ़ॉर्मेंस और संसाधन की खपत को कंट्रोल करने के लिए, एक अहम ट्यूनिंग पैरामीटर है. यह सेवा बंडल के लेन-देन के लिए, पैरललिज़्म के ज़्यादा से ज़्यादा लेवल को तय करता है. साथ ही, यह दो मुख्य सेवाओं पर सीधे तौर पर असर डालता है:
ऑर्केस्ट्रेशन इंजन: यह सेवा प्रॉपर्टी को पढ़कर यह तय करती है कि ऑर्केस्ट्रेटर, लाइफ़साइकल मैनेजर को एक साथ कितने कॉल (उदाहरण के लिए,
startService,stopService) कर सकता है. यह बूट-अप और मोड ट्रांज़िशन के दौरान परफ़ॉर्मेंस के लिए ज़रूरी है. ऐसा इसलिए, क्योंकि कई बंडल एक साथ स्थिति बदल सकते हैं.लाइफ़साइकल मैनेजर: यह सेवा, प्रॉपर्टी की वैल्यू का इस्तेमाल करके, Binder थ्रेड पूल के साइज़ का हिसाब लगाती है. यह पूल, सभी इनकमिंग अनुरोधों को मैनेज करने के लिए ज़िम्मेदार होता है. इससे यह पक्का होता है कि एलएम के पास, ऑर्केस्ट्रेटर से एक साथ आने वाले अनुरोधों को मैनेज करने के लिए ज़रूरी थ्रेड मौजूद हैं.
अगर यह प्रॉपर्टी सेट नहीं की जाती है, तो दोनों सेवाओं के लिए डिफ़ॉल्ट वैल्यू 12 होती है.
कॉन्फ़िगरेशन का तरीका
BoardConfig.mk फ़ाइल में प्रॉपर्टी सेट करने के लिए, उसे BOARD_BOOTCONFIG वैरिएबल में जोड़ें. इससे यह पक्का होता है कि डिवाइस के बूट होने पर, वैल्यू हर बार लागू हो.
BOARD_BOOTCONFIG += \
androidboot.sdv.max_bundles_management_threads=8
अपने डिवाइस के लिए वैल्यू बदलने के लिए, सही BoardConfig.mk फ़ाइल में इस लाइन में बदलाव करें और फिर से बनाएं.
बूट-टाइम ऑप्टिमाइज़ेशन
ro.sdv.orchestrator.state.ready एक write-once बूलियन प्रॉपर्टी है. यह बूट-टाइम परफ़ॉर्मेंस ऑप्टिमाइज़ेशन की रणनीति का हिस्सा है. इससे पता चलता है कि ऑर्केस्ट्रेशन एजेंट ने अपना इनिशियलाइज़ेशन पूरा कर लिया है और अब वह सेवा बंडलों के लाइफ़साइकल को मैनेज करने के लिए तैयार है. इसका मुख्य मकसद, Orchestrator और उसके मैनेज किए गए सेवा बंडलों को प्राथमिकता देना है. इसके लिए, यह अन्य SDV एजेंट के स्टार्टअप सीक्वेंस को कंट्रोल करता है.
- सेट करने वाला: ऑर्केस्ट्रेशन एजेंट.
- कब: बूट-अप के दौरान एक बार.
- इस्तेमाल: इस प्रॉपर्टी का इस्तेमाल, init सिस्टम करता है. इससे ज़्यादातर एसडीवी एजेंट (अपडेट मैनेजर, VSIDL प्रोवाइडर, हेल्थ मॉनिटर, सर्विस डिस्कवरी, डेटा टनल, आरपीसी, वीपीएम, और टेलीमेट्री) के स्टार्टअप सीक्वेंस को कंट्रोल किया जाता है. ऑर्केस्ट्रेटर को पहले शुरू करके और अन्य एजेंटों को इस प्रॉपर्टी के लिए इंतज़ार करने के लिए कहकर, सिस्टम यह पक्का करता है कि ऑर्केस्ट्रेटर, सिस्टम संसाधनों के लिए प्रतिस्पर्धा किए बिना, सेवा बंडल शुरू करने का अपना ज़रूरी काम शुरू कर सके.
परफ़ॉर्मेंस
सिस्टम बूट होने के दौरान, सभी एजेंट को एक साथ शुरू करने से, संसाधनों के लिए विवाद हो सकता है. इससे बूट होने की पूरी प्रोसेस धीमी हो जाती है. इस समस्या को कम करने के लिए, सिस्टम प्रॉपर्टी का इस्तेमाल करके स्टार्टअप के क्रम को लागू किया जाता है:
- सेवाओं के बंडल की रजिस्ट्री: यह सबसे पहले शुरू होती है, ताकि सेवाओं के बंडल का पूरा मेटाडेटा लोड किया जा सके.
- लाइफ़साइकल मैनेजर और ऑर्केस्ट्रेटर: ये मुख्य एजेंट, रजिस्ट्री के तैयार होते ही शुरू हो जाते हैं. यह प्रोसेस जल्दी शुरू करना ज़रूरी है, क्योंकि इससे ऑर्केस्ट्रेटर को अपने कॉन्फ़िगरेशन का आकलन करने और सेवा बंडल तुरंत शुरू करने की तैयारी करने में मदद मिलती है.
- अन्य एसडीवी एजेंट: Orchestrator के तैयार होने के बाद ही शुरू करें.
इस कंट्रोल की गई सीक्वेंस से यह पक्का होता है कि Orchestrator को सिस्टम के संसाधनों का इस्तेमाल करने की प्राथमिकता मिले, ताकि वह जल्द से जल्द सेवा बंडल शुरू कर सके. इससे सिस्टम को तेज़ी से, ज़्यादा भरोसेमंद तरीके से, और ज़्यादा कुशलता से शुरू किया जा सकता है.
Orchestrator के इस्तेमाल किए गए मोड
ऑर्केस्ट्रेशन एजेंट, वीपीएम से ट्रांसमिट किए गए वाहन और पावर मोड की चालू सदस्यता बनाए रखता है. Orchestrator और Vehicle and Power Management (VPM) सिस्टम के बीच शुरुआती कनेक्शन बनने पर, Orchestrator इन बूलियन सिस्टम प्रॉपर्टी को true पर सेट करता है:
sdv.orchestrator.bootup.power_mode.readysdv.orchestrator.bootup.vehicle_mode.ready
कॉन्फ़िगरेशन फ़ाइल को रेफ़रंस के तौर पर इस्तेमाल करके, ऑर्केस्ट्रेशन एजेंट डाइनैमिक तरीके से सेवा बंडलों का सेट बनाता है. यह सेट, मिले हुए मोड की मौजूदा वैल्यू के आधार पर तय किया जाता है. इसके बाद, ऑर्केस्ट्रेटर लाइफ़साइकल मैनेजर से कम्यूनिकेट करता है. साथ ही, सेवा बंडलों की मौजूदा स्थिति को टारगेट स्थिति के साथ अलाइन करने के लिए, अलग-अलग निर्देश जारी करता है.
वाहन और पावर की स्थितियां
वाहन मोड और पावर मैनेजमेंट (वीपीएम) एजेंट, एसडीवी कॉम्पोनेंट को वाहन की मौजूदा स्थिति के बारे में जानकारी देता है. जैसे, ऑपरेशनल मोड (उदाहरण के लिए, पार्क या ड्राइव) और पावर स्टेटस (उदाहरण के लिए, चालू और बंद). ऑर्केस्ट्रेटर इन वैल्यू का आकलन करता है, ताकि यह तय किया जा सके कि ऑर्केस्ट्रेटर कॉन्फ़िगरेशन के आधार पर, कौनसे सर्विस बंडल चलाने चाहिए. ज़्यादा जानने के लिए, वाहन और पावर मैनेजमेंट देखें.
कस्टम मोड
गाड़ी के कई मोड होते हैं. इसलिए, हम सभी मोड को मॉडल नहीं कर सकते. हर ओईएम की ज़रूरतें अलग-अलग होती हैं. साथ ही, वाहन के मोड को स्टैंडर्ड बनाने से, ओईएम के इस्तेमाल के सभी उदाहरणों को हल नहीं किया जा सकता. इसलिए, हम ओईएम के हिसाब से मोड उपलब्ध कराते हैं. इन्हें कस्टम मोड कहा जाता है. ये मोड, मौजूदा वाहन और पावर मोड को नहीं बढ़ाते हैं. इसके बजाय, ये नए मोड तय करने का तरीका बताते हैं.
फ़ंक्शन:
ग्लोबल स्कोप: कस्टम मोड ग्लोबल होते हैं. ये ऑर्केस्ट्रेटर से मैनेज की जा रही सभी वीएम पर एक जैसे लागू होते हैं.
कंपोज़िशन: कस्टम मोड में बदलाव करने के लिए, दो एलिमेंट का इस्तेमाल किया जाता है:
नाम: यह कस्टम मोड को दिखाने के लिए, OEM की ओर से चुना गया यूनीक आइडेंटिफ़ायर होता है.
वैल्यू: कस्टम मोड की मौजूदा स्थिति. अगर कोई वैल्यू सेट नहीं की गई है, तो यह
UNDEFINEDहो सकती है
ऑर्केस्ट्रेटर की भूमिका: ऑर्केस्ट्रेटर, कस्टम मोड की वैल्यू को सिर्फ़ रिसीव करता है.
सेवा बंडल की भूमिका: हर सेवा बंडल के पास कई कस्टम मोड हो सकते हैं. साथ ही, वह किसी भी कस्टम मोड में नई वैल्यू पब्लिश कर सकता है. एक ही कस्टम मोड का मालिकाना हक, एक से ज़्यादा सेवा बंडलों के पास हो सकता है. इसका मतलब है कि कस्टम मोड को अलग-अलग सोर्स से नई वैल्यू मिल सकती हैं.
पुष्टि करने की ज़िम्मेदारी: ओईएम की यह ज़िम्मेदारी है कि वे यह पक्का करें कि डिवाइस की स्थिति में बदलाव मान्य हो. ऑर्केस्ट्रेटर, नई वैल्यू को स्वीकार कर लेता है.
अनुमानित विशेषताएं:
अनुमानित संख्या: पावर और वाहन मोड, ज़्यादातर सेवा बंडलों के लाइफ़साइकल को मैनेज करते हैं. कस्टम मोड, इसमें सहायक भूमिका निभाते हैं. हमें उम्मीद है कि कस्टम मोड की संख्या कुछ दर्जन होगी, न कि सैकड़ों.
अनुमानित समय: मोड समय-समय पर नहीं भेजे जाते. इसके बजाय, मोड इवेंट पर आधारित होते हैं. ये किसी खास कार्रवाई से ट्रिगर होते हैं. जैसे, दरवाज़ा खोलना, पार्किंग की प्रोसेस शुरू करना, चार्जिंग साइकल शुरू करना, और ओईएम के तय किए गए अन्य इवेंट.
कस्टम मोड के डिज़ाइन की मदद से, खास मोड को तय और मैनेज किया जा सकता है. साथ ही, Orchestrator को स्टेट मशीन लॉजिक की बुनियादी स्थिति के बारे में जानकारी नहीं देनी पड़ती.
इस्तेमाल किए जा सकने वाले मोड
यह पक्का करने के लिए कि सेवा बंडल सिर्फ़ उन कस्टम मोड पर पब्लिश हों जिनके वे मालिक हैं, हर बंडल को अपने ऑर्केस्ट्रेटर कॉन्फ़िगरेशन में, मालिकाना हक वाले कस्टम मोड की सूची का साफ़ तौर पर एलान करना होगा. यह सूची, सेवा बंडल रजिस्ट्री के साथ लोकल वीएम में उपलब्ध होती है. कस्टम मोड के बारे में जानकारी न देने पर, उसे पब्लिश करने की कोशिशों को खारिज कर दिया जाता है.
किसी सेवा बंडल को पब्लिश करने की अनुमति वाले कस्टम मोड का एलान करने के लिए, service_bundle_config प्रोटो स्कीमा को इन चीज़ों के साथ बढ़ाया गया है:
// Service bundle configuration.
//
// Defines service bundle metadata, its instances, and configuration for instances
// lifecycle states depending on the state of the vehicle.
message ServiceBundleConfig {
[...]
// The list of custom modes that this service bundle publishes.
repeated string custom_mode = 5;
}
मोड के आधार पर बंडल कॉन्फ़िगर करना
मौजूदा Orchestrator प्रोटो कॉन्फ़िगरेशन (Condition कॉम्पोनेंट) की मदद से, कस्टम मोड के आधार पर सेवा बंडलों में बदलाव किया जा सकता है:
message Condition {
oneof root {
string power_state = 1;
string vehicle_state = 2;
CustomState custom_state = 3;
Condition not = 4;
Expression and = 5;
Expression or = 6;
}
}
message CustomState {
// Custom mode being checked.
string mode = 1;
// State of the custom mode.
string state = 2;
}
प्रोटो सैंपल
यहां दिए गए उदाहरण में, किसी सेवा बंडल के इंस्टेंस को कॉन्फ़िगर करने का तरीका बताया गया है, ताकि उन्हें TURN और FOG स्थिति के आधार पर शुरू किया जा सके:
service_bundle_config {
package_name: "oem.package"
service_bundle_name: "OemApplication"
instance: "flasher_light"
// Service bundle is allowed to set values for the TURN mode
custom_mode: "TURN"
// Service bundle is allowed to set values for the FOG mode
custom_mode: "FOG"
state {
condition {
custom_state {
mode: "TURN"
state: "LEFT"
}
}
instances_states {
started: "flasher_light"
}
}
state {
condition {
custom_state {
mode: "FOG"
state: "ON"
}
}
// Group assumed to be defined containing all FOG lights instances.
groups_states {
started: "fog_lights"
}
}
}
अपनी पसंद के मुताबिक नए मोड सेट करना
कस्टम मोड की नई वैल्यू सेट करने की प्रोसेस, सर्विस बंडल से शुरू होती है. यह बंडल, उसी वीएम पर चल रहे लोकल ऑर्केस्ट्रेटर को मनचाही वैल्यू भेजता है. इसके बाद, ऑर्केस्ट्रेटर यह पुष्टि करता है कि सेवा बंडल के पास, तय किए गए कस्टम मोड में पब्लिश करने के लिए ज़रूरी अनुमतियां हैं. इसके लिए, वह .textproto में तय किए गए कॉन्फ़िगरेशन का रेफ़रंस देता है. इससे यह तय किया जाता है कि वैल्यू को अन्य वीएम में भेजना है या नहीं. प्रॉपगेट होने के बाद, हर ऑर्केस्ट्रेटर अपने कॉन्फ़िगरेशन की समीक्षा करता है, ताकि उन सेवा बंडलों की सूची मिल सके जिनके लिए स्थिति बदलनी है.
RPC
हर वीएम पर चलने वाला हर Orchestrator, एक आरपीसी सर्वर बनाता है. यह सर्वर, कस्टम मोड की नई वैल्यू को सुनने के लिए होता है. कस्टम मोड को अपडेट करने के लिए, हर सेवा बंडल को सर्वर के लिए एक आरपीसी क्लाइंट बनाना होगा. एसीएल लागू किए जाते हैं, ताकि बिना अनुमति वाले बंडल को सर्वर से कनेक्ट होने से रोका जा सके.
आरपीसी के ज़रिए नई वैल्यू सेट करने के लिए, प्रोटो डेफ़िनिशन इस उदाहरण की तरह दिखती है:
syntax = "proto3";
import "google/protobuf/timestamp.proto";
package com.sdv.google.Orchestrator;
// Representation of the request used by service bundles to update a custom mode.
// Service bundles are permitted to update only the custom modes specifically designated
// for them within the Orchestrator configuration.
message SetCustomStateRequest {
// Required.
// The name of the custom mode.
// The mode string can not be longer than 56 characters and can only contain
// letters, numbers, dashes, dots and underscores: [a-zA-Z0-9_-.].
// No other special character nor spaces should be present in the mode.
string mode = 1;
// Required.
// The new value for the custom mode.
// The value string can not be longer than 56 characters and can only contain
// letters, numbers, dashes, dots and underscores: [a-zA-Z0-9_-.].
// No other special character nor spaces should be present in the value.
string value = 2;
// Required.
// The timestamp in which the new custom mode value was set. This is used to
// prevent race conditions whenever different service bundles in different
// VMs want to set a new value for the same custom mode.
// We use this timestamp to order the requests and we promise eventual
// consistency: while temporary inconsistencies may occur, the system will
// eventually converges to the correct state.
.google.protobuf.Timestamp timestamp = 3;
}
// Representation of the set custom state response.
message SetCustomStateResponse {}
// Orchestrator interface for service bundles that update the value of a
// custom mode.
// When a new value is received, it is propagated to Orchestrators running on
// other VMs.
service CustomStateService {
// Updates the value for the custom mode.
// Returns the error:
// - PermissionDenied: the service is not authorized to update the custom mode.
// - InvalidArgument: the provided mode and/or value are not valid.
rpc SetCustomState(SetCustomStateRequest) returns (SetCustomStateResponse) {};
}
पावर ट्रांज़िशन रद्द करना
ऑर्केस्ट्रेटर, SHUTDOWN_CANCELLED पावर मोड (वीपीएम से ऑर्केस्ट्रेटर को भेजा गया) के ज़रिए, चालू पावर ट्रांज़िशन को रद्द करने की अनुमति देता है.
उदाहरण के लिए, यहां Orchestrator के कॉन्फ़िगरेशन के बारे में बताया गया है:
state {
condition {
power_state: "SUSPEND_TO_RAM_ENTER"
}
instances_states {
started: "instance-1"
started: "instance-2"
started: "instance-3"
}
}
SHUTDOWN_CANCELLED मोड मिलने पर, दो मुख्य स्थितियां Orchestrator के व्यवहार को तय करती हैं. दोनों ही मामलों में, SHUTDOWN_CANCELLED पावर मोड को
कतार के आखिर में जोड़ दिया जाता है. इसके बाद, SHUTDOWN_CANCELLED को तब लागू किया जाता है, जब
लाइन में लगे एलिमेंट इस्तेमाल कर लिए जाते हैं.
पहली स्थिति: फ़िलहाल, पावर मोड चालू है
अगर Orchestrator, पावर मोड को अपडेट कर रहा है, तो चालू मोड को रद्द करने का अनुरोध किया जाता है. लाइफ़साइकल मैनेजर, ट्रांज़िशन को रद्द करने की सुविधा अपने-आप नहीं देता. हालांकि, Orchestrator यह पुष्टि करता है कि सेवा के नए बंडल के अनुरोध शुरू नहीं किए गए हैं.
उदाहरण: अगर पिछले उदाहरण में कॉन्फ़िगरेशन से instance-1, SHUTDOWN_CANCELLED मोड मिलने के दौरान शुरू होने की प्रोसेस में है, तो instance-1 शुरू होने की प्रोसेस पूरी करता है. हालांकि, instance-2 और instance-3, शुरू की गई स्थिति में ट्रांज़िशन नहीं करते हैं.
दूसरा विकल्प: प्रोसेसिंग के क्रम में पावर मोड मौजूद है
अगर ऑर्केस्ट्रेटर, नॉन-पावर मोड के अपडेट को प्रोसेस कर रहा है और मोड की सूची में पावर मोड के अपडेट का अनुरोध है, तो पावर ट्रांज़िशन को सूची से हटा दिया जाता है. इस वजह से, यह लागू नहीं हो पाता.
उदाहरण: पिछले उदाहरण में दिए गए कॉन्फ़िगरेशन का इस्तेमाल करके, अगर ऑर्केस्ट्रेटर, पावर से जुड़े अपडेट के अलावा किसी दूसरे अपडेट (जैसे कि वाहन का अपडेट) पर काम कर रहा है और SUSPEND_TO_RAM_ENTER को कतार में रखा गया है, तो SHUTDOWN_CANCELLED के नतीजे मिलने पर, किसी भी इंस्टेंस (instance-1, instance-2, instance-3) को शुरू नहीं किया जाएगा.
लागू करने का उदाहरण
मिडलवेयर से जनरेट किए गए कोड का इस्तेमाल करके, RPC सर्वर के लिए क्लाइंट बनाने वाले क्लाइंट का कैटलॉग इस उदाहरण की तरह दिख सकता है:
# proto-file: //system/software_defined_vehicle/vsidl/language/src/protos/sdv/vsidl/v1/syntax.proto
# proto-message: VsidlEntry
package: "package_name"
service_bundle {
name: "service_bundle_name"
client {
service: "com.android.sdv.orchestrator.CustomStateService"
}
}
कोड जनरेट करते समय, आपको Orchestrator कैटलॉग में डिपेंडेंसी जोड़नी होगी:
--dependency-catalog-path orchestration/engine/stable/vsidl/*
नई वैल्यू भेजने के लिए क्लाइंट कोड ऐसा दिखता है:
let fqin = ServiceFqin::builder()
.sdv_vm_name("vm_name")
.sdv_package_name("package_name")
.service_bundle_name("service_bundle_name")
.service_instance_name("instance_name")
.build()
.unwrap();
let context_ref = ContextRef::create(fqin);
let comms = Arc::new(SdvComms { context: context_ref });
// service_bundle_name is the bundle generated with middleware code that defines
// the RPC client to "com.android.sdv.orchestrator.CustomStateService".
let client = service_bundle_name::new(comms).await.unwrap();
let rpc_client = client
.create_rpc_client::<Client>(
UnitName::builder()
.vm_name(comms.context.get_self_fqin().get_sdv_vm_name())
.package_name("com.android.sdv.orchestrator")
.bundle_name("OrchestratorServiceBundle")
.service_unit_name(Client::DEFAULT_UNIT_NAME)
.build()
.unwrap(),
ClientOptions::default(),
)
.await;
let client = Arc::new(rpc_client.unwrap());
let request = SetCustomStateRequest {
mode: custom_mode_name,
value: custom_mode_value,
timestamp: MessageField::some(Timestamp::now()),
..Default::default()
};
let result = client.SetCustomState(&request).await;
// Process result
डीबग करने वाले टूल
Orchestrator एजेंट में dumpsys टूल काम करता है. इसे चालू SDV इंस्टेंस पर यह कमांड चलाकर चालू किया जा सकता है:
adb shell dumpsys com.google.sdv.ISdvAgent/orch
इस टूल का इस्तेमाल करके, Orchestrator एजेंट की इंटरनल स्थिति के बारे में ज़्यादा जानकारी पाएं और उसे डीबग करें. ऐसा करने पर, यह जानकारी दिखती है:
- मौजूदा मोड की स्थिति: चालू वाहन, पावर, और कस्टम मोड देखें.
- कस्टम मोड पब्लिशर: यह पता लगाएं कि कौनसी सेवाएं कस्टम मोड पब्लिश कर सकती हैं और किन मोड में पब्लिश कर सकती हैं.
- हर सेवा के लिए ज़रूरी स्थिति: पहले से तय की गई शर्तों और मौजूदा मोड के आधार पर, हर सेवा बंडल की स्थिति के बारे में जानें. इससे यह पता लगाने में मदद मिलती है कि कोई सेवा, उम्मीद के मुताबिक क्यों नहीं चल रही है.
- मोड लागू होने की स्थिति: इससे, लागू किए गए मोड की मौजूदा स्थिति के बारे में साफ़ तौर पर जानकारी मिलती है. अगर कोई मोड लागू नहीं किया गया है, तो इससे लागू किए गए पिछले मोड की जानकारी मिलती है.
- मोड लागू करने के लिए इंतज़ार की सूची: उन मोड को देखें जिन्हें लागू किया जाना है.
उदाहरण के लिए:
AGENT NAME: SDV Agent dump - Orchestrator
AGENT FQIN: instance1:com.android.sdv.orchestrator.OrchestratorServiceBundle/default
AGENT STATE: See orchestrator state below.
----------------
----------------
INTERNAL STATE REPORTERS:
*NAME: Configuration state
*REPORT:
Active modes:
MODE VALUE TIMESTAMP (scs, ns)
Power POWER_OFF_EXIT -
Vehicle VEHICLE_ON -
Custom("CHARGING") ON 1750757590 (scs) 466507459 (ns)
Custom("TIRE_PRESSURE") front-left 1750757570 (scs) 554522995 (ns)
Modes allowed to publish by bundle (FQIN: modes):
com.android.sdv.sample.orchestration/CustomModeControlBundle: CHARGING, TIRE_PRESSURE
Requested state for instances:
STATE FQIN
Started com.android.sdv.sample.orchestration/CustomModeControlBundle/always-started-instance
Started com.android.sdv.sample.orchestration/OrchestratedServiceBundle/my-instance
Started com.sdv.oem.sample.diagnostics/DiagnosticsSampleWithDataItem/instance
Started com.sdv.oem.sample.diagnostics/DiagnosticsSampleWithEvent/instance
Started com.sdv.oem.user_preferences/UserPreferencesServiceBundle/default
----------------
*NAME: Engine state
*REPORT:
Last mode enforced was Custom("CHARGING") with value "ON"
Next modes to process: []
----------------
ऑर्केस्ट्रेटर की ओर से मैनेज किए जाने वाले अलग-अलग सेवा बंडलों के बारे में ज़्यादा जानने के लिए, Lifecycle Manager से मौजूदा dumpsys का इस्तेमाल इस तरह करें:
dumpsys google.sdv.lifecycle.ILifecycleManager/default
ऐसा करने से, हर सेवा की लाइफ़साइकल की स्थिति के बारे में ज़्यादा जानकारी मिलती है. ऑर्केस्ट्रेटर के dumpsys आउटपुट को LifecycleManager के आउटपुट के साथ जोड़ने पर, VM में सेवा बंडलों के लाइफ़साइकल की पूरी जानकारी मिलती है.