הטמעת לוגיקה עסקית

  1. מוודאים שבספריית הקטלוג של VSIDL יש את קובצי ה-build, ה-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 יוצר קישורי תוכנת ביניים ופיגומים של חבילות שירות (lib.rs,‏ service_bundle.rs ו-main.rs) ל-Rust. אם אתם כותבים חבילת שירות ב-C++‎, אתם צריכים להטמיע ישירות את הממשקים של מחזור החיים (libsdv_lifecycle_client_cpp) והתקשורת (libsdv_comms_cpp):

    • שרתי RPC ‏ (Rust): מטמיעים את המאפיינים שנוצרו מ-lib.rs.
    • לקוחות פרסום, הרשמה ו-RPC‏ (Rust): קוראים לפונקציות שנוצרו בתוך service_bundle.rs כדי ליצור אינטראקציה עם שירותים אחרים.
    • מחזור חיים ותקשורת (C++‎): יוצרים מחלקת משנה של ServiceBundle ומפעילים את נקודות הקצה של אפליקציות לשליחת הודעות, אפליקציות רשומות או RPC ב-onStart.

    חלודה

    1. מריצים את הפקודה הבאה כדי ליצור הטמעה בסיסית:

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

      כשמריצים את vsidlc עם הדגל --services, נוצרת הטמעת Rust סטנדרטית לכל חבילת שירות. הוא מספק את קוד המקור (main.rs) וקובץ תצורת build‏ (Android.bp) עם כל יחסי התלות, כך שהחבילה יכולה להחליף הודעות ברירת מחדל באופן מיידי בזמן שאתם מתמקדים בלוגיקה העסקית.

    2. לכל חבילת שירות, אפשר למצוא את ההטמעה של Rust בכתובת:

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

    3. כברירת מחדל, ההטמעה שנוצרת יוצרת הודעות עם ערכי ברירת מחדל ושולחת אותן בין בעלי תוכן דיגיטלי למנויים או בין לקוחות RPC לשרתים. כדי לשנות את ההתנהגות הזו, צריך למצוא את ההערות TODO בקובץ main.rs ולשנות אותן לפי ההעדפות שלכם. לדוגמה:

      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. יוצרים יעד Soong של ספריית חבילת שירות בקובץ Android.bp חדש או קיים:

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

המאמרים הבאים

כדי לפרוס את חבילות השירות, קראו את המאמר פיתוח ופריסה של חבילות שירות.