A/B আপডেট বাস্তবায়ন করুন

যেসব OEM এবং SoC বিক্রেতা A/B সিস্টেম আপডেট বাস্তবায়ন করতে চান, তাদের অবশ্যই নিশ্চিত করতে হবে যে তাদের বুটলোডার boot_control HAL প্রয়োগ করে এবং কার্নেলে সঠিক প্যারামিটার প্রেরণ করে।

বুট কন্ট্রোল HAL বাস্তবায়ন করুন

A/B-সক্ষম বুটলোডারগুলিকে অবশ্যই hardware/libhardware/include/hardware/boot_control.h এ থাকা boot_control HAL-টি ইমপ্লিমেন্ট করতে হবে। আপনি system/extras/bootctl ইউটিলিটি এবং system/extras/tests/bootloader/ ব্যবহার করে ইমপ্লিমেন্টেশনগুলি পরীক্ষা করতে পারেন।

আপনাকে অবশ্যই নীচে দেখানো স্টেট মেশিনটিও বাস্তবায়ন করতে হবে:

চিত্র ১. বুটলোডার স্টেট মেশিন

কার্নেল সেট আপ করুন

এ/বি সিস্টেম আপডেট বাস্তবায়ন করতে:

  1. নিম্নলিখিত কার্নেল প্যাচ সিরিজটি চেরিপিক করুন (প্রয়োজন হলে):
  2. নিশ্চিত করুন যে কার্নেল কমান্ড লাইন আর্গুমেন্টগুলিতে নিম্নলিখিত অতিরিক্ত আর্গুমেন্টগুলি অন্তর্ভুক্ত রয়েছে:
    skip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"
    ... যেখানে <public-key-id> ভ্যালুটি হলো ভেরিটি টেবিলের সিগনেচার যাচাই করতে ব্যবহৃত পাবলিক কী-এর আইডি (বিস্তারিত জানতে, dm-verity দেখুন)।
  3. পাবলিক কী সম্বলিত .X509 সার্টিফিকেটটি সিস্টেম কী-রিং-এ যুক্ত করুন:
    1. .der ফরম্যাটে ফরম্যাট করা .X509 সার্টিফিকেটটি kernel ডিরেক্টরির রুটে কপি করুন। যদি .X509 সার্টিফিকেটটি .pem ফাইল হিসেবে ফরম্যাট করা থাকে, তাহলে .pem থেকে .der ফরম্যাটে রূপান্তর করতে নিম্নলিখিত openssl কমান্ডটি ব্যবহার করুন:
      openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
    2. সিস্টেম কী-রিং-এর অংশ হিসেবে সার্টিফিকেটটি অন্তর্ভুক্ত করতে zImage টি বিল্ড করুন। যাচাই করার জন্য, procfs এন্ট্রিটি পরীক্ষা করুন (এর জন্য KEYS_CONFIG_DEBUG_PROC_KEYS সক্রিয় থাকা আবশ্যক):
      angler:/# cat /proc/keys
      
      1c8a217e I------     1 perm 1f010000     0     0 asymmetri
      Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f []
      2d454e3e I------     1 perm 1f030000     0     0 keyring
      .system_keyring: 1/4
      .X509 সার্টিফিকেটটির সফল অন্তর্ভুক্তি সিস্টেম কী-রিং-এ পাবলিক কী-টির উপস্থিতি নির্দেশ করে (হাইলাইট করা অংশটি পাবলিক কী আইডি নির্দেশ করে)।
    3. স্পেসটিকে # দিয়ে প্রতিস্থাপন করুন এবং এটিকে কার্নেল কমান্ড লাইনে <public-key-id> হিসেবে পাস করুন। উদাহরণস্বরূপ, <public-key-id> এর জায়গায় Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f পাস করুন।

বিল্ড ভেরিয়েবল সেট করুন

A/B-সক্ষম বুটলোডারকে অবশ্যই নিম্নলিখিত বিল্ড ভেরিয়েবল মানদণ্ড পূরণ করতে হবে:

A/B লক্ষ্যমাত্রার জন্য অবশ্যই সংজ্ঞায়িত করতে হবে
  • AB_OTA_UPDATER := true
  • AB_OTA_PARTITIONS := \
    boot \
    system \
    vendor
    এবং update_engine মাধ্যমে আপডেট করা অন্যান্য পার্টিশন (রেডিও, বুটলোডার, ইত্যাদি)।
  • PRODUCT_PACKAGES += \
    update_engine \
    update_verifier
উদাহরণস্বরূপ, /device/google/marlin/+/android-7.1.0_r1/device-common.mk দেখুন। আপনি ঐচ্ছিকভাবে কম্পাইলিং অংশে বর্ণিত পোস্ট-ইনস্টল (কিন্তু প্রি-রিবুট) dex2oat ধাপটি সম্পাদন করতে পারেন।
A/B টার্গেটের জন্য জোরালোভাবে সুপারিশ করা হচ্ছে।
  • TARGET_NO_RECOVERY := true সংজ্ঞায়িত করুন
  • BOARD_USES_RECOVERY_AS_BOOT := true সংজ্ঞায়িত করুন
  • BOARD_RECOVERYIMAGE_PARTITION_SIZE সংজ্ঞায়িত করবেন না।
A/B লক্ষ্যের জন্য সংজ্ঞায়িত করা সম্ভব নয়
  • BOARD_CACHEIMAGE_PARTITION_SIZE
  • BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
ডিবাগ বিল্ডের জন্য ঐচ্ছিক PRODUCT_PACKAGES_DEBUG += update_engine_client

পার্টিশন (স্লট) সেট করুন

A/B ডিভাইসগুলির জন্য রিকভারি পার্টিশন বা ক্যাশ পার্টিশনের প্রয়োজন হয় না, কারণ অ্যান্ড্রয়েড এখন আর এই পার্টিশনগুলি ব্যবহার করে না। ডেটা পার্টিশনটি এখন ডাউনলোড করা OTA প্যাকেজের জন্য ব্যবহৃত হয় এবং রিকভারি ইমেজ কোডটি বুট পার্টিশনে থাকে। যে সমস্ত পার্টিশন A/B করা হয়েছে, সেগুলির নামকরণ নিম্নলিখিতভাবে করা উচিত (স্লটগুলির নাম সর্বদা a , b , ইত্যাদি হয়): boot_a , boot_b , system_a , system_b , vendor_a , vendor_b

ক্যাশে

নন-এ/বি আপডেটের ক্ষেত্রে, ডাউনলোড করা ওটিএ প্যাকেজগুলো সংরক্ষণ করতে এবং আপডেট প্রয়োগ করার সময় ব্লকগুলোকে সাময়িকভাবে জমা রাখতে ক্যাশ পার্টিশন ব্যবহার করা হতো। ক্যাশ পার্টিশনের আকার নির্ধারণের কোনো ভালো উপায় ছিল না: এটি কতটা বড় হওয়া দরকার তা নির্ভর করত আপনি কোন ধরনের আপডেট প্রয়োগ করতে চান তার উপর। সবচেয়ে খারাপ পরিস্থিতি হতো যদি ক্যাশ পার্টিশনটি সিস্টেম ইমেজের সমান বড় হতো। এ/বি আপডেটের ক্ষেত্রে ব্লক জমা রাখার কোনো প্রয়োজন নেই (কারণ আপনি সবসময় এমন একটি পার্টিশনে লিখছেন যা বর্তমানে ব্যবহৃত হচ্ছে না) এবং স্ট্রিমিং এ/বি আপডেটের ক্ষেত্রে, প্রয়োগ করার আগে পুরো ওটিএ প্যাকেজটি ডাউনলোড করারও প্রয়োজন হয় না।

পুনরুদ্ধার

