تنفيذ منطق العمل

  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. اكتب رمزًا مخصّصًا لتنفيذ منطق مؤسستك:

    • خوادم RPC: نفِّذ السمات من lib.rs.
    • عملاء النشر والاشتراك وRPC: استدعِ الدوال التي تم إنشاؤها ضمن service_bundle.rs للتفاعل مع الخدمات الأخرى.

    الصدأ (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 والخوادم. لتعديل هذا السلوك، ابحث عن تعليقات TODO في main.rs واضبطها حسب تفضيلاتك. على سبيل المثال:

      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() {
          // Dynamic resources(sockets, files, etc) should be allocated 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 phase requires the service bundle to delete the dynamic resources
          // (sockets, files, etc) that were previously 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,
      }
      

الخطوات التالية

لنشر حِزم الخدمات، اطّلِع على مقالة إنشاء حِزم الخدمات ونشرها.