Instrument Cluster API

Instrument Cluster API(Android API)를 사용하면 Google 지도를 비롯한 내비게이션 앱을 자동차의 보조 디스플레이(예: 계기판 핸들 뒤)에 표시할 수 있습니다. 이 페이지에서는 보조 디스플레이를 제어하는 ​​서비스를 생성한 다음 내비게이션 앱이 사용자 인터페이스를 표시할 수 있도록 CarService 와 서비스를 통합하는 방법을 설명합니다.

술어

이 페이지에서는 다음 용어가 사용됩니다.

용어 설명
CarInstrumentClusterManager 외부 앱이 계기판에서 활동을 시작하고 계기판이 활동을 표시할 준비가 되면 콜백을 수신할 수 있게 해주는 CarManager 인스턴스입니다.
CarManager CarService 에서 구현한 자동차 관련 서비스와 상호작용하기 위해 외부 앱에서 사용하는 모든 관리자의 기본 클래스입니다.
CarService 외부 앱(Google 지도 포함)과 Instrument Cluster 액세스와 같은 자동차 관련 기능 간의 통신을 제공하는 Android 플랫폼 서비스입니다.
목적지 차량이 이동할 최종 목적지입니다.
도착 예정 시간 목적지 도착 예상 시간.
헤드유닛(HU) 자동차에 내장된 기본 계산 단위입니다. HU는 모든 Android 코드를 실행하며 자동차의 중앙 디스플레이에 연결됩니다.
계기판 스티어링 휠 뒤, 차량 계기판 사이에 위치한 보조 디스플레이입니다. 이는 자동차 내부 네트워크(CAN 버스)를 통해 HU에 연결된 독립적인 계산 장치이거나 HU에 연결된 보조 디스플레이일 수 있습니다.
InstrumentClusterRenderingService Instrument Cluster 디스플레이와 인터페이스하는 데 사용되는 서비스의 기본 클래스입니다. OEM은 OEM 관련 하드웨어와 상호 작용하는 이 클래스의 확장을 제공해야 합니다.
키친싱크 앱 Android Automotive에 포함된 테스트 앱입니다.
노선 차량이 목적지에 도달하기 위해 이동하는 특정 경로입니다.
싱글톤 서비스 android:singleUser 속성이 있는 Android 서비스입니다. 언제든지 최대 하나의 서비스 인스턴스가 Android 시스템에서 실행됩니다.

전제 조건

통합을 개발하려면 다음 요소가 있어야 합니다.

  • 안드로이드 개발 환경. Android 개발 환경을 설정하려면 빌드 요구 사항을 참조하세요.
  • 안드로이드 소스코드를 다운로드하세요. https://android.googlesource.com 의 pi-car-release 분기(또는 그 이상)에서 최신 버전의 Android 소스 코드를 받으세요.
  • 헤드유닛(HU). Android 9 이상을 실행할 수 있는 Android 기기. 이 기기에는 자체 디스플레이가 있어야 하며 새로운 Android 빌드로 디스플레이를 플래시할 수 있어야 합니다.
  • 계기판은 다음 중 하나입니다.
    • HU에 연결된 물리적 보조 디스플레이입니다. 장치 하드웨어 및 커널이 다중 디스플레이 관리를 지원하는지 여부.
    • 독립 유닛. 네트워크 연결을 통해 HU에 연결된 모든 계산 장치로, 자체 디스플레이에 비디오 스트림을 수신하고 표시할 수 있습니다.
    • 에뮬레이트된 디스플레이. 개발 중에 다음과 같은 에뮬레이트된 환경 중 하나를 사용할 수 있습니다.
      • 시뮬레이션된 보조 디스플레이. AOSP Android 배포판에서 시뮬레이션된 보조 디스플레이를 활성화하려면 설정 시스템 앱의 개발자 옵션 설정으로 이동한 다음 보조 디스플레이 시뮬레이션을 선택하세요. 이 구성은 물리적 보조 디스플레이를 연결하는 것과 동일하지만 이 디스플레이는 기본 디스플레이 위에 겹쳐진다는 제한이 있습니다.
      • 에뮬레이트된 계기판. Android Automotive에 포함된 Android 에뮬레이터는 ClusterRenderingService 서비스가 보조 디스플레이에 연결된 계기판을 표시하는 옵션을 제공합니다.
      • 에뮬레이터 _qemu-pipes . ClusterRenderingService 서비스는 보조 디스플레이에 연결됩니다. 이 에뮬레이트된 외부 디스플레이에 연결하기 위한 참조 계기판 구현입니다.

