รูปแบบไฟล์ APEX

เปิดตัวรูปแบบคอนเทนเนอร์ Android Pony EXpress (APEX) ใน Android 10 คน และใช้ในขั้นตอนการติดตั้งสำหรับระบบระดับล่าง โมดูล รูปแบบนี้ช่วยให้อัปเดตคอมโพเนนต์ของระบบที่ไม่พอดีได้ง่ายขึ้น เป็นโมเดลแอปพลิเคชัน Android มาตรฐาน คอมโพเนนต์ตัวอย่างบางรายการเป็นแบบเนทีฟ บริการและไลบรารี ชั้นการจัดการฮาร์ดแวร์ (HAL), รันไทม์ (ART) และห้องสมุดของชั้นเรียน

คำว่า "APEX" สามารถอ้างอิงไฟล์ APEX ได้ด้วย

ฉากหลัง

แม้ว่า Android จะรองรับการอัปเดตโมดูลที่พอดีกับแอปมาตรฐาน โมเดล (เช่น บริการ กิจกรรม) ผ่านแอปโปรแกรมติดตั้งแพ็กเกจ (เช่น แอป Google Play Store) ซึ่งใช้โมเดลที่คล้ายกันสำหรับคอมโพเนนต์ระบบปฏิบัติการระดับต่ำกว่า มีข้อเสียดังต่อไปนี้

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

การออกแบบ

ส่วนนี้จะอธิบายการออกแบบระดับสูงของรูปแบบไฟล์ APEX และ ตัวจัดการ APEX ซึ่งเป็นบริการจัดการไฟล์ APEX

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับเหตุผลที่เลือกการออกแบบนี้สำหรับ APEX โปรดดู ทางเลือกที่นำมาพิจารณาเมื่อพัฒนา APEX

รูปแบบ APEX

นี่คือรูปแบบของไฟล์ APEX

รูปแบบไฟล์ APEX

รูปที่ 1 รูปแบบไฟล์ APEX

ที่ระดับบนสุด ไฟล์ APEX คือไฟล์ ZIP ที่ใช้จัดเก็บไฟล์ ไม่ได้บีบอัดและมีขนาดอยู่ที่ 4 KB

ไฟล์ APEX 4 ไฟล์มีดังนี้

  • apex_manifest.json
  • AndroidManifest.xml
  • apex_payload.img
  • apex_pubkey

ไฟล์ apex_manifest.json มีชื่อแพ็กเกจและเวอร์ชันของ ระบุไฟล์ APEX นี่คือ ApexManifest บัฟเฟอร์โปรโตคอลในรูปแบบ JSON

ไฟล์ AndroidManifest.xml ช่วยให้ไฟล์ APEX สามารถใช้เครื่องมือที่เกี่ยวข้องกับ APK และ โครงสร้างพื้นฐาน เช่น ADB, PackageManager และแอปโปรแกรมติดตั้งแพ็กเกจ (เช่น Play Store) ตัวอย่างเช่น ไฟล์ APEX สามารถใช้เครื่องมือที่มีอยู่ เช่น aapt เพื่อตรวจสอบข้อมูลเมตาพื้นฐานจากไฟล์ ไฟล์มีชื่อแพ็กเกจและ ข้อมูลเวอร์ชัน โดยทั่วไปแล้ว ข้อมูลนี้มีอยู่ใน apex_manifest.json

แนะนำให้ใช้ apex_manifest.json มากกว่า AndroidManifest.xml สำหรับโค้ดใหม่และ ระบบที่ทำงานกับ APEX AndroidManifest.xml อาจมี ข้อมูลการกำหนดเป้าหมายที่เครื่องมือเผยแพร่แอปที่มีอยู่สามารถใช้ได้

apex_payload.img คืออิมเมจระบบไฟล์ ext4 ที่ได้รับการสนับสนุนโดย dm-verity รูปภาพ จะต่อเชื่อมขณะรันไทม์ผ่านอุปกรณ์ Loopback โดยเฉพาะอย่างยิ่ง โครงสร้างแฮชและ บล็อกข้อมูลเมตาสร้างขึ้นโดยใช้ไลบรารี libavb เพย์โหลดระบบไฟล์ ไม่ได้แยกวิเคราะห์ (เนื่องจากรูปภาพควรติดตั้งได้ในตำแหน่ง) ไฟล์ทั่วไปคือ ซึ่งรวมอยู่ในไฟล์ apex_payload.img

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

หลักเกณฑ์การตั้งชื่อ APEX

เพื่อช่วยป้องกันความขัดแย้งในการตั้งชื่อระหว่าง APEX ใหม่ในขณะที่แพลตฟอร์มก้าวหน้า ใช้หลักเกณฑ์การตั้งชื่อดังต่อไปนี้

  • com.android.*
    • สงวนไว้สำหรับ AOSP APEXes ไม่เจาะจงสำหรับบริษัทหรืออุปกรณ์ใดๆ
  • com.<companyname>.*
    • สงวนไว้สำหรับบริษัท อุปกรณ์หลายเครื่องที่อาจใช้งานอยู่ บริษัท
  • com.<companyname>.<devicename>.*
    • สงวนไว้สำหรับ APEX เฉพาะกับอุปกรณ์หนึ่งๆ (หรืออุปกรณ์ชุดย่อย)

ผู้จัดการ APEX

