Orchestrator הוא סוכן SDV מקומי שפועל בכל מכונה וירטואלית (VM) ומספק מנגנון לשליטה על מועד היצירה, ההפעלה, ההפסקה או ההשמדה של חבילות שירות. הפעולה הזו מתבצעת באמצעות הגדרת תזמור, שבה מגדירים קבוצה של כללים שקובעים מתי ואיך יתבצעו פעולות על מופעים של חבילות שירותים. הכללים האלה מבוססים על מצבים של הרכב, מצבי הפעלה ומצבים מותאמים אישית.
אפשר להגדיר את Orchestrator בהגדרות APEX או באמצעות הגדרות לכל מכונה וירטואלית. מערכת ההגדרות המבוזרת הזו מאפשרת לעדכן חלקים בכל חבילת שירותים באופן עצמאי דרך Service Bundle Registry, כמו שמוצג כאן.
איור 1. דיאגרמת הגדרת Orchestrator.
הגדרות שלא תלויות ברכב לא משתנות בהתאם ליצרן או לרכב. ההגדרה נשארת זהה בכל כלי הרכב של כל יצרן ציוד מקורי. ההגדרות הספציפיות לרכב יכולות להיות שונות ברכבים שונים של יצרני ציוד מקורי שונים, אבל יכול להיות שההגדרות יהיו זהות בכל הרכבים שמיוצרים על ידי יצרן ציוד מקורי מסוים.
הגדרות APEX
בזמן הריצה, כלי האורקסטרציה עובר למאגר של חבילות השירות כדי לאחזר אורקסטרציה של SDV לכל חבילת שירות, טוען ומנתח כל הגדרה. מידע נוסף זמין במאמר מטא-נתונים של תזמור.
הגדרה לכל מכונה וירטואלית
כשה-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, ובמשך זמן של תהליך build באמצעות קובץ makefile (עם התוסף .mk) או קובץ סקריפט של משאבים, עם התוסף .rc.
הגדרת המאפיין בזמן הריצה
הגדרת המאפיין בזמן הריצה שימושית לבדיקה או לביצוע שינויים זמניים, כי הערך נשמר גם אחרי הפעלה מחדש:
adb root
adb shell setprop persist.sdv.orchestrator_config_path {$path_to_file}.textproto
הגדרת המאפיין בזמן הבנייה
כדי להגדיר את המאפיין הזה כחלק מתצורת ה-build של המכשיר, מוסיפים שורה לקובץ ה-makefile של המוצר או של הלוח. האפשרות הזו מתאימה במיוחד להגדרת ערך ברירת מחדל לתמונת מכשיר חדשה.
# 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, המאפיין הזה לא יחליף אותו באתחולים הבאים.
אפשר להגדיר את ro.boot.sdv.orchestrator_config_path באמצעות bootconfig או שורת הפקודה של ליבת המערכת.
פורמט קובץ
מגדירים את תצורת התיאום בפורמט .textproto (לדוגמה, בטקסט מובנה) כדי שאפשר יהיה לטעון תצורות חדשות בזמן הריצה.
תחביר ההגדרות
בקטע הזה מוסבר על תחביר ההגדרות.
חבילות שירות
כל חבילת שירותים צריכה להיות מוגדרת באמצעות הגדרת חבילת השירותים, שמזהה את החבילה ב-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"
}
}
סכמת Proto
דוגמה לסכימת פרוטו:
// 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;
}
הגדרה ברמת ה-VM
ההגדרה של מכונת ה-VM מאפשרת להגדיר מיפויי קבוצות והגדרות לקבוצות. הוא משמש ליצירת מודל של תלות בין חבילות שירות ברמת המכונה הווירטואלית, וכך מאפשר גמישות בשינוי המצב של כמה חבילות שירות בו-זמנית. כל המופעים של קבוצה מועברים למצב שצוין.
ה-Orchestrator לא מבטיח את הסדר שבו מתבצע שינוי הסטטוס. הכלי Orchestrator מעביר כל מופע למצב הנתון.
הקבוצות מוצהרות באופן מרומז באמצעות השם 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"
}
הגדרת קבוצה
להצהרה על קבוצה אין השפעה. כדי שהקבוצות יופעלו על ידי Orchestrator, צריך להגדיר אותן. לדוגמה, המערכת לניהול תזמור צריכה לדעת באילו תנאים או באיזה מצב של המכונה הווירטואלית או הרכב הקבוצות צריכות לפעול.
אפשר להגדיר קבוצות באופן דומה להגדרת מופעים של שירותים, כלומר באמצעות מצבי הגדרה. ההבדל היחיד הוא השימוש ב-groups_states
במקום ב-instances_states בתחביר:
state {
condition {
power_state: "ON"
}
groups_states {
started: "Body"
started: "Adas"
}
}
סכמת Proto
הנה סכימת proto לדוגמה:
// 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כשמחילים מצב על הקבוצה, המצב חל על כל מופע של חבילת שירותים בקבוצה. לא מוחלת הזמנה לגבי המועד שבו מופעלים מופעים.
המדינות הנתמכות הן:
startedאחרי שמתקשרים אלService::on_start.createdאחרי שקוראים ל-
Service::new, אבל לפני שקוראים ל-Service::on_start.או
אחרי שקוראים ל-
Service::on_stop, אבל לפני שקוראים ל-Service::drop.
destroyedאחרי שמתקשרים אלService::drop.
Ruleset
מצב ההגדרה יכול להיות פעיל או לא פעיל, בהתאם לתנאי. יכולים להיות כמה מצבים פעילים בכל רגע נתון. כשסוכן תזמור מקבל עדכון אות, כל מצבי התצורה מוערכים לפני שינוי מחזור החיים של חבילות השירות. מצבי מופע השירות מוערכים לפי הכללים הבאים:
אם אף אחד מהמצבים הפעילים לא חל על מופע השירות, הוא מושמד.
כשמצב פעיל אחד או יותר חל, סדר העדיפות הזה חל:
- ל-
destroyedיש עדיפות מוחלטת. startedקודם ל-created.
- ל-
סכמת Proto
הנה סכימת proto לדוגמה:
// 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 יש תצוגה הוליסטית של מצבי השירות, והוא מנהל את המעברים בין המצבים, ולכן הוא הרכיב המתאים ביותר להפעלה של אסטרטגיית ההפעלה מחדש והניסיון החוזר. Lifecycle Manager (LM) מדווח על קריסות של חבילות שירות ל-Orchestrator באמצעות הודעות על סגירת binder. כדי להימנע מקריאות מיותרות של binder אל LM, ה-Orchestrator שומר במטמון את המצב האחרון של כל חבילה (בין אם היא הצליחה או לא) ולא מחיל מחדש מעברים אם המצב האחרון הידוע זהה למצב החדש המבוקש.
הגדרת ניסיון חוזר
אפשר להגדיר את אסטרטגיית ההפעלה מחדש והניסיון החוזר לכל מופע בהגדרות של כלי התזמור באמצעות retry_mapping. אם 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 מקבל בקשה לעבור למצב חדש בזמן הפעלה מחדש של חבילה (או בזמן שהיא נמצאת בתור של מופעים להפעלה מחדש), הוא מבטל את השחזור שמתבצע. המעבר למצב החדש מתבצע, ומונה הניסיונות חוזר לאפס כדי לאפשר סדרה חדשה של ניסיונות להגיע למצב היעד החדש.
הכלי Orchestrator מבחין בין סוגים שונים של שגיאות שמוחזרות על ידי Lifecycle Manager כדי לקבוע את אסטרטגיית הניסיון החוזר:
- שגיאות זמניות (
SERVICE_NOT_FOUND, OPERATION_FAILED,INTERNAL_ERROR): כלי התזמור מנסה לבצע את הפעולה שוב בלי לבצע פעולות ניקוי נתונים מיוחדות. - שגיאות מתמשכות (
VALUE_CORRUPTED,INVALID_ARGUMENT): המערכת מניחה שחבילת השירות נמצאת במצב פגום ומנסה להפסיק את מופע השירות לפני שמנסה שוב לבצע את הפעולה כדי להבטיח הפעלה מחדש תקינה. - שגיאות קבועות (
PERMISSION_DENIED): המערכת לא מנסה לבצע את הפעולה שוב, והחבילה נחשבת למצב שלא ניתן לשחזר.
אם Lifecycle Manager קורס, כל התהליכים של חבילת השירותים אובדים. מכיוון שהמצב בפועל לא ידוע, כלי התזמור מבטל את התוקף של כל מופע ומחיל אסטרטגיית הפעלה מחדש עם ניסיונות חוזרים שנותרו כדי להביא כל מופע למצב האחרון שנדרש.
כדי למנוע לולאות שחזור אינסופיות לחבילות שקורסות או נכשלות שוב ושוב, מונה הניסיונות החוזרים מאופס רק ל-max_retries אחרי שמצליחה פעולה במחזור החיים, או כשמתבקשת העברה למצב חדש. אם חבילה ממצה את מכסת הניסיונות החוזרים שלה בגלל כשלים עוקבים (לדוגמה, כשל במעבר ואחריו קריסה), היא לא מופעלת מחדש עד שהמונה של הניסיונות החוזרים מאופס.
דיווח על מצב המכשיר לכלי תקינות המערכת
ה-Orchestrator חושף ממשק פנימי של binder שה-Health Monitor (HM) נרשם אליו, וכך הוא יכול לקבל עדכונים שוטפים לגבי המצב של כל חבילות השירות. באמצעות הממשק הזה, כלי התיזמור מדווח באופן פעיל על:
- מצב מחזור החיים: המצב המיועד של המופע על סמך ההגדרה הנוכחית והמצבים הפעילים (למשל: התחיל, נוצר או נהרס).
- מצב שחזור: הסטטוס של ההגעה למצב מחזור החיים המיועד, שמציין אם המופע פועל, אם הוא מנסה כרגע לבצע שחזור אחרי כשל, או אם השחזור נכשל אחרי שמוצו כל הניסיונות.
המידע הזה מדווח על כל המקרים, כולל מקרים שלא נרשמו למעקב אחר אותות חיים. HM משתמש במידע הזה כדי להטמיע את ממשקי ה-API שלו ולדווח על מצב המכונה הווירטואלית. מידע נוסף זמין במאמר בנושא מעקב אחר מדדים בריאותיים.
דוגמאות
בקטע הזה מוצגות דוגמאות להגדרת מצבים עם תנאים.
דוגמה של שירות בסיסי
- אין לו תנאי ולכן הוא תמיד פעיל.
- מפעיל מופע שירות יחיד.
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.הצהרה על כמה מופעים של שירות שקשור ל-HVAC כ-
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.המצב הזה יכול להיחשב כמצב של חיסכון באנרגיה.
הצהרה על מופע שירות אחד שקשור ל-HVAC כ-
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" } }
דוגמה לשימוש ב-Life onboard
תנאי: פעיל אם
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"
}
}
הגדרה ברמת ה-VM
# 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) יכול מנהל התזמור לבצע למנהל מחזור החיים. זה חשוב במיוחד לביצועים במהלך האתחול והמעברים בין מצבים, שבהם יכול להיות שחבילות רבות ישנו את המצב שלהן בו-זמנית.Lifecycle Manager: השירות הזה משתמש בערך המאפיין כדי לחשב את הגודל של מאגר השרשורים של Binder, שאחראי לטפל בכל הבקשות הנכנסות. כך אפשר לוודא שיש למודל השפה מספיק שרשורים כדי לטפל בבקשות בו-זמניות מהכלי לניהול תהליכים.
אם לא מגדירים את המאפיין הזה, ערך ברירת המחדל של שני השירותים הוא 12.
שיטת ההגדרה
אפשר להגדיר את המאפיין בקובץ BoardConfig.mk במכשיר על ידי הוספתו למשתנה BOARD_BOOTCONFIG. כך מוודאים שהערך יוחל בכל פעם שהמכשיר מופעל.
BOARD_BOOTCONFIG += \
androidboot.sdv.max_bundles_management_threads=8
כדי לשנות את הערך של המכשיר, צריך לשנות את השורה הזו בקובץ BoardConfig.mk המתאים ולבנות מחדש.
אופטימיזציה של זמן האתחול
ro.sdv.orchestrator.state.ready הוא מאפיין בוליאני write-once שמהווה חלק משיטת אופטימיזציה של ביצועים בזמן האתחול. ההודעה הזו מציינת שהסוכן של Orchestration סיים את האתחול שלו ומוכן להתחיל לנהל את מחזור החיים של חבילות השירות. המטרה העיקרית שלו היא לתת עדיפות להפעלה של Orchestrator וחבילות השירותים המנוהלים שלו, על ידי שליטה ברצף ההפעלה של סוכני SDV אחרים.
- הוגדר על ידי: סוכן התזמור.
- מתי: פעם אחת במהלך רצף האתחול.
- שימוש: המערכת משתמשת במאפיין הזה כדי לשלוט ברצף ההפעלה של רוב הסוכנים של SDV (Updates Manager, VSIDL provider, Health Monitor, Service Discovery, Data Tunnel, RPC, VPM ו-Telemetry). אם מתחילים את כלי התזמור מוקדם ומגדירים סוכנים אחרים להמתין למאפיין הזה, המערכת מוודאת שכלי התזמור יוכל להתחיל את המשימה הקריטית שלו של הפעלת חבילות שירותים בלי להתחרות על משאבי המערכת.
ביצועים
במהלך אתחול המערכת, הפעלה של כל הסוכנים בו-זמנית עלולה לגרום לתחרות על משאבים ולהאט את תהליך האתחול הכולל. כדי לפתור את הבעיה הזו, סדר הפעלה רציף נאכף באמצעות מאפייני מערכת:
- מאגר חבילות שירותים: מתחיל ראשון כדי לטעון את כל המטא-נתונים של חבילות השירותים.
- Lifecycle Manager ו-Orchestrator: סוכני הליבה האלה מתחילים לפעול ברגע שהרישום מוכן. ההתחלה המוקדמת הזו חשובה מאוד כי היא מאפשרת ל-Orchestrator להתחיל להעריך את ההגדרה שלו ולהתכונן להפעלת חבילות שירות באופן מיידי.
- סוכני SDV אחרים: יתחילו לפעול רק אחרי שכלי התזמור יהיה מוכן.
הרצף המבוקר הזה מבטיח שהכלי Orchestrator יקבל עדיפות בשימוש במשאבי המערכת כדי להפעיל חבילות שירותים בהקדם האפשרי, וכך יתבצע אתחול מהיר, יעיל וצפוי יותר של המערכת.
מצבים שצורכים על ידי כלי התזמור
סוכן התיאום שומר על מינוי פעיל למצבי הרכב וההפעלה שמועברים על ידי VPM. אחרי שמקימים את החיבור הראשוני בין Orchestrator לבין מערכת ניהול הרכב וההספק (VPM), Orchestrator מגדיר את מאפייני המערכת הבוליאניים הבאים לערך true:
sdv.orchestrator.bootup.power_mode.readysdv.orchestrator.bootup.vehicle_mode.ready
סוכן האורקסטרציה משתמש בקובץ תצורה כהפניה, ומחשב באופן דינמי את קבוצת חבילות השירות שצריכות להיות במצב פעיל על סמך הערכים הנוכחיים של המצבים שהתקבלו. לאחר מכן, כלי התיזמור מתקשר עם כלי ניהול מחזור החיים, ומנפיק פקודות שונות כדי להתאים את המצב בפועל של חבילות השירות למצב היעד המחושב.
מצבי הרכב והטעינה
הסוכן Vehicle mode and power management (VPM) מאפשר לרכיבי SDV לקבל מידע על המצב הנוכחי של הרכב, כמו מצב הפעולה (לדוגמה, חניה או נסיעה) וסטטוס ההפעלה (לדוגמה, מופעל או מושהה). הכלי Orchestrator מעריך את הערכים האלה כדי להגדיר אילו חבילות שירותים צריכות לפעול על סמך ההגדרה של הכלי. מידע נוסף מופיע במאמר בנושא ניהול כלי רכב וצריכת חשמל.
מצבים מותאמים אישית
יש כל כך הרבה מצבי נסיעה שאי אפשר ליצור מודל לכולם. לכל יצרן ציוד מקורי יש צרכים שונים, ואי אפשר לטפל בכל תרחישי השימוש של יצרני ציוד מקורי באמצעות סטנדרטיזציה של מצבי הרכב. לכן, אנחנו תומכים במצבים ספציפיים ליצרן ציוד מקורי (OEM), שנקראים מצבים בהתאמה אישית. המצבים האלה לא מרחיבים את מצבי הרכב וההפעלה הקיימים. במקום זאת, הם מאפשרים להגדיר מצבים חדשים.
פונקציונליות:
היקף גלובלי: מצבים מותאמים אישית הם גלובליים, והם חלים באופן אחיד על כל המכונות הווירטואליות שמנוהלות על ידי כלי האורקסטרציה.
הרכב: כל שינוי במצב מותאם אישית מורכב משני רכיבים:
שם: מזהה ייחודי שנבחר על ידי יצרן הציוד המקורי כדי לייצג את המצב המותאם אישית.
ערך: המצב הנוכחי של מצב מותאם אישית, שיכול להיות
UNDEFINEDאם לא מוגדר ערך.
תפקיד Orchestrator: ה-Orchestrator פועל כמקבל פסיבי של ערכים של מצב מותאם אישית.
תפקיד חבילת השירותים: כל חבילת שירותים יכולה להיות הבעלים של כמה מצבים מותאמים אישית, ויכולה לפרסם ערכים חדשים לכל אחד מהם. יכול להיות שלכמה חבילות שירותים יהיה אותו מצב מותאם אישית, כלומר מצב מותאם אישית יכול לקבל ערכים חדשים ממקורות שונים.
אחריות לאימות: יצרני ציוד מקורי (OEM) אחראים לוודא שמעברי המצבים תקינים. הכלי Orchestrator מקבל כל ערך חדש.
מאפיינים משוערים:
מספר משוער: מצבי הפעלה ומצבי רכב מנהלים את מחזור החיים של רוב חבילות השירות, ומצבים מותאמים אישית ממלאים תפקיד משלים. אנחנו צופים שמספר המצבים המותאמים אישית יהיה עשרות ולא מאות.
תזמון משוער: המצבים לא נשלחים באופן תקופתי. במקום זאת, המצבים מבוססים על אירועים ומופעלים על ידי פעולות ספציפיות, כמו פתיחת דלת, הפעלת רצף חנייה, התחלת מחזור טעינה ואירועים דומים אחרים בעלי משמעות שהוגדרה על ידי יצרן ציוד מקורי (OEM).
עיצוב מצב מותאם אישית מאפשר להגדיר ולנהל מצבים ספציפיים, ובו בזמן מאפשר ל-Orchestrator להישאר אגנוסטי לגבי הלוגיקה של מכונת המצבים הבסיסית.
מצבים נתמכים
כדי לוודא שחבילות שירותים מתפרסמות רק במצבים מותאמים אישית שבבעלותן, כל חבילה צריכה להצהיר באופן מפורש על רשימת המצבים המותאמים אישית שבבעלותה במסגרת ההגדרה של Orchestrator, שזמינה במכונה הווירטואלית המקומית עם רישום חבילת השירותים. ניסיונות לפרסם במצב מותאם אישית שלא הוגדר נדחים.
כדי להצהיר על המצבים המותאמים אישית שחבילת שירותים יכולה לפרסם (ולכן היא הבעלים שלהם), סכמת ה-proto 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;
}
דוגמה ל-proto
בדוגמה הבאה אפשר לראות איך מגדירים הפעלה של מופעים של חבילת שירותים על סמך מצב 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"
}
}
}
הגדרת מצבים חדשים בהתאמה אישית
התהליך של הגדרת ערך חדש של מצב מותאם אישית מתחיל בחבילת השירות, שמעבירה את הערך הרצוי ל-Orchestrator המקומי שפועל באותו VM. לאחר מכן, כלי התזמור מאמת שלחבילת השירות יש את ההרשאות הנדרשות לפרסום במצב המותאם אישית שצוין, תוך הפניה להגדרה שמוגדרת ב-.textproto, כדי לקבוע אם להפיץ את הערך למכונות וירטואליות אחרות. אחרי ההפצה, כל Orchestrator בודק את ההגדרה שלו כדי למצוא את רשימת חבילות השירותים שצריך לשנות את המצב שלהן.
RPC
כל Orchestrator שפועל בכל מכונה וירטואלית יוצר שרת RPC כדי להאזין לערכים חדשים של מצב מותאם אישית. כל חבילת שירות שרוצה לעדכן מצב מותאם אישית צריכה ליצור לקוח RPC לשרת. רשימות ACL נאכפות כדי למנוע מצרורות לא מורשים להתחבר לשרת.
הגדרת הפרוטו להגדרת ערך חדש באמצעות RPC נראית כך example:
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) {};
}
ביטול של מעברים בין מצבי צריכת חשמל
ה-Orchestrator מאפשר לבטל מעברים שוטפים בין מצבי צריכת חשמל באמצעות מצב צריכת החשמל SHUTDOWN_CANCELLED (שנשלח מ-VPM אל ה-Orchestrator).
לדוגמה, נניח שהגדרתם את 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 אחרי שכל האלמנטים בתור נצרכו.
תרחיש 1: המצב הנוכחי הוא מצב צריכת חשמל
אם Orchestrator מבצע עדכון של מצב צריכת חשמל, מתבצעת בקשה לביטול המצב שנמצא בתהליך. למרות שמנהל מחזור החיים לא תומך באופן מובנה בביטול מעבר שנמצא בתהליך, כלי התיזמור מוודא שלא מתחילות בקשות חדשות לחבילות שירותים.
דוגמה: אם instance-1 מההגדרה בדוגמה הקודמת נמצא בתהליך של הפעלה כשמתקבל מצב SHUTDOWN_CANCELLED, הפעלת instance-1 תושלם. עם זאת, המעברים של instance-2 ושל instance-3 למצב התחלתי לא מתבצעים.
תרחיש 2: מצב צריכת חשמל קיים בתור העיבוד
אם ה-Orchestrator מעבד עדכון של מצב שאינו מצב צריכת חשמל, ויש בקשת הפעלה בתור של המצבים לביצוע, המעבר למצב צריכת חשמל מוסר מהתור. כך נמנעת ההרצה שלו.
לדוגמה: אם משתמשים בהגדרה שבדוגמה הקודמת, והכלי Orchestrator פועל על עדכון שלא קשור להפעלה (כמו עדכון של רכב) והערך 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: []
----------------
כדי לקבל מידע נוסף על חבילות שירותים פרטניות שמנוהלות על ידי Orchestrator, אפשר להשתמש ב-dumpsys הקיים מ-Lifecycle Manager באופן הבא:
dumpsys google.sdv.lifecycle.ILifecycleManager/default
כך תוכלו לקבל מידע מפורט על מצב מחזור החיים של כל שירות. שילוב של פלט dumpsys של Orchestrator עם פלט של LifecycleManager מאפשר לקבל תמונה מלאה של מחזור החיים של חבילות השירות במכונה הווירטואלית.