Hướng dẫn triển khai và cấu trúc các lựa chọn ưu tiên của người dùng

Trang này cung cấp hướng dẫn về cấu trúc của hệ thống Lựa chọn ưu tiên của người dùng SDV và hướng dẫn triển khai dịch vụ cũng như ứng dụng có thể kiểm soát của người dùng.

Tổng quan về cấu trúc

Hệ thống Lựa chọn ưu tiên của người dùng tách biệt việc lưu trữ và quản lý chế độ cài đặt của người dùng với việc thực thi và áp dụng các chế độ cài đặt đó. Các thuật ngữ chính về cấu trúc được tóm tắt trong bảng sau:

Tính năngMô tảVai tròTrách nhiệm
Dịch vụ do người dùng kiểm soát Một gói dịch vụ SDV tiêu chuẩn quản lý một miền cụ thể (ví dụ: HVAC, ghế ô tô, âm thanh) Cung cấp trạng thái dự kiến của các chức năng và hạn chế của phần cứng hoặc hệ thống con mà nó kiểm soát.
  • Đăng ký: Thông báo cho tác nhân lựa chọn ưu tiên của người dùng về những chế độ cài đặt mà tác nhân này hỗ trợ (siêu dữ liệu, giá trị mặc định, các ràng buộc).
  • Thực thi và tự chủ: Nhận yêu cầu thay đổi chế độ cài đặt, xác thực các yêu cầu đó dựa trên trạng thái hiện tại và các quy tắc an toàn, đồng thời áp dụng các yêu cầu đó cho phần cứng. Duy trì quyền tự chủ hoàn toàn và chỉ định xem có chấp nhận hay từ chối thay đổi chế độ cài đặt.
Tác nhân lựa chọn ưu tiên của người dùng Orchestrator trung tâm Cung cấp bộ nhớ tập trung, tính năng quản lý hồ sơ người dùng và trung tâm thông báo.
  • Bộ nhớ: Lưu giữ các chế độ cài đặt cho mỗi người dùng (ví dụ: người lái xe, hành khách).
  • Định tuyến: Các proxy thay đổi yêu cầu từ ứng dụng (ví dụ: giao diện người dùng (HMI)) thành dịch vụ phù hợp mà người dùng có thể kiểm soát.
  • Thông báo: Truyền tin về các thay đổi cho các bên liên quan (chế độ xem hoặc HMI) bằng cách sử dụng giao diện ChangeNotifier.
  • Quản lý người dùng: Xử lý việc chuyển đổi người dùng và áp dụng trạng thái liên tục chính xác cho tất cả các dịch vụ đã đăng ký.
Ứng dụng lựa chọn ưu tiên của người dùng Một ứng dụng hoặc dịch vụ cung cấp giao diện người dùng, chẳng hạn như ứng dụng IVI có HMI hoặc logic khác cần tương tác với lựa chọn ưu tiên của người dùng Tương tác với người dùng, hiển thị chế độ cài đặt và bắt đầu các yêu cầu thay đổi.
  • Hiển thị: Trình bày các chế độ cài đặt và ràng buộc hiện tại cho người dùng.
  • Yêu cầu thay đổi: Gửi các nội dung sửa đổi chế độ cài đặt do người dùng khởi tạo đến tác nhân lựa chọn ưu tiên của người dùng.
  • Nhận thông báo: Đăng ký và phản hồi các nội dung cập nhật chế độ cài đặt theo thời gian thực.

Triển khai một dịch vụ do người dùng kiểm soát

Để thông báo cho tác nhân Lựa chọn ưu tiên của người dùng biết những khoá hiện có, kiểu dữ liệu, giá trị mặc định và các ràng buộc (ví dụ: giá trị tối thiểu và tối đa), gói dịch vụ của bạn phải tương tác với giao diện UserPreferencesRegistryService. Khi dịch vụ của bạn bắt đầu, dịch vụ đó phải đăng ký các chế độ cài đặt mà dịch vụ đó hiển thị. Tác nhân gọi RequestSettingsChange trên dịch vụ của bạn khi người dùng cố gắng sửa đổi một chế độ cài đặt (hoặc khi chuyển đổi người dùng).

