API Instrument Cluster

Sử dụng Instrument Cluster API (API Cụm đồng hồ) (một API Android) để hiển thị các ứng dụng chỉ đường, bao gồm cả Google Maps, trên màn hình phụ trong ô tô, chẳng hạn như phía sau vô lăng trên bảng đồng hồ. Trang này mô tả cách tạo một dịch vụ để điều khiển màn hình phụ đó và tích hợp dịch vụ với CarService để các ứng dụng chỉ đường có thể hiển thị giao diện người dùng.

Thuật ngữ

Các thuật ngữ sau đây được sử dụng trên trang này.

CarInstrumentClusterManager
Một thực thể của CarManager cho phép các ứng dụng bên ngoài chạy một hoạt động trên Màn hình cụm đồng hồ và nhận lệnh gọi lại khi Màn hình cụm đồng hồ sẵn sàng hiển thị các hoạt động.
CarManager
Lớp cơ sở của tất cả trình quản lý mà các ứng dụng bên ngoài sử dụng để tương tác với các dịch vụ dành riêng cho xe do CarService triển khai.
CarService
Dịch vụ Nền tảng Android cung cấp khả năng giao tiếp giữa các ứng dụng bên ngoài (bao gồm cả Google Maps) và các tính năng dành riêng cho ô tô, chẳng hạn như quyền truy cập vào Bảng đồng hồ.
Đích đến
Điểm đến cuối cùng mà xe sẽ di chuyển đến.
Thời gian đến dự kiến (ETA)
Thời gian đến dự kiến tại một điểm đến.
Đầu phát trung tâm (HU)
Đơn vị tính toán chính được nhúng trong ô tô. HU chạy tất cả mã Android và được kết nối với màn hình trung tâm trong ô tô.
Nhóm dụng cụ
Màn hình phụ nằm phía sau vô lăng và giữa các đồng hồ của xe. Đây có thể là một đơn vị tính toán độc lập được kết nối với HU thông qua mạng nội bộ của ô tô (bus CAN) hoặc màn hình phụ được gắn với HU.
InstrumentClusterRenderingService
Lớp cơ sở cho dịch vụ dùng để giao tiếp với màn hình cụm đồng hồ. Nhà sản xuất thiết bị gốc phải cung cấp một tiện ích của lớp này tương tác với phần cứng dành riêng cho nhà sản xuất thiết bị gốc.
Ứng dụng KitchenSink
Ứng dụng kiểm thử đi kèm với Android Automotive.
Hành trình
Đường dẫn cụ thể mà xe di chuyển để đến một đích đến.
Dịch vụ singleton
Một dịch vụ Android có thuộc tính android:singleUser. Tại bất kỳ thời điểm nào, tối đa một phiên bản của dịch vụ sẽ chạy trên hệ thống Android.

Điều kiện tiên quyết

Trước khi tiếp tục, hãy đảm bảo bạn có các phần tử sau:

  • Môi trường phát triển Android. Để thiết lập môi trường phát triển Android, hãy xem Yêu cầu về bản dựng.
  • Tải mã nguồn Android xuống. Tải phiên bản mới nhất của mã nguồn Android từ nhánh pi-car-release (hoặc phiên bản mới hơn) tại https://android.googlesource.com.
  • Đầu phát trung tâm (HU). Thiết bị Android có thể chạy Android 9 (trở lên). Thiết bị này phải có màn hình riêng và có khả năng cài đặt ROM cho màn hình bằng các bản dựng Android mới.
  • Cụm đồng hồ là một trong những loại sau:
    • Màn hình phụ thực tế được gắn vào HU. Nếu phần cứng và hạt nhân của thiết bị hỗ trợ việc quản lý nhiều màn hình.
    • Đơn vị độc lập. Bất kỳ đơn vị điện toán nào được kết nối với HU thông qua kết nối mạng, có khả năng nhận và hiển thị luồng video trên màn hình riêng.
    • Màn hình được mô phỏng. Trong quá trình phát triển, bạn có thể sử dụng một trong các môi trường được mô phỏng sau:
      • Màn hình phụ được mô phỏng. Để bật màn hình phụ được mô phỏng trên bất kỳ bản phân phối Android AOSP nào, hãy chuyển đến phần cài đặt Tuỳ chọn cho nhà phát triển trong ứng dụng hệ thống Cài đặt, sau đó chọn Mô phỏng màn hình phụ Cấu hình này tương đương với việc đính kèm màn hình phụ thực tế, với giới hạn là màn hình này được xếp chồng lên màn hình chính.
      • Cụm đồng hồ đo được mô phỏng. Trình mô phỏng Android đi kèm với AAOS cung cấp một tuỳ chọn để hiển thị cụm đồng hồ bằng ClusterRenderingService.

