สร้างอินเทอร์เฟซ HAL

คุณต้องใช้ HIDL เพื่ออธิบายแฟล็กบิลด์ทั้งหมดที่ใช้สำหรับการคอมไพล์เฟรมเวิร์กแบบมีเงื่อนไข ต้องจัดกลุ่มและรวมแฟล็กการสร้างที่เกี่ยวข้องไว้ในไฟล์ .hal ไฟล์เดียว การใช้ HIDL เพื่อระบุรายการการกำหนดค่า มีประโยชน์ดังนี้

  • มีการกำหนดเวอร์ชัน (หากต้องการเพิ่มรายการการกำหนดค่าใหม่ ผู้ให้บริการ/OEM ต้องขยาย HAL อย่างชัดเจน)
  • มีเอกสารประกอบครบถ้วน
  • การควบคุมการเข้าถึงโดยใช้ SELinux
  • ตรวจสอบความสมเหตุสมผลของรายการการกำหนดค่าผ่าน ชุดทดสอบของผู้ให้บริการ (ตรวจสอบช่วง ตรวจสอบการพึ่งพาซึ่งกันและกันระหว่างรายการ ฯลฯ)
  • API ที่สร้างขึ้นโดยอัตโนมัติทั้งใน C++ และ Java

ระบุแฟล็กการสร้างที่เฟรมเวิร์กใช้

เริ่มต้นด้วยการระบุการกำหนดค่าบิลด์ที่ใช้ในการคอมไพล์เฟรมเวิร์กแบบมีเงื่อนไข จากนั้นเลิกใช้การกำหนดค่าที่ล้าสมัยเพื่อลดขนาดชุด ตัวอย่างเช่น ชุดแฟล็กการสร้างต่อไปนี้ระบุไว้สำหรับ surfaceflinger

  • TARGET_USES_HWC2
  • TARGET_BOARD_PLATFORM
  • TARGET_DISABLE_TRIPLE_BUFFERING
  • TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS
  • NUM_FRAMEBUFFER_SURFACE_BUFFERS
  • TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK
  • VSYNC_EVENT_PHASE_OFFSET_NS
  • SF_VSYNC_EVENT_PHASE_OFFSET_NS
  • PRESENT_TIME_OFFSET_FROM_VSYNC_NS
  • MAX_VIRTUAL_DISPLAY_DIMENSION

สร้างอินเทอร์เฟซ HAL

การกำหนดค่าบิลด์สำหรับระบบย่อยจะเข้าถึงผ่านอินเทอร์เฟซ HAL ส่วนอินเทอร์เฟซสำหรับระบุค่าการกำหนดค่าจะจัดกลุ่มไว้ในแพ็กเกจ HAL android.hardware.configstore (ปัจจุบันอยู่ที่เวอร์ชัน 1.0) ตัวอย่างเช่น หากต้องการสร้างไฟล์อินเทอร์เฟซ HAL สำหรับ surfaceflinger ใน hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal ให้ทำดังนี้

package android.hardware.configstore@1.0;

interface ISurfaceFlingerConfigs {
    // TO-BE-FILLED-BELOW
};

หลังจากสร้างไฟล์ .hal แล้ว ให้เรียกใช้ hardware/interfaces/update-makefiles.sh เพื่อเพิ่มไฟล์ .hal ใหม่ลงในไฟล์ Android.bp และ Android.mk

เพิ่มฟังก์ชันสำหรับแฟล็กบิลด์

เพิ่มฟังก์ชันใหม่ลงในอินเทอร์เฟซสำหรับแต่ละฟีเจอร์ที่สร้าง ตัวอย่างเช่น ใน hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal

interface ISurfaceFlingerConfigs {
    disableTripleBuffering() generates(OptionalBool ret);
    forceHwcForVirtualDisplays() generates(OptionalBool ret);
    enum NumBuffers: uint8_t {
        USE_DEFAULT = 0,
        TWO = 2,
        THREE = 3,
    };
    numFramebufferSurfaceBuffers() generates(NumBuffers ret);
    runWithoutSyncFramework() generates(OptionalBool ret);
    vsyncEventPhaseOffsetNs generates (OptionalUInt64 ret);
    presentTimeOffsetFromSyncNs generates (OptionalUInt64 ret);
    maxVirtualDisplayDimension() generates(OptionalInt32 ret);
};

เมื่อเพิ่มฟังก์ชัน ให้ทำดังนี้

  • ใช้ชื่อที่กระชับ หลีกเลี่ยงการแปลงชื่อตัวแปร Makefile เป็นชื่อฟังก์ชัน และโปรดทราบว่าไม่จำเป็นต้องใช้คำนำหน้า TARGET_ และ BOARD_ อีกต่อไป
  • แสดงความคิดเห็น ช่วยให้นักพัฒนาแอปเข้าใจวัตถุประสงค์ของ รายการกำหนดค่า วิธีที่รายการกำหนดค่าเปลี่ยนลักษณะการทำงานของเฟรมเวิร์ก ค่าที่ใช้ได้ และข้อมูลอื่นๆ ที่เกี่ยวข้อง