เครื่องมือจัดการ APEX (หรือ apexd) เป็นกระบวนการแบบเนทีฟแบบสแตนด์อโลนที่รับผิดชอบ ยืนยัน ติดตั้ง และถอนการติดตั้งไฟล์ APEX กระบวนการนี้เริ่มใช้แล้ว และ พร้อมใช้งานในช่วงต้นของลำดับการเปิดเครื่อง โดยปกติไฟล์ APEX จะได้รับการติดตั้งไว้ล่วงหน้า อุปกรณ์ภายใต้ /system/apex เครื่องมือจัดการ APEX จะใช้ค่าเริ่มต้น หากไม่มีการอัปเดตพร้อมใช้งาน

ลำดับการอัปเดตของ APEX จะใช้ คลาส PackageManager และมีดังนี้

  1. ไฟล์ APEX จะดาวน์โหลดผ่านแอปโปรแกรมติดตั้งแพ็กเกจ, ADB หรือ แหล่งที่มา
  2. ตัวจัดการแพ็กเกจจะเริ่มขั้นตอนการติดตั้ง เมื่อตระหนักว่า ไฟล์นี้เป็น APEX ตัวจัดการแพ็กเกจจะโอนการควบคุมไปยัง APEX
  3. ผู้จัดการ APEX จะยืนยันไฟล์ APEX
  4. หากไฟล์ APEX ได้รับการยืนยันแล้ว ฐานข้อมูลภายในของตัวจัดการ APEX จะเป็น อัปเดตเพื่อให้แสดงว่าไฟล์ APEX เปิดใช้งานเมื่อเปิดเครื่องครั้งถัดไป
  5. ผู้ส่งคำขอติดตั้งจะได้รับการออกอากาศเมื่อแพ็กเกจเสร็จสมบูรณ์ การยืนยันของคุณ
  6. หากต้องการติดตั้งต่อ คุณต้องรีบูตระบบ
  7. เมื่อเปิดเครื่องครั้งถัดไป ตัวจัดการ APEX จะเริ่มต้น อ่านฐานข้อมูลภายใน และ ค่าต่อไปนี้สำหรับไฟล์ APEX แต่ละไฟล์ที่ระบุ

    1. ยืนยันไฟล์ APEX
    2. สร้างอุปกรณ์ Loopback จากไฟล์ APEX
    3. สร้างอุปกรณ์บล็อกตัวแมปอุปกรณ์ที่ด้านบนของอุปกรณ์ Loopback
    4. ติดตั้งอุปกรณ์บล็อกตัวทำแผนที่อุปกรณ์เข้ากับเส้นทางที่ไม่ซ้ำกัน (เช่น /apex/name@ver)

เมื่อไฟล์ APEX ทั้งหมดที่ระบุไว้ในฐานข้อมูลภายในถูกต่อเชื่อมแล้ว APEX Manager ให้บริการ Binder สำหรับคอมโพเนนต์อื่นๆ ของระบบเพื่อค้นหา ข้อมูลเกี่ยวกับไฟล์ APEX ที่ติดตั้ง ตัวอย่างเช่น อีกระบบหนึ่ง สามารถค้นหารายการไฟล์ APEX ที่ติดตั้งในอุปกรณ์หรือค้นหา เส้นทางที่แน่นอนซึ่งมีการต่อเชื่อม APEX ที่เฉพาะเจาะจงเพื่อให้เข้าถึงไฟล์ได้

ไฟล์ APEX คือไฟล์ APK

ไฟล์ APEX เป็นไฟล์ APK ที่ถูกต้อง เนื่องจากเป็นไฟล์ ZIP ที่มีการรับรอง (โดยใช้ APK Signature Scheme) ที่มีไฟล์ AndroidManifest.xml ซึ่งทำให้ APEX เพื่อใช้โครงสร้างพื้นฐานสำหรับไฟล์ APK เช่น แอปโปรแกรมติดตั้งแพ็กเกจ ยูทิลิตีการลงชื่อ และโปรแกรมจัดการแพ็กเกจ

ไฟล์ AndroidManifest.xml ภายในไฟล์ APEX เป็นไฟล์เล็กที่สุด โดยประกอบด้วย แพ็กเกจ name, versionCode และแพ็กเกจที่ไม่บังคับ targetSdkVersion, minSdkVersion และ maxSdkVersion สำหรับการกำหนดเป้าหมายแบบละเอียด ข้อมูลนี้ช่วยให้ APEX ส่งผ่านช่องทางที่มีอยู่ เช่น แอปโปรแกรมติดตั้งแพ็กเกจ และ ADB

ประเภทไฟล์ที่รองรับ

รูปแบบ APEX รองรับไฟล์ประเภทต่อไปนี้

  • Libs ที่แชร์แบบเนทีฟ
  • ไฟล์ปฏิบัติการที่มาพร้อมเครื่อง
  • ไฟล์ JAR
  • ไฟล์ข้อมูล
  • ไฟล์การกำหนดค่า

ซึ่งไม่ได้หมายความว่า APEX จะอัปเดตประเภทไฟล์เหล่านี้ได้ทั้งหมด เป็นไฟล์หรือไม่ ประเภทการอัปเดตจะขึ้นอยู่กับแพลตฟอร์ม และความเสถียรของคำจำกัดความของ อินเทอร์เฟซสำหรับประเภทไฟล์มีดังนี้

ตัวเลือกการรับรอง

ไฟล์ APEX จะมีการลงชื่อ 2 วิธี ก่อนอื่น apex_payload.img (โดยเฉพาะ ตัวบ่งชี้ vbmeta ที่ต่อท้าย apex_payload.img) จะได้รับการลงนามด้วยคีย์ จากนั้น APEX ทั้งหมดจะลงชื่อโดยใช้ APK Signature Scheme v3 มีการใช้คีย์ที่แตกต่างกัน 2 คีย์ ในขั้นตอนนี้

