Android 11 แยกพาร์ติชัน product ออก ทำให้พาร์ติชันนี้ไม่ขึ้นอยู่กับพาร์ติชัน system และ vendor การเปลี่ยนแปลงเหล่านี้ทำให้คุณควบคุมการเข้าถึงอินเทอร์เฟซแบบเนทีฟและ Java ของพาร์ติชัน product ได้แล้ว (ซึ่งคล้ายกับวิธีที่การบังคับใช้อินเทอร์เฟซทำงานสำหรับพาร์ติชัน vendor)
บังคับใช้อินเทอร์เฟซแบบเนทีฟ
หากต้องการเปิดใช้การบังคับใช้อินเทอร์เฟซแบบเนทีฟ ให้ตั้งค่า PRODUCT_PRODUCT_VNDK_VERSION เป็น current (ระบบจะตั้งค่าเวอร์ชันเป็น current โดยอัตโนมัติเมื่อระดับ API ที่จัดส่งสำหรับเป้าหมายมากกว่า 29) การบังคับใช้จะอนุญาตให้ทำสิ่งต่อไปนี้
- โมดูลแบบเนทีฟในพาร์ติชัน
productลิงก์กับ- โมดูลอื่นๆ ในพาร์ติชัน
productที่มีไลบรารีแบบคงที่ ใช้ร่วมกัน หรือส่วนหัวแบบคงที่หรือแบบไดนามิก - ไลบรารี VNDK ในพาร์ติชัน
systemแบบไดนามิก
- โมดูลอื่นๆ ในพาร์ติชัน
- ไลบรารี JNI ใน APK ที่แยกออกในพาร์ติชัน
productลิงก์กับ ไลบรารีใน/product/libหรือ/product/lib64(นอกเหนือจาก ไลบรารี NDK)
การบังคับใช้ไม่อนุญาตให้ลิงก์อื่นๆ กับพาร์ติชันอื่นที่ไม่ใช่พาร์ติชัน product
การบังคับใช้ในเวลาบิลด์ (Android.bp)
ใน Android 11 โมดูลระบบสามารถสร้างรูปแบบรูปภาพผลิตภัณฑ์นอกเหนือจากรูปแบบรูปภาพหลักและของผู้จำหน่ายได้ เมื่อเปิดใช้การบังคับใช้อินเทอร์เฟซแบบเนทีฟ (PRODUCT_PRODUCT_VNDK_VERSION ตั้งค่าเป็น current)
โมดูลแบบเนทีฟในพาร์ติชัน
productจะอยู่ในรูปแบบผลิตภัณฑ์แทนที่จะอยู่ในรูปแบบหลักโมดูลที่มี
product_available: trueในไฟล์Android.bpจะพร้อมใช้งานสำหรับสินค้าย่อยไลบรารีหรือไบนารีที่ระบุ
product_specific: trueสามารถลิงก์กับไลบรารีอื่นๆ ที่ระบุproduct_specific: trueหรือproduct_available: trueในไฟล์Android.bpไลบรารี VNDK ต้องมี
product_available: trueในไฟล์Android.bpเพื่อให้ไบนารีproductลิงก์กับไลบรารี VNDK ได้
ตารางต่อไปนี้สรุปพร็อพเพอร์ตี้ Android.bp ที่ใช้สร้างรูปแบบรูปภาพ
| พร็อพเพอร์ตี้ใน Android.bp | รูปแบบที่สร้างขึ้น | |
|---|---|---|
| ก่อนการบังคับใช้ | หลังการบังคับใช้ | |
| default (none) | core
(รวม /system, /system_ext และ
/product) |
core
(รวม /system และ /system_ext แต่ไม่รวม
/product) |
system_ext_specific: true |
core | core |
product_specific: true |
core | product |
vendor: true |
vendor | vendor |
vendor_available: true |
core, vendor | core, vendor |
product_available: true |
ไม่มี | core, product |
vendor_available: true AND product_available:
true |
ไม่มี | core, product, vendor |
system_ext_specific: true AND vendor_available:
true |
core, vendor | core, vendor |
product_specific: true AND vendor_available:
true |
core, vendor | product, vendor |
การบังคับใช้ในเวลาบิลด์ (Android.mk)
เมื่อเปิดใช้การบังคับใช้อินเทอร์เฟซแบบเนทีฟ โมดูลแบบเนทีฟที่ติดตั้งในพาร์ติชัน
product จะมีประเภทลิงก์ native:product ซึ่งลิงก์ได้เฉพาะกับ
โมดูล native:product หรือ native:vndk อื่นๆ การพยายามลิงก์กับโมดูลอื่นที่ไม่ใช่โมดูลเหล่านี้จะทำให้ระบบบิวด์สร้างข้อผิดพลาดในการตรวจสอบประเภทลิงก์
การบังคับใช้รันไทม์
เมื่อเปิดใช้การบังคับใช้อินเทอร์เฟซแบบเนทีฟ การกำหนดค่า Linker สำหรับ Bionic Linker จะไม่อนุญาตให้กระบวนการของระบบใช้ไลบรารี product ซึ่งจะสร้างส่วน product สำหรับกระบวนการ product ที่ลิงก์กับไลบรารีภายนอกพาร์ติชัน product ไม่ได้ (อย่างไรก็ตาม กระบวนการดังกล่าวสามารถลิงก์กับไลบรารี VNDK ได้) การพยายามละเมิดการกำหนดค่าลิงก์รันไทม์จะทำให้กระบวนการล้มเหลวและสร้างข้อความแสดงข้อผิดพลาด CANNOT LINK EXECUTABLE
บังคับใช้อินเทอร์เฟซ Java
หากต้องการเปิดใช้การบังคับใช้อินเทอร์เฟซ Java ให้ตั้งค่า PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE เป็น true (ระบบจะตั้งค่าเป็น true โดยอัตโนมัติเมื่อระดับ API ที่จัดส่งสำหรับเป้าหมายมากกว่า 29) เมื่อเปิดใช้ การบังคับใช้จะอนุญาตหรือไม่อนุญาตการเข้าถึงต่อไปนี้
| API | /system | /system_ext | /product | /vendor | /data |
|---|---|---|---|---|---|
| API สาธารณะ | |||||
| @SystemApi | |||||
| @hide API |
เช่นเดียวกับในพาร์ติชัน vendor แอปหรือไลบรารี Java ในพาร์ติชัน product จะได้รับอนุญาตให้ใช้เฉพาะ API สาธารณะและ API ของระบบเท่านั้น และไม่อนุญาตให้ลิงก์กับไลบรารีที่ใช้ API ที่ซ่อนอยู่ ข้อจำกัดนี้รวมถึงการลิงก์ในเวลาที่บิวด์ใช้และการสะท้อนในรันไทม์
การบังคับใช้ในเวลาบิลด์
ในเวลาบิลด์ ใช้ Make และ Soong จะตรวจสอบว่าโมดูล Java ในพาร์ติชัน product ไม่ได้ใช้ API ที่ซ่อนอยู่โดยการตรวจสอบช่อง platform_apis และ sdk_version sdk_version ของแอปในพาร์ติชัน product ต้อง
กรอกเป็น current, system_current หรือเวอร์ชันตัวเลขของ API และ
ช่อง platform_apis ต้องว่างเปล่า
การบังคับใช้รันไทม์
รันไทม์ของ Android จะตรวจสอบว่าแอปในพาร์ติชัน product ไม่ได้ใช้ API ที่ซ่อนอยู่ ซึ่งรวมถึงการสะท้อน โปรดดูรายละเอียดที่ ข้อจำกัดเกี่ยวกับ
อินเทอร์เฟซที่ไม่ใช่ SDK
เปิดใช้การบังคับใช้อินเทอร์เฟซผลิตภัณฑ์
ใช้ขั้นตอนในส่วนนี้เพื่อเปิดใช้การบังคับใช้อินเทอร์เฟซผลิตภัณฑ์
| ขั้นตอน | งาน | ต้องระบุ |
|---|---|---|
| 1 | กำหนด Make ไฟล์ของระบบเองที่ระบุแพ็กเกจสำหรับพาร์ติชัน
system จากนั้นตั้งค่าการตรวจสอบข้อกำหนดเส้นทางอาร์ติแฟกต์
ใน device.mk (เพื่อป้องกันไม่ให้โมดูลที่ไม่ใช่ระบบติดตั้ง
ในพาร์ติชัน system) |
N |
| 2 | ล้างรายการที่อนุญาต | N |
| 3 | บังคับใช้อินเทอร์เฟซแบบเนทีฟและระบุความล้มเหลวของลิงก์รันไทม์ (สามารถทำงานแบบขนานกับการบังคับใช้ Java ได้) | Y |
| 4 | บังคับใช้อินเทอร์เฟซ Java และยืนยันลักษณะการทำงานของรันไทม์ (สามารถทำงานแบบขนาน กับการบังคับใช้แบบเนทีฟได้) | Y |
| 5 | ตรวจสอบลักษณะการทำงานของรันไทม์ | Y |
| 6 | อัปเดต device.mk ด้วยการบังคับใช้อินเทอร์เฟซผลิตภัณฑ์ |
Y |
ขั้นตอนที่ 1: สร้าง Make ไฟล์และเปิดใช้การตรวจสอบเส้นทางอาร์ติแฟกต์
ในขั้นตอนนี้ คุณจะได้กำหนด Make ไฟล์ของ system
สร้าง Make ไฟล์ที่กำหนดแพ็กเกจสำหรับพาร์ติชัน
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),)ในไฟล์
device.mkให้รับช่วง Make ไฟล์ทั่วไปสำหรับพาร์ติชัน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 ระบบบิลด์จะป้องกันไม่ให้แพ็กเกจที่กำหนดไว้ใน Make ไฟล์อื่นๆ ติดตั้งในเส้นทางที่กำหนดไว้ใน require-artifacts-in-path และ ป้องกันไม่ให้แพ็กเกจที่กำหนดไว้ใน Make ไฟล์ปัจจุบันติดตั้งอาร์ติแฟกต์นอกเส้นทางที่กำหนดไว้ใน require-artifacts-in-path
ในตัวอย่างด้านบน เมื่อตั้งค่า PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS เป็น
strict Make ไฟล์ภายนอก oem_system.mk จะรวมโมดูลที่ติดตั้งใน
พาร์ติชัน root หรือ system ไม่ได้ หากต้องการรวมโมดูลเหล่านี้ คุณต้องกำหนดโมดูลในไฟล์ oem_system.mk เองหรือใน Make ไฟล์ที่รวมไว้
การพยายามติดตั้งโมดูลในเส้นทางที่ไม่ได้รับอนุญาตจะทำให้บิวด์หยุดทำงาน หากต้องการแก้ไขการหยุดทำงาน ให้ทำอย่างใดอย่างหนึ่งต่อไปนี้
ตัวเลือกที่ 1: รวมโมดูลระบบใน Make ไฟล์ที่รวมอยู่ใน
oem_system.mkซึ่งจะทำให้เป็นไปตามข้อกำหนดเส้นทางอาร์ติแฟกต์ (เนื่องจากโมดูลอยู่ใน Make ไฟล์ที่รวมไว้แล้ว) และอนุญาตให้ติดตั้งในชุดเส้นทางใน `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 Make ไฟล์ ขั้นตอนนี้ไม่บังคับ เนื่องจากไม่จำเป็นต้องกำหนดรูปภาพ system ทั่วไปเพื่อเปิดใช้การบังคับใช้อินเทอร์เฟซผลิตภัณฑ์ อย่างไรก็ตาม การล้างรายการที่อนุญาตจะเป็นประโยชน์ในการกำหนดขอบเขต system ด้วย system_ext
ขั้นตอนที่ 3: บังคับใช้อินเทอร์เฟซแบบเนทีฟ
ในขั้นตอนนี้ ให้ตั้งค่า PRODUCT_PRODUCT_VNDK_VERSION := current จากนั้นมองหาข้อผิดพลาดในการบิลด์และรันไทม์ แล้วแก้ไขข้อผิดพลาดเหล่านั้น วิธีตรวจสอบการบูตและบันทึกของอุปกรณ์ รวมถึงค้นหาและแก้ไขความล้มเหลวของลิงก์รันไทม์
ตั้งค่า
PRODUCT_PRODUCT_VNDK_VERSION := currentบิวด์อุปกรณ์และมองหาข้อผิดพลาดในการบิวด์ คุณอาจเห็นการหยุดทำงานของบิลด์ 2-3 รายการสำหรับสินค้าย่อยของผลิตภัณฑ์หรือสินค้าย่อยหลักที่ขาดหายไป การหยุดทำงานที่พบบ่อย ได้แก่
- โมดูล
hidl_interfaceใดก็ตามที่มีproduct_specific: trueจะไม่พร้อมใช้งานสำหรับโมดูลระบบ หากต้องการแก้ไข ให้แทนที่product_specific: trueด้วยsystem_ext_specific: true - โมดูลอาจไม่มีสินค้าย่อยที่โมดูลผลิตภัณฑ์ต้องการ หากต้องการแก้ไข ให้ทำให้โมดูลนั้นพร้อมใช้งานสำหรับพาร์ติชัน
productโดย ตั้งค่าproduct_available: trueหรือย้ายโมดูลไปยังพาร์ติชันproductโดยตั้งค่าproduct_specific: true
- โมดูล
แก้ไขข้อผิดพลาดในการบิวด์และตรวจสอบว่าอุปกรณ์บิวด์สำเร็จ
แฟลชรูปภาพและมองหาข้อผิดพลาดรันไทม์ในการบูตและบันทึกของอุปกรณ์
- หากแท็ก
linkerจากบันทึกกรอบการทดสอบแสดงข้อความCANNOT LINK EXECUTABLEแสดงว่า Make ไฟล์ไม่มีทรัพยากร Dependency (และไม่ได้บันทึกไว้ในเวลาบิลด์) - หากต้องการตรวจสอบจากระบบบิวด์ ให้เพิ่มไลบรารีที่จำเป็นลงในช่อง
shared_libs:หรือrequired:
- หากแท็ก
แก้ไขการขึ้นต่อกันที่ขาดหายไปโดยใช้คำแนะนำที่ระบุไว้ข้างต้น
ขั้นตอนที่ 4: บังคับใช้อินเทอร์เฟซ Java
ในขั้นตอนนี้ ให้ตั้งค่า PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true จากนั้นค้นหาและแก้ไขข้อผิดพลาดในการบิลด์ที่เกิดขึ้น มองหาข้อผิดพลาด 2 ประเภทต่อไปนี้
ข้อผิดพลาดประเภทลิงก์ ข้อผิดพลาดนี้แสดงว่าแอปลิงก์กับโมดูล 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 ที่มองเห็นได้ (ไม่ซ่อนอยู่) หรือค้นหา 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 (ซึ่งจะสร้างบันทึกเมื่อแอปใช้ API ที่ซ่อนอยู่) หรือคุณจะใช้เครื่องมือวิเคราะห์แบบคงที่
veridex
เพื่อดูประเภทการใช้งาน (การลิงก์หรือการสะท้อน) ระดับข้อจำกัด และสแต็กการเรียกใช้
ไวยากรณ์ veridex
./art/tools/veridex/appcompat.sh --dex-file={apk file}ตัวอย่างผลลัพธ์ veridex
#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 tool
ขั้นตอนที่ 6: อัปเดต device.mk
หลังจากแก้ไขความล้มเหลวในการบิวด์และรันไทม์ทั้งหมดแล้ว และตรวจสอบว่าลักษณะการทำงานของรันไทม์เป็นไปตามที่คาดไว้ ให้ตั้งค่าต่อไปนี้ใน device.mk
PRODUCT_PRODUCT_VNDK_VERSION := currentPRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true