Hãy làm theo các bước trong phần này để cho phép Lựa chọn ưu tiên của người dùng (và người dùng có HMI) kiểm soát dịch vụ của bạn.

  1. Xác định các giao diện dịch vụ trong tệp VSIDL:

    • Là một máy chủ, hãy triển khai com.sdv.google.user_preferences.user_controllable.UserControllableService. Nhờ đó, nhân viên hỗ trợ có thể gửi cho bạn yêu cầu thay đổi.
    • Là một ứng dụng khách, hãy sử dụng com.sdv.google.user_preferences.UserPreferencesRegistryService. Thao tác này sẽ đăng ký chế độ cài đặt của bạn khi khởi động.

    Ví dụ sau đây cho thấy service_bundle.vsidl cho một dịch vụ do người dùng kiểm soát:

    service_bundle {
        name: "MyFeatureService"
        server {
            service: "com.sdv.google.user_preferences.user_controllable.UserControllableService"
        }
        client {
            service: "com.sdv.google.user_preferences.UserPreferencesRegistryService"
        }
    }
    
  2. Đăng ký các chế độ cài đặt khi khởi động trong giao thức khoá user_preferences_registry_service.proto:

    1. Kết nối với UserPreferencesRegistryService.
    2. Tạo một thực thể của RegisterSettingsRequest.
    3. Xác định một thực thể của SettingsGroup (một tập hợp các chế độ cài đặt theo logic).
    4. Đối với mỗi chế độ cài đặt, hãy xác định:

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

    Ví dụ sau đây là trong Rust theo khái niệm:

    let temperature_setting = SettingDefinition {
        name: "TEMPERATURE".to_string(),
        kind: SettingKind::PER_USER.into(),
        default_value: Value::Int64(22), // Default 22 degrees
        constraint: Some(Constraints::Int64Constraints(Int64Constraints {
            min_value: Some(16),
            max_value: Some(32),
            ..Default::default()
        })),
        ..Default::default()
    };
    
    registry_client.RegisterSettings(&RegisterSettingsRequest {
        group_name: "HVAC".to_string(),
        version: "1.0".to_string(),
        settings_definitions: vec![temperature_setting],
    }).await?;
    
  3. Xử lý các yêu cầu thay đổi chế độ cài đặt trong user_controllable_service.proto:

    1. Triển khai RPC RequestSettingsChange.
    2. Xác thực xem các giá trị được yêu cầu có hợp lệ trong bối cảnh hiện tại hay không (ví dụ: nếu phần cứng đã sẵn sàng).
    3. Áp dụng logic cụ thể để áp dụng thay đổi (ví dụ: di chuyển ghế, thay đổi tốc độ quạt).
    4. Trả về các giá trị được áp dụng trong RequestSettingsChangeResponse:
    5. Nếu bạn chấp nhận thay đổi, hãy trả về giá trị mới.
    6. Nếu bạn từ chối hoặc giới hạn giá trị, hãy trả về giá trị mà bạn đã đặt (hoặc giữ lại).

    Ví dụ sau đây là trong Rust theo khái niệm:

    async fn RequestSettingsChange(
        &self,
        _caller_id: ServiceFqin,
        request: &RequestSettingsChangeRequest
    ) -> SdvResult<RequestSettingsChangeResponse> {
        let mut applied_settings = Vec::new();
    
        for setting in &request.settings {
            if self.hardware.set_value(setting.key, setting.value).is_ok() {
                // Change accepted
                applied_settings.push(setting.clone());
            } else {
                // Change rejected, return current actual value
                let current_val = self.hardware.get_value(setting.key);
                applied_settings.push(create_setting(setting.key, current_val));
            }
        }
    
        Ok(RequestSettingsChangeResponse {
            settings: applied_settings,
        })
    }
    
  4. Triển khai RPC FactoryReset để đưa hệ thống con về trạng thái ban đầu:

    1. Đặt lại tất cả chế độ cài đặt về giá trị mặc định (như được xác định trong cấu hình mã của bạn).
    2. Gọi UpdateSettings trên dịch vụ đăng ký để thông báo cho tác nhân rằng các giá trị đã thay đổi bên ngoài (do quá trình đặt lại, chứ không phải do yêu cầu của người dùng).