ทางฝั่งอุปกรณ์ คีย์สาธารณะที่สอดคล้องกับคีย์ส่วนตัวที่ใช้ในการลงนาม ติดตั้งข้อบ่งชี้ vbmeta แล้ว เครื่องมือจัดการ APEX จะใช้คีย์สาธารณะเพื่อ ตรวจสอบ APEX ที่ถูกขอให้ติดตั้ง APEX แต่ละรายการต้องลงนาม คีย์ที่แตกต่างกันและมีการบังคับใช้ทั้งในเวลาบิลด์และรันไทม์

APEX ในพาร์ติชันในตัว

ไฟล์ APEX อาจอยู่ในพาร์ติชันในตัว เช่น /system พาร์ติชันมีค่ามากกว่า dm-verity แล้ว ดังนั้นไฟล์ APEX จะถูกต่อเชื่อมโดยตรง ผ่านทางอุปกรณ์ Loopback

ถ้ามี APEX อยู่ในพาร์ติชันในตัว คุณสามารถอัปเดต APEX ได้โดยดำเนินการดังนี้ แสดงแพ็กเกจ APEX ที่มีชื่อแพ็กเกจเดียวกันและมีมูลค่ามากกว่าหรือเท่ากับ เป็นรหัสเวอร์ชัน APEX ใหม่ถูกจัดเก็บไว้ใน /data และเช่นเดียวกับ APK เวอร์ชันที่ติดตั้งใหม่จะแสดงเงาของเวอร์ชันที่มีอยู่แล้ว พาร์ติชัน แต่ APEX แตกต่างจาก APK ตรงที่เวอร์ชัน APEX ที่ติดตั้งใหม่มีเพียง เปิดใช้งานหลังจากรีบูต

ข้อกำหนดของเคอร์เนล

Linux ต่อไปนี้เพื่อรองรับโมดูลหลัก APEX บนอุปกรณ์ Android ต้องมีฟีเจอร์เคอร์เนล: ไดรเวอร์ Loopback และ dm-verity Loopback ไดรเวอร์จะต่อเชื่อมอิมเมจระบบไฟล์ในโมดูล APEX และยืนยันความถูกต้องของ โมดูล APEX

ประสิทธิภาพของตัวขับ Loopback และ dm-verity เป็นสิ่งสำคัญในการบรรลุผล ระบบมีประสิทธิภาพที่ดีเมื่อใช้โมดูล APEX

เวอร์ชันเคอร์เนลที่รองรับ

โมดูลหลัก APEX ได้รับการสนับสนุนในอุปกรณ์ที่ใช้เคอร์เนลเวอร์ชัน 4.4 หรือ สูงขึ้น อุปกรณ์ใหม่ที่จะเปิดตัวโดยใช้ Android 10 ขึ้นไป ต้องใช้เคอร์เนลเวอร์ชัน 4.9 ขึ้นไปเพื่อรองรับโมดูล APEX

แพตช์ของเคอร์เนลที่จำเป็น

แพตช์เคอร์เนลที่จำเป็นสำหรับการรองรับโมดูล APEX จะรวมอยู่ใน แผนผัง Android Common ในการรับแพตช์เพื่อรองรับ APEX โปรดใช้เวอร์ชันล่าสุด ของ Android Common

Kernel เวอร์ชัน 4.4

เวอร์ชันนี้รองรับเฉพาะอุปกรณ์ที่อัปเกรดจาก Android 9 เป็น Android 10 และต้องการรองรับโมดูล APEX หากต้องการดาวน์โหลด จำเป็นต้องอัปเดตแพตช์ การรวมดาวน์จาก Branch ของ android-4.4 แนะนำ รายการแพตช์ที่จำเป็นแต่ละรายการมีดังนี้ สำหรับเคอร์เนลเวอร์ชัน 4.4

  • UPSTREAM: ลูป: เพิ่ม ioctl สำหรับการเปลี่ยนขนาดบล็อกเชิงตรรกะ (4.4)
  • BACKPORT: บล็อก/ลูป: ตั้งค่า hw_sectors (4.4)
  • UPSTREAM: ลูป: เพิ่ม LOOP_SET_BLOCK_SIZE ใน ioctl ที่ใช้ร่วมกัน (4.4)
  • ANDROID: mnt: แก้ไข next_descendent (4.4)
  • ANDROID: mnt: การต่อเชื่อมใหม่ควรเผยแพร่ไปยังทาสของทาส (4.4)
  • ANDROID: mnt: เผยแพร่การติดตั้งใหม่อย่างถูกต้อง (4.4)
  • เปลี่ยนกลับ "ANDROID: เวอร์ชัน dm เวอร์ชัน: เพิ่มขนาดการดึงข้อมูลล่วงหน้าขั้นต่ำ" (4.4)
  • UPSTREAM: วนซ้ำ: ทิ้งแคชหากออฟเซ็ตหรือ block_size มีการเปลี่ยนแปลง (4.4)

Kernel เวอร์ชัน 4.9/4.14/4.19

หากต้องการรับแพตช์ที่จำเป็นสำหรับเคอร์เนลเวอร์ชัน 4.9/4.14/4.19 ให้ผสานจาก สาขา android-common

ตัวเลือกการกำหนดค่าเคอร์เนลที่จำเป็น

รายการต่อไปนี้แสดงข้อกําหนดการกําหนดค่าพื้นฐานสําหรับการรองรับ โมดูล APEX ที่เปิดตัวใน Android 10 รายการที่มีเครื่องหมายดอกจัน (*) เป็นข้อกำหนดที่มีตั้งแต่ Android 9 และต่ำกว่า

