Instrument Cluster API

Użyj interfejsu Instrument Cluster API (interfejsu API Androida), aby wyświetlać aplikacje do nawigacji, w tym Mapy Google, na dodatkowym wyświetlaczu w samochodzie, np. za kierownicą na panelu wskaźników. Na tej stronie dowiesz się, jak utworzyć usługę do sterowania tym drugim wyświetlaczem i jak zintegrować ją z CarService, aby aplikacje nawigacyjne mogły wyświetlać interfejs użytkownika.

Terminologia

Na tej stronie używamy tych terminów.

CarInstrumentClusterManager
Instancja CarManager, która umożliwia aplikacjom zewnętrznym uruchamianie aktywności w klastrze przyrządów i otrzymywanie wywołań zwrotnych, gdy klaster jest gotowy do wyświetlania aktywności.
CarManager
Klasa bazowa wszystkich menedżerów używanych przez aplikacje zewnętrzne do interakcji z usługami związanymi z samochodem, które są implementowane przez CarService.
CarService
Usługa platformy Androida, która zapewnia komunikację między aplikacjami zewnętrznymi (w tym Mapami Google) a funkcjami związanymi z samochodem, takimi jak dostęp do tablicy rozdzielczej.
Miejsce docelowe
Ostateczny cel, do którego pojazd ma dojechać.
Szacowany czas dotarcia
Szacowany czas dotarcia do miejsca docelowego.
Jednostka główna (HU)
Główna jednostka obliczeniowa umieszczona w samochodzie. HU uruchamia cały kod Androida i jest połączony z wyświetlaczem centralnym w samochodzie.
Instrument Cluster
Dodatkowy wyświetlacz znajdujący się za kierownicą i między elementami sterowania. Może to być niezależna jednostka obliczeniowa połączona z HU przez wewnętrzną sieć samochodu (szyna CAN) lub dodatkowy wyświetlacz podłączony do HU.
InstrumentClusterRenderingService
Klasa podstawowa usługi używana do interfejsu z wyświetlaczem Instrument Cluster. Producenci OEM muszą udostępnić rozszerzenie tej klasy, które będzie współpracować ze sprzętem konkretnego producenta.
Aplikacja KitchenSink
Testowa aplikacja dołączona do Androida Automotive.
Trasa
Określona ścieżka, po której porusza się pojazd, aby dotrzeć do miejsca docelowego.
Usługa singleton
Usługa na Androidzie z atrybutem android:singleUser. W danym momencie w systemie Android działa maksymalnie 1 występowanie usługi.

Wymagania wstępne

Zanim przejdziesz dalej, przygotuj te elementy:

  • Środowisko programistyczne Androida Aby skonfigurować środowisko programistyczne Androida, zapoznaj się z artykułem Wymagania dotyczące kompilacji.
  • Pobierz kod źródłowy Androida. Pobierz najnowszą wersję kodu źródłowego Androida z gałęzi pi-car-release (lub nowszej) na stronie https://android.googlesource.com.
  • Główna jednostka (HU). urządzenie z Androidem w wersji 9 (lub nowszej), Urządzenie musi mieć własny wyświetlacz i możliwość flashowania wyświetlacza nowymi wersjami Androida.
  • Zbiór instrumentów to:
    • Fizyczny wyświetlacz dodatkowy podłączony do HU. czy sprzęt i jądro urządzenia obsługują zarządzanie wieloma wyświetlaczami.
    • Niezależna jednostka. dowolna jednostka obliczeniowa połączona z HU przez połączenie sieciowe, która może odbierać i wyświetlać strumień wideo na własnym wyświetlaczu;
    • Emulowany wyświetlacz Podczas tworzenia możesz korzystać z jednego z tych emulowanych środowisk:
      • Symulowane wyświetlacze dodatkowe. Aby włączyć symulowany wyświetlacz pomocniczy w dowolnej dystrybucji Androida AOSP, otwórz ustawienia Opcje dla deweloperów w aplikacji systemowej Ustawienia, a następnie wybierz Symuluj wyświetlacze pomocnicze. Ta konfiguracja jest równoważna podłączeniem fizycznego wyświetlacza pomocniczego, z tym ograniczeniem, że wyświetlacz jest nakładany na wyświetlacz główny.
      • Emulowany klaster instrumentów Dołączony do AAOS emulator Androida umożliwia wyświetlanie panelu sterowania z użyciem usługi ClusterRenderingService.

