Instrument Cluster API

ใช้ Instrument Cluster API (Android API) เพื่อแสดงแอปการนำทาง รวมถึง Google Maps บนจอแสดงผลรองในรถ เช่น ด้านหลังพวงมาลัยบนแผงหน้าปัด หน้านี้จะอธิบายวิธีสร้างบริการเพื่อควบคุมจอแสดงผลรองและผสานรวมบริการกับ CarService เพื่อให้แอปการนำทางแสดงอินเทอร์เฟซผู้ใช้ได้

คำศัพท์

หน้านี้ใช้คำศัพท์ต่อไปนี้

CarInstrumentClusterManager
อินสแตนซ์ของ CarManager ที่ช่วยให้แอปภายนอกเปิดใช้งานกิจกรรมในแผงหน้าปัดและรับการเรียกกลับเมื่อแผงหน้าปัดพร้อมแสดงกิจกรรม
CarManager
คลาสพื้นฐานของผู้จัดการทั้งหมดที่แอปภายนอกใช้เพื่อโต้ตอบกับบริการเฉพาะรถยนต์ที่ CarService ติดตั้งใช้งาน
บริการด้านรถยนต์
บริการแพลตฟอร์ม Android ที่ให้การสื่อสารระหว่างแอปภายนอก (รวมถึง Google Maps) กับฟีเจอร์เฉพาะของรถยนต์ เช่น การเข้าถึงหน้าปัด
ปลายทาง
ปลายทางสุดท้ายที่ยานพาหนะจะไปยัง
เวลาถึงโดยประมาณ (ETA)
เวลาถึงโดยประมาณที่จุดหมาย
ฮังการี (HU)
หน่วยประมวลผลหลักที่ฝังอยู่ในรถยนต์ HU ทำงานด้วยโค้ด Android ทั้งหมดและเชื่อมต่อกับจอแสดงผลส่วนกลางในรถ
แผงหน้าปัด
จอแสดงผลรองอยู่หลังพวงมาลัยและระหว่างหน้าปัดของรถ ซึ่งอาจเป็นหน่วยประมวลผลอิสระที่เชื่อมต่อกับ HU ผ่านเครือข่ายภายในของรถยนต์ (CAN Bus) หรือจอแสดงผลรองที่แนบอยู่กับ HU
InstrumentClusterRenderingService
คลาสพื้นฐานสําหรับบริการที่ใช้เป็นอินเทอร์เฟซกับจอแสดงผลของแผงหน้าปัด OEM ต้องจัดหาส่วนขยายของคลาสนี้ที่โต้ตอบกับฮาร์ดแวร์เฉพาะของ OEM
แอป KitchenSink
แอปทดสอบที่มาพร้อมกับ Android Automotive
เส้นทาง
เส้นทางที่เฉพาะเจาะจงซึ่งยานพาหนะใช้เพื่อไปยังจุดหมาย
บริการ Singleton
บริการ Android ที่มีแอตทริบิวต์ android:singleUser บริการจะทำงานในระบบ Android ได้สูงสุด 1 อินสแตนซ์ในแต่ละครั้ง

สิ่งที่ต้องมีก่อน

โปรดตรวจสอบว่าคุณมีองค์ประกอบต่อไปนี้ก่อนที่จะดําเนินการต่อ

  • สภาพแวดล้อมการพัฒนา Android หากต้องการตั้งค่าสภาพแวดล้อมการพัฒนาซอฟต์แวร์ Android โปรดดูข้อกำหนดการสร้าง
  • ดาวน์โหลดซอร์สโค้ด Android ดาวน์โหลดซอร์สโค้ด Android เวอร์ชันล่าสุดจากสาขา pi-car-release (หรือเวอร์ชันที่ใหม่กว่า) ที่ https://android.googlesource.com
  • หน่วยหลัก (HU) อุปกรณ์ Android ที่ใช้งาน Android 9 (หรือเวอร์ชันที่ใหม่กว่า) ได้ อุปกรณ์นี้ต้องมีจอแสดงผลของตัวเองและสามารถแฟลชจอแสดงผลด้วยบิลด์ Android ใหม่
  • หน้าปัดคือสิ่งใดสิ่งหนึ่งต่อไปนี้
    • จอแสดงผลรองจริงที่แนบอยู่กับ HU หากฮาร์ดแวร์และเคอร์เนลของอุปกรณ์รองรับการจัดการจอแสดงผลหลายจอ
    • หน่วยอิสระ หน่วยประมวลผลใดก็ตามที่เชื่อมต่อกับ HU ผ่านการเชื่อมต่อเครือข่าย ซึ่งสามารถรับและแสดงสตรีมวิดีโอบนจอแสดงผลของตัวเอง
    • จอแสดงผลจำลอง ในระหว่างการพัฒนา คุณสามารถใช้สภาพแวดล้อมจำลองอย่างใดอย่างหนึ่งต่อไปนี้
      • จอแสดงผลรองจำลอง หากต้องการเปิดใช้จอแสดงผลรองจำลองในระบบปฏิบัติการ AOSP ของ Android ให้ไปที่การตั้งค่าตัวเลือกสำหรับนักพัฒนาซอฟต์แวร์ในแอประบบการตั้งค่า แล้วเลือกจำลองจอแสดงผลรอง การกำหนดค่านี้จะเทียบเท่ากับการต่อจอแสดงผลรองจริง โดยมีข้อจำกัดคือจอแสดงผลนี้จะวางซ้อนทับจอแสดงผลหลัก
      • หน้าปัดแบบจำลอง โปรแกรมจำลอง Android ที่รวมอยู่ใน AAOS มีตัวเลือกในการแสดงแผงหน้าปัดด้วย ClusterRenderingService