(*) CONFIG_AIO=Y # AIO support (for direct I/O on loop devices)
CONFIG_BLK_DEV_LOOP=Y # for loop device support
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 # pre-create 16 loop devices
(*) CONFIG_CRYPTO_SHA1=Y # SHA1 hash for DM-verity
(*) CONFIG_CRYPTO_SHA256=Y # SHA256 hash for DM-verity
CONFIG_DM_VERITY=Y # DM-verity support

ข้อกำหนดพารามิเตอร์บรรทัดคำสั่ง Kernel

เพื่อให้รองรับ APEX โปรดตรวจสอบว่าพารามิเตอร์บรรทัดคำสั่งของเคอร์เนลเป็นไปตามข้อกำหนดต่อไปนี้ ข้อกำหนด

  • ต้องไม่ตั้งค่า loop.max_loop
  • loop.max_part ต้อง <= 8

สร้าง APEX

หัวข้อนี้จะอธิบายวิธีสร้าง APEX โดยใช้ระบบบิลด์ของ Android ต่อไปนี้เป็นตัวอย่างของ Android.bp สำหรับ APEX ชื่อ apex.test

apex {
    name: "apex.test",
    manifest: "apex_manifest.json",
    file_contexts: "file_contexts",
    // libc.so and libcutils.so are included in the apex
    native_shared_libs: ["libc", "libcutils"],
    binaries: ["vold"],
    java_libs: ["core-all"],
    prebuilts: ["my_prebuilt"],
    compile_multilib: "both",
    key: "apex.test.key",
    certificate: "platform",
}

ตัวอย่าง apex_manifest.json:

{
  "name": "com.android.example.apex",
  "version": 1
}

ตัวอย่าง file_contexts:

(/.*)?           u:object_r:system_file:s0
/sub(/.*)?       u:object_r:sub_file:s0
/sub/file3       u:object_r:file3_file:s0

ประเภทไฟล์และตำแหน่งใน APEX

ประเภทไฟล์ สถานที่ตั้งใน APEX
คลังภาพที่แชร์ /lib และ /lib64 (/lib/arm สำหรับ แขนแปลใน x86)
ไฟล์สั่งการ /bin
ไลบรารี Java /javalib
สำเร็จรูป /etc

ทรัพยากร Dependency แบบทรานซิทีฟ

ไฟล์ APEX จะรวมทรัพยากร Dependency แบบทรานซิทีฟของไลบรารีที่แชร์แบบเนทีฟโดยอัตโนมัติ หรือไฟล์ปฏิบัติการ ตัวอย่างเช่น ถ้า libFoo ขึ้นอยู่กับ libBar ไลบรารี 2 อันจะเป็น รวมเมื่อมีเพียง libFoo เท่านั้นที่ปรากฏในพร็อพเพอร์ตี้ native_shared_libs

จัดการ ABI หลายรายการ

ติดตั้งพร็อพเพอร์ตี้ native_shared_libs สำหรับทั้งหลักและรอง อินเทอร์เฟซไบนารีของแอปพลิเคชัน (ABI) ของอุปกรณ์ หาก APEX กำหนดเป้าหมายอุปกรณ์ ที่มี ABI เดียว (ซึ่งก็คือ 32 บิตเท่านั้น หรือ 64 บิตเท่านั้น) เฉพาะไลบรารีที่มี ติดตั้ง ABI ที่เกี่ยวข้องแล้ว

ติดตั้งพร็อพเพอร์ตี้ binaries สำหรับ ABI หลักของอุปกรณ์เท่านั้นตามที่ ที่อธิบายไว้ด้านล่าง

  • หากอุปกรณ์เป็นแบบ 32 บิตเท่านั้น เฉพาะไบนารี 32 บิตจะเป็น ติดตั้งไว้แล้ว
  • หากอุปกรณ์เป็นแบบ 64 บิตเท่านั้น ไบนารี 64 บิตเท่านั้นจะเป็น ติดตั้งไว้แล้ว

วิธีเพิ่มการควบคุม ABI ของไลบรารีและไบนารีแบบเนทีฟโดยละเอียด ให้ใช้ multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries] พร็อพเพอร์ตี้

  • first: จับคู่ ABI หลักของอุปกรณ์ ตัวเลือกนี้เป็นค่าเริ่มต้นสำหรับ ไบนารี
  • lib32: จับคู่ ABI 32 บิตของอุปกรณ์ หากรองรับ
  • lib64: ตรงกับ ABI 64 บิตของอุปกรณ์ที่รองรับ
  • prefer32: จับคู่ ABI 32 บิตของอุปกรณ์ หากรองรับ หาก ไม่รองรับ ABI 32 บิต ตรงกับ ABI 64 บิต
  • both: ตรงกับ ABI ทั้ง 2 รายการ ตัวเลือกนี้เป็นค่าเริ่มต้นสำหรับ native_shared_libraries

พร็อพเพอร์ตี้ java, libraries และ prebuilts เข้ากันได้กับ ABI

ตัวอย่างนี้มีไว้สำหรับอุปกรณ์ที่รองรับ 32/64 และไม่ต้องการเลือก 32

apex {
    // other properties are omitted
    native_shared_libs: ["libFoo"], // installed for 32 and 64
    binaries: ["exec1"], // installed for 64, but not for 32
    multilib: {
        first: {
            native_shared_libs: ["libBar"], // installed for 64, but not for 32
            binaries: ["exec2"], // same as binaries without multilib.first
        },
        both: {
            native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib
            binaries: ["exec3"], // installed for 32 and 64
        },
        prefer32: {
            native_shared_libs: ["libX"], // installed for 32, but not for 64
        },
        lib64: {
            native_shared_libs: ["libY"], // installed for 64, but not for 32
        },
    },
}

การลงชื่อ vbmeta

