การบังคับใช้อินเทอร์เฟซพาร์ติชันผลิตภัณฑ์ Part

Android 11 unbundles product พาร์ทิชันที่ทำให้มันเป็นอิสระจาก system และ vendor พาร์ทิชัน ในฐานะที่เป็นส่วนหนึ่งของการเปลี่ยนแปลงเหล่านี้ตอนนี้คุณสามารถควบคุม product เข้าถึงพาร์ทิชันเพื่อการเชื่อมต่อพื้นเมืองและ Java (ซึ่งคล้ายกับวิธีการทำงานของการบังคับใช้อินเตอร์เฟซสำหรับ vendor พาร์ทิชัน)

การบังคับใช้อินเทอร์เฟซดั้งเดิม

เมื่อต้องการเปิดใช้การบังคับใช้อินเตอร์เฟซพื้นเมืองชุด PRODUCT_PRODUCT_VNDK_VERSION เพื่อ current (รุ่นที่มีการตั้งค่าโดยอัตโนมัติ current เมื่อระดับ API การจัดส่งสินค้าสำหรับเป้าหมายมากกว่า 29. ) การบังคับใช้จะช่วยให้:

  • โมดูลพื้นเมืองใน product พาร์ทิชันเพื่อการเชื่อมโยง:
    • แบบคงที่หรือแบบไดนามิกเพื่อโมดูลอื่น ๆ ใน product พาร์ทิชันที่มีคงที่ใช้ร่วมกันหรือห้องสมุดส่วนหัว
    • แบบไดนามิกห้องสมุด VNDK ใน system พาร์ทิชัน
  • ห้องสมุด JNI ใน APK ที่ unbundled ใน product พาร์ทิชันที่จะเชื่อมโยงไปยังห้องสมุดใน /product/lib หรือ /product/lib64 (นี่คือนอกเหนือไปจากห้องสมุด NDK)

การบังคับใช้กฎหมายไม่อนุญาตให้มีการเชื่อมโยงอื่น ๆ เพื่อพาร์ทิชันอื่น ๆ นอกเหนือจาก product พาร์ทิชัน

การบังคับใช้เวลาในการสร้าง (Android.bp)

ใน Android 11 โมดูลระบบสามารถสร้างตัวเลือกรูปภาพผลิตภัณฑ์เพิ่มเติมจากตัวเลือกรูปภาพหลักและตัวเลือกของผู้ขาย เมื่อการบังคับใช้อินเตอร์เฟซพื้นเมืองถูกเปิดใช้งาน ( PRODUCT_PRODUCT_VNDK_VERSION มีการตั้งค่า current ):

  • โมดูลพื้นเมืองใน product พาร์ทิชันที่อยู่ในตัวแปรสินค้าแทนตัวแปรหลัก

  • โมดูลกับ vendor_available: true ในของพวกเขา Android.bp ไฟล์ที่มีอยู่กับตัวแปรที่แตกต่างของผลิตภัณฑ์และผู้ขาย

  • ห้องสมุดหรือไบนารีที่ระบุ product_specific: true ลิงก์สามารถไปยังห้องสมุดอื่น ๆ ที่ระบุ product_specific: true หรือ vendor_available: true ในของพวกเขา Android.bp ไฟล์

  • ห้องสมุด VNDK ต้องมี vendor_available: true ในของพวกเขา Android.bp ไฟล์เพื่อให้ product ไบนารีสามารถเชื่อมโยงไป libs VNDK

ตารางต่อไปนี้สรุป Android.bp คุณสมบัติใช้ในการสร้างสายพันธุ์ภาพ

คุณสมบัติใน Android.bp สร้างตัวแปรแล้ว
ก่อนบังคับใช้ หลังบังคับใช้
ค่าเริ่มต้น (ไม่มี) แกน

(รวมถึง /system , /system_ext และ /product )

แกน

(รวมถึง /system และ /system_ext แต่ไม่ /product )