রিকভারি র‍্যাম ডিস্কটি এখন boot.img ফাইলের মধ্যে থাকে। রিকভারি মোডে যাওয়ার সময়, বুটলোডার কার্নেল কমান্ড লাইনে skip_initramfs অপশনটি যোগ করতে পারে না

নন-এ/বি আপডেটের ক্ষেত্রে, রিকভারি পার্টিশনে আপডেট প্রয়োগ করার জন্য ব্যবহৃত কোড থাকে। এ/বি আপডেটগুলো সাধারণ বুট করা সিস্টেম ইমেজে চলমান update_engine দ্বারা প্রয়োগ করা হয়। ফ্যাক্টরি ডেটা রিসেট এবং আপডেট প্যাকেজের সাইডলোডিং বাস্তবায়নের জন্য এখনও একটি রিকভারি মোড রয়েছে (যেখান থেকে "রিকভারি" নামটি এসেছে)। রিকভারি মোডের কোড এবং ডেটা সাধারণ বুট পার্টিশনের একটি র‍্যামডিস্কে সংরক্ষিত থাকে; সিস্টেম ইমেজে বুট করার জন্য, বুটলোডার কার্নেলকে র‍্যামডিস্ক এড়িয়ে যেতে বলে (অন্যথায় ডিভাইসটি রিকভারি মোডে বুট হয়)। রিকভারি মোড আকারে ছোট (এবং এর বেশিরভাগই আগে থেকেই বুট পার্টিশনে ছিল), তাই বুট পার্টিশনের আকার বাড়ে না।

এফস্ট্যাব

A/B করা পার্টিশনগুলোর জন্য slotselect আর্গুমেন্টটি অবশ্যই লাইনে থাকতে হবে। উদাহরণস্বরূপ:

<path-to-block-device>/vendor  /vendor  ext4  ro
wait,verify=<path-to-block-device>/metadata,slotselect

কোনো পার্টিশনের নাম vendor রাখা উচিত নয়। এর পরিবর্তে, vendor_a অথবা vendor_b পার্টিশনটি নির্বাচিত হবে এবং /vendor মাউন্ট পয়েন্টে মাউন্ট করা হবে।

কার্নেল স্লট আর্গুমেন্ট

বর্তমান স্লট সাফিক্সটি একটি নির্দিষ্ট ডিভাইস ট্রি (DT) নোডের ( /firmware/android/slot_suffix ) মাধ্যমে অথবা androidboot.slot_suffix কার্নেল কমান্ড লাইন বা bootconfig আর্গুমেন্টের মাধ্যমে প্রদান করতে হবে।

ডিফল্টরূপে, ফাস্টবুট একটি A/B ডিভাইসের বর্তমান স্লটটি ফ্ল্যাশ করে। যদি আপডেট প্যাকেজটিতে অন্য, অ-বর্তমান স্লটের জন্যও ইমেজ থাকে, তবে ফাস্টবুট সেই ইমেজগুলোও ফ্ল্যাশ করে। উপলব্ধ বিকল্পগুলির মধ্যে রয়েছে:

  • --slot SLOT . ডিফল্ট আচরণকে অগ্রাহ্য করে আর্গুমেন্ট হিসেবে দেওয়া স্লটটি ফ্ল্যাশ করার জন্য ফাস্টবুটকে নির্দেশ দেয়।
  • --set-active [ SLOT ] . স্লটটিকে সক্রিয় হিসেবে সেট করুন। যদি কোনো ঐচ্ছিক আর্গুমেন্ট নির্দিষ্ট না করা হয়, তাহলে বর্তমান স্লটটি সক্রিয় হিসেবে সেট করা হবে।
  • fastboot --help . কমান্ডগুলো সম্পর্কে বিস্তারিত জানুন।