ประเภทการคืนค่าของฟังก์ชันอาจเป็น Optional[Bool|String|Int32|UInt32|Int64|UInt64] ประเภทจะกำหนดไว้ ใน types.hal ในไดเรกทอรีเดียวกัน และจะรวมค่าดั้งเดิมไว้กับฟิลด์ ที่ระบุว่า HAL ระบุค่าหรือไม่ หากไม่ระบุ ระบบจะใช้ค่าเริ่มต้น

struct OptionalString {
    bool specified;
    string value;
};

เมื่อเหมาะสม ให้กำหนด Enum ที่แสดงถึงประเภทของ รายการกำหนดค่าได้ดีที่สุด และใช้ Enum นั้นเป็นประเภทการคืนค่า ในตัวอย่างด้านบน มีการกำหนด NumBuffers enum เพื่อจำกัดจำนวนค่าที่ถูกต้อง เมื่อกำหนดประเภทข้อมูลที่กำหนดเองดังกล่าว ให้เพิ่มฟิลด์หรือค่า enum (เช่น USE_DEFAULT) เพื่อระบุว่า HAL ระบุค่าหรือไม่

ไม่จำเป็นที่แฟล็กบิลด์เดียวจะต้องกลายเป็นฟังก์ชันเดียวใน HIDL หรือเจ้าของโมดูลอาจรวบรวมแฟล็กการสร้างที่เกี่ยวข้องอย่างใกล้ชิดไว้ใน โครงสร้างและมีฟังก์ชันที่แสดงผลโครงสร้างนั้น (การทำเช่นนี้จะช่วยลด จำนวนการเรียกฟังก์ชันได้)

ตัวอย่างเช่น ตัวเลือกในการรวมแฟล็กการสร้าง 2 รายการไว้ในโครงสร้างเดียว ใน hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal คือ

 interface ISurfaceFlingerConfigs {
    // other functions here
    struct SyncConfigs {
        OptionalInt64 vsyncEventPhaseoffsetNs;
        OptionalInt64 presentTimeoffsetFromSyncNs;
    };
    getSyncConfigs() generates (SyncConfigs ret);
    // other functions here
};

ทางเลือกอื่นๆ สำหรับฟังก์ชัน HAL เดียว

นอกจากฟังก์ชัน HAL เดียวสำหรับแฟล็กการสร้างทั้งหมดแล้ว อินเทอร์เฟซ HAL ยังมีฟังก์ชันง่ายๆ เช่น getBoolean(string key) และ getInteger(string key) ด้วย ระบบจะจัดเก็บคู่key=valueจริงในไฟล์แยกต่างหาก และบริการ HAL จะให้ค่าโดยการอ่าน/แยกวิเคราะห์ไฟล์เหล่านั้น

แม้ว่าวิธีนี้จะกำหนดได้ง่าย แต่ก็ไม่ได้รวมประโยชน์ ที่ HIDL มอบให้ (การกำหนดเวอร์ชันที่บังคับใช้ ความสะดวกในการจัดทำเอกสาร การควบคุมการเข้าถึง) จึงไม่แนะนำให้ใช้วิธีนี้

อินเทอร์เฟซเดียวและหลายอินเทอร์เฟซ

การออกแบบอินเทอร์เฟซ HAL สำหรับรายการการกำหนดค่ามีตัวเลือก 2 อย่างดังนี้

  • อินเทอร์เฟซเดียวที่ครอบคลุมรายการการกำหนดค่าทั้งหมด
  • อินเทอร์เฟซหลายรายการ ซึ่งแต่ละรายการครอบคลุมชุดรายการการกำหนดค่าที่เกี่ยวข้อง

อินเทอร์เฟซเดียวจะใช้งานง่ายกว่า แต่เมื่อเพิ่มรายการการกำหนดค่าลงในไฟล์เดียวมากขึ้นเรื่อยๆ ก็อาจทำให้ดูแลรักษาได้ยาก นอกจากนี้ การควบคุมการเข้าถึงยังไม่ละเอียด ดังนั้นกระบวนการที่ได้รับสิทธิ์เข้าถึงอินเทอร์เฟซจะอ่านรายการกำหนดค่าทั้งหมดได้ (ไม่สามารถให้สิทธิ์เข้าถึงรายการกำหนดค่าบางส่วนได้) หรือหากไม่ได้รับสิทธิ์เข้าถึง ระบบจะอ่านรายการการกำหนดค่าไม่ได้

Android จึงใช้อินเทอร์เฟซหลายรายการที่มี HAL เดียว อินเทอร์เฟซสำหรับกลุ่มรายการการกำหนดค่าที่เกี่ยวข้อง เช่น ISurfaceflingerConfigs สำหรับรายการกำหนดค่าที่เกี่ยวข้องกับ surfaceflinger และ IBluetoothConfigs สำหรับรายการกำหนดค่าที่เกี่ยวข้องกับบลูทูธ