สถาปัตยกรรมการผสานรวม

คอมโพเนนต์การผสานรวม

การผสานรวม Instrument Cluster API ประกอบด้วยคอมโพเนนต์ 3 รายการต่อไปนี้

  • CarService
  • แอปการนำทาง
  • บริการแผงหน้าปัด OEM

คอมโพเนนต์การผสานรวม

บริการด้านรถยนต์

CarService จะทำหน้าที่เป็นสื่อกลางระหว่างแอปการนำทางกับรถยนต์ เพื่อให้มั่นใจว่ามีแอปการนำทางที่ใช้งานอยู่เพียงแอปเดียวในแต่ละขณะ และมีเพียงแอปที่มีสิทธิ์ android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL เท่านั้นที่ส่งข้อมูลไปยังรถยนต์ได้

CarService เริ่มต้นบริการเฉพาะรถยนต์ทั้งหมดและให้สิทธิ์เข้าถึงบริการเหล่านี้ผ่านชุดเครื่องมือจัดการ แอปที่ทำงานในรถจะเข้าถึงตัวจัดการเหล่านี้ได้เพื่อโต้ตอบกับบริการ

สำหรับการติดตั้งใช้งานหน้าปัดรถยนต์ OEM ยานยนต์ต้องสร้างการใช้งาน InstrumentClusterRendererService ที่กําหนดเองและอัปเดต ClusterRenderingService

เมื่อแสดงผลแผงหน้าปัด ระหว่างกระบวนการบูต CarService จะอ่านคีย์ InstrumentClusterRendererService ของ ClusterRenderingService เพื่อค้นหาการติดตั้งใช้งาน InstrumentClusterService ใน AOSP รายการนี้ชี้ไปที่บริการแสดงผลการใช้งานคลัสเตอร์ตัวอย่างของ Navigation State API

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

บริการที่กล่าวถึงในรายการนี้ได้รับการเริ่มต้นและเชื่อมโยงกับ CarService เมื่อแอปการนำทาง เช่น Google Maps ขอ CarInstrumentClusterManager CarService จะจัดหาตัวจัดการที่จะอัปเดตสถานะแผงหน้าปัดจาก InstrumentClusterRenderingService ที่เชื่อมโยง (ในกรณีนี้ bound หมายถึง Android Services)

บริการแผงหน้าปัด

OEM จะต้องสร้างแพ็กเกจ Android (APK) ที่มีคลาสย่อยของ ClusterRenderingService

ชั้นเรียนนี้มีวัตถุประสงค์ 2 อย่าง ได้แก่

  • ให้อินเทอร์เฟซ Android และอุปกรณ์แสดงผลหน้าปัด (วัตถุประสงค์ของหน้านี้)
  • รับและแสดงผลข้อมูลอัปเดตสถานะการนำทาง เช่น การแนะนำการนำทางแบบเลี้ยวต่อเลี้ยว

สำหรับวัตถุประสงค์แรก การใช้งาน InstrumentClusterRendererService ของ OEM ต้องเริ่มต้นการแสดงผลรองที่ใช้แสดงผลข้อมูลบนหน้าจอในห้องโดยสารของรถยนต์ และสื่อสารข้อมูลนี้ไปยัง CarService โดยการเรียกใช้เมธอด InstrumentClusterRendererService.setClusterActivityOptions() และ InstrumentClusterRendererService.setClusterActivityState()

