Build and deploy service bundles

After you have created the middleware and written your custom code, you can deploy your service bundles as APEX files.

  1. Create SDV configuration files:

    Rust

    1. Generate SDV configuration files by running:

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

      Running vsidlc with the --apex flag automatically generates all necessary configuration files, including:

      • APEX manifest (apex_manifest.json)
      • SDV metadata manifest (sdv_service_bundles_manifest.textproto)
      • Linker configuration (linker.config.json)
      • SELinux file contexts (file_contexts)
      • Public and private keys (.avbpubkey and .pem)
      • Permission declarations and orchestration configurations
      • An Android.bp file defining all necessary Soong modules.

      You can find the generated configurations under:

      /path/to/output/apex/
      

      and,

      /path/to/output/configs/
      

    C++

    1. Create an SDV metadata manifest file, service_bundle.manifest.textproto with these essential execution metadata fields:

      • Name of the service according to the naming conventions
      • Integer and string representation of the service bundle version
      • Path to the library created previously

      Preparing essential service bundle metadata is mandatory for service bundle packaging and deployment.

      # proto-file: //system/software_defined_vehicle/core_services/service_bundles_registry/proto/sdv_service_bundles_manifest.proto
      # proto-message: SdvServiceBundleManifestEntry
      
      # SDV service bundle metadata definition with mandatory fields.
      sdv_service_bundle_metadata {
        # Service bundle name.
        name: "ServiceBundleName"
        # Service bundle integer version.
        version_number: 42
        # Service bundle version as a string.
        version_name: "42.alpha"
        # Service bundle library path.
        native_library_path: "lib64/libservice_bundle.so"
      }
      
    2. Create a new linker configuration file, linker.config.json:

      { "visible": true }
      
    3. Create a new apex_manifest.json file with these fields:

      • Unique SDV package name according to the SDV naming conventions
      • Version of the APEX
      • Dependency on SDV Comms libs
      {
        "name": "com.sdv.oem.apex_and_module_name",
        "version": 1,
        "requireNativeLibs": [
            "libsdv_comms_ctx_ffi.so",
            "libsdv_comms_dt_ffi.so",
            "libsdv_comms_id_ffi.so",
            "libsdv_comms_sd_ffi.so"
        ]
      }
      
    4. Create a public key, apex_name.apex_key.avbpubkey and a private key, apex_name.apex_key.pem.

    5. Create a new SELinux file context apex_file_contexts.

      (/.*)?    u:object_r:system_file:s0
      

      To learn more, see Security context and categories.

    6. Create prebuilt targets in a new or an existing Android.bp file:

      // SDV manifest file prebuilt.
      prebuilt_etc {
          name: "com.sdv.oem.apex_and_module_name.service_bundles_manifest",
          // The source filename of the manifest file.
          src: "service_bundle.manifest.textproto",
          // The name of the installed file needs be `sdv_service_bundles_manifest.textproto`.
          filename: "sdv_service_bundles_manifest.textproto",
          // Disable direct installation of the prebuilt to one of the partitions.
          // The manifest is used only inside of an apex.
          installable: false,
      }
      // The linker config to allow libraries for the apex to be linkable.
      linker_config {
          name: "com.sdv.oem.apex_and_module_name. linker_config",
          src: "linker.config.json",
          // Disable direct installation of the prebuilt to one of the partitions.
          // The linker configuration is used only inside of an apex.
          installable: false,
      }
      // Key to be used for signing the apex.
      apex_key {
          name: "apex_name.apex_key",
          public_key: "apex_name.apex_key.avbpubkey",
          private_key: "apex_name.apex_key.pem",
      }
      
    7. Create a new APEX module in a new or existing Android.bp file. Use the SDV package name as the APEX module name.

      apex {
          name: "com.sdv.oem.apex_and_module_name",
          // The service bundle(s) to be included in the apex.
          native_shared_libs: [
              "libservice_bundle",
          ],
          prebuilts: [
              // SDV service bundles manifest file.
              "com.sdv.oem.apex_and_module_name.service_bundles_manifest",
              // Linker configuration to enable loading library from apex.
              "com.sdv.oem.apex_and_module_name.linker_config",
          ],
          // Json manifest file describes metadata of the APEX package.
          // The 'name' field from the JSON is used as a mounting point.
          manifest: "apex_manifest.json",
          // Setting the security contexts to files in this APEX bundle.
          file_contexts: "apex_file_contexts",
          // Name of the apex_key module that provides the private key to sign the APEX bundle.
          key: "apex_name.apex_key",
          // Mark apex as non-updatable for now, this might be revisited going forward.
          updatable: false,
          // Service bundle package is installed into /product partition.
          product_specific: true,
      }
      
  2. To include the new makefile in an SDV image, add the new APEX module to the PRODUCT_PACKAGES in the product makefile. For example, see sdv_samples_core_services.mk.

  3. If you're using Cuttlefish, run the following command to start a device:

    sdv-cf create --instance_name=instance1
    
  4. Run the service bundle when the system is booted:

    # Grant root access.
    adb root
    # Launch the new service bundle.
    adb shell sdv_service_bundle start \
      local-vm:com.sdv.oem.apex_and_module_name.ServiceBundleName/instance-1
    

Service bundle dependency management

In some scenarios, you can use static linking of the service bundle dependencies to reduce APEX size and service bundle memory footprint, and to improve the startup time of the service bundles. These scenarios include APEXes with:

  • Single service bundles
  • Several service bundles that don't share many common dependencies

To enable static linking, add the following properties to the service bundle library definition:

// Service bundle library.
rust_ffi_shared {
  // See rust_ffi_shared basic template.
  ...
  // uses static linking for the dependencies
  prefer_rlib: true,
  // needed to correctly resolve commstack deps
  ld_flags: ["-Wl,--no-as-needed"],
}

For each situation, we recommend you confirm that static linking to dependencies leads to improvements in memory footprint and start times of service bundles.

Debug (dumpsys)

The lifecycle manager implements the dumpsys interface. This interface displays the list of service bundles to the user that are in either the created or started state. The interface also displays the FQIN or UID of the service bundle process.

To view the current state and identifiers of your service bundles, execute:

# Grant root access.
adb root

# Execute dumpsys to see service bundles state
adb shell dumpsys google.sdv.lifecycle.ILifecycleManager/default

What's next

To automatically execute vsidlc and enable the IDE plugin to work with dependencies, see Automatic catalog updates and LSP integration.