OTA สำหรับอุปกรณ์ที่ไม่ใช่ A/B ที่มีพาร์ติชันแบบไดนามิก

Android 10 รองรับพาร์ติชันแบบไดนามิก ซึ่งเป็นระบบการแบ่งพาร์ติชันพื้นที่ผู้ใช้ที่สามารถสร้าง ปรับขนาด และลบพาร์ติชันในระหว่างการอัปเดตแบบ OTA ได้

หน้านี้อธิบายวิธีปรับขนาดพาร์ติชันแบบไดนามิกของไคลเอ็นต์ OTA ระหว่างการอัปเดตสำหรับอุปกรณ์ที่ไม่ใช่ A/B

สำหรับอุปกรณ์ที่ไม่ใช่ A/B ระบบจะใช้การอัปเดต OTA สำหรับพาร์ติชันแบบไดนามิกโดยใช้ updater ในแพ็กเกจการอัปเดต

อัปเดตอุปกรณ์ที่จะเปิดตัว

ส่วนนี้ใช้กับอุปกรณ์ที่ไม่ใช่ A/B ซึ่งเปิดตัวด้วยการรองรับพาร์ติชันแบบไดนามิก โดยอุปกรณ์เหล่านี้จะอัปเกรดจาก Android 10 เป็นเวอร์ชันที่ใหม่กว่า

สร้างแพ็กเกจอัปเดต

แพ็กเกจอัปเดต OTA สร้างขึ้นโดยสคริปต์ ota_from_target_files ซึ่งอยู่ภายใต้ build/make/tools/releasetools โดยค่าเริ่มต้น สคริปต์จะสร้างแพ็กเกจที่อัปเดตพาร์ติชัน system และ vendor หากมีพาร์ติชันแบบไดนามิกเพิ่มเติม เช่น product, product_services หรือ odm การอัปเดตพาร์ติชันเหล่านี้จะต้องสร้างในโค้ดเฉพาะอุปกรณ์

หากต้องการสร้างการอัปเดต ให้ใช้ FullOTA_GetBlockDifferences() และ IncrementalOTA_GetBlockDifferences() ในโมดูล Python แบบขยาย ฟังก์ชันทั้ง 2 รายการนี้จะแสดงรายการออบเจ็กต์ BlockDifference โดยแต่ละรายการจะอธิบายแพตช์การอัปเดตที่จะใช้กับพาร์ติชัน พาร์ติชันที่แสดงผลโดยฟังก์ชันทั้ง 2 นี้ไม่ควรแก้ไขด้วยตนเองหรือยืนยันที่อื่น เช่น ใน *_InstallBegin() หรือ *_InstallEnd()

ตัวอย่างการสร้างการอัปเดต

# device/yoyodyne/tardis/releasetools.py

import os
from common import BlockDifference, EmptyImage, GetUserImage

# The joined list of user image partitions of source and target builds.
# - Items should be added to the list if new dynamic partitions are added.
# - Items should not be removed from the list even if dynamic partitions are
#   deleted. When generating an incremental OTA package, this script needs to
#   know that an image is present in source build but not in target build.
USERIMAGE_PARTITIONS = [
    "product",
    "odm",
]

def GetUserImages(input_tmp, input_zip):
  return {partition: GetUserImage(partition, input_tmp, input_zip)
          for partition in USERIMAGE_PARTITIONS
          if os.path.exists(os.path.join(input_tmp,
                                         "IMAGES", partition + ".img"))}

def FullOTA_GetBlockDifferences(info):
  images = GetUserImages(info.input_tmp, info.input_zip)
  return [BlockDifference(partition, image)
          for partition, image in images.items()]

def IncrementalOTA_GetBlockDifferences(info):
  source_images = GetUserImages(info.source_tmp, info.source_zip)
  target_images = GetUserImages(info.target_tmp, info.target_zip)

  # Use EmptyImage() as a placeholder for partitions that will be deleted.
  for partition in source_images:
    target_images.setdefault(partition, EmptyImage())

  # Use source_images.get() because new partitions are not in source_images.
  return [BlockDifference(partition, target_image, source_images.get(partition))
          for partition, target_image in target_images.items()]

อัปเดตโฟลว์

เบื้องหลัง ระบบจะเพิ่มฟังก์ชันต่อไปนี้ลงในสคริปต์ edify

  • unmap_partition(name)
    • ยกเลิกการแมปพาร์ติชันหากมีการแมปไว้ ไม่เช่นนั้นไม่ต้องดำเนินการใดๆ
    • แสดงผลสตริง t เมื่อสําเร็จ หรือสตริงว่างเมื่อไม่สําเร็จ
  • map_partition(name)
    • แมปพาร์ติชันหากยังไม่ได้แมป
    • แสดงผลเส้นทางสัมบูรณ์ของอุปกรณ์บล็อกที่แมปหากสําเร็จ หรือสตริงว่างหากไม่สําเร็จ
  • update_dynamic_partitions(op_list)
    • ใช้รายการการดำเนินการที่ระบุกับข้อมูลเมตาของพาร์ติชันแบบไดนามิก โดยยกเลิกการแมปพาร์ติชันหากจำเป็น
    • แสดงผล t เมื่อดำเนินการสำเร็จ หรือสตริงว่างเมื่อดำเนินการไม่สำเร็จ