สำหรับฟังก์ชันที่ 2 บริการหน้าปัดต้องระบุการใช้งานอินเทอร์เฟซ ClusterRenderingService ที่ได้รับเหตุการณ์การอัปเดตสถานะการนำทาง ซึ่งเข้ารหัสเป็น eventType และข้อมูลเหตุการณ์ที่เข้ารหัสในแพ็กเกจ

ลําดับการผสานรวม

แผนภาพต่อไปนี้แสดงการใช้งานสถานะการนำทางที่แสดงผลข้อมูลอัปเดต

ลําดับการผสานรวม

ในภาพนี้ สีต่างๆ หมายถึงสิ่งต่อไปนี้

  • สีเหลือง CarService และ CarNavigationStatusManager จากแพลตฟอร์ม Android ดูข้อมูลเพิ่มเติมได้ที่ Car และ CAR_NAVIGATION_SERVICE
  • น้ำเงิน InstrumentClusterRendererService ติดตั้งใช้งานโดย OEM
  • สีม่วง แอปการนำทางที่ Google และนักพัฒนาแอปบุคคลที่สามนำมาใช้
  • เขียว CarAppFocusManager ดูข้อมูลเพิ่มเติมได้ที่การใช้ CarAppFocusManager API ด้านล่างและ CarAppFocusManager

ลำดับการไหลของข้อมูลสถานะการนำทางมีดังนี้

  1. CarService เริ่มต้นInstrumentClusterRenderingService
  2. ในระหว่างการเริ่มต้น InstrumentClusterRenderingService จะอัปเดต CarService ด้วยข้อมูลต่อไปนี้
    1. พร็อพเพอร์ตี้การแสดงผลของหน้าปัด เช่น ขอบเขตที่ชัดเจน (ดูรายละเอียดเพิ่มเติมเกี่ยวกับขอบเขตที่ชัดเจนในภายหลัง)
    2. ตัวเลือกกิจกรรมที่จําเป็นในการเปิดใช้งานกิจกรรมภายในจอแสดงผลของแผงหน้าปัด ดูข้อมูลเพิ่มเติมได้ที่ActivityOptions
  3. แอปการนำทาง (เช่น Google Maps สำหรับ Android Automotive หรือแอปแผนที่ใดก็ได้ที่มีสิทธิ์ที่จำเป็น)
    1. รับ CarAppFocusManager โดยใช้คลาส Car จาก car-lib
    2. ก่อนเริ่มเส้นทางแบบเลี้ยวต่อเลี้ยว ให้เรียกใช้ CarAppFocusManager.requestFocus() เพื่อส่ง CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION เป็นพารามิเตอร์ appType
  4. CarAppFocusManager สื่อสารคําขอนี้ให้ CarService ทราบ หากได้รับสิทธิ์ CarService จะตรวจสอบแพ็กเกจแอปการนำทางและค้นหากิจกรรมที่มีการทำเครื่องหมายเป็นหมวดหมู่ android.car.cluster.NAVIGATION
  5. หากพบ แอปการนำทางจะใช้ ActivityOptions ที่ InstrumentClusterRenderingService รายงานเพื่อเปิดใช้งานกิจกรรม และรวมพร็อพเพอร์ตี้การแสดงผลของหน้าปัดเป็นข้อมูลเพิ่มเติมใน Intent

ผสานรวม API