Khả năng tương thích ngược và sự phát triển của giản đồ

Giản đồ của các chế độ cài đặt do một dịch vụ có thể kiểm soát của người dùng xác định được coi là một giao diện công khai. Giao diện này được tác nhân lựa chọn ưu tiên của người dùng và nhiều ứng dụng (ví dụ: HMI) sử dụng. Các ứng dụng này có thể có lịch phát hành khác nhau. Do đó, việc duy trì khả năng tương thích ngược nghiêm ngặt là điều cần thiết để ngăn chặn tình trạng hệ thống không ổn định và sự cố máy khách.

Thay đổi tương thích

Dịch vụ do người dùng kiểm soát chỉ nên giới thiệu những thay đổi tương thích với giản đồ cài đặt của dịch vụ. Những thay đổi này đảm bảo rằng các ứng dụng cũ vẫn hoạt động chính xác mà không cần cập nhật:

  • Thêm một chế độ cài đặt mới, không bắt buộc với giá trị mặc định hợp lý:

    • Đây là chế độ cài đặt không bắt buộc, vì vậy, các ứng dụng phải kiểm tra sự hiện diện của chế độ cài đặt này để hỗ trợ các phiên bản khác nhau của dịch vụ.
    • Các ứng dụng sẽ bỏ qua chế độ cài đặt này nếu chưa được cập nhật để nhận ra chế độ cài đặt này.
    • Nếu không có lựa chọn ưu tiên nào của người dùng cho chế độ cài đặt mới, thì tác nhân sẽ sử dụng giá trị mặc định được cung cấp.

Thay đổi không tương thích

Những thay đổi sau đây được coi là thay đổi có thể gây lỗi và bị cấm vì chúng ngay lập tức ảnh hưởng đến các ứng dụng cũ:

  • Xoá một chế độ cài đặt hiện có.

  • Thay đổi ý nghĩa, đơn vị hoặc kiểu dữ liệu của một chế độ cài đặt hiện có (ví dụ: thay đổi từ số nguyên biểu thị nhiệt độ theo độ C thành số thực biểu thị áp suất theo Pascal).

  • Thay đổi giá trị mặc định của một chế độ cài đặt hiện có. Lý do chính khiến bạn không được phép thay đổi giá trị mặc định là do có thể xảy ra vấn đề phức tạp với việc di chuyển dữ liệu được duy trì. Tác nhân lưu trữ các chế độ cài đặt dựa trên giản đồ đăng ký của dịch vụ. Việc thay đổi giá trị mặc định sẽ đòi hỏi logic phức tạp để di chuyển tất cả hồ sơ người dùng hiện có sang giá trị mặc định mới hoặc có nguy cơ sử dụng giá trị không chính xác về mặt kỹ thuật cho những người dùng chưa bao giờ đặt rõ ràng lựa chọn ưu tiên.

Xử lý các thay đổi bắt buộc có thể gây lỗi

Nếu cần có một thay đổi mang tính đột phá, thì dịch vụ không được sửa đổi chế độ cài đặt hiện có. Phương pháp quản lý quá trình chuyển đổi này trong khi vẫn duy trì khả năng tương thích chủ yếu nằm trong logic dịch vụ do người dùng kiểm soát:

  1. Tạo một chế độ cài đặt mới có định nghĩa, khoá hoặc đơn vị mới mà bạn muốn.
  2. Không dùng chế độ cài đặt hiện có bằng cách đăng ký chế độ cài đặt đó để tương thích. Hãy sử dụng chế độ cài đặt mới này khi bạn phát triển các ứng dụng khách mới.
  3. Khuyên khách hàng mới triển khai logic tương thích trong logic nghiệp vụ của dịch vụ do người dùng kiểm soát.

