Instrument Cluster API

Gunakan Instrument Cluster API (Android API) untuk menampilkan aplikasi navigasi, termasuk Google Maps, di layar sekunder dalam mobil, seperti di belakang kemudi pada panel instrumen. Halaman ini menjelaskan cara membuat layanan untuk mengontrol layar sekunder tersebut dan mengintegrasikan layanan dengan CarService sehingga aplikasi navigasi dapat menampilkan antarmuka pengguna.

Terminologi

Istilah berikut digunakan di halaman ini.

CarInstrumentClusterManager
Instance CarManager yang memungkinkan aplikasi eksternal meluncurkan aktivitas di Cluster Instrumen dan menerima callback saat Cluster Instrumen siap menampilkan aktivitas.
CarManager
Class dasar semua pengelola yang digunakan oleh aplikasi eksternal untuk berinteraksi dengan layanan khusus mobil yang diimplementasikan oleh CarService.
LayananMobil
Layanan Platform Android yang menyediakan komunikasi antara aplikasi eksternal (termasuk Google Maps) dan fitur khusus mobil, seperti akses Cluster Instrumen.
Tujuan
Tujuan akhir yang akan dituju oleh kendaraan.
Perkiraan waktu tiba (PWT)
Perkiraan waktu tiba di tujuan.
Head unit (HU)
Unit komputasi utama yang disematkan di mobil. HU menjalankan semua kode Android dan terhubung ke layar pusat di mobil.
Cluster Instrumen
Layar sekunder yang terletak di belakang kemudi dan di antara instrumen mobil. Layar ini dapat berupa unit komputasi independen yang terhubung ke HU melalui jaringan internal mobil (CAN bus) atau layar sekunder yang terpasang ke HU.
InstrumentClusterRenderingService
Class dasar untuk layanan yang digunakan untuk berinteraksi dengan layar Cluster Instrumen. OEM harus menyediakan ekstensi class ini yang berinteraksi dengan hardware khusus OEM.
Aplikasi KitchenSink
Aplikasi pengujian yang disertakan dengan Android Automotive.
Rute
Jalur tertentu yang dilalui kendaraan untuk tiba di tujuan.
Layanan singleton
Layanan Android dengan atribut android:singleUser. Pada waktu tertentu, paling banyak satu instance layanan yang berjalan di sistem Android.

Prasyarat

Sebelum melanjutkan, pastikan Anda memiliki elemen berikut:

  • Lingkungan pengembangan Android. Untuk menyiapkan lingkungan pengembangan Android lingkungan pengembangan, lihat Persyaratan build.
  • Download kode sumber Android. Dapatkan kode sumber Android versi terbaru dari cabang pi-car-release (atau yang lebih baru) di https://android.googlesource.com.
  • Head unit (HU). Perangkat Android yang dapat menjalankan Android 9 (atau yang lebih baru). Perangkat ini harus memiliki layar sendiri dan dapat mem-flash layar dengan build Android baru.
  • Cluster Instrumen adalah salah satu hal berikut:
    • Layar sekunder fisik yang terpasang ke HU. Jika hardware dan kernel perangkat mendukung pengelolaan beberapa layar.
    • Unit independen. Unit komputasi apa pun yang terhubung ke HU melalui koneksi jaringan, yang dapat menerima dan menampilkan streaming video di layarnya sendiri.
    • Layar yang diemulasi. Selama pengembangan, Anda dapat menggunakan salah satu dari lingkungan yang diemulasi berikut:
      • Layar sekunder yang disimulasikan. Untuk mengaktifkan layar sekunder yang disimulasikan di distribusi Android AOSP mana pun, buka setelan Opsi Developer di aplikasi sistem Setelan, lalu pilih Simulasikan layar sekunder Konfigurasi ini setara dengan melampirkan layar sekunder fisik, dengan batasan bahwa layar ini ditimpa di atas layar utama.
      • Cluster instrumen yang diemulasi. Emulator Android yang disertakan dengan AAOS menyediakan opsi untuk menampilkan cluster instrumen dengan ClusterRenderingService.