통합 아키텍처

통합 구성 요소

Instrument Cluster API의 모든 통합은 다음 세 가지 구성 요소로 구성됩니다.

  • CarService
  • 내비게이션 앱
  • OEM 계기판 서비스

통합 구성 요소

자동차 서비스

CarService 내비게이션 앱과 자동차 사이를 중재하여 주어진 시간에 하나의 내비게이션 앱만 활성화되고 android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL 권한이 있는 앱만 자동차에 데이터를 보낼 수 있도록 합니다.

CarService 모든 자동차 관련 서비스를 부트스트랩하고 일련의 관리자를 통해 이러한 서비스에 대한 액세스를 제공합니다. 서비스와 상호작용하기 위해 자동차에서 실행되는 앱은 이러한 관리자에 액세스할 수 있습니다.

계기판 구현을 위해 자동차 OEM은 InstrumentClusterRendererService의 사용자 정의 구현을 생성하고 ClusterRenderingService 서비스가 보조 디스플레이에 연결되도록 업데이트해야 합니다.

Instrument Cluster를 렌더링할 때 부팅 프로세스 중에 CarService ClusterRenderingService 서비스의 InstrumentClusterRendererService 키를 읽고 보조 디스플레이에 연결됩니다. InstrumentClusterService 구현을 찾습니다. AOSP에서 이 항목은 Navigation State API 샘플 클러스터 구현 렌더링 서비스를 가리킵니다.

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

이 항목에 언급된 서비스는 초기화되어 CarService 에 바인딩됩니다. Google 지도와 같은 내비게이션 앱이 CarInstrumentClusterManager 요청하면 CarService 바인딩된 InstrumentClusterRenderingService 에서 Instrument Cluster 상태를 업데이트하는 관리자를 제공합니다. (이 경우 바운드는 Android Services 를 나타냅니다.)

계기판 서비스

OEM은 보조 디스플레이에 연결된 ClusterRenderingService 서비스의 하위 클래스를 포함하는 Android 패키지(APK)를 생성해야 합니다. ClusterRenderingService 서비스는 보조 디스플레이에 연결됩니다. 샘플을 위해.

이 클래스는 두 가지 용도로 사용됩니다.

  • 인터페이스 Android 및 Instrument Cluster 렌더링 장치를 제공합니다(이 페이지의 목적).
  • 단계별 내비게이션 안내와 같은 내비게이션 상태 업데이트를 수신하고 렌더링합니다.

첫 번째 목적으로 InstrumentClusterRendererService 의 OEM 구현은 차량 내부 화면에 정보를 렌더링하는 데 사용되는 보조 디스플레이를 초기화하고 InstrumentClusterRendererService.setClusterActivityOptions()InstrumentClusterRendererService.setClusterActivityState() 메서드를 호출하여 이 정보를 CarService 에 전달해야 합니다.

두 번째 기능의 경우 Instrument Cluster 서비스는 보조 디스플레이에 연결된 ClusterRenderingService 서비스 구현을 제공해야 합니다. eventType 으로 인코딩된 탐색 상태 업데이트 이벤트 와 번들로 인코딩된 이벤트 데이터를 수신하는 인터페이스입니다.

통합 순서

다음 다이어그램은 업데이트를 렌더링하는 탐색 상태의 구현을 보여줍니다.

통합 순서

이 그림에서 색상은 다음을 나타냅니다.

  • 노란색. CarServiceCarNavigationStatusManager Android 플랫폼에서 제공됩니다. 자세한 내용은 자동차CAR_NAVIGATION_SERVICE를 참조하세요.
  • 청록색. OEM이 구현한 InstrumentClusterRendererService 입니다.
  • 보라. Google 및 타사 개발자가 구현한 내비게이션 앱입니다.
  • 녹색. CarAppFocusManager . 자세한 내용은 아래 CarAppFocusManager API 사용CarAppFocusManager 를 참조하세요.

