ในอดีต Android รองรับเฉพาะหน้าหน่วยความจำขนาด 4 KB ซึ่งได้ เพิ่มประสิทธิภาพหน่วยความจำของระบบสำหรับปริมาณหน่วยความจำทั้งหมดโดยเฉลี่ยที่ อุปกรณ์ Android มักจะมี ตั้งแต่ Android 15 เป็นต้นไป AOSP จะรองรับ อุปกรณ์ที่กำหนดค่าให้ใช้หน้าขนาด 16 KB (อุปกรณ์ 16 KB) หากแอปใช้ไลบรารี NDK ไม่ว่าจะโดยตรงหรือโดยอ้อมผ่าน SDK คุณจะต้องสร้างแอปใหม่เพื่อให้ทำงานในอุปกรณ์ที่มีขนาด 16 KB เหล่านี้ได้
เนื่องจากผู้ผลิตอุปกรณ์ยังคงสร้างอุปกรณ์ที่มีหน่วยความจำจริง (RAM) มากขึ้น อุปกรณ์จำนวนมากเหล่านี้จะใช้ขนาดหน้า 16 KB (และในที่สุดก็จะใหญ่ขึ้น) เพื่อเพิ่มประสิทธิภาพของอุปกรณ์ การเพิ่มการรองรับอุปกรณ์ที่มีขนาดหน้า 16 KB จะช่วยให้แอปของคุณทำงานบนอุปกรณ์เหล่านี้ได้ และช่วยให้แอปได้รับประโยชน์จากการปรับปรุงประสิทธิภาพที่เกี่ยวข้อง หากไม่มีการคอมไพล์ใหม่ แอปจะใช้ไม่ได้ในอุปกรณ์แบบ 16 KB ใน Android รุ่นต่อๆ ไป
เราได้ให้คำแนะนำเกี่ยวกับวิธีตรวจสอบว่าแอปได้รับผลกระทบหรือไม่ วิธีสร้างแอปใหม่ (หากมี) และวิธีทดสอบแอปในสภาพแวดล้อมแบบ 16 KB โดยใช้โปรแกรมจำลอง (รวมถึงอิมเมจระบบ Android 15 สำหรับ Android Emulator) เพื่อช่วยให้คุณเพิ่มการรองรับแอปได้
ข้อกำหนดด้านความเข้ากันได้ของ Google Play
เพื่อให้มั่นใจว่าแอปของคุณจะทำงานได้อย่างถูกต้องใน Android เวอร์ชันล่าสุด แอปทั้งหมดที่กำหนดเป้าหมายเป็น Android 15 (ระดับ API 35) ขึ้นไปต้องรองรับหน้าหน่วยความจำขนาด 16 KB ในอุปกรณ์ 64 บิตบน Google Play ตั้งแต่วันที่ 1 กุมภาพันธ์ 2027 เป็นต้นไป หากการอัปเดตแอปของคุณไม่รองรับหน้าหน่วยความจำขนาด 16 KB คุณจะเผยแพร่การอัปเดตเหล่านี้ไม่ได้
ประโยชน์และประสิทธิภาพที่เพิ่มขึ้น
อุปกรณ์ที่กำหนดค่าหน้าเว็บขนาด 16 KB จะใช้หน่วยความจำโดยเฉลี่ยมากกว่าเล็กน้อย แต่ปรับปรุงประสิทธิภาพการทำงานได้หลากหลายสำหรับทั้งระบบและแอป ดังนี้
- เวลาเปิดแอปลดลงขณะที่ระบบมีภาระเกี่ยวกับหน่วยความจำ: ลดลงโดยเฉลี่ย 3.16% โดยการปรับปรุงที่เห็นได้ชัดมากขึ้น (สูงสุด 30%) สำหรับบางแอปที่เราทดสอบ
- การลดพลังงานในระหว่างการเปิดแอป: ลดลง 4.56% โดยเฉลี่ย
- การเปิดตัวกล้องเร็วขึ้น: Hot Start เร็วขึ้น 4.48% โดยเฉลี่ย และ Cold Start เร็วขึ้น 6.60% โดยเฉลี่ย
- ปรับปรุงเวลาในการบูตระบบ: เร็วขึ้น 8% (ประมาณ 950 มิลลิวินาที) โดยเฉลี่ย
การปรับปรุงเหล่านี้อิงตามการทดสอบขั้นต้นของเรา และผลลัพธ์ในอุปกรณ์จริงอาจแตกต่างกัน เราจะให้การวิเคราะห์เพิ่มเติมเกี่ยวกับโอกาสในการได้ผู้ใช้ใหม่สำหรับแอปขณะที่เราทำการทดสอบต่อไป
ตรวจสอบว่าแอปของคุณได้รับผลกระทบหรือไม่
หากแอปใช้โค้ดเนทีฟ คุณควรสร้างแอปใหม่ ให้รองรับอุปกรณ์ขนาด 16 KB หากไม่แน่ใจว่าแอปใช้โค้ดเนทีฟหรือไม่ คุณสามารถใช้ APK Analyzer เพื่อระบุว่ามีโค้ดเนทีฟหรือไม่ จากนั้นตรวจสอบการจัดแนวของส่วน ELF สำหรับไลบรารีที่ใช้ร่วมกันที่คุณพบ Android Studio ยังมีฟีเจอร์ที่จะช่วยให้คุณตรวจหาปัญหาการจัดแนวโดยอัตโนมัติได้ด้วย
หากแอปใช้เฉพาะโค้ดที่เขียนในภาษาโปรแกรม Java หรือ Kotlin ซึ่งรวมถึงไลบรารีหรือ SDK ทั้งหมด แสดงว่าแอปของคุณรองรับอุปกรณ์ขนาด 16 KB อยู่แล้ว อย่างไรก็ตาม เราขอแนะนำให้คุณทดสอบแอปในสภาพแวดล้อมแบบ 16 KB เพื่อยืนยันว่าไม่มีการถดถอยที่ไม่คาดคิดในลักษณะการทำงานของแอป
แอปของคุณใช้โค้ดแบบเนทีฟหรือไม่
แอปของคุณใช้โค้ดแบบเนทีฟหากตรงกับข้อใดข้อหนึ่งต่อไปนี้
- แอปของคุณใช้โค้ด C/C++ (เนทีฟ) หากแอปใช้ Android NDK แสดงว่าแอปใช้โค้ดแบบเนทีฟ
- แอปของคุณลิงก์กับไลบรารีแบบเนทีฟหรือทรัพยากร Dependency ของบุคคลที่สาม (เช่น SDK) ที่ใช้ไลบรารีหรือทรัพยากร Dependency ดังกล่าว
- แอปของคุณสร้างโดยเครื่องมือสร้างแอปของบุคคลที่สามที่ใช้ไลบรารีแบบเนทีฟในอุปกรณ์
ระบุไลบรารีแบบเนทีฟโดยใช้ตัววิเคราะห์ APK
ตัววิเคราะห์ APK เป็นเครื่องมือที่ช่วยให้คุณประเมินแง่มุมต่างๆ ของ APK ที่สร้างขึ้นได้ วิธีตรวจสอบว่าแอปของคุณใช้โค้ดแบบเนทีฟหรือไม่ (ไม่ว่าจะรองรับขนาดหน้า 16 KB หรือไม่ก็ตาม)
- เปิด Android Studio แล้วคลิกไฟล์ > เปิด แล้วเลือกโปรเจ็กต์ใดก็ได้
จากแถบเมนู ให้คลิก Build > Analyze APK...
เลือก APK ที่ต้องการวิเคราะห์
ดูในโฟลเดอร์
libซึ่งโฮสต์ไฟล์ออบเจ็กต์ที่แชร์ (.so) หากมี หากมีไฟล์ออบเจ็กต์ที่แชร์อยู่ แสดงว่าแอปใช้โค้ดแบบเนทีฟ คอลัมน์การจัดแนวจะแสดงข้อความเตือนสำหรับไฟล์ที่มีปัญหาเกี่ยวกับการจัดแนว หากไม่มีไฟล์ออบเจ็กต์ที่ใช้ร่วมกันหรือไม่มีโฟลเดอร์libแสดงว่าแอปไม่ได้ใช้โค้ดแบบเนทีฟ
ตรวจหาปัญหาการจัดแนวด้วยการตรวจสอบอัตโนมัติ
Android Studio จะเตือนคุณล่วงหน้าหากไลบรารีหรือ APK ที่สร้างไว้ล่วงหน้าไม่เป็นไปตามข้อกำหนด 16 KB ใช้เครื่องมือตัววิเคราะห์ APK เพื่อตรวจสอบว่าไลบรารีใดที่ต้องอัปเดตหรือต้องทำการเปลี่ยนแปลงโค้ดหรือไม่
Lint ใน Android Studio ยังไฮไลต์ไลบรารีแบบเนทีฟที่ไม่ได้จัดเรียงตามรูปแบบความจำขนาด 16 KB ด้วย
ตรวจสอบการจัดเรียงของกลุ่ม ELF สำหรับไลบรารีที่ใช้ร่วมกัน
สำหรับคลังที่ใช้ร่วมกัน ให้ตรวจสอบว่ากลุ่ม ELF ของคลังที่ใช้ร่วมกันได้รับการจัดวางอย่างเหมาะสมโดยใช้การจัดวาง ELF ขนาด 16 KB
ใช้ตัววิเคราะห์ APK (แนะนำ)
วิธีที่ง่ายที่สุดในการยืนยันการจัดแนวคลังที่ใช้ร่วมกันคือใช้ตัววิเคราะห์ APK ใน Android Studio หากไฟล์ออบเจ็กต์ที่แชร์ไม่ได้จัดแนว 16 KB คอลัมน์การจัดแนวจะแสดงข้อความเตือน
ใช้สคริปต์ check_elf_alignment.sh (Linux หรือ macOS)
หากคุณกำลังพัฒนาบน Linux หรือ macOS และต้องการใช้สคริปต์ คุณสามารถใช้สคริปต์ check_elf_alignment.sh ได้ดังนี้
บันทึกสคริปต์
check_elf_alignment.shลงในไฟล์เรียกใช้สคริปต์ในไฟล์ APK ของแอปโดยทำดังนี้
check_elf_alignment.sh APK_NAME.apkสคริปต์จะแสดงผล
ALIGNEDหรือUNALIGNEDสำหรับคลังที่ใช้ร่วมกันarm64-v8aทั้งหมดหากไลบรารีที่ใช้ร่วมกัน
arm64-v8aหรือx86_64มีUNALIGNEDคุณจะต้องอัปเดตแพ็กเกจสำหรับไลบรารีเหล่านั้น จากนั้นคอมไพล์แอปใหม่และทดสอบอีกครั้งโดยทำตามขั้นตอนในส่วนนี้
ใช้เครื่องมือบรรทัดคำสั่งโดยตรง
ทำตามขั้นตอนต่อไปนี้เพื่อตรวจสอบการจัดแนวของเซกเมนต์ ELF โดยใช้เครื่องมือบรรทัดคำสั่งโดยตรง
- ตรวจสอบว่าได้ติดตั้งเครื่องมือสร้าง Android SDK เวอร์ชัน 35.0.0 ขึ้นไปและ Android NDK โดยใช้เครื่องมือจัดการ SDK ใน Android Studio หรือเครื่องมือบรรทัดคำสั่ง
sdkmanager แตกไฟล์ APK ของแอปโดยทำดังนี้
Linux หรือ macOS
unzip APK_NAME.apk -d /tmp/my_apk_outWindows (PowerShell)
Expand-Archive -Path .\APK_NAME.apk -DestinationPath ~\tmp\my_apk_outในไดเรกทอรีชั่วคราวที่คุณแตกไฟล์ APK ให้ตรวจสอบเนื้อหาของไดเรกทอรี
libเพื่อหาไฟล์ออบเจ็กต์ที่แชร์ (.so) ไฟล์เหล่านี้เป็นไฟล์ออบเจ็กต์ที่ใช้ร่วมกันแบบเดียวกับที่คุณเห็นขณะระบุไลบรารีแบบเนทีฟโดยใช้ตัววิเคราะห์ APK เรียกใช้คำสั่งต่อไปนี้ในไฟล์ออบเจ็กต์ที่ใช้ร่วมกันแต่ละไฟล์Linux หรือ macOS
SDK_ROOT_LOCATION/Android/sdk/ndk/NDK_VERSION/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump -p SHARED_OBJECT_FILE.so | grep LOADWindows (PowerShell)
SDK_ROOT_LOCATION\Android\sdk\ndk\NDK_VERSION\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-objdump.exe -p SHARED_OBJECT_FILE.so | Select-String -Pattern "LOAD"โดย
SDK_ROOT_LOCATIONคือเส้นทางไปยังไดเรกทอรีที่คุณติดตั้ง Android SDK,SHARED_OBJECT_FILEคือชื่อไฟล์ออบเจ็กต์ที่ใช้ร่วมกันที่คุณกำลังตรวจสอบ และNDK_VERSIONคือเวอร์ชันของ Android NDK ที่คุณติดตั้ง (เช่น28.0.12433566) ผลลัพธ์จะมีลักษณะดังต่อไปนี้สำหรับแต่ละไฟล์ที่คุณตรวจสอบLOAD off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**14 LOAD off 0x0000000000042a90 vaddr 0x0000000000043a90 paddr 0x0000000000043a90 align 2**14 LOAD off 0x0000000000046230 vaddr 0x0000000000048230 paddr 0x0000000000048230 align 2**14ตรวจสอบบรรทัดเอาต์พุตเพื่อให้แน่ใจว่ากลุ่มการโหลดไม่มีค่าต่ำกว่า
2**14หากเซกเมนต์การโหลดมีค่าเป็น2**13,2**12หรือต่ำกว่า คุณจะต้องอัปเดตแพ็กเกจสำหรับไลบรารีเหล่านั้น จากนั้นคอมไพล์แอปใหม่และทดสอบอีกครั้งโดยทำตามขั้นตอนในส่วนนี้ถัดไป ให้เรียกใช้เครื่องมือบรรทัดคำสั่ง
zipalignในไฟล์ APK ของแอปLinux หรือ macOS
SDK_ROOT_LOCATION/Android/sdk/build-tools/35.0.0/zipalign -v -c -P 16 4 APK_NAME.apkWindows (PowerShell)
SDK_ROOT_LOCATION\Android\sdk\build-tools\35.0.0\zipalign.exe -v -c -P 16 4 APK_NAME.apkโดย
SDK_ROOT_LOCATIONคือเส้นทางไปยังไดเรกทอรีที่คุณติดตั้ง Android SDK และAPK_NAMEคือชื่อไฟล์ APK ของแอป บรรทัดสุดท้ายของเอาต์พุตจะระบุว่า "Verification successful" หากคลังที่ใช้ร่วมกันทั้งหมดสอดคล้องกันอย่างถูกต้องหากการยืนยันไม่สำเร็จ คุณจะต้องปรับไลบรารีที่ใช้ร่วมกันบางรายการให้สอดคล้องกัน ดังนั้นคุณจะต้องอัปเดตแพ็กเกจสำหรับไลบรารีเหล่านั้น จากนั้นคอมไพล์แอปอีกครั้งและทดสอบอีกครั้งโดยทำตามขั้นตอนในส่วนนี้
ตรวจสอบแฟล็กความปลอดภัยของ RELRO
เพื่อลดการใช้ประโยชน์จากช่องโหว่ด้านความปลอดภัย Linker สมัยใหม่จะใช้แฟล็ก Relocation Read-Only (RELRO) เพื่อทำให้ส่วนเป้าหมายการย้ายตำแหน่ง (เช่น .got และ .data.rel.ro) ของไฟล์ออบเจ็กต์ที่แชร์เป็นแบบอ่านอย่างเดียวหลังจากการย้ายตำแหน่งแบบไดนามิกเสร็จสมบูรณ์
เปิดใช้แฟล็ก RELRO ในบิลด์
เมื่อ GNU_RELRO แชร์กลุ่ม LOAD ที่เขียนได้กับข้อมูลที่เขียนได้ที่ตามมา (เช่น .data หรือ .bss) ที่อยู่สิ้นสุดของกลุ่ม GNU_RELRO (VirtAddr + MemSiz) ต้องจัดแนว 16 KB (0x4000) มิฉะนั้น เมื่อ Android Linker ทำเครื่องหมายหน้าขนาด 16 KB ที่มีส่วนท้ายของ GNU_RELRO เป็นแบบอ่านอย่างเดียว ข้อมูลที่เขียนได้ที่อยู่ติดกันซึ่งอยู่ในส่วนที่เหลือของหน้าขนาด 16 KB เดียวกันนั้นจะกลายเป็นแบบอ่านอย่างเดียวด้วย ซึ่งจะทำให้แอปขัดข้องขณะรันไทม์โดยมีข้อผิดพลาดในการแบ่งกลุ่ม (SIGSEGV) เมื่อมีการเขียนข้อมูลนั้น
ซึ่งมักเกิดขึ้นหากไฟล์ .so สร้างขึ้นด้วย Toolchain ของ NDK r27 และต่ำกว่าโดยไม่ได้เปิดใช้แฟล็กที่เกี่ยวข้อง
ใช้ตัววิเคราะห์ APK (แนะนำ)
คุณสามารถใช้ตัววิเคราะห์ APK ใน Android Studio เพื่อตรวจสอบสถานะการจัดเรียง RELRO ของไฟล์ออบเจ็กต์ที่แชร์ได้โดยตรง
ใช้เครื่องมือบรรทัดคำสั่ง
หากต้องการตรวจสอบการจัดข้อความด้วยตนเองหรือต้องการทำให้กระบวนการเป็นแบบอัตโนมัติ ให้ทำตามขั้นตอนต่อไปนี้
ขั้นตอนที่ 1: ตรวจสอบส่วนหัวของโปรแกรม
เรียกใช้คำสั่งต่อไปนี้ในไฟล์ออบเจ็กต์ที่แชร์แต่ละไฟล์ (ใน Linux ให้แทนที่ darwin-x86_64 ด้วย linux-x86_64)
Linux หรือ macOS
SDK_ROOT_LOCATION/Android/sdk/ndk/NDK_VERSION/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf -Wl SHARED_OBJECT_FILE.so | grep 'LOAD\|RELRO\|Type'
Windows (PowerShell)
SDK_ROOT_LOCATION\Android\sdk\ndk\NDK_VERSION\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-readelf.exe -Wl SHARED_OBJECT_FILE.so | Select-String -Pattern 'LOAD|RELRO|Type'
ระบบจะพิมพ์สตริง GNU_RELRO หากมีกลุ่ม RELRO
ขั้นตอนที่ 2: ยืนยันการปฏิบัติตามข้อกำหนด 16 KB สำหรับ RELRO
ไฟล์ออบเจ็กต์ที่แชร์จะเป็นไปตามข้อกำหนด 16 KB สำหรับ RELRO หากเป็นไปตามเงื่อนไขข้อใดข้อหนึ่งต่อไปนี้
- ไม่มีส่วน
GNU_RELROในส่วนหัวของโปรแกรม - ที่อยู่สิ้นสุดของ
GNU_RELROมีการจัดแนว 16 KB: ผลรวมของที่อยู่เสมือน (VirtAddr) และขนาดหน่วยความจำ (MemSiz) หารด้วย 16 KB (0x4000) จะเหลือเศษ (โมดูโล) เป็นศูนย์:(VirtAddr + MemSiz) % 0x4000 == 0 - ไม่มีข้อมูลที่เขียนได้ตามหลัง
GNU_RELROในกลุ่มLOADเดียวกัน:GNU_RELROใช้พื้นที่ที่เหลือทั้งหมดของกลุ่มLOADที่มีอยู่ (หมายถึงLOAD.VirtAddr + LOAD.MemSiz == RELRO.VirtAddr + RELRO.MemSiz) ดังนั้น จึงไม่มีส่วน.dataหรือ.bssที่เขียนได้แชร์หน้าต่อท้าย
ตัวอย่าง
ตัวอย่างต่อไปนี้แสดงวิธีประเมินเอาต์พุต llvm-readelf สำหรับการกำหนดค่า GNU_RELRO ต่างๆ
ตัวอย่างที่ 1: ไฟล์ .so ที่ไม่สอดคล้องกัน (ไม่เป็นไปตามข้อกำหนด)
ในตัวอย่างนี้ GNU_RELRO แชร์ส่วน RW LOAD กับข้อมูลที่เขียนได้ที่ตามมา และที่อยู่สิ้นสุดไม่ใช่จำนวนทวีคูณของ 0x4000:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x0cfaf0 0x0cfaf0 R E 0x4000
LOAD 0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x02510 0x04510 RW 0x4000
GNU_RELRO 0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x01510 0x01510 R 0x1
- สูตร:
(VirtAddr + MemSiz) % 0x4000 == 0 - ผลลัพธ์:
(0xdfaf0 + 0x01510) % 0x4000 = 0xE1000 % 0x4000 == 0x1000
เนื่องจาก 0x1000 ไม่ใช่ 0 และส่วน LOAD ที่มีอยู่ยังคงผ่าน 0xE1000 (สิ้นสุดที่ 0xdfaf0 + 0x04510 = 0xE4000) ไฟล์ .so นี้จึงไม่เป็นไปตามข้อกำหนด 16 KB ในอุปกรณ์ขนาด 16 KB ตัวลิงก์จะปัดเศษช่วงการป้องกัน RELRO เป็นขอบเขตหน้าขนาด 16 KB โดยทำเครื่องหมาย 0xDC000 (ตัวแบ่งหน้าก่อนหน้า) ถึง 0xE4000 เป็นแบบอ่านอย่างเดียว อย่างไรก็ตาม ส่วน .data และ .bss ที่เขียนได้ของไฟล์ .so อยู่ในช่วงย่อยตั้งแต่ 0xE1000 ถึง 0xE4000 ซึ่งส่งผลให้เกิดข้อผิดพลาดในการแบ่งกลุ่มเมื่อแก้ไขขณะรันไทม์ สร้างไฟล์ .so นี้ใหม่ตามที่อธิบายไว้ในส่วนคอมไพล์แอปโดยใช้การจัดวาง ELF ขนาด 16 KB
ตัวอย่างที่ 2: ไฟล์ .so ที่จัดเรียงแล้วซึ่งมีกลุ่ม RELRO (เป็นไปตามข้อกำหนด)
ในตัวอย่างนี้ จุดสิ้นสุดของกลุ่ม GNU_RELRO อยู่ที่ขอบเขตหน้าขนาด 16 KB
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x0cfaf0 0x0cfaf0 R E 0x4000
LOAD 0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x01510 0x03510 RW 0x4000
GNU_RELRO 0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x00510 0x00510 R 0x1
- สูตร:
(VirtAddr + MemSiz) % 0x4000 == 0 - ผลลัพธ์:
(0xdfaf0 + 0x00510) % 0x4000 = 0xE0000 % 0x4000 == 0
เนื่องจากเศษที่เหลือคือ 0 การป้องกัน RELRO จึงสิ้นสุดลงอย่างสมบูรณ์ที่ขอบเขตหน้า 0xE0000 โดยไม่ส่งผลกระทบต่อข้อมูลที่เขียนได้ซึ่งเริ่มต้นที่ 0xE0000
ตัวอย่างที่ 3: ไฟล์ .so ที่ไม่มีกลุ่ม RELRO (เป็นไปตามข้อกำหนด)
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000680 0x000680 R E 0x4000
LOAD 0x000680 0x0000000000004680 0x0000000000004680 0x0001d8 0x0001d8 RW 0x4000
ไฟล์ .so นี้ไม่มีกลุ่ม GNU_RELRO ดังนั้นปัญหาขอบเขตหน้า RELRO จึงไม่มีผล (แม้ว่าจะยังคงแนะนำให้เปิดใช้ RELRO เพื่อความปลอดภัย)
ตัวอย่างที่ 4: GNU_RELRO ในกลุ่ม LOAD ของตัวเอง (เป็นไปตามนโยบาย)
ในตัวอย่างนี้ GNU_RELRO ไม่ได้สิ้นสุดที่ขอบเขต 16 KB แต่ยังคงเป็นไปตามข้อกำหนดเนื่องจากไม่มีข้อมูลที่เขียนได้ตามมาในกลุ่ม LOAD เดียวกัน
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000680 0x000680 R E 0x4000
LOAD 0x000680 0x0000000000004680 0x0000000000004680 0x0001d8 0x000980 RW 0x4000
GNU_RELRO 0x000680 0x0000000000004680 0x0000000000004680 0x0001d8 0x000980 R 0x1
- สูตร:
(VirtAddr + MemSiz) % 0x4000 == 0 - ผลลัพธ์:
(0x4680 + 0x0980) % 0x4000 = 0x5000 % 0x4000 == 0x1000
แม้ว่า 0x1000 จะไม่ใช่ 0 แต่ไฟล์ .so นี้ก็ยังคงเป็นไปตามข้อกำหนด 16 KB
เมื่อเปรียบเทียบ GNU_RELRO กับกลุ่ม LOAD ที่มีอยู่ (รายการ LOAD ที่ 2) จะเห็นว่าทั้ง 2 รายการเริ่มต้นที่ VirtAddr 0x4680 และสิ้นสุดที่ที่อยู่เดียวกัน (0x4680 + 0x0980 = 0x5000)
เนื่องจากทั้งกลุ่ม LOAD มีเฉพาะข้อมูล RELRO จึงไม่มีข้อมูล .data หรือ .bss ที่เขียนได้ในช่วงย่อยตั้งแต่ 0x5000 ถึง 0x8000 (ไลบรารีไม่มีข้อมูลที่เขียนได้ซึ่งไม่ใช่ RELRO หรือกลุ่ม LOAD ที่เขียนได้ที่ตามมาจะเริ่มต้นที่ขอบเขตหน้า 16 KB แยกต่างหากที่ 0x8000 หรือมากกว่านั้น) การป้องกันแบบอ่านอย่างเดียวของ Linker จะไม่ทับซ้อนกับข้อมูลที่เขียนได้ ดังนั้นจึงไม่เกิดข้อผิดพลาดในการแบ่งกลุ่ม
สร้างแอปที่รองรับอุปกรณ์ที่ใช้หน้าหน่วยความจำขนาด 16 KB
หากแอปใช้โค้ดแบบเนทีฟ ให้ทำตามขั้นตอนที่ระบุไว้ในส่วนต่อไปนี้เพื่อให้แน่ใจว่าแอปของคุณรองรับอุปกรณ์ขนาด 16 KB
- อัปเดตการสร้างแพ็กเกจของคลังที่ใช้ร่วมกัน
- คอมไพล์แอปโดยใช้การจัดวาง ELF ขนาด 16 KB
- แก้ไขโค้ดและแก้ปัญหาเกี่ยวกับรันไทม์
- เพิ่มประสิทธิภาพตัวจัดสรรการจัดสรรหน่วยความจำที่กำหนดเอง (หากมี)
- ตรวจสอบ SDK เพื่อดูการรองรับขนาด 16 KB
อัปเดตการสร้างแพ็กเกจของคลังที่ใช้ร่วมกัน
อัปเกรดเป็น AGP เวอร์ชัน 8.5.1 ขึ้นไปและใช้ไลบรารีที่ใช้ร่วมกันที่ไม่ได้บีบอัด
ใช้ bundletool เพื่อยืนยันการจัดแนวซิป
หากต้องการดูการจัดแนวของแพ็กเกจ ให้ใช้คำสั่งต่อไปนี้
bundletool dump config --bundle=<my .aab> | grep alignment
หากเห็น PAGE_ALIGNMENT_16K แสดงว่า Bundle ของคุณขอการจัดเรียงไฟล์ ZIP ขนาด 16 KB หากเห็น PAGE_ALIGNMENT_4K แสดงว่าคำสั่งนี้กำหนดให้ APK ที่สร้างจาก AAB นี้มีไฟล์ .so ที่จัดแนว 4 KB ในไฟล์ ZIP
AGP เวอร์ชัน 8.5.1 ขึ้นไป
อุปกรณ์ขนาด 16 KB ต้องใช้แอปที่มาพร้อมกับคลังที่ใช้ร่วมกันที่ไม่ได้บีบอัดเพื่อจัดวางคลังที่ใช้ร่วมกันเหล่านั้นในขอบเขตที่จัดวางด้วย zip ขนาด 16 KB โดยคุณจะต้องอัปเกรดเป็นปลั๊กอิน Android Gradle (AGP) เวอร์ชัน 8.5.1 ขึ้นไป ดูรายละเอียดเกี่ยวกับกระบวนการอัปเกรดได้ที่ส่วนผู้ช่วยอัปเกรดปลั๊กอิน Android Gradle
AGP เวอร์ชัน 8.5 หรือต่ำกว่า
หากอัปเกรด AGP เป็นเวอร์ชัน 8.5.1 ขึ้นไปไม่ได้ คุณสามารถเปลี่ยนไปใช้คลังที่ใช้ร่วมกันแบบบีบอัดแทนได้ อัปเดตการกำหนดค่า Gradle เพื่อให้ Gradle บีบอัดคลังที่ใช้ร่วมกันเมื่อสร้างแพ็กเกจแอปเพื่อหลีกเลี่ยงปัญหาการติดตั้งแอปที่มีคลังที่ใช้ร่วมกันที่ไม่ได้จัดวาง
ดึงดูด
เพิ่มตัวเลือกต่อไปนี้ในไฟล์ build.gradle
android {
...
packagingOptions {
jniLibs {
useLegacyPackaging true
}
}
}
Kotlin
เพิ่มตัวเลือกต่อไปนี้ในไฟล์ build.gradle.kts
android {
...
packagingOptions {
jniLibs {
useLegacyPackaging = true
}
}
}
AGP เวอร์ชัน 8.0 หรือต่ำกว่า
หากใช้ AGP เวอร์ชัน 8.0 หรือต่ำกว่า คุณจะต้องปิดใช้ตัวเลือกไลบรารีแบบเนทีฟที่ไม่ได้บีบอัดสำหรับ App Bundle ในไฟล์ gradle.properties ด้วย โดยทำดังนี้
android.bundle.enableUncompressedNativeLibs=false
คอมไพล์แอปโดยใช้การจัดวาง ELF ขนาด 16 KB
อุปกรณ์ขนาด 16 KB กำหนดให้ต้องจัดวางเซกเมนต์ ELF ของคลังที่ใช้ร่วมกันอย่างเหมาะสมโดยใช้การจัดวาง ELF ขนาด 16 KB เพื่อให้แอปทำงานได้
สำหรับนักพัฒนาเกม หากเกมของคุณทำงานบนเกมเอนจิน Unity โปรดดูคู่มือ Unity หากเกมของคุณทำงานบนเกมเอนจิน Unreal โปรดดูคู่มือ Unreal สำหรับเกมเอนจินแบบเนทีฟ โปรดอ่านคู่มือนี้ต่อ
หากต้องการคอมไพล์แอปโดยใช้การจัดแนว ELF ขนาด 16 KB ให้ทำตามขั้นตอนในส่วนใดส่วนหนึ่งต่อไปนี้ โดยขึ้นอยู่กับเวอร์ชันของ Android NDK ที่คุณใช้
Android NDK r28 ขึ้นไป
NDK เวอร์ชัน r28 ขึ้นไปจะคอมไพล์แบบจัดวางขนาด 16 KB โดยค่าเริ่มต้น
Android NDK r27 และต่ำกว่า
หากต้องการรองรับการคอมไพล์คลังที่ใช้ร่วมกันซึ่งจัดเรียงขนาด 16 KB ด้วย Android NDK เวอร์ชัน r27 หรือต่ำกว่า ให้ใช้แฟล็ก Linker ต่อไปนี้
-Wl,-z,max-page-size=16384
-Wl,-z,common-page-size=16384
วิธีอัปเดตไฟล์การกำหนดค่าระบบบิลด์มีดังนี้
ndk-build
หากใช้ ndk-build ให้อัปเดต Android.mk เพื่อเปิดใช้การจัดแนว ELF ขนาด 16 KB ดังนี้
LOCAL_LDFLAGS += -Wl,-z,max-page-size=16384 -Wl,-z,common-page-size=16384
CMake
หากใช้ CMake ให้อัปเดต CMakeLists.txt เพื่อเปิดใช้การจัดแนว ELF ขนาด 16 KB ดังนี้
target_link_options(${CMAKE_PROJECT_NAME} PRIVATE
"-Wl,-z,max-page-size=16384"
"-Wl,-z,common-page-size=16384"
)
แก้ไขโค้ดและแก้ปัญหาเกี่ยวกับรันไทม์
แม้ว่าแอปจะจัดแนวขนาด 16 KB แล้ว แต่แอปอาจพบข้อผิดพลาดหากตำแหน่งในโค้ดถือว่าอุปกรณ์ใช้ขนาดหน้าเว็บที่เฉพาะเจาะจง วิธีหลีกเลี่ยงปัญหามีดังนี้ ทำตามขั้นตอนต่อไปนี้
นำทรัพยากร Dependency ที่ฮาร์ดโค้ดซึ่งอ้างอิงค่าคงที่
PAGE_SIZEหรืออินสแตนซ์ในตรรกะโค้ดที่ถือว่าขนาดหน้าเว็บของอุปกรณ์คือ 4 KB (4096) ออกโปรดใช้
getpagesize()หรือsysconf(_SC_PAGESIZE)แทนมองหาการใช้งาน
mmap()และ API อื่นๆ ที่ต้องใช้อาร์กิวเมนต์ที่จัดแนวหน้า และแทนที่ด้วยทางเลือกอื่นหากจำเป็น
ในบางกรณี หากแอปใช้ PAGE_SIZE เป็นค่าที่สะดวกซึ่งไม่ได้เชื่อมโยงกับขนาดหน้าเว็บที่สำคัญ การดำเนินการนี้จะไม่ทำให้แอปขัดข้องเมื่อใช้ในโหมด 16 KB อย่างไรก็ตาม หากส่งค่านี้ไปยังเคอร์เนลด้วย mmap โดยไม่มี MAP_FIXED เคอร์เนลจะยังคงใช้ทั้งหน้า ซึ่งทำให้สิ้นเปลืองหน่วยความจำบางส่วน ด้วยเหตุผลเหล่านี้ ระบบจึงไม่กำหนด PAGE_SIZE เมื่อเปิดใช้โหมด 16 KB ใน NDK r27 ขึ้นไป
หากแอปของคุณใช้ PAGE_SIZE ในลักษณะนี้และไม่เคยส่งค่านี้ไปยังเคอร์เนลโดยตรง ให้สร้างตัวแปรใหม่ที่มีชื่อใหม่เพื่อแสดงว่าตัวแปรนี้ใช้เพื่อวัตถุประสงค์อื่นและไม่ได้แสดงหน้าหน่วยความจำจริง แทนที่จะใช้ PAGE_SIZE
เพิ่มประสิทธิภาพตัวจัดสรรการจัดสรรหน่วยความจำที่กำหนดเอง
ในระบบ 16 KB หน่วยความจำกายภาพที่เล็กที่สุดที่ระบบปฏิบัติการจัดสรรจะมีขนาดใหญ่กว่าระบบ 4 KB ถึง 4 เท่า หากตัวจัดสรรที่กำหนดเองได้รับการออกแบบตามสมมติฐาน 4 KB ตัวจัดสรรอาจกระจายออบเจ็กต์ขนาดเล็กไปยังหน้าขนาด 16 KB หลายหน้าและเก็บหน่วยความจำว่างไว้โดยไม่จำเป็น ซึ่งอาจเพิ่มการใช้งานหน่วยความจำจริง (RSS) อย่างมากและลดประสิทธิภาพของ Swap ที่บีบอัด (ZRAM)
หากโค้ดของคุณจัดการพูลหน่วยความจำของตัวเอง ให้ทำตามคำแนะนำต่อไปนี้
1. หลีกเลี่ยงเกณฑ์ไบต์ที่ฮาร์ดโค้ดเพื่อเพิ่มพื้นที่หน่วยความจำ
ตัวจัดสรรจำนวนมากใช้ขีดจำกัดไบต์คงที่เพื่อตัดสินใจว่าจะปล่อยหน่วยความจำกลับไปยังระบบปฏิบัติการโดยใช้ madvise(MADV_DONTNEED) เมื่อใด (เช่น ปล่อยหน่วยความจำเฉพาะเมื่อออบเจ็กต์ที่ใช้งานอยู่ใช้พื้นที่น้อยกว่า 8 KB)
ในระบบ 16 KB แม้แต่ออบเจ็กต์ที่ทำงานอยู่ขนาด 16 ไบต์เพียงรายการเดียวก็ตรึงหน้าขนาด 16 KB ทั้งหน้า (ซึ่งมากกว่า 8 KB) ด้วยเหตุนี้ จึงไม่ถึงเกณฑ์การปล่อย และ Allocator จะไม่คืนหน่วยความจำที่ไม่ได้ใช้โดยรอบให้กับเคอร์เนล
สิ่งที่ต้องทำ: อย่าใช้ค่าคงที่ไบต์ที่ฮาร์ดโค้ดสำหรับฮิวริสติกการปล่อยหน้าเว็บ
ปรับขนาดเกณฑ์การปล่อยแบบไดนามิกที่รันไทม์ตามขนาดหน้าจริงโดยใช้ sysconf(_SC_PAGESIZE)
2. เติมหน้าเว็บที่ใช้แล้วก่อน (การจัดสรรแบบหนาแน่นก่อน)
หากตัวจัดสรรจัดสรรหน่วยความจำตามลำดับเข้าก่อนออกก่อน (FIFO) หรือแบบวนรอบ (Round-Robin) การจัดสรรใหม่จะกระจายไปทั่วหน้าขนาด 16 KB ที่มีข้อมูลอยู่บางส่วน ออบเจ็กต์เดียวในหน้าจะเก็บข้อมูลขนาด 16 KB ทั้งหมดไว้ใน RAM จริง
สิ่งที่ต้องทำ: จัดสรรออบเจ็กต์ใหม่จากหน้าหรือ Slab ที่เต็ม (หนาแน่น) ที่สุดก่อนเสมอ ก่อนที่จะแตะหน้าว่างหรือหน้าที่มีการใช้งานน้อย การมุ่งเน้นการจัดสรรใหม่ในหน้าที่ไม่สะอาดอยู่แล้วจะช่วยให้หน้าที่มีการใช้งานน้อยลดลงเหลือออบเจ็กต์ที่ใช้งานอยู่เป็น 0 โดยธรรมชาติ เพื่อให้สามารถปล่อยหน้าขนาด 16 KB ทั้งหน้าไปยังระบบปฏิบัติการได้
3. จัดแนวพูลหน่วยความจำให้เป็น 16 KB และรักษาขนาดพูลให้อยู่ในระดับปานกลาง
ช่วงหลายหน้าที่ออกแบบมาสำหรับระบบขนาด 4 KB อาจมีหน่วยความจำที่ไม่ได้ใช้งานมากเกินไปในเคอร์เนลขนาด 16 KB นอกจากนี้ คลาสขนาดที่หารด้วย 16 KB ไม่ลงตัวจะทำให้เกิดการกระจาย Fragment ที่ส่วนท้ายของแต่ละหน้า
สิ่งที่ต้องทำ
- ตรวจสอบว่าพูลหน่วยความจำ ขอบเขต Slab และการจัดแนวบัฟเฟอร์ทั้งหมดเป็นจำนวนเท่าที่แน่นอนของขนาดหน้าเว็บรันไทม์
- ประเมินขนาดช่วงหลายหน้าสำหรับคลาสออบเจ็กต์ขนาดเล็กอีกครั้งเพื่อหลีกเลี่ยงการจัดสรร Slab ขนาดใหญ่เกินไปซึ่งจะดักจับหน่วยความจำที่ไม่มีการใช้งาน
4. ปล่อยหน่วยความจำกายภาพสำหรับบัฟเฟอร์ขนาดใหญ่ที่แคชไว้ทันที
ตัวจัดสรรที่กำหนดเองมักจะแคชบัฟเฟอร์ขนาดใหญ่ (> 64 KB) ในพูลในหน่วยความจำเพื่อให้สามารถนำกลับมาใช้ใหม่ได้โดยไม่ต้องเสียค่าใช้จ่ายเพิ่มเติมสำหรับการเรียกใช้ระบบ mmap หรือ munmap อย่างไรก็ตาม การเก็บรักษาบัฟเฟอร์ที่สกปรกเหล่านี้ไว้ในหน่วยความจำจะทำให้ RAM จริงเสียไปหลายเมกะไบต์ขณะรอตัวจับเวลาการขับออก
สิ่งที่ต้องทำ: เก็บช่วงที่อยู่หน่วยความจำเสมือนที่สงวนไว้สำหรับการนำกลับมาใช้ใหม่อย่างรวดเร็ว แต่ให้เรียกใช้ madvise(..., MADV_DONTNEED) หรือ madvise(..., MADV_FREE) ทันทีเมื่อส่งคืนบัฟเฟอร์ไปยังแคช ระบบปฏิบัติการจะเรียกคืน RAM จริงทันที ขณะที่แอปยังคงใช้ที่อยู่เสมือนซ้ำได้ทันทีโดยไม่ต้องจัดสรรใหม่
5. ล้างหน่วยความจำเมื่อว่างแทนที่จะล้างเมื่อมีการจัดสรรสำหรับการบีบอัด ZRAM
Android ใช้การสลับแบบบีบอัด (ZRAM) เพื่อเก็บแอปที่ทำงานอยู่เบื้องหลังไว้ในหน่วยความจำ ในอุปกรณ์ขนาด 16 KB หากหน้าเว็บมีออบเจ็กต์ที่ใช้งานอยู่แม้เพียงรายการเดียว หน้าเว็บขนาด 16 KB ทั้งหน้าจะยังคงอยู่หรือถูกสลับไปยัง ZRAM ข้อมูลขยะที่เหลืออยู่ (เช่น พอยน์เตอร์และสตริงที่ไม่มีการใช้งาน) ในส่วนที่ว่างก่อนหน้านี้ของหน้าเว็บนั้นจะบีบอัดได้ไม่ดีนัก
หาก Allocator ของคุณล้างหน่วยความจำ (เช่น เพื่อความปลอดภัยหรือการจัดสรรที่เริ่มต้นเป็น 0) ให้พิจารณาล้างเมื่อยกเลิกการจัดสรร (free()) แทนที่จะล้างเมื่อจัดสรร
- หน้าเว็บที่ปักหมุดไว้ใช้ทรัพยากรน้อยลง: หน่วยความจำที่ไม่มีการใช้งานในหน้าเว็บขนาด 16 KB ที่มีข้อมูลอยู่บางส่วนจะถูกบีบอัดจนแทบไม่เหลืออะไรเลยใน ZRAM ดังนั้นหน้าเว็บที่ปักหมุดไว้จึงไม่ทำให้พื้นที่ Swap จริงสูญเปล่า
- ค่าใช้จ่ายเพิ่มเติมของแคชต่ำสุด: ในขณะที่เรียกใช้
free()หน่วยความจำจะทำงานในแคช CPU อยู่แล้ว ซึ่งจะช่วยหลีกเลี่ยงการไม่พบแคชเพิ่มเติมในภายหลัง
สรุปคำแนะนำ
| พื้นที่ | คำแนะนำ | ผลกระทบที่คาดหวัง |
|---|---|---|
| เกณฑ์การล้างข้อมูล | ปรับขนาดเกณฑ์การเผยแพร่แบบไดนามิกโดยใช้ sysconf(_SC_PAGESIZE) |
ป้องกันไม่ให้ตรรกะการเผยแพร่เกิดการติดตายอย่างถาวร |
| ลำดับการจัดสรร | จัดสรรจากหน้าหรือ Slab ที่หนาแน่นที่สุด (เกือบเต็ม) ก่อน | ลดหน่วยความจำที่ใช้ (RSS) โดยการรวมออบเจ็กต์ที่ใช้งานอยู่เข้าด้วยกัน |
| การกำหนดขนาดช่วง | จัดคลาสขนาดให้สอดคล้องกับจำนวนเท่าของ 16 KB และหลีกเลี่ยง Slab ที่มีขนาดใหญ่เกินไป | กำจัดการกระจาย Fragment ของหน้าส่วนท้ายและลดหน่วยความจำที่ไม่ได้ใช้ |
| แคชบัฟเฟอร์ | เรียกใช้ madvise(MADV_DONTNEED) ทันทีเมื่อแคชบัฟเฟอร์ขนาดใหญ่ |
กำจัด RAM ที่ไม่ได้ใช้งานซึ่งทำให้เครื่องช้าลง ขณะเดียวกันก็ยังคงใช้หน่วยความจำเสมือนได้อย่างรวดเร็ว |
| Swap / ZRAM | ล้างหน่วยความจำใน free() แทนการจัดสรร |
ปรับปรุงอัตราส่วนการบีบอัด ZRAM เพื่อให้หน้าเว็บที่ปักหมุดใช้ทรัพยากรน้อยลง |
ตรวจสอบ SDK เพื่อดูการรองรับขนาด 16 KB
SDK จำนวนมากเข้ากันได้กับขนาดหน้า 16 KB โดยเฉพาะอย่างยิ่งหากคุณสร้างขึ้นเองหรือใช้เวอร์ชันที่สร้างไว้ล่วงหน้าล่าสุด อย่างไรก็ตาม เนื่องจาก SDK ที่สร้างไว้ล่วงหน้าหรือ SDK บางเวอร์ชันไม่รองรับขนาด 16 KB คุณจึงควรตรวจสอบเว็บไซต์ของผู้ให้บริการ SDK แต่ละรายเพื่อดูว่าควรใช้เวอร์ชันใดกับขนาด 16 KB
ทดสอบแอปในสภาพแวดล้อมแบบ 16 KB
หลังจากสร้างแอปที่รองรับอุปกรณ์ขนาด 16 KB แล้ว คุณจะต้องทดสอบแอปในสภาพแวดล้อมขนาด 16 KB เพื่อดูว่าแอปมีปัญหาการถดถอยหรือไม่ โดยทำตามขั้นตอนต่อไปนี้
ตั้งค่า Android 15 SDK ขึ้นไป
ตั้งค่าสภาพแวดล้อมการทดสอบอย่างใดอย่างหนึ่งต่อไปนี้
เริ่มอุปกรณ์ทดสอบ แล้วเรียกใช้คำสั่งต่อไปนี้เพื่อยืนยันว่าอุปกรณ์ใช้สภาพแวดล้อม 16 KB
adb shell getconf PAGE_SIZEคำสั่งควรแสดงผลค่าเป็น
16384เรียกใช้คำสั่ง
zipalignต่อไปนี้เพื่อยืนยันว่าแอปของคุณจัดแนวแบบ 16 KB โดยที่ APK_NAME คือชื่อไฟล์ APK ของแอปzipalign -c -P 16 -v 4 APK_NAME.apkทดสอบแอปอย่างละเอียด โดยเน้นที่ส่วนที่อาจได้รับผลกระทบจากการเปลี่ยนอินสแตนซ์โค้ดที่อ้างอิงขนาดหน้าเว็บที่เฉพาะเจาะจง
ตั้งค่าโปรแกรมจำลองของ Android ด้วยอิมเมจระบบแบบ 16 KB
หากต้องการตั้งค่าสภาพแวดล้อมขนาด 16 KB โดยใช้โปรแกรมจำลองของ Android ให้ทำตามขั้นตอนต่อไปนี้
- ใน Android Studio ให้คลิกเครื่องมือ > เครื่องมือจัดการ SDK
ในแท็บแพลตฟอร์ม SDK ให้เลือกแสดงรายละเอียดแพ็กเกจ แล้วขยายส่วน Android VanillaIceCream ขึ้นไป และเลือกอิมเมจระบบโปรแกรมจำลองต่อไปนี้อย่างใดอย่างหนึ่งหรือทั้ง 2 อย่าง โดยขึ้นอยู่กับอุปกรณ์เสมือนจริงที่คุณต้องการสร้าง
- อิมเมจระบบ ARM 64 v8a ขนาดหน้า 16 KB เวอร์ชันทดลองของ Google APIs
- อิมเมจระบบ Intel x86_64 Atom ขนาดหน้า 16 KB เวอร์ชันทดลองของ Google APIs
คลิกใช้ > ตกลงเพื่อดาวน์โหลดอิมเมจระบบที่คุณเลือก
ทำตามขั้นตอนเพื่อตั้งค่าอุปกรณ์เสมือนจริงสำหรับ Android 15 และเมื่อระบบแจ้งให้เลือกอิมเมจระบบ ให้เลือกอิมเมจระบบขนาด 16 KB ที่คุณดาวน์โหลดไว้ หากระบบไม่แนะนำโดยอัตโนมัติ คุณจะดูอิมเมจระบบขนาด 16 KB ได้ในแท็บอิมเมจอื่นๆ
เปิดโปรแกรมจำลอง
หลังจากตั้งค่าโปรแกรมจำลองของ Android และอุปกรณ์เสมือนจริงเสร็จแล้ว ให้เปิดโปรแกรมจำลองจากเมนูอุปกรณ์เป้าหมายหรือจากบรรทัดคำสั่ง
เปิดใช้โหมด 16 KB ในอุปกรณ์โดยใช้ตัวเลือกสำหรับนักพัฒนาแอป
สลับตัวเลือกสำหรับนักพัฒนาแอปบูตโดยใช้หน้าหน่วยความจำขนาด 16 KB เพื่อบูตอุปกรณ์ในโหมด 16 KB
ใน Android 15 เวอร์ชัน QPR คุณสามารถใช้ตัวเลือกสำหรับนักพัฒนาแอปที่มีในอุปกรณ์บางรุ่นเพื่อบูตอุปกรณ์ในโหมด 16 KB และทำการทดสอบในอุปกรณ์ได้ ก่อนใช้ตัวเลือกสำหรับนักพัฒนาซอฟต์แวร์ ให้ไปที่การตั้งค่า > ระบบ > การอัปเดตซอฟต์แวร์ แล้วใช้การอัปเดตที่มี
ตัวเลือกสำหรับนักพัฒนาแอปนี้พร้อมใช้งานในอุปกรณ์ต่อไปนี้
Pixel 8 และ 8 Pro (ที่ใช้ Android 15 QPR1 ขึ้นไป)
Pixel 8a (ใช้ Android 15 QPR1 ขึ้นไป)
Pixel 9, 9 Pro และ 9 Pro XL (ใช้ Android 15 QPR2 ขึ้นไป)
Pixel 9a (ใช้ Android 16 ขึ้นไป)
โหมดความเข้ากันได้แบบย้อนหลัง 16 KB
คำเตือนในโหมดความเข้ากันได้กับขนาดหน้า
ตัวเลือกความเข้ากันได้แบบย้อนหลัง 16 KB จะพร้อมใช้งานเมื่ออุปกรณ์ทำงานด้วยเคอร์เนล 16 KB เครื่องมือจัดการแพ็กเกจจะเรียกใช้แอปในโหมดความเข้ากันได้แบบย้อนหลังขนาด 16 KB เมื่อเป็นไปตามเงื่อนไขต่อไปนี้
- หากแอปมีไฟล์ ELF (ที่มีนามสกุล
.so) ที่มีการจัดแนวกลุ่ม LOAD ขนาด 4 KB - หาก APK ที่บีบอัดมีไฟล์ ELF ที่ไม่ได้บีบอัดซึ่งจัดเรียง ZIP ขนาด 4 KB
หากเครื่องมือจัดการแพ็กเกจเปิดใช้โหมดความเข้ากันได้แบบย้อนหลัง 16 KB สำหรับแอป แอปจะแสดงคำเตือนเมื่อเปิดใช้งานครั้งแรกว่ากำลังทำงานในโหมดความเข้ากันได้แบบย้อนหลัง 16 KB
โหมดความเข้ากันได้แบบย้อนหลัง 16 KB ช่วยให้แอปบางแอปทำงานได้ แต่เพื่อให้มีความน่าเชื่อถือและความเสถียรสูงสุด แอปควรได้รับการจัดแนวให้รองรับขนาดหน้า 16 KB
ในหน้าข้อมูลแอป ในส่วนขั้นสูง ให้สลับการตั้งค่าเรียกใช้แอปด้วยโหมดเข้ากันได้กับขนาดหน้าเพื่อเปิดหรือปิดใช้โหมดความเข้ากันได้แบบย้อนหลัง 16 KB สำหรับแอปที่เฉพาะเจาะจง การตั้งค่านี้จะปรากฏเฉพาะเมื่ออุปกรณ์ทำงานด้วยขนาดหน้า 16 KB
การตั้งค่าโหมดเข้ากันได้กับขนาดหน้า
วิธีบังคับให้เปิดความเข้ากันได้แบบย้อนหลัง 16 KB สำหรับทุกแอปในอุปกรณ์
adb shell setprop bionic.linker.16kb.app_compat.enabled true
adb shell setprop pm.16kb.app_compat.disabled false
วิธีบังคับปิดความเข้ากันได้แบบย้อนหลัง 16 KB สำหรับทุกแอปในอุปกรณ์
adb shell setprop bionic.linker.16kb.app_compat.enabled false
adb shell setprop pm.16kb.app_compat.disabled true
ใน Android 17 คุณยังสามารถบังคับปิดความเข้ากันได้แบบย้อนหลัง 16 KB สำหรับทุกแอปและทำให้ไบนารีที่เข้ากันไม่ได้ถูกยกเลิกทันทีได้ด้วย โดยทำดังนี้
adb shell setprop bionic.linker.16kb.app_compat.enabled fatal
adb shell setprop pm.16kb.app_compat.disabled true
ตั้งค่าพร็อพเพอร์ตี้ android:pageSizeCompat เป็นเปิดใช้หรือปิดใช้เพื่อเปิดหรือปิดโหมดความเข้ากันได้แบบย้อนหลังสำหรับแอปที่เฉพาะเจาะจงใน AndroidManifest.xml เมื่อตั้งค่าพร็อพเพอร์ตี้นี้ แอปจะไม่แสดงคำเตือนโหมดความเข้ากันได้แบบย้อนหลังเมื่อเปิดแอป