Cấu trúc tích hợp

Thành phần tích hợp

Mọi hoạt động tích hợp API Cụm đồng hồ đều bao gồm 3 thành phần sau:

  • CarService
  • Ứng dụng chỉ đường
  • Dịch vụ cụm đồng hồ OEM

Thành phần tích hợp

CarService

CarService dàn xếp giữa các ứng dụng chỉ đường và ô tô, đảm bảo rằng chỉ có một ứng dụng chỉ đường đang hoạt động tại một thời điểm nhất định và chỉ những ứng dụng có quyền android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL mới có thể gửi dữ liệu đến ô tô.

CarService khởi động tất cả các dịch vụ dành riêng cho ô tô và cung cấp quyền truy cập vào các dịch vụ này thông qua một loạt trình quản lý. Để tương tác với các dịch vụ, ứng dụng chạy trong ô tô có thể truy cập vào các trình quản lý này.

Để triển khai cụm đồng hồ, nhà sản xuất thiết bị gốc (OEM) trong ngành ô tô phải tạo một phương thức triển khai tuỳ chỉnh của InstrumentClusterRendererService và cập nhật ClusterRenderingService.

Khi hiển thị một Bảng đồng hồ, trong quá trình khởi động, CarService sẽ đọc khoá InstrumentClusterRendererService của ClusterRenderingService để xác định vị trí triển khai InstrumentClusterService. Trong AOSP, mục nhập này trỏ đến dịch vụ kết xuất triển khai cụm mẫu API Trạng thái điều hướng:

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

Dịch vụ được đề cập trong mục này được khởi tạo và liên kết với CarService. Khi các ứng dụng chỉ đường, chẳng hạn như Google Maps, yêu cầu CarInstrumentClusterManager, CarService sẽ cung cấp một trình quản lý cập nhật trạng thái của Cụm đồng hồ đo từ InstrumentClusterRenderingService đã liên kết. (Trong trường hợp này, bound (gắn) đề cập đến Dịch vụ Android.)

Dịch vụ Cụm đồng hồ

Nhà sản xuất thiết bị gốc (OEM) phải tạo một Gói Android (APK) chứa một lớp con của ClusterRenderingService.

Lớp này phục vụ hai mục đích:

  • Cung cấp giao diện Android và thiết bị kết xuất cụm đồng hồ (mục đích của trang này).
  • Nhận và hiển thị thông tin cập nhật về trạng thái điều hướng, chẳng hạn như hướng dẫn điều hướng từng chặng.

Đối với mục đích đầu tiên, việc triển khai InstrumentClusterRendererService của OEM phải khởi chạy màn hình phụ dùng để hiển thị thông tin trên màn hình trong khoang ô tô và truyền thông tin này đến CarService bằng cách gọi các phương thức InstrumentClusterRendererService.setClusterActivityOptions()InstrumentClusterRendererService.setClusterActivityState().

Đối với hàm thứ hai, dịch vụ Cụm đồng hồ đo phải cung cấp cách triển khai giao diện ClusterRenderingService nhận sự kiện cập nhật trạng thái điều hướng. Các sự kiện này được mã hoá dưới dạng eventType và dữ liệu sự kiện được mã hoá trong một gói.

Trình tự tích hợp

Sơ đồ sau đây minh hoạ cách triển khai trạng thái điều hướng hiển thị nội dung cập nhật:

Trình tự tích hợp

Trong hình minh hoạ này, màu sắc biểu thị những nội dung sau:

  • Vàng. CarServiceCarNavigationStatusManager do nền tảng Android cung cấp. Để tìm hiểu thêm, hãy xem phần Ô tôCAR_NAVIGATION_SERVICE.
  • Xanh lơ. InstrumentClusterRendererService do OEM triển khai.
  • Tím. Ứng dụng Điều hướng do Google và nhà phát triển bên thứ ba triển khai.
  • Xanh lục. CarAppFocusManager. Để tìm hiểu thêm, hãy xem phần Sử dụng API CarAppFocusManager bên dưới và CarAppFocusManager.