탐색 상태 정보 흐름은 다음 순서를 따릅니다.

  1. CarService InstrumentClusterRenderingService 를 초기화합니다.
  2. 초기화 중에 InstrumentClusterRenderingService 다음을 사용하여 CarService 업데이트합니다.
    1. 모호하지 않은 경계와 같은 계기판 표시 속성(나중에 모호하지 않은 경계에 대한 자세한 내용 참조)
    2. Instrument Cluster 디스플레이 내에서 활동을 시작하는 데 필요한 활동 옵션(자세한 내용은 ActivityOptions 참조)
  3. 내비게이션 앱(예: Android Automotive용 Google 지도 또는 필수 권한이 ​​있는 지도 앱):
    1. car-lib의 Car 클래스를 사용하여 CarAppFocusManager 얻습니다.
    2. 세부 경로 안내가 시작되기 전에 CarAppFocusManager.requestFocus() 를 호출하여 CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION appType 매개변수로 전달합니다.
  4. CarAppFocusManager 이 요청을 CarService 에 전달합니다. 승인된 경우 CarService 내비게이션 앱 패키지를 검사하고 android.car.cluster.NAVIGATION 카테고리로 표시된 활동을 찾습니다.
  5. 탐색 앱이 발견되면 InstrumentClusterRenderingService 에서 보고한 ActivityOptions 사용하여 활동을 시작하고 Instrument Cluster 디스플레이 속성을 인텐트에 추가 항목으로 포함합니다.

API 통합

InstrumentClusterRenderingService 구현은 다음을 수행해야 합니다.

  • AndroidManifest.xml에 다음 값을 추가하여 싱글톤 서비스로 지정합니다. 이는 초기화 및 사용자 전환 중에도 Instrument Cluster 서비스의 단일 복사본이 실행되도록 하는 데 필요합니다.
    android:singleUser="true"
  • BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE 시스템 권한을 보유하세요. 이는 Android 시스템 이미지의 일부로 포함된 계기판 렌더링 서비스만 CarService :
    <uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
    
    에 의해 바인딩되도록 보장합니다.

InstrumentClusterRenderingService 구현

서비스를 구축하려면:

  1. ClusterRenderingService 서비스에서 확장되는 클래스를 작성하여 보조 디스플레이에 연결합니다.
  2. 그런 다음 AndroidManifest.xml 파일에 해당 항목을 추가합니다. 이 클래스는 계기판 디스플레이를 제어하고 탐색 상태 API 데이터를 ( 선택적으로 ) 렌더링할 수 있습니다.
  3. onCreate() 중에 이 서비스를 사용하여 렌더링 하드웨어와의 통신을 초기화합니다. 옵션은 다음과 같습니다:
    • 계기판에 사용할 보조 디스플레이를 결정합니다.
    • Instrument Cluster 앱이 렌더링된 이미지를 외부 장치로 렌더링하고 전송할 수 있도록 가상 디스플레이를 생성합니다(H.264와 같은 비디오 스트리밍 형식 사용).
  4. 위에 표시된 디스플레이가 준비되면 이 서비스는 InstrumentClusterRenderingService#setClusterActivityLaunchOptions() 호출하여 Instrument Cluster에 활동을 표시하는 데 사용해야 하는 정확한 ActivityOptions 정의해야 합니다. 다음 매개변수를 사용하세요.
    • 범주. ClusterRenderingService 서비스는 보조 디스플레이에 연결됩니다.
    • ActivityOptions. Instrument Cluster에서 활동을 시작하는 데 사용할 수 있는 ActivityOptions 인스턴스입니다. 예를 들어 AOSP의 샘플 Instrument Cluster 구현에서:
      getService().setClusterActivityLaunchOptions(
         CATEGORY_NAVIGATION,
         ActivityOptions.makeBasic()
            .setLaunchDisplayId(displayId));
      
  5. Instrument Cluster가 활동을 표시할 준비가 되면 이 서비스는 InstrumentClusterRenderingService#setClusterActivityState() 호출해야 합니다. 다음 매개변수를 사용하세요.
    • category ClusterRenderingService 서비스는 보조 디스플레이에 연결됩니다.
    • ClusterRenderingService 서비스로 생성된 state 은 보조 디스플레이에 연결됩니다.
    • 다음 데이터를 제공하십시오.
      • visible 계기판을 표시하고 콘텐츠를 표시할 준비가 되도록 지정합니다.
      • unobscuredBounds 콘텐츠를 표시하기에 안전한 계기판 디스플레이 내 영역을 정의하는 직사각형입니다. 예를 들어 다이얼과 게이지로 덮이는 영역입니다.
  6. Service#dump() 메서드를 재정의하고 디버깅에 유용한 상태 정보를 보고합니다(자세한 내용은 dumpsys 참조).

