Interfejs API klastra instrumentów

Użyj interfejsu API zestawu wskaźników (interfejs API systemu Android), aby wyświetlać aplikacje nawigacyjne, w tym Mapy Google, na dodatkowym wyświetlaczu w samochodzie, na przykład za kierownicą na desce rozdzielczej. Na tej stronie opisano, jak utworzyć usługę sterującą tym dodatkowym wyświetlaczem, a następnie zintegrować tę usługę z CarService , aby aplikacje nawigacyjne mogły wyświetlać interfejs użytkownika.

Terminologia

Na tej stronie używane są następujące terminy:

Termin Opis
CarInstrumentClusterManager Instancja CarManager , która umożliwia aplikacjom zewnętrznym uruchamianie działań w zestawie wskaźników i otrzymywanie wywołań zwrotnych, gdy zestaw wskaźników jest gotowy do wyświetlania działań.
CarManager Klasa podstawowa wszystkich menedżerów używanych przez aplikacje zewnętrzne do interakcji z usługami specyficznymi dla samochodu realizowanymi przez CarService .
CarService Usługa platformy Android zapewniająca komunikację między aplikacjami zewnętrznymi (w tym Mapami Google) i funkcjami specyficznymi dla samochodu, takimi jak dostęp do zestawu wskaźników.
Miejsce docelowe Ostateczny cel, do którego będzie nawigował pojazd.
ETA Szacowany czas dotarcia do celu.
Jednostka główna (HU) Podstawowa jednostka obliczeniowa wbudowana w samochód. HU obsługuje cały kod Androida i jest podłączony do centralnego wyświetlacza w samochodzie.
Klaster instrumentów Wyświetlacz dodatkowy umieszczony za kierownicą i pomiędzy przyrządami samochodowymi. Może to być niezależna jednostka obliczeniowa podłączona do HU poprzez sieć wewnętrzną samochodu (magistrala CAN) lub dodatkowy wyświetlacz podłączony do HU.
InstrumentClusterRenderingService Klasa bazowa usługi używanej do komunikacji z wyświetlaczem zestawu wskaźników. Producenci OEM muszą zapewnić rozszerzenie tej klasy, które współdziała ze sprzętem specyficznym dla OEM.
Aplikacja KitchenSink Aplikacja testowa dołączona do Android Automotive.
Trasa Określona trasa, po której porusza się pojazd, aby dotrzeć do celu.
Usługa Singletona Usługa systemu Android z atrybutem android:singleUser . W danym momencie maksymalnie jedna instancja usługi działa na systemie Android.

Warunki wstępne

Aby rozwinąć integrację, pamiętaj o posiadaniu tych elementów:

  • Środowisko programistyczne Androida. Aby skonfigurować środowisko programistyczne systemu Android, zobacz 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) pod adresem https://android.googlesource.com .
  • Jednostka główna (HU). Urządzenie z Androidem, na którym można uruchomić system Android 9 (lub nowszy). To urządzenie musi mieć własny wyświetlacz i mieć możliwość flashowania wyświetlacza w nowych wersjach Androida.
  • Zestaw wskaźników to jeden z następujących elementów:
    • Fizyczny wyświetlacz dodatkowy podłączony do HU. Jeśli sprzęt i jądro urządzenia obsługują zarządzanie wieloma wyświetlaczami.
    • Niezależna jednostka. Dowolna jednostka obliczeniowa podłączona do HU za pośrednictwem połączenia sieciowego, zdolna do odbierania i wyświetlania strumienia wideo na własnym wyświetlaczu.
    • Emulowany wyświetlacz. Podczas programowania możesz użyć jednego z następujących emulowanych środowisk:
      • Symulowane wyświetlacze wtórne. Aby włączyć symulowany ekran dodatkowy w dowolnej dystrybucji AOSP Androida, przejdź do ustawień Opcji programisty w aplikacji systemowej Ustawienia, a następnie wybierz Symuluj wyświetlacze dodatkowe. Ta konfiguracja jest równoznaczna z podłączeniem fizycznego dodatkowego wyświetlacza, z tym ograniczeniem, że ten wyświetlacz jest nałożony na główny wyświetlacz.
      • Emulowany zestaw wskaźników. Emulator Androida dołączony do Android Automotive umożliwia wyświetlanie zestawu wskaźników z usługą ClusterRenderingService podłączoną do dodatkowego wyświetlacza.
      • emulator _qemu-pipes . Usługa ClusterRenderingService jest podłączona do dodatkowego wyświetlacza. referencyjna implementacja zestawu wskaźników, aby połączyć się z tym emulowanym wyświetlaczem zewnętrznym.