Luồng thông tin Trạng thái điều hướng tuân theo trình tự sau:

  1. CarService khởi chạy InstrumentClusterRenderingService.
  2. Trong quá trình khởi tạo, InstrumentClusterRenderingService sẽ cập nhật CarService bằng:
    1. Các thuộc tính hiển thị của Bảng đồng hồ, chẳng hạn như ranh giới không bị che khuất (xem thêm thông tin chi tiết về ranh giới không bị che khuất sau).
    2. Các tuỳ chọn hoạt động cần thiết để khởi chạy các hoạt động bên trong màn hình Nhóm đồng hồ. Để tìm hiểu thêm, hãy xem phần ActivityOptions.
  3. Ứng dụng chỉ đường (chẳng hạn như Google Maps cho Android Automotive hoặc bất kỳ ứng dụng bản đồ nào có các quyền bắt buộc):
    1. Lấy CarAppFocusManager bằng cách sử dụng lớp Car từ car-lib.
    2. Trước khi bắt đầu chỉ đường từng chặng, hãy gọi CarAppFocusManager.requestFocus() để truyền CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION dưới dạng tham số appType.
  4. CarAppFocusManager thông báo yêu cầu này cho CarService. Nếu được cấp, CarService sẽ kiểm tra gói ứng dụng điều hướng và xác định một hoạt động được đánh dấu bằng danh mục android.car.cluster.NAVIGATION.
  5. Nếu tìm thấy, ứng dụng chỉ đường sẽ sử dụng ActivityOptions do InstrumentClusterRenderingService báo cáo để khởi chạy hoạt động và bao gồm các thuộc tính hiển thị của Cụm đồng hồ đo làm thông tin bổ sung trong ý định.

Tích hợp API

Việc triển khai InstrumentClusterRenderingService phải:

  • Được chỉ định là dịch vụ singleton bằng cách thêm giá trị sau vào AndroidManifest.xml. Điều này là cần thiết để đảm bảo rằng một bản sao duy nhất của dịch vụ Màn hình cụm đồng hồ chạy, ngay cả trong quá trình khởi chạy và chuyển đổi người dùng:
    android:singleUser="true"
  • Giữ quyền hệ thống BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE. Điều này đảm bảo rằng chỉ dịch vụ kết xuất cụm đồng hồ được đưa vào hình ảnh hệ thống Android mới được liên kết với CarService:
    <uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
    

Triển khai InstrumentClusterRenderingService

Cách tạo dịch vụ:

  1. Viết một lớp mở rộng từ ClusterRenderingService rồi thêm mục tương ứng vào tệp AndroidManifest.xml. Lớp này kiểm soát màn hình Cụm đồng hồ và có thể (không bắt buộc) hiển thị dữ liệu API Trạng thái điều hướng.
  2. Trong onCreate(), hãy sử dụng dịch vụ này để khởi chạy quá trình giao tiếp với phần cứng kết xuất. Các lựa chọn bao gồm:
    • Xác định màn hình phụ sẽ được sử dụng cho Cụm đồng hồ.
    • Tạo màn hình ảo để ứng dụng Cụm đồng hồ hiển thị và truyền hình ảnh đã kết xuất đến một đơn vị bên ngoài (sử dụng định dạng truyền trực tuyến video, chẳng hạn như H.264).
  3. Khi màn hình được chỉ định ở trên đã sẵn sàng, dịch vụ này phải gọi InstrumentClusterRenderingService#setClusterActivityLaunchOptions() để xác định chính xác ActivityOptions phải được dùng để hiển thị một Hoạt động trên Bảng đồng hồ. Sử dụng các thông số sau:
    • category. ClusterRenderingService.
    • ActivityOptions. Một thực thể ActivityOptions có thể dùng để chạy một Hoạt động trong Nhóm đồng hồ. Ví dụ: từ cách triển khai mẫu Màn hình cụm đồng hồ trên AOSP:
      getService().setClusterActivityLaunchOptions(
        CATEGORY_NAVIGATION,
        ActivityOptions.makeBasic()
            .setLaunchDisplayId(displayId));
  4. Khi cụm đồng hồ đã sẵn sàng hiển thị các hoạt động, dịch vụ này phải gọi InstrumentClusterRenderingService#setClusterActivityState(). Sử dụng các thông số sau:
    • category ClusterRenderingService.
    • Gói state được tạo bằng ClusterRenderingService. Hãy nhớ cung cấp dữ liệu này:
      • visible Chỉ định cụm đồng hồ hiển thị và sẵn sàng hiển thị nội dung.
      • unobscuredBounds Hình chữ nhật xác định khu vực trong màn hình cụm đồng hồ an toàn để hiển thị nội dung. Ví dụ: các khu vực được bao phủ bởi mặt đồng hồ và đồng hồ đo.
  5. Ghi đè phương thức Service#dump() và báo cáo thông tin trạng thái hữu ích cho việc gỡ lỗi (xem dumpsys để biết thêm thông tin).