ลงนาม APEX แต่ละรายการด้วยคีย์ต่างกัน เมื่อต้องใช้คีย์ใหม่ ให้สร้าง คู่คีย์สาธารณะ-ส่วนตัวและสร้างโมดูล apex_key ใช้พร็อพเพอร์ตี้ key เพื่อ ลงนาม APEX โดยใช้คีย์ คีย์สาธารณะจะรวมอยู่ในส่วน APEX ที่ชื่อ avb_pubkey

# create an rsa key pair
openssl genrsa -out foo.pem 4096

# extract the public key from the key pair
avbtool extract_public_key --key foo.pem --output foo.avbpubkey

# in Android.bp
apex_key {
    name: "apex.test.key",
    public_key: "foo.avbpubkey",
    private_key: "foo.pem",
}

ในตัวอย่างข้างต้น ชื่อของคีย์สาธารณะ (foo) จะกลายเป็นรหัสของ รหัสของคีย์ที่ใช้ในการลงนาม APEX จะเขียนอยู่ใน APEX ระหว่างรันไทม์ apexd จะยืนยัน APEX โดยใช้คีย์สาธารณะที่มีรหัสเดียวกันในอุปกรณ์

การลงนาม APEX

รับรอง APEX ในลักษณะเดียวกันกับที่รับรอง APK ลงนาม APEXes 2 ครั้ง 1 ครั้งสำหรับ ระบบไฟล์ขนาดเล็ก (apex_payload.img ไฟล์) และครั้งเดียวสำหรับทั้งไฟล์

หากต้องการลงนาม APEX ที่ระดับไฟล์ ให้ตั้งค่าพร็อพเพอร์ตี้ certificate ใน 3 วิธีต่อไปนี้

  • ไม่ได้ตั้งค่า: หากไม่ได้ตั้งค่าไว้ ระบบจะลงชื่อ APEX ด้วยใบรับรองที่อยู่ ที่ PRODUCT_DEFAULT_DEV_CERTIFICATE หากไม่ได้ตั้งค่า Flag ไว้ เส้นทางเริ่มต้น ไปยัง build/target/product/security/testkey
  • <name>: APEX ลงนามด้วยใบรับรอง <name> เดียวกันกับ เป็น PRODUCT_DEFAULT_DEV_CERTIFICATE
  • :<name>: APEX ลงนามด้วยใบรับรองที่กำหนดโดย โมดูล Soong ชื่อ <name> โมดูลใบรับรองสามารถกำหนดเป็น ติดตาม
android_app_certificate {
    name: "my_key_name",
    certificate: "dir/cert",
    // this will use dir/cert.x509.pem (the cert) and dir/cert.pk8 (the private key)
}

ติดตั้ง APEX

หากต้องการติดตั้ง APEX ให้ใช้ ADB

adb install apex_file_name
adb reboot

หากตั้งค่า supportsRebootlessUpdate เป็น true ใน apex_manifest.json และ APEX ที่ติดตั้งอยู่ในปัจจุบันจะไม่มีการใช้งาน (เช่น บริการใดก็ตามที่อยู่ใน ) จากนั้น คุณสามารถติดตั้ง APEX ใหม่ได้โดยไม่ต้องรีบูตด้วย แฟล็ก --force-non-staged

adb install --force-non-staged apex_file_name

ใช้ APEX

หลังจากรีบูต ระบบจะต่อเชื่อม APEX ไว้ที่ /apex/<apex_name>@<version> ไดเรกทอรี คุณสามารถต่อเชื่อม APEX เดียวกันได้หลายเวอร์ชันพร้อมกัน เส้นทางที่สอดคล้องกับเวอร์ชันล่าสุดในบรรดาเส้นทางต่อเชื่อมคือ ต่อเชื่อมแบบต่อเชื่อมที่ /apex/<apex_name>

ไคลเอ็นต์สามารถใช้เส้นทางที่ผูกไว้เพื่ออ่านหรือเรียกใช้ไฟล์จาก APEX

โดยทั่วไป APEX จะมีการใช้งานดังนี้

  1. OEM หรือ ODM โหลด APEX ล่วงหน้าภายใต้ /system/apex เมื่ออุปกรณ์ จัดส่งแล้ว
  2. ไฟล์ใน APEX จะเข้าถึงได้ผ่านเส้นทาง /apex/<apex_name>/
  3. เมื่อติดตั้ง APEX เวอร์ชันอัปเดตใน /data/apex แล้ว เส้นทาง ชี้ไปที่ APEX ใหม่หลังจากรีบูต

อัปเดตบริการด้วย APEX

วิธีอัปเดตบริการโดยใช้ APEX

  1. ทำเครื่องหมายบริการในพาร์ติชันระบบเป็นอัปเดตได้ เพิ่มตัวเลือก updatable ไปยังคำจำกัดความของบริการ

    /system/etc/init/myservice.rc:
    
    service myservice /system/bin/myservice
        class core
        user system
        ...
        updatable
    
  2. สร้างไฟล์ .rc ใหม่สำหรับบริการที่อัปเดต ใช้ตัวเลือก override เพื่อกำหนดบริการที่มีอยู่ใหม่

    /apex/my.apex/etc/init.rc:
    
    service myservice /apex/my.apex/bin/myservice
        class core
        user system
        ...
        override
    

คุณกำหนดคำจำกัดความของบริการได้ในไฟล์ .rc ของ APEX เท่านั้น แอ็กชัน ระบบไม่รองรับทริกเกอร์ใน APEXes

หากบริการที่ทำเครื่องหมายว่าสามารถอัปเดตได้เริ่มขึ้นก่อนที่จะเปิดใช้งาน APEX การเริ่มต้นจะล่าช้าจนกว่าการเปิดใช้งาน APEX จะเสร็จสมบูรณ์