Arsitektur integrasi

Komponen integrasi

Setiap integrasi Instrument Cluster API terdiri dari tiga komponen berikut:

  • CarService
  • Aplikasi navigasi
  • Layanan Cluster Instrumen OEM

Komponen integrasi

LayananMobil

CarService memediasi antara aplikasi navigasi dan mobil, memastikan bahwa hanya satu aplikasi navigasi yang aktif pada waktu tertentu dan hanya aplikasi dengan izin android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL yang dapat mengirim data ke mobil.

CarService mem-bootstrap semua layanan khusus mobil dan menyediakan akses ke layanan ini melalui serangkaian pengelola. Untuk berinteraksi dengan layanan, aplikasi yang berjalan di mobil dapat mengakses pengelola ini.

Untuk implementasi cluster instrumen, OEM otomotif harus membuat implementasi kustom InstrumentClusterRendererService dan memperbarui ClusterRenderingService.

Saat merender Cluster Instrumen, selama proses booting, the CarService membaca kunci InstrumentClusterRendererService dari the ClusterRenderingService untuk menemukan implementasi InstrumentClusterService. Di AOSP, entri ini mengarah ke layanan render implementasi cluster contoh Navigation State API:

<string name="instrumentClusterRendererService">
android.car.cluster/.ClusterRenderingService
</string>

Layanan yang dirujuk dalam entri ini diinisialisasi dan terikat ke CarService. Saat aplikasi navigasi, seperti Google Maps, meminta CarInstrumentClusterManager, CarService akan menyediakan pengelola yang memperbarui status Cluster Instrumen dari InstrumentClusterRenderingService yang terikat. (Dalam hal ini, terikat mengacu pada Layanan Android.)

Layanan Cluster Instrumen

OEM harus membuat Paket Android (APK) yang berisi subclass dari ClusterRenderingService.

Class ini memiliki dua tujuan:

  • Menyediakan antarmuka Android dan perangkat rendering Cluster Instrumen (tujuan halaman ini).
  • Menerima dan merender pembaruan status navigasi, seperti panduan navigasi belokan demi belokan.

Untuk tujuan pertama, implementasi OEM InstrumentClusterRendererService harus menginisialisasi layar sekunder yang digunakan untuk merender informasi di layar dalam kabin mobil dan mengomunikasikan informasi ini ke CarService dengan memanggil metode InstrumentClusterRendererService.setClusterActivityOptions() dan InstrumentClusterRendererService.setClusterActivityState().

Untuk fungsi kedua, layanan Cluster Instrumen harus menyediakan implementasi antarmuka ClusterRenderingService yang menerima pembaruan status navigasi peristiwa, yang dienkode sebagai eventType dan data peristiwa yang dienkode dalam paket.

Urutan integrasi

Diagram berikut mengilustrasikan implementasi status navigasi yang merender pembaruan:

Urutan integrasi

Dalam ilustrasi ini, warna menunjukkan hal berikut:

  • Kuning. CarService dan CarNavigationStatusManager yang disediakan oleh platform Android. Untuk mempelajari lebih lanjut, lihat Mobil dan CAR_NAVIGATION_SERVICE.
  • Sian. InstrumentClusterRendererService diimplementasikan oleh OEM.
  • Ungu. Aplikasi Navigasi yang diimplementasikan oleh Google dan developer pihak ketiga developer.
  • Hijau. CarAppFocusManager. Untuk mempelajari lebih lanjut, lihat Menggunakan CarAppFocusManager API di bawah dan CarAppFocusManager.