system_ext_specific: true แกน แกน
product_specific: true แกน ผลิตภัณฑ์
vendor: true ผู้ขาย ผู้ขาย
vendor_available: true แกนกลาง, ผู้ขาย หลัก ผลิตภัณฑ์ ผู้จำหน่าย
system_ext_specific: true และ vendor_available: true แกนกลาง, ผู้ขาย หลัก ผลิตภัณฑ์ ผู้จำหน่าย
product_specific: true และ vendor_available: true แกนกลาง, ผู้ขาย สินค้า ผู้ขาย

การบังคับใช้เวลาในการสร้าง (Android.mk)

เมื่อการบังคับใช้อินเตอร์เฟซพื้นเมืองถูกเปิดใช้งานโมดูลพื้นเมืองติดตั้งกับ product พาร์ทิชันที่มี native:product ประเภทการเชื่อมโยงที่สามารถเชื่อมโยงเท่านั้นที่จะอื่น ๆ native:product หรือ native:vndk โมดูล การพยายามลิงก์ไปยังโมดูลอื่นนอกเหนือจากนี้จะทำให้ระบบบิลด์สร้างข้อผิดพลาดในการตรวจสอบประเภทลิงก์

การบังคับใช้รันไทม์

เมื่อการบังคับใช้อินเตอร์เฟซพื้นเมืองถูกเปิดใช้งานการตั้งค่าสำหรับลิงเกอร์ลิงเกอร์ไบโอนิคไม่อนุญาตให้กระบวนการของระบบที่จะใช้ product ห้องสมุด, การสร้าง product ส่วนสำหรับ product กระบวนการที่ไม่สามารถเชื่อมโยงไปยังห้องสมุดนอก product พาร์ทิชัน ( แต่กระบวนการดังกล่าวสามารถ ลิงก์ไปยังไลบรารี VNDK) ความพยายามที่จะละเมิดการกำหนดค่าเชื่อมโยงรันไทม์สาเหตุกระบวนการที่จะล้มเหลวและสร้าง CANNOT LINK EXECUTABLE ข้อผิดพลาด

การบังคับใช้อินเตอร์เฟส Java

เมื่อต้องการเปิดใช้การบังคับใช้อินเตอร์เฟซ Java ชุด PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE ไป true (ค่าจะถูกกำหนดโดยอัตโนมัติเพื่อให้ true เมื่อระดับ API การจัดส่งสินค้าสำหรับเป้าหมายมากกว่า 29. ) เมื่อเปิดใช้งานบังคับใช้จะช่วยให้ / ไม่อนุญาตให้เข้าถึงต่อไปนี้

API /ระบบ /system_ext /ผลิตภัณฑ์ /ผู้ขาย /ข้อมูล
API สาธารณะ
@SystemApi
@ซ่อน API

ในขณะที่ vendor พาร์ทิชันแอปหรือห้องสมุด Java ใน product พาร์ทิชันที่ได้รับอนุญาตให้ใช้เฉพาะประชาชนและระบบ APIs; ไม่อนุญาตให้ลิงก์ไปยังไลบรารีที่ใช้ API ที่ซ่อนอยู่ ข้อจำกัดนี้รวมถึงการลิงก์ ณ เวลาสร้างและการสะท้อนในรันไทม์

สร้างการบังคับใช้เวลา

เวลาที่สร้าง, เป็น Soong และตรวจสอบว่าโมดูล Java ใน product พาร์ทิชันไม่ใช้ API ซ่อนโดยการตรวจสอบ platform_apis และ sdk_version สาขา sdk_version ปพลิเคชันใน product พาร์ทิชันต้องเต็มไปด้วย current , system_current หรือรุ่นที่เป็นตัวเลขของ API และ platform_apis ฟิลด์ต้องว่างเปล่า

การบังคับใช้รันไทม์

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

การเปิดใช้งานการบังคับใช้ส่วนต่อประสานผลิตภัณฑ์

ใช้ขั้นตอนในหัวข้อนี้เพื่อเปิดใช้งานการบังคับใช้ส่วนต่อประสานผลิตภัณฑ์