Architektura integracji

Komponenty integracji

Każda integracja interfejsu Instrument Cluster API składa się z tych 3 komponentów:

  • CarService
  • Aplikacje do nawigacji
  • OEM Instrument Cluster Service

Komponenty integracji

CarService

CarService pośredniczy między aplikacjami do nawigacji a samochodem, zapewniając, że w danym momencie aktywna jest tylko jedna aplikacja do nawigacji, a tylko aplikacje z uprawnieniem android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL mogą wysyłać dane do samochodu.

CarService uruchamia wszystkie usługi związane z samochodem i zapewnia dostęp do tych usług za pomocą serii menedżerów. Aby korzystać z usług, aplikacje działające w samochodzie mogą uzyskiwać dostęp do tych menedżerów.

W przypadku implementacji tablicy rozdzielczej firmy motoryzacyjnej OEM musi utworzyć niestandardową implementację InstrumentClusterRendererService i zaktualizować ClusterRenderingService.

Podczas renderowania klastra instrumentów w trakcie procesu uruchamiania CarService odczytuje klucz InstrumentClusterRendererService usługi ClusterRenderingService, aby zlokalizować implementację InstrumentClusterService. W AOSP ten wpis wskazuje na renderowanie usługi w ramach przykładowej implementacji klastra interfejsu API stanu nawigacji:

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

Usługa wymieniona w tym wpisie jest inicjowana i wiązana z CarService. Gdy aplikacje do nawigacji, takie jak Mapy Google, wysyłają żądanie do CarInstrumentClusterManager, CarService udostępnia menedżera, który aktualizuje stan grupy przyrządów na podstawie powiązanego elementu InstrumentClusterRenderingService. (W tym przypadku powiązany oznacza Usługi Androida).

Usługa Instrument Cluster

Producenci OEM muszą utworzyć pakiet Androida (APK), który zawiera podklasę ClusterRenderingService.

Te zajęcia mają 2 cele:

  • Udostępnia interfejs Androida i urządzenie do renderowania instrumentu (cel tej strony).
  • Odbiera i wyświetla aktualizacje stanu nawigacji, takie jak wskazówki dojazdu zakręt po zakręcie.

W pierwszym przypadku implementacje OEM InstrumentClusterRendererService muszą zainicjować dodatkowy wyświetlacz używany do renderowania informacji na ekranach w kabince samochodu oraz przekazać te informacje do CarService, wywołując metody InstrumentClusterRendererService.setClusterActivityOptions()InstrumentClusterRendererService.setClusterActivityState().

W przypadku drugiej funkcji usługa Instrument Cluster musi zapewniać implementację interfejsu ClusterRenderingService, który odbiera zdarzenia aktualizacji stanu nawigacji, które są kodowane jako eventType i dane zdarzeń zaszyfrowane w pakiecie.

Sekwencja integracji

Poniższy diagram przedstawia implementację stanu nawigacji, który renderuje aktualizacje:

Sekwencja integracji

Na tej ilustracji kolory oznaczają:

  • Żółty. CarServiceCarNavigationStatusManager udostępnione przez platformę Androida. Więcej informacji znajdziesz w usługach CarCAR_NAVIGATION_SERVICE.
  • Cyjan. InstrumentClusterRendererService wdrożony przez producenta OEM.
  • Fioletowy. Aplikacja Nawigacja wdrożona przez Google i deweloperów zewnętrznych.
  • Zielony. CarAppFocusManager. Więcej informacji znajdziesz w artykule Korzystanie z interfejsu CarAppFocusManager API poniżej oraz w artykule CarAppFocusManager.

