Bu sayfada, SDV Kullanıcı Tercihleri sisteminin mimarisi hakkında bir kılavuz ve kullanıcı tarafından kontrol edilebilen bir hizmet ile istemci uygulama talimatları yer almaktadır.
Mimariye genel bakış
Kullanıcı Tercihleri sistemi, kullanıcı ayarlarının depolanmasını ve yönetilmesini bu ayarların uygulanmasından ve zorunlu kılınmasından ayırır. Temel mimari terimler tabloda özetlenmiştir:
| Özellik | Açıklama | Rol | Sorumluluk |
|---|---|---|---|
| Kullanıcı tarafından kontrol edilebilen hizmet | Belirli bir alanı (ör. HVAC, araba koltukları, ses) yöneten standart bir SDV hizmet paketi | Kontrol ettiği donanımın veya alt sistemin özelliklerinin ve kısıtlamalarının amaçlanan durumunu sağlar. |
|
| Kullanıcı tercihleri aracısı | Merkezi düzenleyici | Merkezi depolama, kullanıcı profili yönetimi ve bildirim merkezi sağlar. |
|
| Kullanıcı tercihleri istemcisi | Kullanıcı arayüzü sağlayan bir uygulama veya hizmet (ör. kullanıcı tercihlerine göre etkileşimde bulunması gereken bir HMI veya başka bir mantık içeren bir IVI uygulaması) | Kullanıcılarla etkileşim kurar, ayarları gösterir ve değişiklik isteklerini başlatır. |
|
Kullanıcı tarafından kontrol edilebilen bir hizmet uygulama
Kullanıcı Tercihleri aracısına hangi anahtarların mevcut olduğunu, veri türlerini, varsayılan değerlerini ve kısıtlamalarını (ör. minimum ve maksimum değerler) bildirmek için hizmet paketinizi UserPreferencesRegistryService arayüzüyle etkileşime geçirmelisiniz. Hizmetiniz başladığında, kullanıma sunduğu ayarları kaydetmesi gerekir. Kullanıcı bir ayarı değiştirmeye çalıştığında (veya kullanıcılar arasında geçiş yaparken) hizmetinizde RequestSettingsChange işlevi çağrılır.
Kullanıcı Tercihleri'nin (ve HMI'ye sahip bir kullanıcının) hizmetinizi kontrol etmesine izin vermek için bu bölümdeki adımları uygulayın.
VSIDL dosyasında hizmet arayüzlerini tanımlayın:
- Sunucu olarak
com.sdv.google.user_preferences.user_controllable.UserControllableService'yı uygulayın. Bu ayar, temsilcinin size değişiklik istekleri göndermesine olanak tanır. - Müşteri olarak
com.sdv.google.user_preferences.UserPreferencesRegistryServicekullanın. Bu işlem, başlatma sırasında ayarlarınızı kaydeder.
Aşağıdaki örnekte, kullanıcı tarafından kontrol edilebilen bir hizmet için
service_bundle.vsidlgösterilmektedir:service_bundle { name: "MyFeatureService" server { service: "com.sdv.google.user_preferences.user_controllable.UserControllableService" } client { service: "com.sdv.google.user_preferences.UserPreferencesRegistryService" } }- Sunucu olarak
Başlangıçta anahtar proto'daki kayıt ayarları
user_preferences_registry_service.proto:UserPreferencesRegistryServiceağına bağlanın.RegisterSettingsRequestörneği oluşturun.SettingsGroupörneğini (ayarların mantıksal koleksiyonu) tanımlayın.Her ayar için şunları tanımlayın:
* **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).Şu numaraya telefon et:
RegisterSettings().
Aşağıdaki örnek, kavramsal Rust dilindedir:
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.protoiçinde ayar değiştirme isteklerini işleme:RequestSettingsChangeRPC'sini uygulayın.- İstenen değerlerin geçerli bağlamda (ör. donanım hazırsa) geçerli olup olmadığını doğrulayın.
- Değişikliği uygulamak için belirli bir mantık uygulayın (örneğin, koltuğu hareket ettirin, fan hızını değiştirin).
RequestSettingsChangeResponseiçinde uygulanan değerleri döndürür:- Değişikliği kabul ettiyseniz yeni değeri döndürün.
- Değeri reddettiyseniz veya sınırladıysanız ayarladığınız (veya sakladığınız) değeri döndürün.
Aşağıdaki örnek, kavramsal Rust dilindedir:
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, }) }Alt sisteminizi temiz bir duruma geri döndürmek için
FactoryResetRPC'yi uygulayın:- Tüm ayarları varsayılan değerlerine (kod yapılandırmanızda tanımlandığı şekilde) sıfırlayın.
- Değerlerin harici olarak (sıfırlama yoluyla, kullanıcı isteğiyle değil) değiştirildiğini aracıya bildirmek için kayıt hizmetinde
UpdateSettingsişlevini çağırın.
Geriye dönük uyumluluk ve şema gelişimi
Kullanıcı tarafından kontrol edilebilen bir hizmet tarafından tanımlanan ayarların şeması, herkese açık arayüz olarak kabul edilir. Bu arayüz, kullanıcı tercihleri aracısı ve farklı yayın planlarına sahip olabilecek çeşitli istemciler (ör. HMI'ler) tarafından kullanılır. Bu nedenle, sistem kararsızlığını ve istemci bozulmasını önlemek için sıkı bir geriye dönük uyumluluk sağlamak önemlidir.
Uyumlu değişiklikler
Kullanıcı tarafından kontrol edilebilen bir hizmet, ayar şemasına yalnızca uyumlu değişiklikler getirmelidir. Bu değişiklikler, eski istemcilerin güncellemeler olmadan doğru şekilde çalışmaya devam etmesini sağlar:
Makul bir varsayılan değere sahip yeni ve isteğe bağlı bir ayar ekleyin:
- Bu ayar isteğe bağlıdır. Bu nedenle, istemcilerin hizmetin farklı sürümlerini desteklemek için bu ayarın varlığını kontrol etmesi gerekir.
- Güncellenerek bu ayarı tanımayan istemciler ayarı yoksayar.
- Yeni ayarla ilgili kullanıcı tercihi yoksa aracı, sağlanan varsayılan değeri kullanır.
Uyumsuz değişiklikler
Aşağıdaki değişiklikler, eski istemcileri hemen etkilediği için uyumluluğu bozan değişiklikler olarak kabul edilir ve yasaktır:
Mevcut bir ayarı kaldırma
Mevcut bir ayarın anlamını, birimini veya veri türünü değiştirme (örneğin, santigrat cinsinden sıcaklığı temsil eden bir tam sayıdan Pascal cinsinden basıncı temsil eden bir kayan sayıya geçme).
Mevcut bir ayarın varsayılan değerini değiştirin. Varsayılan değer değişikliklerinin yasaklanmasının temel nedeni, kalıcı veri taşıma işleminde yaşanabilecek olası sorunlardır. Ajan, hizmetin kayıt şemasına göre ayarları depolar. Varsayılan bir değeri değiştirmek, mevcut tüm kullanıcı profillerini yeni varsayılana taşımak için karmaşık bir mantık gerektirir. Aksi takdirde, tercihi açıkça ayarlamayan kullanıcılar için teknik olarak yanlış bir değer kullanma riski ortaya çıkar.
Zarar veren gerekli değişiklikleri işleme
Kullanıcıları etkileyen bir değişiklik yapılması gerekiyorsa hizmet, mevcut ayarı değiştirmemelidir. Bu geçişi uyumluluğu koruyarak yönetme yaklaşımı, öncelikle kullanıcı tarafından kontrol edilebilen hizmet mantığında yer alır:
- İstediğiniz yeni tanım, anahtar veya birimle yeni bir ayar oluşturun.
- Uyumluluk için kaydederek mevcut ayarın desteğini sonlandırın. Yeni müşteriler geliştirirken bu yeni ayarı kullanın.
- Yeni müşterilere, kullanıcı tarafından kontrol edilebilen hizmetin iş mantığı içinde uyumluluk mantığı uygulamalarını tavsiye edin.
Hizmetin RequestSettingsChange uygulaması, bir ayarda yapılan değişikliğin, desteği sonlandırılan karşılığında ve karşılığında yapılan değişikliğin ayarda yansıtılmasını sağlamalıdır.
Örnek uyumluluk mantığı:
Bir hizmet, eski ayar
TEMPERATURE_C(Celsius) desteğini sonlandırıpTEMPERATURE_K(Kelvin) ayarını kullanıma sunuyor.Aracı, yeni ayarı güncelleme isteği gönderdiğinde:
Hizmet,
TEMPERATURE_Kiçin bir istek alır (örneğin, 295,15 K).Hizmetin mantığı, bunu santigrat dereceye (22 °C) dönüştürür ve eski istemcilerde tutarlılığı korumak için her iki değeri de dahili olarak güncelleyip kalıcı hale getirir.
Temsilci, eski bir istemciden kullanımdan kaldırılan ayar için istek gönderdiğinde:
- Hizmet,
TEMPERATURE_Ciçin bir istek alır (örneğin, 24 °C). - Hizmet, bu değeri Kelvin'e (297,15 K) dönüştürür ve her iki değeri de dahili olarak güncelleyip kalıcı hale getirir.
- Hizmet,
Bu çift yazma stratejisi, yayın takvimlerinden bağımsız olarak tüm istemcilerin tutarlı ve doğru veriler okumasını sağlar. Böylece, harici yayın uyuşmazlıklarından kaynaklanan bozulmalar önlenir.
İstemci uygulama
UserPreferences temsilcisiyle etkileşim kuran bir istemci (ör. HMI) uygulamak için:
Belirli kullanıcı tercihleri arayüzleriyle etkileşim kurmak için istemci hizmeti paketinizi tanımlayın. VSIDL dosyanızda:
- Sunucu olarak, istemcinize ayar değişiklikleriyle ilgili gerçek zamanlı bildirimler göndermesi için
com.sdv.google.user_preferences.view.ChangeNotifieruygulayın. - Müşteri olarak,
com.sdv.google.user_preferences.UserPreferencesManagementServicesimgesini kullanarak ayar değişiklikleri isteyebilir ve güncellemeleri takip edebilirsiniz. - İstemci olarak, kullanıcı profillerini (ör. oluşturma, seçme, silme, fabrika ayarlarına sıfırlama) yönetmek için
com.sdv.google.user_preferences.UserPreferencesAdminServicesimgesini kullanın.
Aşağıdaki örnekte bir istemci için
service_bundle.vsidldosyası gösterilmektedir: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" } }Yetkilendirme politikalarını buna göre ekleyin. Kullanıcı tercihi aracısının iletişim kurmasına izin vermek için belirtilen sunuculara yönelik bir istemci oluşturun. Örneğin:
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 }- Sunucu olarak, istemcinize ayar değişiklikleriyle ilgili gerçek zamanlı bildirimler göndermesi için
İstek ayarlarını
UserPreferencesManagementServicebölümünde değiştirebilirsiniz:UserPreferencesManagementServiceağına bağlanın.RequestSettingsChangeRequestörneği oluşturun,SettingsGroupIdve istediğiniz ayarları belirtin.- İsteğe bağlı.
ChangePersistencePolicydeğeriniPERSISTENT_CHANGE(varsayılan) veyaNON_PERSISTENT_CHANGEolarak ayarlayın. - Şu numaraya telefon et:
RequestSettingsChange().
Aşağıdaki örnek, kavramsal Rust dilindedir:
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.protovechange_notifier.protoile ayar değişikliklerine abone olma:- Hizmet paketinize
ChangeNotifierarayüzündenOnSettingsChangeTBG'sini uygulayın. Kullanıcı tercihleri aracısı, bir değişiklik olduğunda bu yöntemi çağırır. UserPreferencesManagementServiceağına bağlanın.- İzlemek istediğiniz
SubscribeToSettingsChangeAndGetSettingsRequestbelirten birSettingsGroupIdoluşturun. - Ayarların durumunu geri döndürmek ve gelecekteki güncellemeleri
OnSettingsChangeuygulamanız üzerinden göndermek içinSubscribeToSettingsChangeAndGetSettings()işlevini çağırın.
ChangeNotifierarayüzünü uygulama ile ilgili aşağıdaki örnek, kavramsal Rust dilindedir:#[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()) } }Aşağıdaki abonelik örneği kavramsal Rust dilindedir:
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?;- Hizmet paketinize
İsteğe bağlı: Kullanıcı profillerini yöneten istemciler (ör. özel bir ayarlar uygulaması), yönetici hizmetiyle etkileşim kurmak için
user_preferences_admin_service.protokullanabilir:UserPreferencesAdminServiceağına bağlanın.- Kullanıcı profillerini yönetmek için
CreateUser,SelectUser,DeleteUser,FactoryResetveListUsersgibi RPC'leri kullanın.
Aşağıdaki kullanıcı oluşturma örneği kavramsal Rust dilindedir:
admin_service_client.CreateUser(&CreateUserRequest { user: Some(User { id: 1, flags: UserFlags::DRIVER.value(), ..Default::default() }).into(), ..Default::default() }).await?;user_preferences_admin_service.protoile yönetici hizmeti üzerinden kullanılabilir ayarları ve kullanıcıları keşfedin:ListUsers()üzerindeUserPreferencesAdminService'yi çağırarak tüm kayıtlı kullanıcıların listesini alın.UserPreferencesAdminServiceüzerindeGetUserSettings(user_id)işlevini çağırarak belirli bir kullanıcının ayarlarını alın.
Aşağıdaki kullanıcıları listeleme ve ayarları alma örneği kavramsal Rust dilindedir:
// 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); }
Akış özeti
- İstemci, aracının yönetim ve idari hizmetlerine bağlanır.
- İstemci, ayar gruplarını keşfedip bunlara abone olur ve ilk durumu gösterir.
- İstemci, aracıya bir
RequestSettingsChangegönderir. - Temsilci, güncellenmiş ayarlar ve durumla birlikte müşteriye bir
OnSettingsChangebildirimi gönderir.
Çalışan tam bir örnek için HMIService bölümündeki @samples/user_preferences/v1/ konusuna bakın.
Aracıyı uygulama
Düzenleyici tarafından başlatılan bir hizmet paketi, kullanıcı tercihlerini uygulayan bir aracıdır. Kolaylık sağlamak için bir referans uygulaması sağlanır.
Ayrıca, aracı için bu örnek hizmet paketi user_preferences_sample.vsidl dosyası sağlanır:
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"
}
}
Uygulama, oluşturulan ara yazılımı kullanabilir ve kullanıcı tercihleri aracını uygulayan hizmet paketi tarafından referans verilen bir rust_ffi_shared içinde derlenmelidir:
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"
}
İstemcinin yetkilendirme politikası .textproto dosyasında gerekli izinler olmalıdır:
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
}
Ek: Temel kavramlar
Bu bölümde bazı temel kavramlar açıklanmaktadır.
Kullanıcılar
Her araç kullanıcısı (User sınıfı), tercihlerini saklayabileceği bir hesap oluşturabilir. Kullanıcı tercihleri yalnızca araç sürücülerinin hesaplarını destekler.
Misafir sürücüler, tek kullanımdan sonra otomatik olarak silinen geçici hesaplar oluşturabilir.
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;
}
Ayarlar grupları
Ayar grupları (SettingsGroup sınıfı), ilgili ayarları düzenleyip yönetir.
Araçtaki her yapılandırılabilir bileşen, ayarlarını anahtar/değer çiftleri olarak gösterilen bir ayar listesinden oluşan gruplar halinde tanımlar. Örneğin, elektrikli koltuklara sahip araçlar, sürücü koltuğu için bir ayar grubu, ön yolcu koltuğu için de başka bir ayar grubu tanımlayabilir. Her iki grup da aynı ada sahip ayarları içerir.
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;
}
Ayarlar
Ayarı (Setting sınıfı), SettingsGroup içindeki tek bir ayarı temsil eder. Bu mesaj, ayarın adı olan bir anahtar ve birkaç türden biri olabilen bir değerden oluşur.
Bu örnekte, bir ayarın anahtar ve değerle nasıl temsil edildiği gösterilmektedir:
// 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;
}
}
Ayar tanımları
Ayarlar tanımları (SettingDefinition sınıfı), bir ayar grubundaki tek tek ayarlar için şablon görevi görür. Bu özellikler, ayarın tüm kullanıcılarla paylaşılıp paylaşılmadığı, her kullanıcıya özel olup olmadığı veya harici olarak yönetilip yönetilmediği (geçiş) gibi ayarın temel özelliklerini belirtir.
Önemli olarak, ayar tanımları, ayarın değeriyle ilgili tüm kısıtlamaları da (ör. minimum ve maksimum değerler, izin verilen artışlar veya sınırlı bir seçenek grubu) tanımlar. Bu kısıtlamalar, her ayar için veri bütünlüğünü ve tutarlılığını sağlar.
// 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;
}
Kullanıcı bir ayarı güncellediğinde gerçekleşen etkinliklerin örnek sırası
Bu örnekte, bir kullanıcı ayarı güncellemek için Android Automotive OS (AAOS) araç içi bilgi-eğlence (IVI) sistemini kullandığında gerçekleşen etkinliklerin sırası gösterilmektedir:
Şekil 1. Kullanıcı bir ayarı değiştirdiğinde gerçekleşen etkinlikler.
Bir araç çalıştırıldığında gerçekleşen etkinliklerin örnek sırası
Bu örnekte, SDV Kullanıcı Tercihleri'nin bir araç çalıştırılırken kullanıcının tercih ettiği ayarları nasıl uyguladığı gösterilmektedir:
Şekil 2. Bir araç çalıştırıldığında gerçekleşen etkinlikler.