實作商業邏輯

  1. 確認 VSIDL 目錄包含必要的建構、protobuf 和 VSIDL 檔案。如要從現有範例開始,請在 /system/software_defined_vehicle/samples/vsidl/stable/catalog 下方尋找有效的目錄資料夾範例。

    目錄結構範例:

    my_catalog/
    ├── Android.bp          # Defines rust_protobuf modules for .proto files
    ├── types.proto         # Protobuf message / RPC service definitions
    └── architecture.vsidl  # VSIDL service bundle definitions
    
  2. 編寫自訂程式碼,實作商業邏輯。

    vsidlc 會為 Rust 產生中介軟體繫結和服務套件架構 (lib.rs、service_bundle.rs 和 main.rs)。如果使用 C++ 編寫服務套件,請直接實作生命週期 (libsdv_lifecycle_client_cpp) 和通訊 (libsdv_comms_cpp) 介面:

    • RPC 伺服器 (Rust):實作 lib.rs 產生的特徵。
    • 發布、訂閱和 RPC 用戶端 (Rust):呼叫 service_bundle.rs 內產生的函式,與其他服務互動。
    • 生命週期和通訊 (C++):子類別 ServiceBundle,並在 onStart 中初始化發布者、訂閱者或 RPC 端點。

    Rust

    1. 執行下列指令,生成骨架實作:

      vsidlc -c /path/to/catalog -o /path/to/output --services
      

      執行 vsidlc 並加上 --services 旗標,會為每個服務套件產生樣板 Rust 實作。這會提供原始碼 (main.rs) 和建構設定檔 (Android.bp),其中包含所有依附元件,因此套件可以立即交換預設訊息,您則可專注於商業邏輯。

    2. 如要查看各服務套件的 Rust 實作,請前往:

      /path/to/output/services/ServiceBundleName/src/main.rs。

    3. 根據預設,產生的實作會建立具有預設值的訊息,並在發布端和訂閱端之間,或 RPC 用戶端和伺服器之間傳送。如要修改這項行為,請在 main.rs 中找到 TODO 註解,並依偏好調整。例如:

      rust async fn handle_tire_pressure_range_unique_publisher( publisher: sdv::mw::Publisher<TirePressureRange>, ) { loop { // TODO: Modify the frequency of publishing messages here. sleep(Duration::from_secs(1)).await; // TODO: Modify the message content here. let message = TirePressureRange::default(); info!("Publishing on TirePressureRange#UNIQUE"); publisher.publish(&message).unwrap(); } }

    4. 為確保下次執行 vsidlc 時,您對生成檔案所做的修改不會遭到覆寫,請將 services 資料夾移出 /path/to/output 資料夾。

    C++

    1. 建立新的標頭檔案 src/lib.hpp,並為服務套件建立類別:

      #pragma once
      #include <sdv/service_bundle.h>
      #include <sdv/context.hpp>
      
      namespace com::sdv::oem::service_bundle {
      
      // Sample implementation of the service bundle interface.
      class ServiceBundleName : public android::sdv::service_bundle::ServiceBundle {
      public:
          ServiceBundleName(sdv_comms::ctx::Context context);
          ~ServiceBundleName();
          void onStart() override;
          void onStop() override;
      };
      }  // namespace com::sdv::oem::service_bundle
      
    2. 建立新的來源檔案 src/lib.cpp,並加入類別實作:

      #include "src/lib.hpp"
      #include <sdv/sb_macro.h>
      #include <iostream>
      using com::sdv::oem::service_bundle::ServiceBundleName;
      
      // Register the new service bundle.
      REGISTER_SERVICE_BUNDLE(ServiceBundleName);
      
      // Sample implementation of the service bundle interface.
      namespace com::sdv::oem::service_bundle {
      // Creates a new instance of the ServiceBundleName.
      // Called when service bundle is created by the system.
      // Context object is provided as a parameter that gives access to the
      // communication stack APIs.
      ServiceBundleName::ServiceBundleName([[maybe_unused]] sdv_comms::ctx::Context context) :
        ServiceBundle(context) {
          // Memory allocations and static data loading should be done as
          // part of this method.
          //
          // Loading of the dynamic resources (sockets, files, etc)
          // is strongly discouraged due to possible Suspend-to-RAM scenario.
          //
          // The dynamic data can be loaded in the onStart method.
      }
      
      // Called when the service bundle is started by the system.
      void ServiceBundleName::onStart() {
          // Allocate dynamic resources (sockets, files, publishers, and
          // subscribers such as TirePressureRange#UNIQUE) during this call.
      }
      
      // Called when the service bundle is stopped by the system in preparation
      // for shutdown or suspend to RAM/Disc.
      void ServiceBundleName::onStop() {
          // Stop active publishing loops and release the dynamic resources
          // that were allocated in the onStart method.
      }
      
      // Called when the service bundle is destroyed by the system.
      ServiceBundleName::~ServiceBundleName() {
          // Static resources deallocation needs to be implemented in the destructor.
      }
      }  // namespace com::sdv::oem::service_bundle
      
    3. 在新的或現有的 Android.bp 檔案中,建立服務套件程式庫 Soong 目標:

      // Service bundle library.
      cc_library_shared {
        name: "libservice_bundle",
        srcs: ["src/lib.cpp",],
        // Allows the library to be available inside APEX.
        apex_available: [
            "//apex_available:platform",
            "//apex_available:anyapex",
        ],
        shared_libs: [
          // Service Bundle lifecycle C++ API.
          "libsdv_lifecycle_client_cpp",
          // commstack library that provides context object reference
          "libsdv_comms_cpp",
        ],
      
        // Service bundle package is packed into /product apexes.
        product_specific: true,
      }
      

後續步驟

如要部署服務套件,請參閱「建構及部署服務套件」。