ขั้นตอน งาน ที่จำเป็น
1 กำหนด Makefile ระบบของคุณเองที่ระบุแพคเกจสำหรับ system พาร์ทิชันจากนั้นตั้งค่าการตรวจสอบความต้องการของเส้นทางสิ่งประดิษฐ์ใน device.mk (เพื่อป้องกันโมดูล nonsystem จากการติดตั้งกับ system พาร์ทิชัน) NS
2 ล้างรายการที่อนุญาต NS
3 บังคับใช้อินเทอร์เฟซดั้งเดิมและระบุความล้มเหลวของลิงก์รันไทม์ (สามารถทำงานควบคู่ไปกับบังคับใช้ Java) Y
4 บังคับใช้ส่วนต่อประสาน Java และตรวจสอบพฤติกรรมรันไทม์ (สามารถทำงานควบคู่กับการบังคับใช้ดั้งเดิม) Y
5 ตรวจสอบพฤติกรรมรันไทม์ Y
6 ปรับปรุง device.mk กับการบังคับใช้อินเตอร์เฟซสินค้า Y

ขั้นตอนที่ 1: สร้าง makefile และเปิดใช้งานการตรวจสอบเส้นทางของสิ่งประดิษฐ์

ในขั้นตอนนี้คุณสามารถกำหนด system Makefile

  1. สร้าง Makefile แพคเกจที่กำหนดสำหรับการที่ system พาร์ทิชัน ยกตัวอย่างเช่นการสร้าง oem_system.mk ไฟล์ที่มีต่อไปนี้:

    $(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk)
    $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk)
    
    # Applications
    PRODUCT_PACKAGES += \
        CommonSystemApp1 \
        CommonSystemApp2 \
        CommonSystemApp3 \
    
    # Binaries
    PRODUCT_PACKAGES += \
        CommonSystemBin1 \
        CommonSystemBin2 \
        CommonSystemBin3 \
    
    # Libraries
    PRODUCT_PACKAGES += \
        CommonSystemLib1 \
        CommonSystemLib2 \
        CommonSystemLib3 \
    
    PRODUCT_SYSTEM_NAME := oem_system
    PRODUCT_SYSTEM_BRAND := Android
    PRODUCT_SYSTEM_MANUFACTURER := Android
    PRODUCT_SYSTEM_MODEL := oem_system
    PRODUCT_SYSTEM_DEVICE := generic
    
    # For system-as-root devices, system.img should be mounted at /, so we
    # include ROOT here.
    _my_paths := \
     $(TARGET_COPY_OUT_ROOT)/ \
     $(TARGET_COPY_OUT_SYSTEM)/ \
    
    $(call require-artifacts-in-path, $(_my_paths),)
    
  2. ใน device.mk ไฟล์สืบทอด Makefile ทั่วไปสำหรับ system พาร์ทิชันและเปิดใช้งานการตรวจสอบความต้องการของเส้นทางสิ่งประดิษฐ์ ตัวอย่างเช่น:

    $(call inherit-product, $(SRC_TARGET_DIR)/product/oem_system.mk)
    
    # Enable artifact path requirements checking
    PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := strict
    

เกี่ยวกับข้อกำหนดเส้นทางสิ่งประดิษฐ์

เมื่อ PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS ถูกตั้งค่าเป็น true หรือ strict แพคเกจการป้องกันการสร้างระบบที่กำหนดไว้ใน makefiles อื่น ๆ จากการติดตั้งเพื่อเส้นทางที่กำหนดไว้ใน require-artifacts-in-path และป้องกันไม่ให้แพคเกจที่กำหนดไว้ใน Makefile ปัจจุบันจากการติดตั้งสิ่งประดิษฐ์นอกเส้นทางที่กำหนดไว้ใน require-artifacts-in-path