Alur informasi Status Navigasi mengikuti urutan ini:

  1. CarService menginisialisasi InstrumentClusterRenderingService.
  2. Selama inisialisasi, InstrumentClusterRenderingService memperbarui CarService dengan:
    1. Properti tampilan Cluster Instrumen, seperti batas yang tidak terhalang (lihat detail selengkapnya tentang batas yang tidak terhalang nanti).
    2. Opsi aktivitas yang diperlukan untuk meluncurkan aktivitas di dalam tampilan Cluster Instrumen. Untuk mempelajari lebih lanjut, lihat ActivityOptions.
  3. Aplikasi navigasi (seperti Google Maps untuk Android Automotive atau aplikasi peta apa pun dengan izin yang diperlukan):
    1. Mendapatkan CarAppFocusManager menggunakan class Car dari car-lib.
    2. Sebelum petunjuk belokan demi belokan dimulai, panggil CarAppFocusManager.requestFocus() untuk meneruskan CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION sebagai appType parameter.
  4. CarAppFocusManager mengomunikasikan permintaan ini ke CarService. Jika diizinkan, CarService akan memeriksa paket aplikasi navigasi dan menemukan aktivitas yang ditandai dengan kategori android.car.cluster.NAVIGATION.
  5. Jika ditemukan, aplikasi navigasi akan menggunakan ActivityOptions yang dilaporkan oleh InstrumentClusterRenderingService untuk meluncurkan aktivitas dan menyertakan properti tampilan Cluster Instrumen sebagai tambahan dalam intent.

Mengintegrasikan API

Implementasi InstrumentClusterRenderingService harus:

  • Ditentukan sebagai layanan singleton dengan menambahkan nilai berikut ke AndroidManifest.xml. Hal ini diperlukan untuk memastikan bahwa satu salinan layanan Cluster Instrumen berjalan, bahkan selama inisialisasi dan pengalihan pengguna:
    android:singleUser="true"
  • Memiliki izin sistem BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE. Hal ini menjamin bahwa hanya layanan rendering Cluster Instrumen yang disertakan sebagai bagian dari image sistem Android yang pernah terikat oleh CarService:
    <uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
    

Mengimplementasikan InstrumentClusterRenderingService

Untuk membuat layanan:

  1. Tulis class yang diperluas dari ClusterRenderingService lalu tambahkan entri yang sesuai ke file AndroidManifest.xml Anda. Class ini mengontrol tampilan Cluster Instrumen dan dapat (secara opsional) merender data Navigation State API.
  2. Selama onCreate(), gunakan layanan ini untuk menginisialisasi komunikasi dengan hardware rendering. Opsinya mencakup:
    • Menentukan layar sekunder yang akan digunakan untuk Cluster Instrumen.
    • Membuat layar virtual sehingga aplikasi Cluster Instrumen merender dan mengirimkan gambar yang dirender ke unit eksternal (menggunakan format streaming video, seperti H.264).
  3. Saat layar yang ditunjukkan di atas siap, layanan ini harus memanggil InstrumentClusterRenderingService#setClusterActivityLaunchOptions() untuk menentukan ActivityOptions yang tepat yang harus digunakan untuk menampilkan Aktivitas di Cluster Instrumen. Gunakan parameter ini:
    • category. ClusterRenderingService.
    • ActivityOptions. Instance ActivityOptions yang dapat digunakan untuk meluncurkan Aktivitas di Cluster Instrumen. Misalnya, dari implementasi Cluster Instrumen contoh di AOSP:
      getService().setClusterActivityLaunchOptions(
        CATEGORY_NAVIGATION,
        ActivityOptions.makeBasic()
            .setLaunchDisplayId(displayId));
  4. Saat Cluster Instrumen siap menampilkan aktivitas, layanan ini harus memanggil InstrumentClusterRenderingService#setClusterActivityState(). Gunakan parameter ini: parameter:
    • category ClusterRenderingService.
    • state Paket yang dibuat dengan ClusterRenderingService. Pastikan untuk memberikan data ini:
      • visible Menentukan Cluster Instrumen sebagai terlihat dan siap untuk menampilkan konten.
      • unobscuredBounds Persegi panjang yang menentukan area dalam tampilan Cluster Instrumen tempat konten dapat ditampilkan dengan aman. Misalnya, area yang tercakup oleh tombol dan pengukur.
  5. Ganti metode Service#dump() dan laporkan informasi status yang berguna untuk proses debug (lihat dumpsys untuk mengetahui informasi selengkapnya).