Việc triển khai RequestSettingsChange của dịch vụ phải đảm bảo rằng một thay đổi đối với một chế độ cài đặt sẽ được phản ánh trong chế độ cài đặt tương ứng không dùng nữa và một thay đổi đối với chế độ cài đặt tương ứng sẽ được phản ánh trong chế độ cài đặt.

Ví dụ về logic tương thích:

  1. Một dịch vụ ngừng sử dụng chế độ cài đặt cũ TEMPERATURE_C (Độ C) và giới thiệu TEMPERATURE_K (Độ Kelvin).

  2. Khi nhân viên hỗ trợ gửi yêu cầu cập nhật chế độ cài đặt mới:

    • Dịch vụ này nhận được yêu cầu về TEMPERATURE_K (ví dụ: 295, 15 K).

    • Logic của dịch vụ sẽ chuyển đổi giá trị này thành độ C (22°C), đồng thời cập nhật và duy trì cả hai giá trị này trong nội bộ để đảm bảo tính nhất quán cho các ứng dụng cũ.

  3. Khi tác nhân gửi yêu cầu về chế độ cài đặt không dùng nữa từ một ứng dụng cũ:

    • Dịch vụ nhận được yêu cầu về TEMPERATURE_C (ví dụ: 24°C).
    • Dịch vụ này sẽ chuyển đổi giá trị này thành độ Kelvin (297,15 K) và cập nhật cũng như duy trì cả hai giá trị này trong nội bộ.

Chiến lược ghi kép này đảm bảo rằng tất cả các ứng dụng, bất kể lịch phát hành của chúng, đều đọc dữ liệu nhất quán và chính xác, tránh tình trạng gián đoạn do sự không khớp giữa các bản phát hành bên ngoài.

Triển khai một ứng dụng