ในตัวอย่างข้างต้นด้วย PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS ตั้งค่าให้ strict , Makefiles นอก oem_system.mk ไม่สามารถรวมโมดูลการติดตั้งไปยัง root หรือ system พาร์ทิชัน จะรวมถึงโมดูลเหล่านี้คุณอาจจะต้องกำหนดไว้ใน oem_system.mk ไฟล์ตัวเองหรือใน Makefile รวม ความพยายามที่จะติดตั้งโมดูลไปยังพาธที่ไม่อนุญาตทำให้เกิดการหยุดบิลด์ ในการแก้ไขช่วงพัก ให้ทำอย่างใดอย่างหนึ่งต่อไปนี้:

  • ตัวเลือกที่ 1: รวมโมดูลของระบบใน makefiles ที่รวมอยู่ใน oem_system.mk สิ่งนี้ทำให้ตรงตามข้อกำหนดของเส้นทางสิ่งประดิษฐ์ (เนื่องจากขณะนี้โมดูลมีอยู่ใน makefile ที่รวมอยู่) และอนุญาตให้ติดตั้งชุดของพาธใน `require-artifacts-in-path

  • ตัวเลือกที่ 2: การติดตั้งโมดูลไป system_ext หรือ product พาร์ทิชัน (และไม่ได้ติดตั้งโมดูลไปยัง system พาร์ทิชัน)

  • ตัวเลือกที่ 3: เพิ่มโมดูลไป PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST รายการนี้แสดงรายการโมดูลที่อนุญาตให้ติดตั้งได้

ขั้นตอนที่ 2: ล้างรายการที่อนุญาต

ในขั้นตอนนี้ให้คุณ PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST ว่างเพื่อให้อุปกรณ์ทั้งหมดที่ใช้ oem_system.mk ยังสามารถแบ่งปันเดียว system ภาพ การลบรายชื่อที่ได้รับอนุญาตให้ย้ายโมดูลใด ๆ ในรายการที่จะ system_ext หรือ product พาร์ทิชันหรือเพิ่มไปยัง system ไฟล์แต่งหน้า ขั้นตอนนี้เป็นตัวเลือกเพราะการกำหนดร่วมกัน system ภาพไม่จำเป็นต้องเปิดการใช้งานอินเตอร์เฟซการบังคับใช้สินค้า แต่ล้างรายการได้รับอนุญาตให้เป็นประโยชน์สำหรับการกำหนด system เขตแดนกับ system_ext

ขั้นตอนที่ 3: บังคับใช้อินเทอร์เฟซดั้งเดิม

ในขั้นตอนนี้คุณตั้ง PRODUCT_PRODUCT_VNDK_VERSION := current แล้วมองหาการสร้างและรันไทม์ข้อผิดพลาดและแก้ไขปัญหา วิธีตรวจสอบการบู๊ตอุปกรณ์และบันทึก รวมถึงค้นหาและแก้ไขความล้มเหลวของลิงก์รันไทม์:

  1. ชุด PRODUCT_PRODUCT_VNDK_VERSION := current

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

    • ใด ๆ hidl_interface โมดูลที่มี product_specific: true จะไม่สามารถใช้ได้สำหรับโมดูลระบบ ในการแก้ไขปัญหาแทนที่ product_specific: true ด้วย system_ext_specfic: true
    • โมดูลอาจไม่มีตัวเลือกสินค้าที่จำเป็นสำหรับโมดูลผลิตภัณฑ์ ในการแก้ไขปัญหาให้โมดูลที่สามารถใช้ได้กับ product พาร์ทิชันโดยการตั้งค่า vendor_available: true หรือย้ายโมดูลไปยัง product พาร์ทิชันโดยการตั้งค่า product_specific: true
  3. แก้ไขข้อผิดพลาดของบิลด์และตรวจสอบให้แน่ใจว่าสร้างอุปกรณ์ได้สำเร็จ

  4. แฟลชอิมเมจและมองหาข้อผิดพลาดรันไทม์ในการบู๊ตอุปกรณ์และบันทึก

    • ถ้า linker แท็กจากบันทึกกรณีทดสอบแสดงให้เห็นว่า CANNOT LINK EXECUTABLE ข้อความทำให้ไฟล์จะหายไปพึ่งพา (และยังไม่ถูกจับเวลาที่สร้าง)
    • ในการตรวจสอบได้จากการสร้างระบบเพิ่มห้องสมุดต้องไป shared_libs: หรือ required: ฟิลด์
  5. แก้ไขการพึ่งพาที่ขาดหายไปโดยใช้คำแนะนำที่ให้ไว้ด้านบน

ขั้นตอนที่ 4: บังคับใช้อินเทอร์เฟซ Java

ในขั้นตอนนี้คุณตั้ง PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true แล้วค้นหาและแก้ไขข้อผิดพลาดในการสร้างผล ค้นหาข้อผิดพลาดเฉพาะสองประเภท:

  • ข้อผิดพลาดประเภทลิงก์ ข้อผิดพลาดนี้แสดงให้เห็นว่าแอปเชื่อมโยงไปยังโมดูล Java ที่มีความกว้าง sdk_version ในการแก้ไขปัญหาคุณสามารถขยายแอป sdk_version หรือ จำกัด ห้องสมุด sdk_version ตัวอย่างข้อผิดพลาด:

    error: frameworks/base/packages/SystemUI/Android.bp:138:1: module "SystemUI" variant "android_common": compiles against system API, but dependency "telephony-common" is compiling against private API.Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.
    
  • ข้อผิดพลาดของสัญลักษณ์ ข้อผิดพลาดนี้บ่งชี้ว่าไม่พบสัญลักษณ์เนื่องจากอยู่ใน API ที่ซ่อนอยู่ หากต้องการแก้ไข ให้ใช้ API ที่มองเห็นได้ (ไม่ซ่อน) หรือค้นหาทางเลือกอื่น ตัวอย่างข้อผิดพลาด:

    frameworks/opt/net/voip/src/java/com/android/server/sip/SipSessionGroup.java:1051: error: cannot find symbol
                ProxyAuthenticate proxyAuth = (ProxyAuthenticate)response.getHeader(
                                               ^
      symbol:   class ProxyAuthenticate
      location: class SipSessionGroup.SipSessionImpl
    

ขั้นตอนที่ 5: ตรวจสอบพฤติกรรมรันไทม์

ในขั้นตอนนี้ คุณตรวจสอบการทำงานของรันไทม์ตามที่คาดไว้ สำหรับปพลิเคชันที่มีแก้ปัญหาได้คุณสามารถตรวจสอบการใช้งาน API ซ่อนไว้โดยการเข้าสู่ระบบโดยใช้ StrictMode.detectNonSdkApiUsage (ซึ่งจะสร้างบันทึกเมื่อ app ใช้ API ที่ซ่อนไว้) หรือคุณสามารถใช้ veridex เครื่องมือในการวิเคราะห์แบบคงที่จะได้รับประเภทของการใช้งาน (การเชื่อมโยงหรือสะท้อน) ระดับข้อ จำกัด และเรียกกอง

  • ไวยากรณ์ Veridex:

    ./art/tools/veridex/appcompat.sh --dex-file={apk file}
    
  • ตัวอย่างผลการตรวจสอบ:

    #1: Linking greylist-max-o Landroid/animation/AnimationHandler;-><init>()V use(s):
           Lcom/android/systemui/pip/phone/PipMotionHelper;-><init>(Landroid/content/Context;Landroid/app/IActivityManager;Landroid/app/IActivityTaskManager;Lcom/android/systemui/pip/phone/PipMenuActivityController;Lcom/android/internal/policy/PipSnapAlgorithm;Lcom/android/systemui/statusbar/FlingAnimationUtils;)V
    
    #1332: Reflection greylist Landroid/app/Activity;->mMainThread use(s):
           Landroidx/core/app/ActivityRecreator;->getMainThreadField()Ljava/lang/reflect/Field;
    

สำหรับรายละเอียดเกี่ยวกับการใช้ veridex โปรดดูที่ การทดสอบโดยใช้เครื่องมือ veridex

ขั้นตอนที่ 6: อัปเดต device.mk

หลังจากแก้ไขทั้งหมดสร้างและรันไทม์ความล้มเหลวและการตรวจสอบว่าพฤติกรรม runtime จะไม่เป็นไปตามคาดตั้งต่อไปนี้ใน device.mk :

  • PRODUCT_PRODUCT_VNDK_VERSION := current
  • PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true