샘플 InstrumentClusterRenderingService 구현

다음 예에서는 원격 물리적 디스플레이에 계측기 클러스터 콘텐츠를 표시하기 위해 VirtualDisplay 생성하는 InstrumentClusterRenderingService 구현을 간략하게 설명합니다.

또는 이 코드는 사용 가능한 것으로 알려진 경우 HU에 연결된 물리적 보조 디스플레이의 displayId 전달할 수 있습니다.

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

CarAppFocusManager API 사용

CarAppFocusManager API는 OEM이 작성한 클러스터 서비스가 주어진 시간에 탐색 포커스가 있는 탐색 앱을 알 수 있도록 하는 getAppTypeOwner() 라는 메서드를 제공합니다. OEM은 기존 CarAppFocusManager#addFocusListener() 메서드를 사용한 다음 getAppTypeOwner() 사용하여 어떤 앱에 포커스가 있는지 알아볼 수 있습니다. 이 정보를 사용하여 OEM은 다음을 수행할 수 있습니다.

  • 클러스터에 표시된 활동을 포커스가 있는 탐색 앱에서 제공하는 클러스터 활동으로 전환합니다.
  • 집중된 내비게이션 앱에 클러스터 활동이 있는지 여부를 감지할 수 있습니다. 집중 내비게이션 앱에 클러스터 활동이 없는 경우(또는 해당 활동이 비활성화된 경우) OEM은 이 신호를 자동차 DIM에 보내 클러스터의 내비게이션 측면을 완전히 건너뛸 수 있습니다.

CarAppFocusManager 사용하여 활성 내비게이션이나 음성 명령과 같은 현재 앱 포커스를 설정하고 수신합니다. 일반적으로 이러한 앱의 인스턴스 하나만 시스템에서 활발하게 실행(또는 집중)됩니다.

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
}

CarAppFocusManager#getAppTypeOwner(..) 메서드를 사용하여 포커스가 있는 특정 앱 유형의 현재 소유자 패키지 이름을 검색합니다. 현재 소유자가 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
}

...

부록: 샘플 앱 사용

AOSP는 Navigation State API를 구현하는 샘플 앱을 제공합니다.

이 샘플 앱을 실행하려면 다음 안내를 따르세요.

  1. 지원되는 HU에서 Android Auto를 빌드하고 플래시하세요. 귀하의 기기에 맞는 Android 구축 및 플래싱 지침을 사용하세요. 지침은 참조 보드 사용을 참조하십시오.
  2. 물리적 보조 디스플레이를 HU(지원되는 경우)에 연결하거나 가상 보조 HU를 켭니다.
    1. 설정 앱에서 개발자 모드를 선택하세요.
    2. 설정 > 시스템 > 고급 > 개발자 옵션 > 보조 디스플레이 시뮬레이션 으로 이동합니다.
  3. HU를 재부팅합니다. ClusterRenderingService 서비스는 보조 디스플레이에 연결됩니다.
  4. KitchenSink 앱을 실행하려면:
    1. 서랍을 열어보세요.
    2. 인스타그램 으로 이동 무리 .
    3. 메타데이터 시작 을 클릭하세요.

KitchenSink는 DirectRenderingCluster 서비스에 Instrument Cluster에 모형 사용자 인터페이스를 표시하도록 지시하는 NAVIGATION 포커스를 요청합니다.