Để triển khai một ứng dụng (ví dụ: HMI) tương tác với tác nhân UserPreferences:

  1. Xác định gói dịch vụ khách hàng để tương tác với các giao diện Tuỳ chọn ưu tiên của người dùng cụ thể. Trong tệp VSIDL:

    • Là một máy chủ, hãy triển khai com.sdv.google.user_preferences.view.ChangeNotifier để cho phép tác nhân gửi thông báo theo thời gian thực cho máy khách của bạn về các thay đổi đối với chế độ cài đặt.
    • Là một ứng dụng khách, hãy sử dụng com.sdv.google.user_preferences.UserPreferencesManagementService để yêu cầu sửa đổi chế độ cài đặt và đăng ký nhận thông tin cập nhật.
    • Là một ứng dụng, hãy sử dụng com.sdv.google.user_preferences.UserPreferencesAdminService để quản lý hồ sơ người dùng (ví dụ: tạo, chọn, xoá, đặt lại về trạng thái ban đầu).

    Ví dụ sau đây minh hoạ một tệp service_bundle.vsidl cho một ứng dụng:

    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"
        }
    }
    

    Thêm chính sách uỷ quyền cho phù hợp. Để cho phép tác nhân lựa chọn ưu tiên của người dùng giao tiếp, hãy tạo một máy khách cho các máy chủ được chỉ định. Ví dụ:

    server {
        service: "com.sdv.google.user_preferences.view.ChangeNotifier"
        allow_all_channels: true
    }
    client {
        service: "com.sdv.google.user_preferences.UserPreferencesManagementService"
        allow_all_channels: true
    }
    client {
        service: "com.sdv.google.user_preferences.UserPreferencesAdminService"
        allow_all_channels: true
    }
    
  2. Bạn có thể thay đổi chế độ cài đặt yêu cầu trong UserPreferencesManagementService:

    1. Kết nối với UserPreferencesManagementService.
    2. Tạo một thực thể của RequestSettingsChangeRequest, chỉ định SettingsGroupId và các chế độ cài đặt mong muốn.
    3. Không bắt buộc. Đặt ChangePersistencePolicy thành PERSISTENT_CHANGE (mặc định) hoặc NON_PERSISTENT_CHANGE.
    4. Gọi RequestSettingsChange().

    Ví dụ sau đây là trong Rust theo khái niệm:

    management_client.RequestSettingsChange(&RequestSettingsChangeRequest {
        settings_group_id: Some(SettingsGroupId {
            service_fqin: hvac_service_fqin.to_string(),
            name: "HVAC".to_string(),
            ..Default::default()
        }).into(),
        settings: vec![Setting {
            key: "TEMPERATURE".to_string(),
            value: Some(Value::Int64(24)),
            ..Default::default()
        }],
        change_persistence_policy: ChangePersistencePolicy::PERSISTENT_CHANGE.into(),
        ..Default::default()
    }).await?;
    
  3. Đăng ký nhận thông báo về các thay đổi đối với chế độ cài đặt bằng user_preferences_management_service.protochange_notifier.proto:

    1. Triển khai RPC OnSettingsChange từ giao diện ChangeNotifier trong gói dịch vụ của bạn. Tác nhân Lựa chọn ưu tiên của người dùng sẽ gọi phương thức này khi có thay đổi.
    2. Kết nối với UserPreferencesManagementService.
    3. Tạo một SubscribeToSettingsChangeAndGetSettingsRequest chỉ định SettingsGroupId mà bạn muốn theo dõi.
    4. Để trả về trạng thái của các chế độ cài đặt, sau đó gửi các bản cập nhật trong tương lai thông qua việc triển khai OnSettingsChange, hãy gọi SubscribeToSettingsChangeAndGetSettings().

    Ví dụ sau đây về cách triển khai giao diện ChangeNotifier là trong Rust theo khái niệm:

    #[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())
        }
    }
    

    Ví dụ sau đây về việc đăng ký là trong Rust theo khái niệm:

    management_client.SubscribeToSettingsChangeAndGetSettings(&SubscribeToSettingsChangeAndGetSettingsRequest {
        settings_group_id: Some(SettingsGroupId {
            service_fqin: hvac_service_fqin.to_string(),
            name: "HVAC".to_string(),
            ..Default::default()
        }).into(),
        ..Default::default()
    }).await?;
    
  4. Không bắt buộc: Các ứng dụng quản lý hồ sơ người dùng (ví dụ: một ứng dụng cài đặt chuyên dụng) có thể sử dụng user_preferences_admin_service.proto để tương tác với dịch vụ quản trị:

    1. Kết nối với UserPreferencesAdminService.
    2. Sử dụng các RPC như CreateUser, SelectUser, DeleteUser, FactoryResetListUsers để quản lý hồ sơ người dùng.

    Ví dụ sau đây về cách tạo người dùng là trong Rust theo khái niệm:

    admin_service_client.CreateUser(&CreateUserRequest {
        user: Some(User {
            id: 1,
            flags: UserFlags::DRIVER.value(),
            ..Default::default()
        }).into(),
        ..Default::default()
    }).await?;
    
  5. Khám phá các chế độ cài đặt và người dùng hiện có thông qua dịch vụ quản trị bằng user_preferences_admin_service.proto:

    1. Lấy danh sách tất cả người dùng đã đăng ký bằng cách gọi ListUsers() trên UserPreferencesAdminService.
    2. Lấy chế độ cài đặt cho một người dùng cụ thể bằng cách gọi GetUserSettings(user_id) trên UserPreferencesAdminService.

    Ví dụ sau đây về việc liệt kê người dùng và nhận chế độ cài đặt là trong Rust theo khái niệm:

    // 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);
    }
    

Tóm tắt quy trình

  1. Ứng dụng bắt đầu và kết nối với các dịch vụ quản lý và quản trị của tác nhân.
  2. Ứng dụng sẽ phát hiện và đăng ký các nhóm chế độ cài đặt, đồng thời hiển thị trạng thái ban đầu.
  3. Ứng dụng sẽ gửi một RequestSettingsChange đến tác nhân.
  4. Tác nhân gửi thông báo OnSettingsChange đến máy khách kèm theo chế độ cài đặt và trạng thái mới nhất.

Để xem ví dụ đầy đủ về cách thức hoạt động, hãy xem HMIService trong @samples/user_preferences/v1/.

Triển khai tác nhân