Przepływ informacji o stanie nawigacji jest zgodny z tą sekwencją:

  1. CarService inicjalizuję InstrumentClusterRenderingService.
  2. Podczas inicjowania InstrumentClusterRenderingService aktualizuje CarService za pomocą:
    1. Właściwości wyświetlania instrumentu klastra, takie jak nieprzejrzyste granice (więcej informacji o nieprzejrzystych granicach znajdziesz dalej).
    2. Opcje aktywności potrzebne do uruchamiania aktywności w wyświetlaczu klastra przyrządów. Więcej informacji znajdziesz w artykule ActivityOptions.
  3. Aplikacja do nawigacji (np. Mapy Google na Androida Automotive lub dowolna aplikacja do map z wymaganymi uprawnieniami):
    1. Uzyskuje CarAppFocusManager, używając klasy Car z biblioteki car-lib.
    2. Przed rozpoczęciem wskazówek dojazdu do celu wywołuje funkcję CarAppFocusManager.requestFocus(), przekazując jako parametr CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION.appType
  4. CarAppFocusManager przekazuje tę prośbę do CarService. Jeśli dostęp zostanie przyznany, CarService sprawdzi pakiet aplikacji do nawigacji i odnajdzie aktywność oznaczoną kategorią android.car.cluster.NAVIGATION.
  5. Jeśli aplikacja do nawigacji znajdzie się na liście, użyje ActivityOptions zgłoszonego przez InstrumentClusterRenderingService, aby uruchomić aktywność, i uwzględni właściwości wyświetlania wyświetlacza kokpitowego jako dodatkowe informacje w intencji.

Integracja z interfejsem API

Implementacja usługi InstrumentClusterRenderingService musi:

  • być oznaczoną jako usługa pojedyncza przez dodanie tej wartości do pliku AndroidManifest.xml; Jest to konieczne, aby mieć pewność, że jedna kopia usługi Instrument Cluster działa nawet podczas inicjalizacji i przełączania użytkowników:
    android:singleUser="true"
  • Uprawnienia systemowe BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE. Gwarantuje to, że tylko usługa renderowania instrumentu z poziomu klastra, która jest częścią obrazu systemu Android, jest związana przez CarService:
    <uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
    

Implementacja InstrumentClusterRenderingService

Aby skompilować usługę:

  1. Napisz klasę rozszerzającą klasę ClusterRenderingService, a następnie dodaj odpowiedni wpis do pliku AndroidManifest.xml. Ta klasa kontroluje wyświetlacz zestawu wskaźników i może (opcjonalnie) renderować dane interfejsu API stanu nawigacji.
  2. Podczas onCreate() używaj tej usługi do inicjowania komunikacji z sprzętem do renderowania. Dostępne opcje:
    • Określ dodatkowy wyświetlacz, który ma być używany przez zestaw wskaźników.
    • Utwórz wyświetlacz wirtualny, aby aplikacja Instrument Cluster mogła renderować i przesyłać obraz do jednostki zewnętrznej (za pomocą formatu strumieniowego wideo, takiego jak H.264).
  3. Gdy wyświetlacz jest gotowy, usługa musi wywołać funkcję InstrumentClusterRenderingService#setClusterActivityLaunchOptions(), aby zdefiniować dokładną wartość ActivityOptions, która musi być użyta do wyświetlania aktywności na panelu sterowania. Użyj tych parametrów:
    • category. ClusterRenderingService.
    • ActivityOptions. instancja ActivityOptions, która może służyć do uruchamiania aktywności w klastrze przyrządów. Na przykład z przykładowej implementacji Instrument Cluster w AOSP:
      getService().setClusterActivityLaunchOptions(
        CATEGORY_NAVIGATION,
        ActivityOptions.makeBasic()
            .setLaunchDisplayId(displayId));
  4. Gdy klaster instrumentów jest gotowy do wyświetlania aktywności, usługa musi wywołać InstrumentClusterRenderingService#setClusterActivityState(). Użyj tych parametrów:
    • category ClusterRenderingService.
    • state Pakiet wygenerowany za pomocą usługi ClusterRenderingService. Pamiętaj, aby podać te dane:
      • visible Określa, że tablica rozdzielcza jest widoczna i gotowa do wyświetlania treści.
      • unobscuredBoundsProstokąt określający obszar na wyświetlaczu panelu sterowania, na którym można bezpiecznie wyświetlać treści. Na przykład obszary objęte tarczami i wskaźnikami.
  5. Zastąpić metodę Service#dump() i przekazać informacje o stanie, które są przydatne do debugowania (więcej informacji znajdziesz w dumpsys).