Implementasi InstrumentClusterRenderingService contoh

Contoh berikut menguraikan implementasi InstrumentClusterRenderingService, yang membuat VirtualDisplay untuk menampilkan konten Cluster Instrumen di layar fisik jarak jauh.

Atau, kode ini dapat meneruskan displayId layar sekunder fisik yang terhubung ke HU, jika diketahui tersedia.

/**
* Sample {@link InstrumentClusterRenderingService} implementation
*/
public class SampleClusterServiceImpl extends InstrumentClusterRenderingService {
   // Used to retrieve or create displays
   private final DisplayManager mDisplayManager;
   // Unique identifier for the display to be used for instrument
   // cluster
   private final String mUniqueId = UUID.randomUUID().toString();
   // Format of the instrument cluster display
   private static final int DISPLAY_WIDTH = 1280;
   private static final int DISPLAY_HEIGHT = 720;
   private static final int DISPLAY_DPI = 320;
   // Area not covered by instruments
   private static final int DISPLAY_UNOBSCURED_LEFT = 40;
   private static final int DISPLAY_UNOBSCURED_TOP = 0;
   private static final int DISPLAY_UNOBSCURED_RIGHT = 1200;
   private static final int DISPLAY_UNOBSCURED_BOTTOM = 680;
   @Override
   public void onCreate() {
      super.onCreate();
      // Create a virtual display to render instrument cluster activities on
      mDisplayManager = getSystemService(DisplayManager.class);
      VirtualDisplay display = mDisplayManager.createVirtualDisplay(
          mUniqueId, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_DPI, null,
          0 /* flags */, null, null);
      // Do any additional initialization (e.g.: start a video stream
      // based on this virtual display to present activities on a remote
      // display).
      onDisplayReady(display.getDisplay());
}
private void onDisplayReady(Display display) {
    // Report activity options that should be used to launch activities on
    // the instrument cluster.
    String category = CarInstrumentClusterManager.CATEGORY_NAVIGATION;
    ActionOptions options = ActivityOptions.makeBasic()
        .setLaunchDisplayId(display.getDisplayId());
    setClusterActivityOptions(category, options);
    // Report instrument cluster state.
    Rect unobscuredBounds = new Rect(DISPLAY_UNOBSCURED_LEFT,
        DISPLAY_UNOBSCURED_TOP, DISPLAY_UNOBSCURED_RIGHT,
        DISPLAY_UNOBSCURED_BOTTOM);
    boolean visible = true;
    ClusterActivityState state = ClusterActivityState.create(visible,
       unobscuredBounds);
    setClusterActivityState(category, options);
  }
}

Menggunakan CarAppFocusManager API

CarAppFocusManager API menyediakan metode bernama getAppTypeOwner(), yang memungkinkan layanan cluster yang ditulis oleh OEM mengetahui aplikasi navigasi mana yang memiliki fokus navigasi pada waktu tertentu. OEM dapat menggunakan metode CarAppFocusManager#addFocusListener() yang ada, lalu menggunakan getAppTypeOwner() untuk mempelajari aplikasi mana yang memiliki fokus. Dengan informasi ini, OEM dapat:

  • Mengalihkan aktivitas yang ditampilkan di cluster ke aktivitas cluster yang disediakan oleh aplikasi navigasi yang memiliki fokus.
  • Dapat mendeteksi apakah aplikasi navigasi yang difokuskan memiliki aktivitas cluster atau tidak. Jika aplikasi navigasi yang difokuskan tidak memiliki aktivitas cluster (atau jika aktivitas tersebut dinonaktifkan), OEM dapat mengirimkan sinyal ini ke DIM mobil sehingga aspek navigasi cluster akan dilewati sepenuhnya.