การติดตั้งใช้งาน InstrumentClusterRenderingService ต้องมีลักษณะดังนี้

  • กำหนดให้เป็นบริการแบบ Singleton โดยเพิ่มค่าต่อไปนี้ลงใน AndroidManifest.xml การดำเนินการนี้จำเป็นเพื่อให้แน่ใจว่าบริการคลัสเตอร์เครื่องมือจะทำงานอยู่เพียงสำเนาเดียว แม้ในระหว่างการเริ่มต้นและการเปลี่ยนผู้ใช้
    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 แล้วเพิ่มรายการที่เกี่ยวข้องลงในไฟล์ AndroidManifest.xml คลาสนี้ควบคุมจอแสดงผลของแผงหน้าปัด และสามารถแสดงผลข้อมูล Navigation State API (ไม่บังคับ)
  2. ในระหว่าง onCreate() ให้ใช้บริการนี้เพื่อเริ่มต้นการสื่อสารกับฮาร์ดแวร์การแสดงผล โดยมีตัวเลือกดังนี้
    • กำหนดจอแสดงผลรองที่จะใช้สำหรับหน้าปัด
    • สร้างจอแสดงผลเสมือนเพื่อให้แอปหน้าปัดแสดงผลและส่งรูปภาพที่แสดงผลไปยังอุปกรณ์ภายนอก (โดยใช้รูปแบบสตรีมมิงวิดีโอ เช่น H.264)
  3. เมื่อจอแสดงผลที่ระบุไว้ข้างต้นพร้อมใช้งาน บริการนี้ต้องเรียกใช้ InstrumentClusterRenderingService#setClusterActivityLaunchOptions() เพื่อกำหนด ActivityOptions ที่แน่นอนซึ่งต้องใช้เพื่อแสดงกิจกรรมบนหน้าปัด ใช้พารามิเตอร์ต่อไปนี้
    • category. ClusterRenderingService
    • ActivityOptions. อินสแตนซ์ ActivityOptions ที่ใช้เพื่อเปิดใช้งานกิจกรรมในแผงหน้าปัดได้ ตัวอย่างเช่น จากตัวอย่างการติดตั้งใช้งานหน้าปัดใน AOSP
      getService().setClusterActivityLaunchOptions(
        CATEGORY_NAVIGATION,
        ActivityOptions.makeBasic()
            .setLaunchDisplayId(displayId));
  4. เมื่อหน้าปัดพร้อมแสดงกิจกรรม บริการนี้จะต้องเรียกใช้ InstrumentClusterRenderingService#setClusterActivityState() ใช้พารามิเตอร์ต่อไปนี้
    • category ClusterRenderingService
    • state Bundle ที่สร้างขึ้นด้วย ClusterRenderingService โปรดระบุข้อมูลต่อไปนี้
      • visible ระบุว่าหน้าปัดแสดงข้อมูลพร้อมใช้งานและพร้อมแสดงเนื้อหา
      • unobscuredBounds สี่เหลี่ยมผืนผ้าที่กําหนดพื้นที่ภายในจอแสดงผลของแผงหน้าปัดที่ปลอดภัยสําหรับแสดงเนื้อหา เช่น บริเวณที่โดนหน้าปัดและหน้าปัดวัด
  5. ลบล้างเมธอด Service#dump() และรายงานข้อมูลสถานะที่เป็นประโยชน์สำหรับการแก้ไขข้อบกพร่อง (ดูข้อมูลเพิ่มเติมที่ dumpsys)

ตัวอย่างการใช้งาน InstrumentClusterRenderingService

ตัวอย่างต่อไปนี้แสดงภาพรวมการติดตั้งใช้งาน InstrumentClusterRenderingService ซึ่งจะสร้าง VirtualDisplay เพื่อแสดงเนื้อหาคลัสเตอร์เครื่องมือบนจอแสดงผลจริงจากระยะไกล

หรือรหัสนี้อาจส่ง displayId ของจอแสดงผลรองจริงที่เชื่อมต่อกับ HU หากทราบว่ามีจอแสดงผลดังกล่าว

/**
* 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 มีเมธอดชื่อ getAppTypeOwner() ซึ่งช่วยให้บริการคลัสเตอร์ที่เขียนโดย OEM ทราบว่าแอปการนำทางใดมีโฟกัสการนำทาง ณ เวลาหนึ่งๆ 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(..) เพื่อดึงข้อมูลชื่อแพ็กเกจของเจ้าของปัจจุบันสำหรับแอปประเภทหนึ่งๆ ที่อยู่ในโฟกัส วิธีนี้อาจแสดงผลชื่อแพ็กเกจมากกว่า 1 รายการหากเจ้าของปัจจุบันใช้ฟีเจอร์ 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. สร้างและแฟลช Android Auto ใน HU ที่รองรับ ใช้วิธีการสร้างและแฟลช Android สำหรับอุปกรณ์ของคุณโดยเฉพาะ ดูวิธีการได้ที่หัวข้อการใช้บอร์ดอ้างอิง
  2. เชื่อมต่อจอแสดงผลรองจริงกับ HU (หากรองรับ) หรือเปิด HU รองเสมือน ดังนี้
    1. เลือกโหมดนักพัฒนาแอปในแอปการตั้งค่า
    2. ไปที่การตั้งค่า > ระบบ > ขั้นสูง > ตัวเลือกสำหรับนักพัฒนาแอป > simulasikan layar sekunder
  3. รีบูต HU
  4. วิธีเปิดแอป KitchenSink
    1. เปิดลิ้นชัก
    2. ไปที่ Inst. Cluster
    3. คลิกเริ่มข้อมูลเมตา

KitchenSink ขอโฟกัสการนําทาง ซึ่งจะสั่งให้DirectRenderingCluster บริการแสดงอินเทอร์เฟซผู้ใช้จำลองบนหน้าปัด