בדף הזה מוסבר על הארכיטקטורה של מערכת העדפות המשתמש ב-SDV, ומופיעות בו הוראות להטמעה של שירות ולקוח שניתנים לשליטה על ידי המשתמש.
סקירה כללית של הארכיטקטורה
מערכת העדפות המשתמש מפרידה בין האחסון והניהול של הגדרות המשתמש לבין האכיפה והיישום של ההגדרות האלה. בטבלה הבאה מופיע סיכום של מונחי הארכיטקטורה העיקריים:
| תכונה | תיאור | תפקיד | אחריות |
|---|---|---|---|
| שירות שניתן לשליטה על ידי המשתמש | חבילת שירותים רגילה של SDV שמנהלת דומיין ספציפי (לדוגמה, מיזוג אוויר, מושבי בטיחות, אודיו) | הוא מספק את המצב המיועד של היכולות והמגבלות של החומרה או של מערכת המשנה שהוא שולט בה. |
|
| סוכן העדפות משתמש | הכלי המרכזי לתזמור | מספקת אחסון מרכזי, ניהול פרופילים של משתמשים ומרכז התראות. |
|
| לקוח העדפות משתמש | אפליקציה או שירות שמספקים ממשק משתמש, למשל אפליקציית IVI עם HMI או לוגיקה אחרת שצריכה ליצור אינטראקציה עם העדפות המשתמש | מבצע אינטראקציה עם משתמשים, מציג הגדרות ויוזם בקשות לשינוי. |
|
הטמעה של שירות שניתן לשליטה על ידי המשתמש
כדי לעדכן את סוכן העדפות המשתמש לגבי המפתחות שקיימים, סוגי הנתונים שלהם, ערכי ברירת המחדל והאילוצים (לדוגמה, ערכים מינימליים ומקסימליים), חבילת השירותים שלכם צריכה ליצור אינטראקציה עם ממשק UserPreferencesRegistryService. כשהשירות מתחיל, הוא צריך לרשום את ההגדרות שהוא חושף. הנציג מפעיל את RequestSettingsChange בשירות שלכם כשמשתמש מנסה לשנות הגדרה (או כשמשתמשים מתחלפים).
כדי לאפשר לשירות שלכם להיות נשלט על ידי העדפות המשתמש (ומשתמש עם HMI), פועלים לפי השלבים שבקטע הזה.
מגדירים את ממשקי השירות בקובץ VSIDL:
- כשרת, צריך להטמיע את
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" } }- כשרת, צריך להטמיע את
הגדרות הרישום מופעלות באתחול בפרוטוקול המפתח
user_preferences_registry_service.proto:- התחברות אל
UserPreferencesRegistryService. - יוצרים מופע של
RegisterSettingsRequest. - מגדירים מופע של
SettingsGroup(אוסף לוגי של הגדרות). לכל הגדרה, מגדירים:
* **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).רוצה להתקשר ל-
RegisterSettings()?
הדוגמה הבאה היא ב-Rust קונספטואלית:
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?;- התחברות אל
איך מטפלים בבקשות לשינוי הגדרות ב-
user_controllable_service.proto:- מטמיעים את ה-RPC
RequestSettingsChange. - בודקים אם הערכים המבוקשים תקפים בהקשר הנוכחי (לדוגמה, אם החומרה מוכנה).
- להחיל לוגיקה ספציפית כדי לבצע את השינוי (לדוגמה, להזיז את המושב, לשנות את מהירות המאוורר).
- החזרת הערכים שהוחלו ב-
RequestSettingsChangeResponse: - אם אישרתם את השינוי, מחזירים את הערך החדש.
- אם דחיתם או הגבלתם את הערך, מחזירים את הערך שהגדרתם (או השארתם).
הדוגמה הבאה היא ב-Rust קונספטואלית:
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, }) }- מטמיעים את ה-RPC
מטמיעים את
FactoryResetRPC כדי להחזיר את מערכת המשנה למצב נקי:- איפוס כל ההגדרות לערכי ברירת המחדל (כפי שהוגדרו בהגדרות הקוד).
- מתקשרים אל
UpdateSettingsבשירות הרישום כדי להודיע לסוכן שהערכים השתנו חיצונית (בגלל האיפוס, ולא בגלל בקשת משתמש).
תאימות לאחור והתפתחות של סכימות
הסכימה של ההגדרות שמוגדרות על ידי שירות שניתן לשליטה על ידי המשתמש נחשבת לממשק ציבורי. הסוכן להעדפות המשתמשים ולקוחות שונים (לדוגמה, ממשקי אדם-מכונה) משתמשים בממשק הזה, ויכול להיות שלכל אחד מהם יש לוחות זמנים שונים להפצה. לכן, חשוב מאוד לשמור על תאימות קפדנית לדור קודם כדי למנוע חוסר יציבות במערכת ושבירה של הלקוח.
שינויים תואמים
שירות שניתן לשליטה על ידי משתמשים צריך להציג רק שינויים תואמים בסכימת ההגדרות שלו. השינויים האלה מבטיחים שלקוחות ישנים ימשיכו לפעול בצורה תקינה בלי עדכונים:
הוספת הגדרה חדשה ואופציונלית עם ערך ברירת מחדל סביר:
- ההגדרה הזו היא אופציונלית, ולכן הלקוחות צריכים לבדוק אם היא קיימת כדי לתמוך בגרסאות שונות של השירות.
- לקוחות מתעלמים מההגדרה הזו אם הם לא עודכנו כך שיזהו אותה.
- אם אין העדפה של המשתמש להגדרה החדשה, הסוכן משתמש בערך ברירת המחדל שסופק.
שינויים לא תואמים
השינויים הבאים נחשבים לשינויים שוברים ואסורים כי הם פוגעים באופן מיידי בלקוחות ישנים יותר:
מסירים הגדרה קיימת.
שינוי המשמעות, היחידה או סוג הנתונים של הגדרה קיימת (לדוגמה, שינוי ממספר שלם שמייצג טמפרטורה בצלזיוס למספר עשרוני שמייצג לחץ בפסקל).
לשנות את ערך ברירת המחדל של הגדרה קיימת. הסיבה העיקרית לאיסור שינויים בערך ברירת המחדל היא הסיבוך הפוטנציאלי בהעברת נתונים שנשמרו. הסוכן שומר את ההגדרות על סמך סכימת הרישום של השירות. שינוי ערך ברירת המחדל ידרוש לוגיקה מורכבת כדי להעביר את כל פרופילי המשתמשים הקיימים לברירת המחדל החדשה, או שיהיה סיכון לשימוש בערך לא תקין מבחינה טכנית עבור משתמשים שלא הגדירו את ההעדפה באופן מפורש.
טיפול בשינויים שעלולים לשבור את התאימות לאחור
אם נדרש שינוי שעלול לשבור את התאימות לאחור, השירות לא יכול לשנות את ההגדרה הקיימת. הגישה לניהול המעבר הזה תוך שמירה על תאימות ממוקמת בעיקר בלוגיקה של השירות שניתנת לשליטה על ידי המשתמש:
- יוצרים הגדרה חדשה עם ההגדרה, המפתח או היחידה החדשים הרצויים.
- הוצאה משימוש של ההגדרה הקיימת על ידי רישום שלה לצורך תאימות. מומלץ להשתמש בהגדרה החדשה הזו כשמפתחים לקוחות חדשים.
- מומלץ להנחות לקוחות חדשים להטמיע לוגיקה של תאימות במסגרת הלוגיקה העסקית של השירות שניתן לשליטה על ידי המשתמש.
ההטמעה של RequestSettingsChange השירות צריכה להבטיח ששינוי בהגדרה אחת ישתקף בהגדרה המקבילה שהוצאה משימוש, ושינוי בהגדרה המקבילה ישתקף בהגדרה.
לוגיקה לדוגמה של תאימות:
שירות מוציא משימוש את ההגדרה הישנה
TEMPERATURE_C(צלזיוס) ומציג את ההגדרהTEMPERATURE_K(קלווין).כשהסוכן שולח בקשה לעדכון ההגדרה חדש:
השירות מקבל בקשה ל-
TEMPERATURE_K(לדוגמה, 295.15 K).הלוגיקה של השירות ממירה את הערך הזה לצלזיוס (22°C) ומעדכנת ושומרת את שני הערכים באופן פנימי כדי לשמור על עקביות עבור לקוחות מדור קודם.
כשהסוכן שולח בקשה להגדרה שהוצאה משימוש מלקוח מדור קודם:
- השירות מקבל בקשה ל-
TEMPERATURE_C(לדוגמה, 24°C). - השירות ממיר את הערך הזה לערך בקלווין (297.15 K) ומעדכן ושומר את שני הערכים באופן פנימי.
- השירות מקבל בקשה ל-
אסטרטגיית הכתיבה הכפולה הזו מבטיחה שכל הלקוחות, בלי קשר ללוח הזמנים של הגרסה שלהם, יקראו נתונים עקביים ומדויקים, וכך יימנעו שיבושים שנגרמים מחוסר התאמה בין גרסאות חיצוניות.
הטמעה של לקוח
כדי להטמיע לקוח (לדוגמה, HMI) שיוצר אינטראקציה עם נציג העדפות המשתמש:
מגדירים את חבילת שירות הלקוח כדי ליצור אינטראקציה עם ממשקי העדפות משתמש ספציפיים. בקובץ ה-VSIDL:
- כשרת, צריך להטמיע את
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 }- כשרת, צריך להטמיע את
אפשר לשנות את הגדרות הבקשה ב
UserPreferencesManagementService:- התחברות אל
UserPreferencesManagementService. - יוצרים מופע של
RequestSettingsChangeRequestומציינים אתSettingsGroupIdואת ההגדרות הרצויות. - אופציונלי. מגדירים את
ChangePersistencePolicyל-PERSISTENT_CHANGE(ברירת מחדל) או ל-NON_PERSISTENT_CHANGE. - רוצה להתקשר ל-
RequestSettingsChange()?
הדוגמה הבאה היא ב-Rust קונספטואלית:
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?;- התחברות אל
הרשמה לקבלת עדכונים על שינויים בהגדרות באמצעות
user_preferences_management_service.protoו-change_notifier.proto:- מטמיעים את ה-RPC
OnSettingsChangeמהממשקChangeNotifierבחבילת השירות. סוכן העדפות המשתמש מפעיל את השיטה הזו כשמתרחש שינוי. - התחברות אל
UserPreferencesManagementService. - יוצרים
SubscribeToSettingsChangeAndGetSettingsRequestומציינים אתSettingsGroupIdשרוצים לעקוב אחריו. - כדי להחזיר את מצב ההגדרות ואז לשלוח עדכונים עתידיים דרך ההטמעה של
OnSettingsChange, צריך לבצע קריאה אלSubscribeToSettingsChangeAndGetSettings().
הדוגמה הבאה להטמעה של הממשק
ChangeNotifierהיא ב-Rust קונספטואלית:#[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()) } }הדוגמה הבאה להרשמה היא ב-Rust קונספטואלית:
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?;- מטמיעים את ה-RPC
אופציונלי: לקוחות שמנהלים פרופילים של משתמשים (לדוגמה, אפליקציית הגדרות ייעודית) יכולים להשתמש ב-
user_preferences_admin_service.protoכדי ליצור אינטראקציה עם שירות האדמין:- התחברות אל
UserPreferencesAdminService. - אפשר להשתמש ב-RPC כמו
CreateUser,SelectUser,DeleteUser,FactoryResetו-ListUsersכדי לנהל פרופילי משתמשים.
הדוגמה הבאה ליצירת משתמש היא ב-Rust קונספטואלי:
admin_service_client.CreateUser(&CreateUserRequest { user: Some(User { id: 1, flags: UserFlags::DRIVER.value(), ..Default::default() }).into(), ..Default::default() }).await?;- התחברות אל
אפשר לגלות את ההגדרות והמשתמשים הזמינים באמצעות שירות הניהול עם
user_preferences_admin_service.proto:- כדי לקבל רשימה של כל המשתמשים הרשומים, קוראים ל-
ListUsers()ב-UserPreferencesAdminService. - כדי לקבל את ההגדרות של משתמש ספציפי, קוראים ל-
GetUserSettings(user_id)ב-UserPreferencesAdminService.
הדוגמה הבאה של רישום משתמשים וקבלת הגדרות היא ב-Rust קונספטואלי:
// 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); }- כדי לקבל רשימה של כל המשתמשים הרשומים, קוראים ל-
סיכום התהליך
- הלקוח מתחיל את השימוש בשירותי הניהול והאדמיניסטרציה של הסוכן ומתחבר אליהם.
- הלקוח מאתר קבוצות של הגדרות ונרשם אליהן, ומציג את המצב הראשוני.
- הלקוח שולח
RequestSettingsChangeלסוכן. - הנציג שולח ללקוח התראה של
OnSettingsChangeעם הגדרות ומצב מעודכנים.
דוגמה מלאה שעובדת מופיעה בקובץ HMIService בתיקייה @samples/user_preferences/v1/.
הטמעה של הסוכן
חבילת שירותים שהופעלה על ידי כלי תזמור מיישמת את סוכן העדפות המשתמש. לנוחותכם, צירפנו הטמעה לדוגמה.
בנוסף, מסופק קובץ 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 class) יכול ליצור חשבון שבו הוא יכול לשמור את ההעדפות שלו. העדפות המשתמש תומכות בחשבונות רק עבור נהגי רכב.
נהגים אורחים יכולים ליצור חשבונות זמניים שנמחקים אוטומטית אחרי שימוש אחד.
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 class) מאפשרות לארגן ולנהל הגדרות שקשורות זו לזו.
כל רכיב שניתן להגדרה ברכב מגדיר את ההגדרות שלו כקבוצות, שמורכבות מרשימה של הגדרות שמיוצגות כצמדי מפתח/ערך. לדוגמה, ברכבים עם מושבים חשמליים אפשר להגדיר קבוצת הגדרות למושב הנהג וקבוצה אחרת למושב שליד הנהג, כששתי הקבוצות מכילות הגדרות עם שמות זהים.
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;
}
הגדרות
ההגדרה, message (Setting class), מייצגת הגדרה אחת בתוך 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 class) משמשות כתבניות להגדרות ספציפיות בתוך קבוצת הגדרות. הם מציינים את המאפיינים הבסיסיים של ההגדרה, כמו האם ההגדרה משותפת לכל המשתמשים, ספציפית לכל משתמש או מנוהלת חיצונית (העברה).
חשוב לדעת שהגדרת ההגדרות כוללת גם הגדרת מגבלות על הערך של ההגדרה, כמו ערכים מינימליים ומקסימליים, מרווחים מותרים או קבוצה מוגבלת של אפשרויות. האילוצים האלה מובילים לתקינות נתונים ועקביות בכל הגדרה.
// 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;
}
דוגמה לרצף אירועים כשמשתמש מעדכן הגדרה
בדוגמה הזו מוצגת רצף האירועים שמתרחשים כשמשתמש משתמש במערכת המולטימדיה (IVI) של מערכת ההפעלה Android Automotive OS (AAOS) ברכב כדי לעדכן הגדרה:
איור 1. אירועים שמתרחשים כשמשתמש משנה הגדרה.
דוגמה לרצף אירועים כשמניעים רכב
בדוגמה הזו אפשר לראות איך SDV User Preferences מחיל את ההגדרות המועדפות של המשתמש כשהרכב מתחיל לפעול:
איור 2. אירועים שמתרחשים כשהרכב מתניע.