A/B আপডেট প্রয়োগ করা

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

বুট কন্ট্রোল HAL প্রয়োগ করা

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

এছাড়াও, আপনাকে নিচে দেখানো স্টেট মেশিন প্রয়োগ করতে হবে:

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

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

A/B সিস্টেম আপডেট প্রয়োগ করতে:

  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> হিসেবে পাস করুন। যেমন, pass Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f-এর পরিবর্তে <public-key-id>।

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

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 ডিভাইসে রিকভারি পার্টিশন বা ক্যাশে পার্টিশনের প্রয়োজন হয় না কারণ Android আর এইসব পার্টিশন ব্যবহার করে না। ডাউনলোড করা OTA প্যাকেজের জন্য এখন ডেটা পার্টিশন ব্যবহার করা হয় এবং বুট পার্টিশনে রিকভারি ইমেজ কোড থাকে। A/B-ড করা সব পার্টিশনকে নিম্নলিখিতভাবে নাম দিতে হবে (স্লটগুলিকে সবসময় a, b, ইত্যাদি নামে ডাকা হয়): boot_a, boot_b, system_a, system_b, vendor_a, vendor_b.

ক্যাশে

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

রিকভারি

রিকভারি RAM ডিস্ক এখন boot.img ফাইলে রয়েছে। রিকভারি মোডে যাওয়ার সময়, বুটলোডার কার্নেল কমান্ড লাইনে skip_initramfs বিকল্পটি রাখতে পারে না।

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

Fstab

slotselect আর্গুমেন্ট অবশ্যই A/B-ed পার্টিশনের লাইনে থাকতে হবে। যেমন:

<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 ডিভাইসে বর্তমান স্লট ফ্ল্যাশ করে। আপডেট প্যাকেজে যদি অন্য, নন-কারেন্ট স্লটের ছবিও থাকে, তাহলে fastboot সেই ছবিগুলিও ফ্ল্যাশ করে। উপলভ্য বিকল্পের মধ্যে রয়েছে:

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

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

  • has-slot:<partition-base-name-without-suffix>। প্রদত্ত পার্টিশনে স্লট কাজ করলে “হ্যাঁ” এবং না করলে “না” রিটার্ন করে।
  • current-slot. এর পরে যে স্লট থেকে বুট করা হবে তার স্লট সাফিক্স রিটার্ন করে।
  • slot-count। উপলভ্য স্লটের সংখ্যা বোঝায় এমন একটি পূর্ণসংখ্যা রিটার্ন করে। বর্তমানে, দুটি স্লট কাজ করে তাই এই ভ্যালু হল 2।
  • slot-successful:<slot-suffix>। প্রদত্ত স্লটটি সফলভাবে বুট করা হয়েছে হিসেবে চিহ্নিত করা হলে "হ্যাঁ" রিটার্ন করে, অন্যথায় "না" রিটার্ন করে।
  • slot-unbootable:<slot-suffix>। প্রদত্ত স্লটটি বুট করার অযোগ্য হিসেবে চিহ্নিত করা থাকলে “হ্যাঁ” রিটার্ন করে, অন্যথায় “না” রিটার্ন করে।
  • 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 মেক ভেরিয়েবল দ্বারা কনফিগার করা হয়।

যেমন, এক জোড়া পার্টিশন 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
    

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