Guide de démarrage rapide : créer et exécuter des bundles de services SDV

Cette page vous explique comment créer un bundle de services SDV, l'empaqueter au format de fichier APEX et l'exécuter sur un appareil Cuttlefish virtuel. Les principales unités d'exécution de code sur le système SDV sont les bundles de services. Les bundles de services fournissent des méthodes de cycle de vie que le système exécute lorsque l'état du système change.

  1. Configurer votre environnement de compilation

    Dans votre répertoire de travail, sourcez le script envsetup.sh pour configurer votre environnement de compilation, définissez Cuttlefish comme cible de compilation et compilez le générateur de code vsidlc :

    source build/envsetup.sh
    lunch sdv_core_cf-aosp_current-userdebug
    m vsidlc
    
  2. Définissez votre architecture en créant un dossier nommé my_catalog avec les fichiers suivants :

    • tire.proto : définit la structure des données que vous envoyez :

      syntax = "proto3";
      
      package com.android.sdv.sample.quickstart;
      
      import "google/protobuf/empty.proto";
      import "sdv/vsidl/v1/annotations.proto";
      
      message TirePressure {
        uint32 pressure = 1;
      }
      
      message TireInfoResponse {
        string serial_number = 1;
        uint32 max_pressure = 2;
      }
      
      service TireService {
        rpc GetTireInfo(google.protobuf.Empty) returns (TireInfoResponse);
      }
      
    • architecture.vsidl : définit les bundles de services et leur communication (pour la coloration syntaxique, la validation et la saisie semi-automatique dans Android Studio for Platform, consultez Modifier les fichiers VSIDL) :

      package: "com.android.sdv.sample.quickstart"
      
      service_bundle {
        name: "Manager"
      
        publisher {
          message: "TirePressure"
          topic: "pressure"
          capacity: 8
        }
      
        server {
          service: "TireService"
          channel: "tire-service"
        }
      }
      
      service_bundle {
        name: "Monitor"
      
        subscriber {
          message: "TirePressure"
          topic: "pressure"
        }
      
        client {
          service: "TireService"
          channel: "tire-service"
        }
      }
      
    • Android.bp : définit le processus de compilation :

      rust_protobuf {
          name: "libquickstart_sample_tire_proto",
          crate_name: "quickstart_sample_tire_proto",
          protos: [
              "tire.proto",
          ],
          source_stem: "quickstart_sample_tire_proto_source",
          rustlibs: [
              "libvsidl_v1_stdlib_proto_rs",
          ],
          proto_flags: [
              "-I external/protobuf/src",
          ],
          vendor_available: true,
          product_available: true,
          apex_available: [
              "//apex_available:platform",
              "//apex_available:anyapex",
          ],
          min_sdk_version: "35",
      }
      
      filegroup {
          name: "vsidl_quickstart_catalog",
          srcs: ["**/*"],
      }
      
  3. Générez un squelette d'implémentation et des fichiers de configuration en exécutant la commande suivante :

    vsidlc -c /path/to/catalog -o /path/to/output --services --apex
    
  4. Pour chaque bundle de services, recherchez l'implémentation Rust dans /path/to/output/services/ServiceBundleName/src/main.rs.

  5. Par défaut, l'implémentation générée crée des messages avec des valeurs par défaut et les envoie entre les éditeurs et les abonnés ou les clients et les serveurs RPC. Pour modifier ce comportement, recherchez les commentaires TODO dans main.rs et ajustez-les selon vos préférences. Exemple :

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

  6. Pour inclure votre bundle dans l'image système, ajoutez le nom du module APEX généré au fichier makefile de votre produit.

    1. Ouvrez le fichier makefile de votre produit (par exemple, device/google/sdv/sdv_core_base/sdv_samples_core_services.mk).

    2. Ajoutez le module à PRODUCT_PACKAGES en ajoutant :

      PRODUCT_PACKAGES += com.android.sdv.sample.quickstart
      PRODUCT_PACKAGES += com_android_sdv_sample_quickstart_orchestration_configurations
      
  7. Créez l'image comme suit :

    m
    

    Une fois que l'image système inclut l'APEX (ou la clé utilisée pour le signer), vous pouvez également créer et déployer des modifications itératives directement à partir de l'icône de marge apex/Android.bp dans Android Studio for Platform. Pour en savoir plus, consultez Déployer des bundles de services SDV.

  8. Exécutez et vérifiez l'exécution du bundle de services :

    1. Démarrez un appareil Cuttlefish virtuel :

      sdv-cf create --instance_name=instance1
      
    2. Exécutez le bundle de services au démarrage du système :

      • Manuellement :

        adb wait-for-device
        adb root
        adb shell sdv_service_bundle start local-vm:com.android.sdv.sample.quickstart.Manager/instance
        adb shell sdv_service_bundle start local-vm:com.android.sdv.sample.quickstart.Monitor/instance
        
      • Utiliser l'outil d'orchestration :

        adb wait-for-device
        adb root
        # Apply global orchestration configuration by setting system property
        adb shell setprop persist.sdv.orchestrator_config_path "etc/orch/vm_quickstart_orch_config.textproto"
        adb reboot
        
    3. Vérifiez l'exécution du bundle de services :

      adb logcat *:F com_android_sdv_sample_quickstart_Manager_instance:* com_android_sdv_sample_quickstart_Monitor_instance:*
      

      Cette commande affiche les journaux qui montrent les bundles de services échangeant des messages :

      03-30 13:41:31.505   967   976 I com_android_sdv_sample_quickstart_Manager_instance: sdv_lm_manager: Publishing on TirePressure#PRESSURE
      03-30 13:41:31.505   983   991 I com_android_sdv_sample_quickstart_Monitor_instance: sdv_lm_monitor: Received message on TirePressure#PRESSURE: [TirePressure { pressure: 0, special_fields: SpecialFields { unknown_fields: UnknownFields { fields: None }, cached_size: CachedSize { size: 0 } } }]
      03-30 13:41:31.626   983   991 I com_android_sdv_sample_quickstart_Monitor_instance: sdv_lm_monitor: Sending request on Monitor/TireService
      03-30 13:41:31.627   967   976 I com_android_sdv_sample_quickstart_Manager_instance: sdv_lm_manager: Received request on Manager/TireService: Empty { special_fields: SpecialFields { unknown_fields: UnknownFields { fields: None }, cached_size: CachedSize { size: 0 } } }
      03-30 13:41:31.627   983   991 I com_android_sdv_sample_quickstart_Monitor_instance: sdv_lm_monitor: Received response on Monitor/TireService: TireInfoResponse { serial_number: "", max_pressure: 0, special_fields: SpecialFields { unknown_fields: UnknownFields { fields: None }, cached_size: CachedSize { size: 0 } } }
      

Étape suivante

En savoir plus sur le langage de définition d'interface des services de véhicule (VSIDL) et sur la façon de définir vos propres packs de services à partir de zéro.