Android 11 เลิกรวมพาร์ติชัน product
ซึ่งทำให้
โดยไม่ขึ้นอยู่กับพาร์ติชัน system
และ vendor
ส่วนหนึ่งของการเปลี่ยนแปลงเหล่านี้
ตอนนี้คุณควบคุมการเข้าถึงของพาร์ติชัน product
สำหรับเนทีฟและ Java ได้แล้ว
อินเทอร์เฟซ (ซึ่งคล้ายกับวิธีบังคับใช้อินเทอร์เฟซสำหรับ vendor
)
พาร์ติชัน)
บังคับใช้อินเทอร์เฟซที่มาพร้อมเครื่อง
หากต้องการเปิดใช้การบังคับใช้อินเทอร์เฟซแบบเนทีฟ ให้ตั้งค่า PRODUCT_PRODUCT_VNDK_VERSION
เป็น current
(ระบบจะตั้งค่าเวอร์ชันเป็น current
โดยอัตโนมัติเมื่อระดับ Shipping 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 | ผลิตภัณฑ์ย่อยที่สร้างแล้ว | |
---|---|---|
ก่อนการบังคับใช้ | หลังบังคับใช้ | |
ค่าเริ่มต้น (ไม่มี) | core
(รวม /system , /system_ext และ
/product ) |
แกนกลางร่างกาย
(รวม /system และ /system_ext แต่ไม่รวม
/product ) |
system_ext_specific: true |
แกนกลาง | แกนกลาง |
product_specific: true |
แกนกลาง | ผลิตภัณฑ์ |
vendor: true |
ผู้จำหน่าย | ผู้จำหน่าย |
vendor_available: true |
แกนกลางร่างกาย ผู้ให้บริการ | หลัก, ผู้ให้บริการ |
product_available: true |
ไม่มี | core, product |
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 |
---|---|---|---|---|---|
Public 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 | กำหนดไฟล์ Make ของระบบของคุณเองซึ่งระบุแพ็กเกจสำหรับพาร์ติชัน system จากนั้นตั้งค่าการตรวจสอบข้อกำหนดของเส้นทางอาร์ติแฟกต์ใน device.mk (เพื่อป้องกันไม่ให้ติดตั้งโมดูลที่ไม่ใช่ระบบลงในพาร์ติชัน system ) |
ไม่ใช่ |
2 | ล้างรายการที่อนุญาต | ไม่ใช่ |
3 | บังคับใช้อินเทอร์เฟซแบบเนทีฟและระบุลิงก์รันไทม์ที่ไม่สำเร็จ (สามารถทํางานควบคู่กับการบังคับใช้ Java ได้) | Y |
4 | บังคับใช้อินเทอร์เฟซ Java และตรวจสอบลักษณะรันไทม์ (เรียกใช้ได้พร้อมกัน ด้วยการบังคับใช้แบบเนทีฟ) | Y |
5 | ตรวจสอบลักษณะการทํางานของรันไทม์ | Y |
6 | อัปเดต device.mk ให้มีการบังคับใช้อินเทอร์เฟซผลิตภัณฑ์ |
Y |
ขั้นตอนที่ 1: สร้างไฟล์ Make และเปิดใช้การตรวจสอบเส้นทางอาร์ติแฟกต์
ในขั้นตอนนี้ คุณจะต้องกำหนด system
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),)
ในไฟล์
device.mk
ให้รับค่ามาจากการแมปไฟล์ทั่วไปสำหรับพาร์ติชัน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
เองหรือในไฟล์ make ที่รวมไว้
การพยายามติดตั้งโมดูลไปยังเส้นทางที่ไม่อนุญาตจะทำให้บิลด์หยุดทำงาน หากต้องการแก้ไขการหยุดพัก ให้ทําอย่างใดอย่างหนึ่งต่อไปนี้
ตัวเลือกที่ 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
แสดงว่าไฟล์ make ไม่มีไฟล์ที่ต้องพึ่งพา (และไม่ได้บันทึกไว้เมื่อสร้าง) - ในการตรวจสอบจากระบบบิลด์ ให้เพิ่มไลบรารีที่จำเป็นลงใน
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 ที่มองเห็นได้ (ไม่ใช่แบบซ่อนอยู่) หรือหาวิธีอื่น ตัวอย่างข้อผิดพลาด
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