Triển khai mẫu InstrumentClusterRenderingService

Ví dụ sau đây trình bày cách triển khai InstrumentClusterRenderingService. Cách này sẽ tạo một VirtualDisplay để trình bày nội dung cụm đo lường trên màn hình thực từ xa.

Ngoài ra, mã này có thể truyền displayId của màn hình phụ thực tế được kết nối với HU, nếu có màn hình phụ.

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

Sử dụng API CarAppFocusManager

API CarAppFocusManager cung cấp một phương thức có tên là getAppTypeOwner(), cho phép dịch vụ cụm do OEM viết biết ứng dụng chỉ đường nào có tiêu điểm chỉ đường tại bất kỳ thời điểm nào. OEM có thể sử dụng phương thức CarAppFocusManager#addFocusListener() hiện có, sau đó sử dụng getAppTypeOwner() để tìm hiểu ứng dụng nào có tiêu điểm. Với thông tin này, OEM có thể:

  • Chuyển hoạt động hiển thị trong cụm sang hoạt động cụm do ứng dụng chỉ đường cung cấp và giữ tiêu điểm.
  • Có thể phát hiện xem ứng dụng điều hướng được lấy làm tâm điểm có hoạt động cụm hay không. Nếu ứng dụng chỉ đường đang được lấy làm tâm điểm không có hoạt động cụm đồng hồ (hoặc nếu hoạt động đó bị tắt), thì nhà sản xuất thiết bị gốc (OEM) có thể gửi tín hiệu này đến DIM của ô tô để bỏ qua hoàn toàn khía cạnh chỉ đường của cụm đồng hồ.

Sử dụng CarAppFocusManager để đặt và theo dõi tiêu điểm ứng dụng hiện tại, chẳng hạn như tính năng điều hướng đang hoạt động hoặc lệnh thoại. Thông thường, chỉ một phiên bản của ứng dụng như vậy đang hoạt động (hoặc được lấy làm tâm điểm) trong hệ thống.

Sử dụng phương thức CarAppFocusManager#addFocusListener(..) để theo dõi các thay đổi về tiêu điểm của ứng dụng:

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
}

Sử dụng phương thức CarAppFocusManager#getAppTypeOwner(..) để truy xuất tên gói của chủ sở hữu hiện tại của một loại ứng dụng nhất định đang được lấy làm tâm điểm. Phương thức này có thể trả về nhiều tên gói nếu chủ sở hữu hiện tại sử dụng tính năng 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
}

...

Phụ lục: Sử dụng ứng dụng mẫu

AOSP cung cấp một ứng dụng mẫu triển khai API Trạng thái điều hướng.

Cách chạy ứng dụng mẫu này:

  1. Tạo và cài đặt Android Auto trên HU được hỗ trợ. Sử dụng hướng dẫn tạo bản dựng và cài đặt ROM Android dành riêng cho thiết bị của bạn. Để được hướng dẫn, hãy xem phần Sử dụng bảng tham chiếu.
  2. Kết nối màn hình phụ thực tế với HU (nếu được hỗ trợ) hoặc bật HU phụ ảo:
    1. Chọn Chế độ nhà phát triển trong ứng dụng Cài đặt.
    2. Chuyển đến Cài đặt > Hệ thống > Nâng cao > Tuỳ chọn cho nhà phát triển > Mô phỏng màn hình phụ.
  3. Khởi động lại HU
  4. Cách chạy ứng dụng KitchenSink:
    1. Mở ngăn.
    2. Chuyển đến Inst. Cluster (Cài đặt cụm).
    3. Nhấp vào BẮT ĐẦU TẠO SIÊU DỮ LIỆU.

KitchenSink yêu cầu tiêu điểm NAVIGATION (ĐIỀU HÀNH), yêu cầu dịch vụ DirectRenderingCluster hiển thị giao diện người dùng được mô phỏng trên Bảng đồng hồ.