Android 11 เลิกรวมพาร์ติชัน product
ซึ่งทำให้
โดยไม่ขึ้นอยู่กับพาร์ติชัน system
และ vendor
ส่วนหนึ่งของการเปลี่ยนแปลงเหล่านี้
ตอนนี้คุณควบคุมการเข้าถึงของพาร์ติชัน product
สำหรับเนทีฟและ Java ได้แล้ว
อินเทอร์เฟซ (ซึ่งคล้ายกับวิธีบังคับใช้อินเทอร์เฟซสำหรับ 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 | สร้างตัวแปรแล้ว | |
---|---|---|
ก่อนบังคับใช้ | หลังบังคับใช้ | |
ค่าเริ่มต้น (ไม่มี) | แกนกลางร่างกาย
(รวม /system , /system_ext และ
/product ) |
แกนกลางร่างกาย
(รวม /system และ /system_ext แต่ไม่รวม
/product ) |
system_ext_specific: true |
แกนกลางร่างกาย | แกนกลางร่างกาย |
product_specific: true |
แกนกลางร่างกาย | ผลิตภัณฑ์ |
vendor: true |
ผู้จำหน่าย | ผู้จำหน่าย |
vendor_available: true |
หลัก, ผู้ให้บริการ | หลัก, ผู้ให้บริการ |
product_available: true |
ไม่มี | แกน, ผลิตภัณฑ์ |
vendor_available: true และ product_available:
true |
ไม่มี | หลัก, ผลิตภัณฑ์, ผู้ให้บริการ |
system_ext_specific: true และ vendor_available:
true |
หลัก, ผู้ให้บริการ | หลัก, ผู้ให้บริการ |
product_specific: true และ vendor_available:
true |
หลัก, ผู้ให้บริการ | ผลิตภัณฑ์, ผู้ให้บริการ |
การบังคับใช้เวลาของบิลด์ (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 สาธารณะ | |||||
@ระบบ API | |||||
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 | กำหนดไฟล์จำนวนมากของระบบของคุณเองซึ่งระบุแพ็กเกจสำหรับ
system พาร์ติชัน แล้วตั้งค่าการตรวจสอบข้อกำหนดของเส้นทางอาร์ติแฟกต์
ใน device.mk (เพื่อป้องกันการติดตั้งโมดูลที่ไม่ใช่ระบบ
ลงในพาร์ติชัน system ) |
ไม่ใช่ |
2 | ล้างรายการที่อนุญาต | ไม่ใช่ |
3 | บังคับใช้อินเทอร์เฟซที่มาพร้อมเครื่องและระบุความล้มเหลวของลิงก์รันไทม์ (ทำงานใน ควบคู่ไปกับการบังคับใช้ Java) | Y |
4 | บังคับใช้อินเทอร์เฟซ Java และตรวจสอบลักษณะรันไทม์ (เรียกใช้ได้พร้อมกัน ด้วยการบังคับใช้แบบดั้งเดิม) | Y |
5 | ตรวจสอบลักษณะการทำงานของรันไทม์ | Y |
6 | อัปเดต device.mk ให้มีการบังคับใช้อินเทอร์เฟซผลิตภัณฑ์ |
Y |
ขั้นตอนที่ 1: สร้าง Makefile และเปิดใช้การตรวจสอบเส้นทางอาร์ติแฟกต์
ในขั้นตอนนี้ คุณจะได้กำหนด Makefile ของ system
สร้าง โปรดตรวจสอบว่าแพ็กเกจสำหรับพาร์ติชัน
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
ให้รับค่า getfile ทั่วไปสำหรับ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
ระบบบิลด์จะป้องกันไม่ให้ติดตั้งแพ็กเกจที่กำหนดไว้ในไฟล์เครื่องสำอางอื่นๆ ลงใน
เส้นทางที่กำหนดไว้ใน require-artifacts-in-path
และ ป้องกันแพ็กเกจ
ที่กำหนดไว้ในไฟล์สร้างปัจจุบันจากการติดตั้งอาร์ติแฟกต์นอกเส้นทาง
กำหนดไว้ในrequire-artifacts-in-path
ในตัวอย่างด้านบน โดยมีการตั้งค่า PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
เป็น
strict
ทำให้ไฟล์นอก oem_system.mk
ไม่สามารถรวมโมดูลที่ติดตั้ง
พาร์ติชัน root
หรือ system
หากต้องการรวมโมดูลเหล่านี้ คุณต้อง
ให้กำหนดในไฟล์ oem_system.mk
เองหรือในไฟล์บิลด์ที่รวมไว้
การพยายามติดตั้งโมดูลไปยังเส้นทางที่ไม่อนุญาตจะทำให้บิลด์หยุดทำงาน วิธีแก้ไข
หยุดพัก ให้ทำอย่างใดอย่างหนึ่งต่อไปนี้
ตัวเลือกที่ 1: ใส่โมดูลระบบในไฟล์ยี่ห้อที่รวมไว้ใน
oem_system.mk
ซึ่งทำให้ระบบเป็นไปตามข้อกำหนดเส้นทางอาร์ติแฟกต์ (เนื่องจากพร็อพเพอร์ตี้ ขณะนี้มีโมดูลอยู่ในไฟล์ประเภทที่รวมไว้) จึงอนุญาตให้ติดตั้ง ชุดของเส้นทางใน "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
และดู
เพื่อหาข้อผิดพลาดของบิลด์และรันไทม์ แล้วทำการแก้ไข วิธีตรวจสอบการเปิดเครื่องและบันทึกของอุปกรณ์
และค้นหาและแก้ไขความล้มเหลวของลิงก์รันไทม์
ตั้งค่า
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
ไฟล์สร้างไม่มีการอ้างอิง (และไม่ได้บันทึกไว้ เวลาบิลด์) - ในการตรวจสอบจากระบบบิลด์ ให้เพิ่มไลบรารีที่จำเป็นลงใน
shared_libs:
หรือrequired:
- หากแท็ก
แก้ไขทรัพยากร Dependency ที่ขาดหายไปโดยใช้คำแนะนำที่ให้ไว้ด้านบน
ขั้นตอนที่ 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 ที่มองเห็นได้ (ไม่มีการซ่อน) หรือค้นหา ทางเลือก ตัวอย่างข้อผิดพลาด
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 เครื่องมือ
ขั้นตอนที่ 6: อัปเดต device.mk
หลังจากแก้ไขความล้มเหลวของบิลด์และรันไทม์ทั้งหมด และตรวจสอบแล้วว่ารันไทม์
ลักษณะการทำงานตามที่คาดไว้ ให้ตั้งค่าต่อไปนี้ใน device.mk
PRODUCT_PRODUCT_VNDK_VERSION := current
PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true