Architektura integracji

Komponenty integracyjne

Każda integracja interfejsu API klastra instrumentów składa się z trzech komponentów:

  • CarService
  • Aplikacje nawigacyjne
  • Usługa klastra przyrządów OEM

Komponenty integracyjne

Serwis samochodowy

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

CarService ładuje wszystkie usługi specyficzne dla samochodu i zapewnia dostęp do tych usług za pośrednictwem szeregu menedżerów. Aby móc wchodzić w interakcję z usługami, aplikacje działające w samochodzie mogą uzyskać dostęp do tych menedżerów.

Aby wdrożyć zestaw wskaźników, producenci OEM z branży motoryzacyjnej muszą utworzyć niestandardową implementację InstrumentClusterRendererService i zaktualizować usługę ClusterRenderingService podłączoną do dodatkowego wyświetlacza.

Podczas renderowania zestawu wskaźników podczas procesu uruchamiania CarService odczytuje klucz InstrumentClusterRendererService usługi ClusterRenderingService podłączonej do dodatkowego wyświetlacza. aby zlokalizować implementację InstrumentClusterService . W AOSP ten wpis wskazuje na usługę renderowania przykładowej implementacji klastra interfejsu API nawigacji stanu:

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

Usługa, o której mowa w tym wpisie, jest inicjowana i powiązana z CarService . Gdy aplikacje nawigacyjne, takie jak Mapy Google, żądają CarInstrumentClusterManager , CarService udostępnia menedżera, który aktualizuje stan zestawu wskaźników z powiązanej InstrumentClusterRenderingService . (W tym przypadku związany odnosi się do usług Androida .)

Usługa klastra instrumentów

Producenci OEM muszą utworzyć pakiet Android (APK) zawierający podklasę usługi ClusterRenderingService podłączonej do dodatkowego wyświetlacza. Usługa ClusterRenderingService jest podłączona do dodatkowego wyświetlacza. dla próbki.

Klasa ta służy dwóm celom:

  • Udostępnia interfejs Androida i urządzenie renderujące klaster instrumentów (cel tej strony).
  • Odbiera i wyświetla aktualizacje stanu nawigacji, takie jak szczegółowe wskazówki nawigacyjne.

W pierwszym celu implementacje OEM InstrumentClusterRendererService muszą zainicjować dodatkowy wyświetlacz używany do renderowania informacji na ekranach w kabinie samochodu i przekazać te informacje do CarService poprzez wywołanie metod InstrumentClusterRendererService.setClusterActivityOptions() i InstrumentClusterRendererService.setClusterActivityState() .

W przypadku drugiej funkcji usługa Instrument Cluster musi zapewniać implementację usługi ClusterRenderingService podłączonej do dodatkowego wyświetlacza. interfejs odbierający zdarzenia aktualizacji statusu nawigacji, które są zakodowane jako eventType i dane zdarzenia zakodowane w pakiecie.

Sekwencja całkowania

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

Sekwencja całkowania

Na tej ilustracji kolory oznaczają:

Przepływ informacji o stanie nawigacji przebiega w następującej kolejności:

  1. CarService inicjuje usługę InstrumentClusterRenderingService .
  2. Podczas inicjalizacji InstrumentClusterRenderingService aktualizuje CarService o:
    1. Właściwości wyświetlania zestawu wskaźników, takie jak widoczne granice (więcej szczegółów na temat niewidocznych granic znajdziesz później).
    2. Opcje działań potrzebne do uruchomienia działań na wyświetlaczu zestawu wskaźników (więcej szczegółów znajdziesz w ActivityOptions .
  3. Aplikacja nawigacyjna (taka jak Google Maps dla Android Automotive lub dowolna aplikacja mapowa z wymaganymi uprawnieniami):
    1. Uzyskuje CarAppFocusManager przy użyciu klasy Car z car-lib.
    2. Przed rozpoczęciem szczegółowych wskazówek wywoływana jest funkcja CarAppFocusManager.requestFocus() w celu przekazania CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION jako parametru appType .
  4. CarAppFocusManager przekazuje to żądanie do CarService . Jeśli zostanie przyznana, CarService sprawdza pakiet aplikacji nawigacyjnej i lokalizuje aktywność oznaczoną kategorią android.car.cluster.NAVIGATION .
  5. Jeśli zostanie znaleziona, aplikacja nawigacyjna korzysta z ActivityOptions zgłoszonych przez InstrumentClusterRenderingService w celu uruchomienia działania i uwzględnia właściwości wyświetlania zestawu wskaźników jako dodatki w zamierzeniu.

Zintegruj interfejs API

Implementacja InstrumentClusterRenderingService musi:

  • Zostań wyznaczony jako usługa pojedyncza, dodając następującą wartość do pliku AndroidManifest.xml. Jest to konieczne, aby zapewnić działanie pojedynczej kopii usługi klastra przyrządów, nawet podczas inicjalizacji i przełączania użytkowników:
    android:singleUser="true"
  • Przytrzymaj uprawnienia systemowe BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE . Gwarantuje to, że tylko usługa renderowania zestawu wskaźników zawarta w obrazie systemu Android będzie zawsze powiązana z CarService :
    <uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
    

Zaimplementuj usługę InstrumentClusterRenderingService

Aby zbudować usługę:

  1. Napisz klasę, która rozszerza usługę ClusterRenderingService podłączoną do dodatkowego wyświetlacza.
  2. a następnie dodaj odpowiedni wpis do pliku AndroidManifest.xml . Ta klasa steruje wyświetlaniem zestawu wskaźników i może ( opcjonalnie ) renderować dane API stanu nawigacji.
  3. Podczas onCreate() użyj tej usługi, aby zainicjować komunikację ze sprzętem renderującym. Opcje obejmują:
    • Określ drugi wyświetlacz, który ma być używany w zestawie wskaźników.
    • Utwórz wirtualny wyświetlacz, aby aplikacja Instrument Cluster renderowała i przesyłała wyrenderowany obraz do jednostki zewnętrznej (przy użyciu formatu strumieniowego przesyłania wideo, takiego jak H.264).
  4. Gdy wyświetlacz wskazany powyżej będzie gotowy, usługa ta musi wywołać InstrumentClusterRenderingService#setClusterActivityLaunchOptions() , aby zdefiniować dokładne ActivityOptions , które muszą zostać użyte do wyświetlenia działania w zestawie wskaźników. Użyj tych parametrów:
    • Kategoria. Usługa ClusterRenderingService jest podłączona do dodatkowego wyświetlacza.
    • ActivityOptions. Instancja ActivityOptions , której można użyć do uruchomienia działania w zestawie wskaźników. Na przykład z przykładowej implementacji klastra instrumentów w AOSP:
      getService().setClusterActivityLaunchOptions(
         CATEGORY_NAVIGATION,
         ActivityOptions.makeBasic()
            .setLaunchDisplayId(displayId));
      
  5. Gdy klaster instrumentów jest gotowy do wyświetlania działań, ta usługa musi wywołać InstrumentClusterRenderingService#setClusterActivityState() . Użyj tych parametrów:
    • category Usługa ClusterRenderingService jest podłączona do dodatkowego wyświetlacza.
    • pakiet state wygenerowany za pomocą usługi ClusterRenderingService jest podłączony do dodatkowego wyświetlacza.
    • Pamiętaj o podaniu następujących danych:
      • visible Określa zestaw wskaźników jako widoczny i gotowy do wyświetlania treści.
      • unobscuredBounds Prostokąt określający obszar na wyświetlaczu zestawu wskaźników, w którym można bezpiecznie wyświetlać treść. Na przykład obszary objęte tarczami i wskaźnikami.
  6. Zastąp metodę Service#dump() i zgłoś informacje o stanie przydatne do debugowania (więcej informacji można znaleźć w dumpsys ).

Przykładowa implementacja InstrumentClusterRenderingService

Poniższy przykład przedstawia implementację InstrumentClusterRenderingService , która tworzy VirtualDisplay w celu prezentacji zawartości klastra instrumentów na zdalnym fizycznym wyświetlaczu.

Alternatywnie, kod ten może przekazać displayId dodatkowego fizycznego wyświetlacza podłączonego do HU, jeśli wiadomo, że taki jest 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);
  }
}