กำหนดค่าระบบให้รองรับการอัปเดต APEX

ตั้งค่าพร็อพเพอร์ตี้ของระบบต่อไปนี้เป็น true เพื่อรองรับการอัปเดตไฟล์ APEX

<device.mk>:

PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true

BoardConfig.mk:
TARGET_FLATTEN_APEX := false

หรือแค่

<device.mk>:

$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)

APEX ที่แยกเป็นหลายรายการ

สำหรับอุปกรณ์เดิม การอัปเดตเวอร์ชันเก่านั้นอาจเป็นไปไม่ได้หรือทำไม่ได้ในบางครั้ง เคอร์เนลเพื่อรองรับ APEX อย่างเต็มรูปแบบ ตัวอย่างเช่น อาจมีการสร้างเคอร์เนลขึ้น โดยไม่มี CONFIG_BLK_DEV_LOOP=Y ซึ่งสำคัญมากสำหรับการต่อเชื่อมระบบไฟล์ ภายใน APEX

APEX แบบกระจายเป็น APEX ที่สร้างขึ้นมาเป็นพิเศษที่สามารถเปิดใช้งานบนอุปกรณ์ที่มี เคอร์เนลเดิม ไฟล์ใน APEX ที่รวมเป็นหลายรายการจะติดตั้งในไดเรกทอรีโดยตรง ภายใต้พาร์ติชันในตัว ตัวอย่างเช่น lib/libFoo.so ใน APEX ที่แยกเป็นหลายรายการ my.apex ได้รับการติดตั้งไปยัง /system/apex/my.apex/lib/libFoo.so

การเปิดใช้งาน APEX ที่แยกเป็นหลายรายการจะไม่เกี่ยวข้องกับอุปกรณ์วนซ้ำ ภาพรวม ไดเรกทอรี /system/apex/my.apex ถูกเชื่อมโยงกับ /apex/name@ver โดยตรง

ไม่สามารถอัปเดต APEX ที่แยกเป็นหลายรายการด้วยการดาวน์โหลดเวอร์ชันที่อัปเดตแล้ว ของ APEX จากเครือข่ายเนื่องจาก APEX ที่ดาวน์โหลดมาไม่สามารถแยกเป็นหลายรายการได้ APEX ที่แยกเป็นหลายรายการจะอัปเดตได้ผ่าน OTA ปกติเท่านั้น

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

ไม่ใช่การผสม APEX ที่ราบเรียบและไม่แบน ที่รองรับ APEX ในอุปกรณ์ต้องเป็นแบบไม่แบนหรือราบเรียบทั้งหมด ซึ่งสำคัญมากเมื่อจัดส่ง APEX ที่ลงนามไว้ล่วงหน้าสำหรับ โปรเจ็กต์ เช่น Mainline APEX ที่ไม่ได้ลงนามล่วงหน้า (สร้างขึ้นจาก แหล่งที่มา) ก็ไม่ควรแยกเป็นหลายรายการและมีการรับรองด้วยคีย์ที่เหมาะสม อุปกรณ์ควรรับค่าจาก updatable_apex.mk ตามที่อธิบายไว้ใน การอัปเดตบริการด้วย APEX

APEX ที่บีบอัด

Android 12 ขึ้นไปมีการบีบอัด APEX สำหรับ ซึ่งช่วยลดผลกระทบต่อพื้นที่เก็บข้อมูลของแพ็กเกจ APEX ที่อัปเดตได้ หลังการอัปเดตเป็น APEX แล้ว แม้จะไม่ได้ใช้เวอร์ชันที่ติดตั้งไว้ล่วงหน้าแล้วก็ตาม ยังใช้พื้นที่เท่าเดิม พื้นที่ที่มีการใช้งานนั้นยังคงไม่สามารถใช้ได้

การบีบอัด APEX ลดผลกระทบของพื้นที่เก็บข้อมูลลงโดยใช้ชุดที่มีการบีบอัดสูง ของไฟล์ APEX ในพาร์ติชันแบบอ่านอย่างเดียว (เช่น พาร์ติชัน /system) แอนดรอยด์ 12 ขึ้นไปใช้อัลกอริทึมการบีบอัดไฟล์ Zip DEFLATE

การบีบอัดไม่มีการเพิ่มประสิทธิภาพสำหรับสิ่งต่อไปนี้

  • APEX ของ Bootstrap ที่ต้องติดตั้งตั้งแต่เนิ่นๆ ในการเปิดเครื่อง ตามลำดับ

  • APEXes ที่ไม่สามารถอัปเดตได้ การบีบอัดจะมีประโยชน์เฉพาะในกรณีที่ติดตั้ง APEX เวอร์ชันที่อัปเดตแล้วเท่านั้น ในพาร์ติชัน /data ดูรายการ APEX ที่อัปเดตทั้งหมดได้ใน ส่วนประกอบของระบบโมดูล

  • APEXes ไลบรารีที่ใช้ร่วมกันแบบไดนามิก เนื่องจาก apexd จะเปิดใช้งานทั้ง 2 เวอร์ชันเสมอ APEX ดังกล่าว (ติดตั้งล่วงหน้าและอัปเกรด) แล้วการบีบอัดไม่ได้เพิ่มคุณค่า

รูปแบบไฟล์ APEX ที่บีบอัด

นี่คือรูปแบบของไฟล์ APEX ที่บีบอัด

แผนภาพแสดงรูปแบบของไฟล์ APEX ที่บีบอัด

รูปที่ 2 รูปแบบไฟล์ APEX ที่บีบอัด