Przykładowa implementacja InstrumentClusterRenderingService

W tym przykładzie przedstawiono implementację InstrumentClusterRenderingService, która tworzy VirtualDisplay, aby wyświetlać zawartość instrumentu Cluster na zewnętrznym wyświetlaczu fizycznym.

Kod może też przekazywać displayId fizycznego dodatkowego wyświetlacza podłączonego do HU, jeśli wiadomo, że jest on dostępny.

/**
* 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);
  }
}

Korzystanie z interfejsu CarAppFocusManager API

Interfejs API CarAppFocusManager udostępnia metodę getAppTypeOwner(), która pozwala usłudze klastra napisanej przez producenta OEM wiedzieć, która aplikacja do nawigacji jest w danym momencie aktywna. Producenci OEM mogą korzystać z dotychczasowej metody CarAppFocusManager#addFocusListener(), a następnie z metody getAppTypeOwner(), aby dowiedzieć się, która aplikacja jest aktywna. Dzięki tym informacjom OEM może:

  • Przełącz aktywność wyświetlaną w klastrze na aktywność klastra udostępnianą przez aplikację do nawigacji, która ma na celu utrzymanie fokusa.
  • Może wykryć, czy aplikacja nawigacji w centrum uwagi ma aktywność skupioną. Jeśli aplikacja do nawigacji, na której skupia się użytkownik, nie ma aktywności w klastrze (lub jeśli taka aktywność jest wyłączona), producenci OEM mogą wysłać ten sygnał do DIM samochodu, aby całkowicie pominąć aspekt nawigacji w klastrze.

Użyj CarAppFocusManager, aby ustawić i słuchać bieżącego fokusa aplikacji, takiego jak aktywna nawigacja czy polecenie głosowe. Zwykle tylko jedno wystąpienie takiej aplikacji jest aktywne (lub skupione) w systemie.

Aby odbierać powiadomienia o zmianach stanu pełnej koncentracji aplikacji, używaj metody CarAppFocusManager#addFocusListener(..):

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
}

Aby pobrać nazwy pakietów należących do bieżącego właściciela danego typu aplikacji, użyj metody CarAppFocusManager#getAppTypeOwner(..). Ta metoda może zwrócić więcej niż jedną nazwę pakietu, jeśli bieżący właściciel korzysta z funkcji 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
}

...

Dodatek: korzystanie z przykładowej aplikacji

AOSP udostępnia przykładową aplikację, która implementuje interfejs Navigation State API.

Aby uruchomić tę przykładową aplikację:

  1. Utwórz i zainstaluj Androida Auto na obsługiwanym HU. Skorzystaj z instrukcji kompilowania i flashowania Androida na swoje urządzenie. Instrukcje znajdziesz w artykule Korzystanie z tablic referencyjnych.
  2. Podłącz do HU dodatkowy wyświetlacz fizyczny (jeśli jest obsługiwany) lub włącz wirtualny dodatkowy HU:
    1. W aplikacji Ustawienia wybierz Tryb programisty.
    2. Otwórz kolejno Ustawienia > System > Zaawansowane > Opcje programisty > Symuluj dodatkowe wyświetlacze.
  3. Zrestartuj HU
  4. Aby uruchomić aplikację KitchenSink:
    1. Otwórz panel.
    2. Otwórz Inst. Cluster.
    3. Kliknij ROZPOCZNIJ METADANY.

Funkcja KitchenSink prosi o skupienie się na NAVIGATION, co instruuje usługę DirectRenderingCluster do wyświetlenia na tablicy rozdzielczej symulowanego interfejsu użytkownika.