Một gói dịch vụ do trình điều phối khởi chạy sẽ triển khai tác nhân lựa chọn ưu tiên của người dùng. Để thuận tiện, chúng tôi cung cấp một cách triển khai tham chiếu.

Ngoài ra, tệp user_preferences_sample.vsidl gói dịch vụ mẫu này dành cho đại lý:

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"
    }
}

Quá trình triển khai có thể sử dụng phần mềm trung gian đã tạo và phải biên dịch thành một rust_ffi_shared được gói dịch vụ tham chiếu triển khai tác nhân lựa chọn ưu tiên của người dùng:

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"
}

Tệp chính sách uỷ quyền .textproto của ứng dụng cần có các quyền cần thiết:

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
}

Phụ lục: Các khái niệm chính

Phần này mô tả một số khái niệm chính.

Người dùng

Mỗi người dùng xe (lớp User) có thể tạo một tài khoản để lưu trữ các lựa chọn ưu tiên của họ. Chế độ Lựa chọn ưu tiên của người dùng chỉ hỗ trợ tài khoản dành cho người lái xe. Người lái xe khách có thể tạo tài khoản tạm thời và tài khoản này sẽ tự động bị xoá sau một lần sử dụng.

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;
}

Nhóm chế độ cài đặt

Các nhóm chế độ cài đặt (lớp SettingsGroup) sắp xếp và quản lý các chế độ cài đặt có liên quan. Mỗi thành phần có thể định cấu hình trong xe sẽ xác định chế độ cài đặt của thành phần đó dưới dạng các nhóm, bao gồm một danh sách các chế độ cài đặt được biểu thị dưới dạng các cặp khoá-giá trị. Ví dụ: xe có ghế điện có thể xác định một nhóm chế độ cài đặt cho ghế lái và một nhóm khác cho ghế hành khách phía trước, trong đó cả hai nhóm đều chứa các chế độ cài đặt có tên giống nhau.

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;
}

Cài đặt

Chế độ cài đặt, thông báo (lớp Setting) biểu thị một chế độ cài đặt trong SettingsGroup. Thông báo này bao gồm một khoá (là tên của chế độ cài đặt) và một giá trị (có thể là một trong nhiều loại).

Ví dụ này cho thấy cách một chế độ cài đặt được biểu thị bằng một khoá và một giá trị:

// 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;
  }
}

Định nghĩa về chế độ cài đặt

Định nghĩa chế độ cài đặt (lớp SettingDefinition) đóng vai trò là mẫu cho từng chế độ cài đặt trong một nhóm chế độ cài đặt. Chúng chỉ định các đặc điểm cơ bản của chế độ cài đặt, chẳng hạn như chế độ cài đặt có được chia sẻ cho tất cả người dùng, dành riêng cho từng người dùng hay được quản lý bên ngoài (truyền qua).

Điều quan trọng là các định nghĩa về chế độ cài đặt cũng xác định mọi ràng buộc đối với giá trị của chế độ cài đặt, chẳng hạn như giá trị tối thiểu và tối đa, mức tăng cho phép hoặc một tập hợp các lựa chọn bị hạn chế. Những ràng buộc này giúp đảm bảo tính toàn vẹn và nhất quán của dữ liệu cho từng chế độ cài đặt.

// 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;
}

Ví dụ về chuỗi sự kiện khi người dùng cập nhật một chế độ cài đặt

Ví dụ này minh hoạ chuỗi sự kiện xảy ra khi người dùng sử dụng Đầu phát giải trí trong xe (IVI) chạy Android Automotive OS (AAOS) để cập nhật một chế độ cài đặt:

Sự kiện khi người dùng thay đổi chế độ cài đặt

Hình 1. Sự kiện khi người dùng thay đổi một chế độ cài đặt.

Ví dụ về chuỗi sự kiện khi xe đang khởi động

Ví dụ này minh hoạ cách SDV User Preferences áp dụng các chế độ cài đặt ưu tiên của người dùng khi xe đang khởi động:

Sự kiện khi xe đang khởi động

Hình 2. Sự kiện khi xe bắt đầu khởi động.