เอกสารนี้อธิบายการออกแบบโซลูชันการแคช APK เพื่อการติดตั้งแอปที่โหลดไว้ล่วงหน้าอย่างรวดเร็วในอุปกรณ์ที่รองรับพาร์ติชัน A/B
OEM สามารถวางแอปที่โหลดไว้ล่วงหน้าและแอปยอดนิยมในแคช APK ที่เก็บไว้ในพาร์ติชัน B ซึ่งส่วนใหญ่ว่างเปล่าในอุปกรณ์ที่แบ่งพาร์ติชัน A/B ใหม่โดยไม่ส่งผลกระทบต่อพื้นที่ข้อมูลที่แสดงต่อผู้ใช้ การมีแคช APK ในอุปกรณ์จะทำให้อุปกรณ์ใหม่หรืออุปกรณ์ที่เพิ่งรีเซ็ตเป็นค่าเริ่มต้นพร้อมใช้งานเกือบทันทีโดยไม่ต้องดาวน์โหลดไฟล์ APK จาก Google Play
กรณีการใช้งาน
- จัดเก็บแอปที่โหลดไว้ล่วงหน้าไว้ในพาร์ติชัน B เพื่อให้ตั้งค่าได้เร็วขึ้น
- จัดเก็บแอปยอดนิยมไว้ในพาร์ติชัน B เพื่อให้การกู้คืนเร็วขึ้น
สิ่งที่ต้องมีก่อน
อุปกรณ์ต้องใช้สิ่งต่อไปนี้จึงจะใช้ฟีเจอร์นี้ได้
- ติดตั้งรุ่น Android 8.1 (O MR1) แล้ว
- ใช้พาร์ติชัน A/B แล้ว
คัดลอกเนื้อหาที่โหลดไว้ล่วงหน้าได้ในระหว่างการบูตครั้งแรกเท่านั้น เนื่องจากในอุปกรณ์ที่รองรับการอัปเดตระบบ A/B พาร์ติชัน B ไม่ได้จัดเก็บไฟล์ภาพระบบ แต่โหลดเนื้อหาล่วงหน้า เช่น ทรัพยากรการสาธิตเวอร์ชันค้าปลีก ไฟล์ OAT และแคช APK หลังจากคัดลอกทรัพยากรไปยังพาร์ติชัน /data (การดำเนินการนี้จะดำเนินการในการบูตครั้งแรก) การอัปเดตผ่านอากาศ (OTA) จะใช้พาร์ติชัน B เพื่อดาวน์โหลดอิมเมจระบบเวอร์ชันอัปเดต
ดังนั้นจึงอัปเดตแคช APK ผ่าน OTA ไม่ได้ แต่จะโหลดล่วงหน้าได้เฉพาะที่โรงงานเท่านั้น การรีเซ็ตเป็นค่าเริ่มต้นจะมีผลกับพาร์ติชัน /data เท่านั้น พาร์ติชัน B ของระบบจะยังคงมีเนื้อหาที่โหลดไว้ล่วงหน้าจนกว่าจะมีการดาวน์โหลดรูปภาพ OTA หลังจากรีเซ็ตเป็นค่าเริ่มต้นแล้ว ระบบจะทำการบูตครั้งแรกอีกครั้ง ซึ่งหมายความว่าการแคช APK จะใช้งานไม่ได้หากมีการดาวน์โหลดรูปภาพ OTA ลงในพาร์ติชัน B แล้วรีเซ็ตอุปกรณ์เป็นค่าเริ่มต้น
การใช้งาน
แนวทางที่ 1 เนื้อหาในพาร์ติชัน system_other
เคล็ดลับ: เนื้อหาที่โหลดไว้ล่วงหน้าจะไม่สูญหายหลังจากรีเซ็ตเป็นค่าเริ่มต้น ระบบจะคัดลอกเนื้อหาดังกล่าวจากพาร์ติชัน B หลังจากรีบูต
ข้อเสีย: ต้องใช้พื้นที่ในพาร์ติชัน B การบูตหลังจากรีเซ็ตเป็นค่าเริ่มต้นจากโรงงานต้องใช้เวลาเพิ่มเติมในการคัดลอกเนื้อหาที่โหลดไว้ล่วงหน้า
ระบบจะเรียกใช้สคริปต์ใน /system/bin/preloads_copy.sh
เพื่อคัดลอกรายการที่โหลดล่วงหน้าระหว่างการบูตครั้งแรก ระบบจะเรียกใช้สคริปต์พร้อมอาร์กิวเมนต์เดียว (เส้นทางไปยังจุดมา운ต์ที่อ่านอย่างเดียวสำหรับพาร์ติชัน system_b
) ดังนี้
หากต้องการใช้ฟีเจอร์นี้ ให้ทําการเปลี่ยนแปลงเฉพาะอุปกรณ์เหล่านี้ ตัวอย่างจาก Marlin มีดังนี้
- เพิ่มสคริปต์ที่จะทำการคัดลอกลงในไฟล์
device-common.mk
(ในกรณีนี้คือdevice/google/marlin/device-common.mk
) ดังนี้ ดูตัวอย่างแหล่งที่มาของสคริปต์ได้ที่ device/google/marlin/preloads_copy.sh# Script that copies preloads directory from system_other to data partition PRODUCT_COPY_FILES += \ device/google/marlin/preloads_copy.sh:system/bin/preloads_copy.sh
- แก้ไขไฟล์
init.common.rc
เพื่อให้สร้างไดเรกทอรีและไดเรกทอรีย่อย/data/preloads
ที่จําเป็น ดูตัวอย่างแหล่งที่มาของไฟล์mkdir /data/preloads 0775 system system
mkdir /data/preloads/media 0775 system system
mkdir /data/preloads/demo 0775 system system
init
ที่ device/google/marlin/init.common.rc - กําหนดโดเมน SELinux ใหม่ในไฟล์
preloads_copy.te
ดูตัวอย่างไฟล์โดเมน SELinux ที่ /device/google/marlin/+/main/sepolicy/preloads_copy.tetype preloads_copy, domain, coredomain; type preloads_copy_exec, exec_type, vendor_file_type, file_type; init_daemon_domain(preloads_copy) allow preloads_copy shell_exec:file rx_file_perms; allow preloads_copy toolbox_exec:file rx_file_perms; allow preloads_copy preloads_data_file:dir create_dir_perms; allow preloads_copy preloads_data_file:file create_file_perms; allow preloads_copy preloads_media_file:dir create_dir_perms; allow preloads_copy preloads_media_file:file create_file_perms; # Allow to copy from /postinstall allow preloads_copy system_file:dir r_dir_perms;
- จดทะเบียนโดเมนใน
ไฟล์ใหม่ โดยทำดังนี้/sepolicy/file_contexts ดูตัวอย่างไฟล์บริบท SELinux ได้ที่ device/google/marlin/sepolicy/preloads_copy.te/system/bin/preloads_copy\.sh u:object_r:preloads_copy_exec:s0
- คุณต้องคัดลอกไดเรกทอรีที่มีเนื้อหาที่โหลดไว้ล่วงหน้าไปยังพาร์ทิชัน
system_other
ในเวลาที่สร้าง นี่คือตัวอย่างการเปลี่ยนแปลงใน Makefile ที่อนุญาตให้คัดลอกทรัพยากรแคช APK จากที่เก็บ Git ของผู้ให้บริการ (ในกรณีของเราคือ /vendor/google_devices/marlin/preloads) ไปยังตำแหน่งในพาร์ติชัน system_other ซึ่งจะคัดลอกไปยัง /data/preloads ในภายหลังเมื่ออุปกรณ์บูตเป็นครั้งแรก สคริปต์นี้จะทำงานเมื่อสร้างเพื่อเตรียมอิมเมจ system_other โดยระบบจะคาดหวังว่าเนื้อหาที่โหลดไว้ล่วงหน้าจะอยู่ใน vendor/google_devices/marlin/preloads OEM มีอิสระในการเลือกชื่อ/เส้นทางที่เก็บจริง# Copy contents of preloads directory to system_other partition PRODUCT_COPY_FILES += \ $(call find-copy-subdir-files,*,vendor/google_devices/marlin/preloads,system_other/preloads)
- แคช APK อยู่ใน
/data/preloads/file_cache
และมีเลย์เอาต์ดังต่อไปนี้ นี่คือโครงสร้างไดเรกทอรีสุดท้ายในอุปกรณ์ OEM มีอิสระในการเลือกแนวทางการติดตั้งใช้งานใดก็ได้ ตราบใดที่โครงสร้างไฟล์สุดท้ายทำซ้ำโครงสร้างที่อธิบายไว้ข้างต้น/data/preloads/file_cache/ app.package.name.1/ file1 fileN app.package.name.N/
วิธีที่ 2 เนื้อหาเกี่ยวกับข้อมูลผู้ใช้ ภาพแฟลชที่โรงงาน
แนวทางอื่นนี้ถือว่าเนื้อหาที่โหลดไว้ล่วงหน้ารวมอยู่ในไดเรกทอรี /data/preloads
ในพาร์ติชัน /data
อยู่แล้ว
ข้อดี: ใช้งานได้ทันทีโดยไม่ต้องปรับแต่งอุปกรณ์เพื่อคัดลอกไฟล์ในการบูตครั้งแรก เนื้อหาอยู่ในพาร์ติชัน /data
อยู่แล้ว
ข้อเสีย: เนื้อหาที่โหลดไว้ล่วงหน้าจะหายไปหลังจากรีเซ็ตเป็นค่าเริ่มต้น แม้ว่าวิธีนี้อาจยอมรับได้สำหรับบางราย แต่อาจใช้ไม่ได้กับ OEM ที่รีเซ็ตอุปกรณ์เป็นค่าเริ่มต้นหลังการตรวจสอบการควบคุมคุณภาพ
เพิ่มเมธอด @SystemApi ใหม่ชื่อ getPreloadsFileCache()
ลงใน android.content.Context
โดยจะแสดงผลเส้นทางแบบสัมบูรณ์ไปยังไดเรกทอรีเฉพาะแอปในแคชที่โหลดไว้ล่วงหน้า
เพิ่มเมธอดใหม่ IPackageManager.deletePreloadsFileCache
ซึ่งอนุญาตให้ลบไดเรกทอรีการโหลดล่วงหน้าเพื่อเรียกคืนพื้นที่ทั้งหมด เฉพาะแอปที่มี SYSTEM_UID เท่านั้นที่เรียกใช้เมธอดนี้ได้ เช่น เซิร์ฟเวอร์ระบบหรือการตั้งค่า
การเตรียมแอป
เฉพาะแอปที่มีสิทธิ์เท่านั้นที่เข้าถึงไดเรกทอรีแคชการโหลดล่วงหน้าได้ คุณต้องติดตั้งแอปในไดเรกทอรี /system/priv-app
จึงจะเข้าถึงได้
การตรวจสอบความถูกต้อง
- หลังจากการบูตครั้งแรก อุปกรณ์ควรมีเนื้อหาในไดเรกทอรี
/data/preloads/file_cache
- เนื้อหาในไดเรกทอรี
file_cache/
ต้องถูกลบหากอุปกรณ์มีพื้นที่เก็บข้อมูลเหลือน้อย
ใช้แอปตัวอย่าง ApkCacheTest เพื่อทดสอบแคช APK
- สร้างแอปโดยเรียกใช้คำสั่งนี้จากไดเรกทอรีรูท
make ApkCacheTest
- ติดตั้งแอปเป็นแอปที่มีสิทธิ์ (โปรดทราบว่ามีเพียงแอปที่มีสิทธิ์เท่านั้นที่เข้าถึงแคช APK ได้)
การดำเนินการนี้ต้องใช้อุปกรณ์ที่รูท
adb root && adb remount
adb shell mkdir /system/priv-app/ApkCacheTest
adb push $ANDROID_PRODUCT_OUT/data/app/ApkCacheTest/ApkCacheTest.apk /system/priv-app/ApkCacheTest/
adb shell stop && adb shell start
- จำลองไดเรกทอรีแคชไฟล์และเนื้อหาของไดเรกทอรีดังกล่าว หากจำเป็น (ต้องใช้สิทธิ์รูทด้วย)
adb shell mkdir -p /data/preloads/file_cache/com.android.apkcachetest
adb shell restorecon -r /data/preloads
adb shell "echo "Test File" > /data/preloads/file_cache/com.android.apkcachetest/test.txt"
- ทดสอบแอป หลังจากติดตั้งแอปและสร้างไดเรกทอรี
file_cache
ทดสอบแล้ว ให้เปิดแอป ApkCacheTest ซึ่งควรแสดงไฟล์test.txt
1 ไฟล์และเนื้อหาของไฟล์ ดูภาพหน้าจอนี้เพื่อดูว่าผลลัพธ์เหล่านี้ปรากฏในอินเทอร์เฟซผู้ใช้อย่างไร
รูปที่ 1 ผลการทดสอบ ApkCache