ที่ระดับบนสุด ไฟล์ APEX ที่บีบอัดคือไฟล์ ZIP ที่มีไฟล์ ไฟล์ apex ในรูปแบบย่อที่มีระดับการบีบอัด 9 และมีไฟล์อื่นๆ โดยไม่มีการบีบอัด

ไฟล์ APEX 1 ไฟล์ประกอบด้วยไฟล์ 4 ไฟล์ ดังนี้

  • original_apex: อ่อนลงด้วยระดับการบีบอัดที่ 9 นี่คือไฟล์ APEX ต้นฉบับที่ไม่มีการบีบอัด
  • apex_manifest.pb: เก็บไว้เท่านั้น
  • AndroidManifest.xml: เก็บไว้เท่านั้น
  • apex_pubkey: เก็บไว้เท่านั้น

ไฟล์ apex_manifest.pb, AndroidManifest.xml และ apex_pubkey สำเนาไฟล์ที่เกี่ยวข้องใน original_apex

สร้าง APEX ที่บีบอัด

APEX ที่บีบอัดสร้างได้โดยใช้เครื่องมือapex_compression_tool.pyซึ่งอยู่ที่ system/apex/tools

มีพารามิเตอร์หลายรายการที่เกี่ยวข้องกับการบีบอัด APEX อยู่ในระบบบิลด์

ใน Android.bp ว่าไฟล์ APEX จะมีการควบคุมโดย พร็อพเพอร์ตี้ compressible:

apex {
    name: "apex.test",
    manifest: "apex_manifest.json",
    file_contexts: "file_contexts",
    compressible: true,
}

แฟล็กผลิตภัณฑ์ PRODUCT_COMPRESSED_APEX ควบคุมว่าอิมเมจระบบสร้างขึ้นหรือไม่ จากต้นทางต้องมีไฟล์ APEX ที่บีบอัด

สำหรับการทดลองในพื้นที่ คุณสามารถบังคับให้บิลด์บีบอัด APEX ได้โดยการตั้งค่า OVERRIDE_PRODUCT_COMPRESSED_APEX= ไปยัง true

ไฟล์ APEX ที่บีบอัดที่สร้างโดยระบบบิลด์จะมีส่วนขยาย .capex ส่วนขยายช่วยให้แยกความแตกต่างระหว่างแบบบีบอัดและไม่บีบอัดได้ง่ายขึ้น ของไฟล์ APEX ได้

อัลกอริทึมการบีบอัดที่รองรับ

Android 12 รองรับเฉพาะการบีบอัดแบบ Deflate-zip

เปิดใช้งานไฟล์ APEX ที่บีบอัดขณะเปิดเครื่อง

ก่อนที่จะเปิดใช้งาน APEX ที่บีบอัดได้ ไฟล์ original_apex ที่อยู่ภายใน คลายการบีบอัดลงในไดเรกทอรี /data/apex/decompressed ผลลัพธ์ที่ได้ ไฟล์ APEX ที่บีบอัดจะฮาร์ดลิงก์อยู่กับไดเรกทอรี /data/apex/active

พิจารณาตัวอย่างต่อไปนี้เพื่อภาพประกอบของกระบวนการที่อธิบายไว้ข้างต้น

ถือว่า /system/apex/com.android.foo.capex เป็น APEX ที่ถูกบีบอัด ด้วย versionCode 37

  1. ไฟล์ original_apex ภายใน /system/apex/com.android.foo.capex คือ คลายการบีบอัดเป็น /data/apex/decompressed/com.android.foo@37.apex
  2. ดำเนินการ restorecon /data/apex/decompressed/com.android.foo@37.apex เพื่อ ให้ยืนยันว่ามีป้ายกำกับ SELinux ที่ถูกต้อง
  3. ตรวจสอบการยืนยันใน /data/apex/decompressed/com.android.foo@37.apex เพื่อตรวจสอบความถูกต้อง: apexd ตรวจสอบคีย์สาธารณะที่รวมไว้ในกลุ่ม /data/apex/decompressed/com.android.foo@37.apexเพื่อยืนยันว่าค่าเท่ากัน กับชุดข้อมูลที่อยู่ใน /system/apex/com.android.foo.capex
  4. ไฟล์ /data/apex/decompressed/com.android.foo@37.apex ลิงก์ถาวรกับ ไดเรกทอรี /data/apex/active/com.android.foo@37.apex
  5. ตรรกะการเปิดใช้งานปกติสำหรับไฟล์ APEX ที่ไม่ได้บีบอัดจะดำเนินการใน /data/apex/active/com.android.foo@37.apex

การโต้ตอบกับ OTA

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

apexd จะแสดง Binder API ทั้ง 2 รายการต่อไปนี้เพื่อรองรับระบบ OTA

  • calculateSizeForCompressedApex - คำนวณขนาดที่ต้องใช้ในการขยาย ไฟล์ APEX ในแพ็กเกจ OTA ซึ่งใช้เพื่อยืนยันว่าอุปกรณ์มี เพียงพอก่อนที่จะดาวน์โหลด OTA
  • reserveSpaceForCompressedApex - จองพื้นที่ในดิสก์ไว้ใช้ในอนาคต โดย apexd สำหรับการขยายไฟล์ APEX ที่บีบอัดภายในแพ็กเกจ OTA

ในกรณีของการอัปเดต A/B OTA จะมี apexd พยายามคลายการบีบอัดใน เป็นส่วนหนึ่งของกิจวัตร OTA หลังการติดตั้ง หากยกเลิกการบีบอัดไม่สำเร็จ apexd ดำเนินการคลายการบีบอัดระหว่างเปิดเครื่องที่ใช้ OTA อัปเดต