Użyj interfejsu API CarAppFocusManager

Interfejs API CarAppFocusManager udostępnia metodę o nazwie getAppTypeOwner() , która pozwala usłudze klastrowania napisanej przez producentów OEM dowiedzieć się, która aplikacja nawigacyjna jest w danym momencie aktywna. Producenci OEM mogą użyć istniejącej metody CarAppFocusManager#addFocusListener() , a następnie użyć getAppTypeOwner() , aby dowiedzieć się, która aplikacja jest aktywna. Dzięki tym informacjom producenci OEM mogą:

  • Przełącz aktywność pokazaną w klastrze na aktywność klastra zapewnioną przez aplikację nawigacyjną, która jest aktywna.
  • Potrafi wykryć, czy skupiona aplikacja nawigacyjna ma aktywność klastra, czy nie. Jeśli skupiona aplikacja nawigacyjna nie ma aktywności klastra (lub jeśli taka aktywność jest wyłączona), producenci OEM mogą wysłać ten sygnał do samochodowego DIM, aby całkowicie pominąć aspekt nawigacji klastra.

Użyj CarAppFocusManager aby ustawić i nasłuchiwać bieżącego fokusu aplikacji, takiego jak aktywna nawigacja lub polecenie głosowe. Zwykle w systemie aktywnie działa (lub jest skupiona) tylko jedna instancja takiej aplikacji.

Użyj metody CarAppFocusManager#addFocusListener(..) , aby nasłuchiwać zmian fokusu aplikacji:

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
}

Użyj metody CarAppFocusManager#getAppTypeOwner(..) , aby pobrać nazwy pakietów bieżącego właściciela danego typu aplikacji, na którym się skupia. 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: Skorzystaj z przykładowej aplikacji

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

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

  1. Kompiluj i flashuj Android Auto na obsługiwanym HU. Skorzystaj z instrukcji tworzenia i flashowania systemu Android specyficznych dla Twojego urządzenia. Aby uzyskać instrukcje, zobacz temat Korzystanie z tablic referencyjnych .
  2. Podłącz fizyczny dodatkowy wyświetlacz do HU (jeśli jest obsługiwany) lub włącz wirtualny dodatkowy wyświetlacz HU:
    1. Wybierz Tryb programisty w aplikacji Ustawienia.
    2. Wybierz Ustawienia > System > Zaawansowane > Opcje programistyczne > Symuluj dodatkowe wyświetlacze .
  3. Uruchom ponownie HU. Usługa ClusterRenderingService jest podłączona do dodatkowego wyświetlacza.
  4. Aby uruchomić aplikację KitchenSink:
    1. Otwórz szufladę.
    2. Przejdź do Inst. Klaster .
    3. Kliknij ROZPOCZNIJ METADANE .

KitchenSink żąda fokusu NAVIGATION, który instruuje usługę DirectRenderingCluster , aby wyświetliła fałszywy interfejs użytkownika w zestawie wskaźników.