Gunakan CarAppFocusManager untuk menetapkan dan memproses fokus aplikasi saat ini, seperti navigasi aktif atau perintah suara. Biasanya, hanya satu instance aplikasi tersebut yang berjalan aktif (atau difokuskan) dalam sistem.

Gunakan metode CarAppFocusManager#addFocusListener(..) untuk memproses perubahan fokus aplikasi:

import android.car.CarAppFocusManager;

...

Car car = Car.createCar(this);
mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE);
mAppFocusManager.addFocusListener(this, CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION);

...

public void onAppFocusChanged(int appType, boolean active) {
    // Use the CarAppFocusManager#getAppTypeOwner(appType) method call
    // to retrieve a list of active package names
}

Gunakan metode CarAppFocusManager#getAppTypeOwner(..) untuk mengambil nama paket pemilik saat ini dari jenis aplikasi tertentu yang menjadi fokus. Metode ini dapat menampilkan lebih dari satu nama paket jika pemilik saat ini menggunakan fitur android:sharedUserId.

import android.car.CarAppFocusManager;

...

Car car = Car.createCar(this);
mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE);
List<String> focusOwnerPackageNames = mAppFocusManager.getAppTypeOwner(
              CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION);

if (focusOwnerPackageNames == null || focusOwnerPackageNames.isEmpty()) {
        // No Navigation app has focus
        // OEM may choose to show their default cluster view
} else {
       // focusOwnerPackageNames
       // Use the PackageManager to retrieve the cluster activity for the package(s)
       // returned in focusOwnerPackageNames
}

...

Mengidentifikasi aplikasi template

Untuk aplikasi navigasi berbasis template yang menggunakan library Aplikasi Mobil, CarAppFocusManager#getAppTypeOwner() akan menampilkan nama paket host (misalnya, com.google.android.apps.automotive.templates.host) karena host memiliki fokus sistem atas nama aplikasi klien.

Untuk mengidentifikasi aplikasi klien yang melakukan navigasi, OEM dapat mengekstrak nama paket dari paket status navigasi yang dikirim dengan CarNavigationStatusManager. Nama paket disimpan dengan kunci active_app_package_name dalam paket yang diterima oleh NavigationRenderer#onNavigationStateChanged(Bundle):

// In your NavigationRenderer implementation
@Override
public void onNavigationStateChanged(Bundle bundle) {
    if (bundle.containsKey("active_app_package_name")) {
        String activeAppPackage = bundle.getString("active_app_package_name");
        // Use the package name to identify the navigating app (e.g., com.waze)
    }
}

Lampiran: Menggunakan aplikasi contoh

AOSP menyediakan aplikasi contoh yang mengimplementasikan Navigation State API.

Untuk menjalankan aplikasi contoh ini:

  1. Buat dan flash Android Auto di HU yang didukung. Gunakan petunjuk pembuatan dan flashing Android yang khusus untuk perangkat Anda. Untuk mengetahui petunjuknya, lihat Menggunakan Papan Referensi.
  2. Hubungkan layar sekunder fisik ke HU (jika didukung) atau aktifkan HU sekunder virtual:
    1. Pilih Mode Developer di aplikasi Setelan.
    2. Buka Setelan > Sistem > Lanjutan > Opsi developer > Simulasikan layar sekunder.
  3. Mulai ulang HU
  4. Untuk meluncurkan aplikasi KitchenSink:
    1. Buka panel.
    2. Buka Cluster Instrumen.
    3. Klik MULAI METADATA.

KitchenSink meminta fokus NAVIGASI, yang menginstruksikan layanan DirectRenderingCluster untuk menampilkan antarmuka pengguna tiruan di Cluster Instrumen.