อาร์กิวเมนต์ op_list ของ update_dynamic_partitions จะชี้ไปยังไฟล์ในแพ็กเกจอัปเดต แต่ละบรรทัดในไฟล์จะระบุการดำเนินการ หากการดำเนินการใดไม่สำเร็จ update_dynamic_partitions จะแสดงผลสตริงว่างทันที การดำเนินการมีดังนี้

  • resize partition-name size
    • ยกเลิกการแมปพาร์ติชัน แล้วปรับขนาดเป็น size
  • remove partition_name
    • ยกเลิกการแมปพาร์ติชัน แล้วนำพาร์ติชันออก
  • add partition-name group-name
    • เพิ่มพาร์ติชันใหม่ลงในกลุ่มที่ระบุ
    • ยกเลิกหากไม่มีกลุ่มหรือมีพาร์ติชันอยู่แล้ว
  • move partition-name group-name
    • ย้ายพาร์ติชันไปยังกลุ่มที่ระบุ
    • ยกเลิกหากไม่มีกลุ่มหรือพาร์ติชัน
  • add_group group-name maximum-size
    • เพิ่มกลุ่มที่มีชื่อและขนาดสูงสุดที่ระบุ
    • ล้มเลิกหากมีกลุ่มนี้อยู่แล้ว
    • maximum_size เท่ากับ 0 หมายความว่าไม่มีการจำกัดขนาดของพาร์ติชันในกลุ่ม ต้องมีการทดสอบเพิ่มเติมเพื่อให้แน่ใจว่าพาร์ติชันในกลุ่มมีขนาดใหญ่ไม่เกินพื้นที่ว่างในอุปกรณ์
  • resize_group group-name maximum-size
    • ปรับขนาดกลุ่มเป็นขนาดสูงสุดที่ระบุ
    • ยกเลิกหากไม่มีกลุ่ม
    • maximum_size เท่ากับ 0 หมายความว่าไม่มีการจำกัดขนาดของพาร์ติชันในกลุ่ม ต้องมีการทดสอบเพิ่มเติมเพื่อให้แน่ใจว่าพาร์ติชันในกลุ่มมีขนาดใหญ่ไม่เกินพื้นที่ว่างในอุปกรณ์
  • remove_group group-name
    • นำกลุ่มออก
    • ล้มเลิกหากมีพาร์ติชันในกลุ่ม
  • remove_all_groups
    • ยกเลิกการแมปพาร์ติชันทั้งหมดออกจากโปรแกรมแมปอุปกรณ์
    • นำพาร์ติชันและกลุ่มทั้งหมดออก

OTA ที่เพิ่มขึ้น

การอัปเดต OTA ที่เพิ่มขึ้นจะใช้ตรรกะต่อไปนี้

  1. ย่อขนาดพาร์ติชัน/ลบพาร์ติชัน/ย้ายพาร์ติชันออกจากกลุ่ม (เพื่อให้มีพื้นที่เพียงพอในการย่อขนาดกลุ่ม)
  2. ย่อกลุ่ม (เพื่อให้มีที่ว่างเพียงพอที่จะเพิ่มกลุ่ม)
  3. ขยายกลุ่ม (เพื่อให้เรามีพื้นที่เพียงพอสำหรับการขยาย/เพิ่มพาร์ติชัน)
  4. ขยายพาร์ติชัน/เพิ่มพาร์ติชัน/ย้ายพาร์ติชันไปยังกลุ่มใหม่

โดยละเอียดคือ update-script สร้างขึ้นด้วยตรรกะนี้

for each shrinking partition:
    block_image_update(map_partition(name), …)

update_dynamic_partitions(op_list)

for each growing / adding partition:
    block_image_update(map_partition(name), …)

ระบบจะสร้างไฟล์ op_list สำหรับ update_dynamic_partitions ด้วยตรรกะต่อไปนี้

for each deleting partition:
    remove
for each partition that changes groups:
    move to "default"
for each shrinking partition:
    resize
for each shrinking / removing group:
    resize_group / remove_group
for each growing / adding group:
    resize_group / add_group
for each adding partition:
    add
for each growing / adding partition:
    resize
for each partition that changes groups:
    move to target group

OTA เต็มรูปแบบ

การอัปเดต OTA แบบเต็มจะใช้ตรรกะต่อไปนี้

  1. ลบกลุ่มและพาร์ติชันที่มีอยู่ทั้งหมด
  2. เพิ่มกลุ่ม
  3. เพิ่มพาร์ติชัน

โดยรายละเอียดคือ update-script สร้างขึ้นด้วยตรรกะนี้

update_dynamic_partitions(op_list)

for each adding partition:
    block_image_update(map_partition(name), …)

ระบบจะสร้างไฟล์ op_list สำหรับ update_dynamic_partitions ด้วยตรรกะต่อไปนี้

remove_all_groups
for each adding group:
    add_group
for each adding partition:
    add
for each adding partition:
    resize