ทางเลือกที่นำมาพิจารณาเมื่อพัฒนา APEX

ตัวเลือกบางส่วนที่ AOSP นำมาพิจารณาเมื่อออกแบบไฟล์ APEX มีดังนี้ รวมถึงเหตุผลที่รวมหรือยกเว้นไว้

ระบบการจัดการแพ็กเกจปกติ

รุ่น Linux มีระบบการจัดการแพ็กเกจ เช่น dpkg และ rpm ซึ่งทรงพลัง สมบูรณ์แบบ และคงทน แต่ไม่ได้หมายความว่า ใช้กับ APEX เพราะไม่สามารถปกป้องพัสดุได้หลังจาก ของคุณ การยืนยันจะดำเนินการเมื่อมีการติดตั้งแพ็กเกจเท่านั้น ผู้โจมตีอาจทำลายความสมบูรณ์ของแพ็กเกจที่ติดตั้งไว้โดยที่ไม่มีใครสังเกตเห็น นี่คือ การถดถอยสำหรับ Android ซึ่งเก็บคอมโพเนนต์ทั้งหมดของระบบไว้ในแบบอ่านอย่างเดียว ระบบไฟล์ซึ่งมีความสมบูรณ์ได้รับการปกป้องโดย dm-verity ใน I/O ทุกครั้ง ช่วง ห้ามมิให้มีการดัดแปลงส่วนประกอบของระบบหรือให้ตรวจพบได้ อุปกรณ์อาจปฏิเสธไม่ให้เปิดเครื่องได้หากถูกบุกรุก

dm-crypt สำหรับความสมบูรณ์

ไฟล์ในคอนเทนเนอร์ APEX มาจากพาร์ติชันในตัว (ตัวอย่างเช่น /system พาร์ติชัน) ที่มีการป้องกันด้วย dm-verity โดยที่การแก้ไข ไม่อนุญาตให้ใช้ไฟล์แม้ว่าจะต่อเชื่อมพาร์ติชันแล้วก็ตาม หากต้องการจัดเตรียม ความปลอดภัยระดับเดียวกับไฟล์ โดยไฟล์ทั้งหมดใน APEX จะเก็บอยู่ในไฟล์ อิมเมจระบบที่จับคู่กับแผนผังแฮชและข้อบ่งชี้ vbmeta ไม่มี dm-verity ซึ่ง APEX ในพาร์ติชัน /data มีช่องโหว่ที่ไม่ได้ตั้งใจ การเปลี่ยนแปลงที่เกิดขึ้นหลังจากได้รับการยืนยันและติดตั้งแล้ว

ที่จริงแล้ว พาร์ติชัน /data ยังได้รับการปกป้องโดยเลเยอร์การเข้ารหัสอีกด้วย เช่น dm-crypt แม้ว่าวิธีนี้จะช่วยป้องกันการปลอมแปลงได้ในระดับหนึ่ง จุดประสงค์หลักคือความเป็นส่วนตัว ไม่ใช่ความซื่อสัตย์ เมื่อผู้โจมตีได้รับสิทธิ์เข้าถึง /data จะไม่มีการป้องกันใดๆ เพิ่มเติม และนี่ก็เป็น การถดถอยเมื่อเทียบกับคอมโพเนนต์ทั้งหมดของระบบที่อยู่ในพาร์ติชัน /system แผนผังแฮชภายในไฟล์ APEX ร่วมกับ dm-verity ให้ ระดับการปกป้องเนื้อหาได้

เปลี่ยนเส้นทางจาก /system ไปยัง /apex

ไฟล์คอมโพเนนต์ของระบบที่รวมอยู่ใน APEX จะสามารถเข้าถึงได้ผ่านเส้นทางใหม่ เช่น /apex/<name>/lib/libfoo.so เมื่อไฟล์ดังกล่าวเป็นส่วนหนึ่งของ /system เข้าถึงได้โดยใช้เส้นทาง เช่น /system/lib/libfoo.so ต ของไฟล์ APEX (ไฟล์ APEX อื่นๆ หรือแพลตฟอร์ม) ต้องใช้ เส้นทาง คุณอาจต้องอัปเดตโค้ดที่มีอยู่เนื่องจากมีการเปลี่ยนเส้นทาง

แม้ว่าวิธีหนึ่งในการหลีกเลี่ยงการเปลี่ยนเส้นทางได้คือการซ้อนทับเนื้อหาของไฟล์ใน ทีม Android ตัดสินใจที่จะไม่วางซ้อนไฟล์ APEX ลงในพาร์ติชัน /system ในพาร์ติชัน /system เนื่องจากอาจส่งผลต่อประสิทธิภาพ จำนวนไฟล์ที่วางซ้อน (อาจวางซ้อนกัน) เพิ่มขึ้น

อีกตัวเลือกหนึ่งคือการลักลอบใช้ฟังก์ชันการเข้าถึงไฟล์ เช่น open, stat และ readlink เพื่อให้เส้นทางที่ขึ้นต้นด้วย /system ถูกเปลี่ยนเส้นทางไปยัง เส้นทางที่เกี่ยวข้องใน /apex ทีม Android ยกเลิกตัวเลือกนี้แล้ว เนื่องจากคุณจะไม่สามารถเปลี่ยนฟังก์ชันทั้งหมดที่ยอมรับเส้นทาง ตัวอย่างเช่น แอปบางแอปลิงก์ Bionic ในเชิงสถิติ ซึ่งจะใช้ฟังก์ชันต่างๆ ในกรณีดังกล่าว แอปเหล่านั้นจะไม่ถูกเปลี่ยนเส้นทาง