যদি বুটলোডারটি ফাস্টবুট (fastboot) প্রয়োগ করে, তবে এটিকে set_active <slot> কমান্ডটি সমর্থন করতে হবে, যা বর্তমান সক্রিয় স্লটটিকে প্রদত্ত স্লটে সেট করে (এর জন্য অবশ্যই সেই স্লটের আনবুটেবল ফ্ল্যাগটি মুছে ফেলতে হবে এবং রিট্রাই কাউন্টকে ডিফল্ট মানে রিসেট করতে হবে)। বুটলোডারটিকে নিম্নলিখিত ভেরিয়েবলগুলোও সমর্থন করতে হবে:

  • has-slot:<partition-base-name-without-suffix> . প্রদত্ত পার্টিশনটি স্লট সমর্থন করলে “yes” রিটার্ন করে, অন্যথায় “no”।
  • current-slot . পরবর্তী যে স্লট থেকে বুট করা হবে, সেই স্লট সাফিক্সটি ফেরত দেয়।
  • slot-count . উপলব্ধ স্লটের সংখ্যা নির্দেশকারী একটি পূর্ণসংখ্যা রিটার্ন করে। বর্তমানে দুটি স্লট সমর্থিত হওয়ায় এর মান হলো 2
  • slot-successful:<slot-suffix> . প্রদত্ত স্লটটি সফলভাবে বুট হচ্ছে বলে চিহ্নিত হলে "yes" রিটার্ন করে, অন্যথায় "no" রিটার্ন করে।
  • slot-unbootable:<slot-suffix> . প্রদত্ত স্লটটি আনবুটেবল হিসেবে চিহ্নিত করা থাকলে “yes” রিটার্ন করে, অন্যথায় “no”।
  • slot-retry-count:<slot-suffix> . প্রদত্ত স্লটটি বুট করার জন্য অবশিষ্ট পুনঃচেষ্টার সংখ্যা।

সমস্ত ভেরিয়েবল দেখতে, fastboot getvar all কমান্ডটি চালান।

OTA প্যাকেজ তৈরি করুন

OTA প্যাকেজ টুলগুলো নন-A/B ডিভাইসের কমান্ডগুলোর মতোই একই কমান্ড অনুসরণ করে। A/B টার্গেটের জন্য বিল্ড ভেরিয়েবলগুলো নির্ধারণ করে target_files.zip ফাইলটি অবশ্যই তৈরি করতে হবে। OTA প্যাকেজ টুলগুলো স্বয়ংক্রিয়ভাবে A/B আপডেটারের ফরম্যাটে প্যাকেজ শনাক্ত ও তৈরি করে।

উদাহরণ:

  • সম্পূর্ণ OTA তৈরি করতে:
    ./build/make/tools/releasetools/ota_from_target_files \
        dist_output/tardis-target_files.zip \
        ota_update.zip
    
  • একটি ক্রমবর্ধমান OTA তৈরি করতে:
    ./build/make/tools/releasetools/ota_from_target_files \
        -i PREVIOUS-tardis-target_files.zip \
        dist_output/tardis-target_files.zip \
        incremental_ota_update.zip
    

পার্টিশন কনফিগার করুন

update_engine একই ডিস্কে সংজ্ঞায়িত যেকোনো একজোড়া A/B পার্টিশন আপডেট করতে পারে। একজোড়া পার্টিশনের একটি সাধারণ প্রিফিক্স (যেমন system বা boot ) এবং প্রতি-স্লট সাফিক্স (যেমন _a ) থাকে। যে পার্টিশনগুলোর জন্য পেলোড জেনারেটর একটি আপডেট সংজ্ঞায়িত করে, সেই পার্টিশনগুলোর তালিকা AB_OTA_PARTITIONS make ভেরিয়েবল দ্বারা কনফিগার করা হয়।

উদাহরণস্বরূপ, যদি bootloader_a এবং booloader_b নামের একজোড়া পার্টিশন অন্তর্ভুক্ত থাকে ( _a এবং _b হলো স্লট সাফিক্স), তাহলে আপনি প্রোডাক্ট বা বোর্ড কনফিগারেশনে নিম্নলিখিত বিষয়গুলো উল্লেখ করে এই পার্টিশনগুলো আপডেট করতে পারেন:

AB_OTA_PARTITIONS := \
  boot \
  system \
  bootloader

update_engine দ্বারা আপডেট করা সমস্ত পার্টিশন সিস্টেমের বাকি অংশ দ্বারা পরিবর্তন করা যাবে না। ইনক্রিমেন্টাল বা ডেল্টা আপডেটের সময়, নতুন স্লটের ডেটা তৈরি করার জন্য বর্তমান স্লটের বাইনারি ডেটা ব্যবহার করা হয়। যেকোনো পরিবর্তনের ফলে আপডেট প্রক্রিয়া চলাকালীন নতুন স্লটের ডেটা ভেরিফিকেশনে ব্যর্থ হতে পারে, এবং ফলস্বরূপ আপডেটটি ব্যর্থ হবে।

পোস্টইনস্টলেশন কনফিগার করুন

আপনি এক সেট কী-ভ্যালু পেয়ার ব্যবহার করে প্রতিটি আপডেট করা পার্টিশনের জন্য পোস্টইনস্টল ধাপটি ভিন্নভাবে কনফিগার করতে পারেন। একটি নতুন ইমেজে /system/usr/bin/postinst এ অবস্থিত কোনো প্রোগ্রাম চালানোর জন্য, সিস্টেম পার্টিশনের ফাইলসিস্টেমের রুটের সাপেক্ষে পাথটি নির্দিষ্ট করুন।

উদাহরণস্বরূপ, usr/bin/postinst হলো system/usr/bin/postinst (যদি RAM ডিস্ক ব্যবহার না করা হয়)। এছাড়াও, mount(2) সিস্টেম কলে পাস করার জন্য ফাইলসিস্টেমের ধরন নির্দিষ্ট করুন। প্রোডাক্ট বা ডিভাইসের .mk ফাইলগুলিতে (যদি প্রযোজ্য হয়) নিম্নলিখিতগুলি যোগ করুন:

AB_OTA_POSTINSTALL_CONFIG += \
  RUN_POSTINSTALL_system=true \
  POSTINSTALL_PATH_system=usr/bin/postinst \
  FILESYSTEM_TYPE_system=ext4

অ্যাপস কম্পাইল করুন

নতুন সিস্টেম ইমেজ দিয়ে রিবুট করার আগে অ্যাপগুলো ব্যাকগ্রাউন্ডে কম্পাইল করা যেতে পারে। ব্যাকগ্রাউন্ডে অ্যাপ কম্পাইল করতে, প্রোডাক্টের ডিভাইস কনফিগারেশনে (প্রোডাক্টের device.mk ফাইলে) নিম্নলিখিতটি যোগ করুন:

  1. বিল্ডে নেটিভ কম্পোনেন্টগুলো অন্তর্ভুক্ত করুন, যাতে কম্পাইলেশন স্ক্রিপ্ট এবং বাইনারিগুলো কম্পাইল হয়ে সিস্টেম ইমেজে অন্তর্ভুক্ত হয়।
      # A/B OTA dexopt package
      PRODUCT_PACKAGES += otapreopt_script
    
  2. কম্পাইলেশন স্ক্রিপ্টটিকে update_engine এর সাথে এমনভাবে সংযুক্ত করুন যাতে এটি একটি পোস্ট-ইনস্টল ধাপ হিসেবে চলে।
      # A/B OTA dexopt update_engine hookup
      AB_OTA_POSTINSTALL_CONFIG += \
        RUN_POSTINSTALL_system=true \
        POSTINSTALL_PATH_system=system/bin/otapreopt_script \
        FILESYSTEM_TYPE_system=ext4 \
        POSTINSTALL_OPTIONAL_system=true
    

অব্যবহৃত দ্বিতীয় সিস্টেম পার্টিশনে প্রি-অপটেড ফাইলগুলি ইনস্টল করার জন্য, "DEX_PREOPT ফাইলগুলির প্রথম বুট ইনস্টলেশন" দেখুন।