ডায়নামিক পার্টিশন প্রয়োগ করা

Linux কার্নেলে dm-linear ডিভাইস-ম্যাপার মডিউল ব্যবহার করে ডায়নামিক পার্টিশনিং প্রয়োগ করা হয়। super পার্টিশনে মেটাডেটা থাকে যা super-এর মধ্যে প্রতিটি ডায়নামিক পার্টিশনের নাম ও ব্লক রেঞ্জের তালিকা দেখায়। প্রথম-স্টেজ init চলাকালীন, এই মেটাডেটা পার্স ও যাচাই করা হয় এবং প্রতিটি ডায়নামিক পার্টিশনকে প্রতিনিধিত্ব করার জন্য ভার্চুয়াল ব্লক ডিভাইস তৈরি করা হয়।

OTA প্রয়োগ করার সময়, প্রয়োজন অনুযায়ী ডায়নামিক পার্টিশন অটোমেটিক তৈরি, ছোট বড় বা মুছে ফেলা হয়। A/B ডিভাইসের ক্ষেত্রে, মেটাডেটার দুটি কপি থাকে এবং পরিবর্তন শুধুমাত্র টার্গেট স্লটকে প্রতিনিধিত্বকারী কপিতেই প্রয়োগ করা হয়।

যেহেতু ডায়নামিক পার্টিশন ইউজারস্পেসে প্রয়োগ করা হয়, তাই বুটলোডারের জন্য প্রয়োজনীয় পার্টিশন ডায়নামিক করা যায় না। যেমন, boot, dtbo ও vbmeta বুটলোডার দ্বারা পড়া হয় এবং তাই এগুলিকে অবশ্যই ফিজিক্যাল পার্টিশন হিসেবে থাকতে হবে।

প্রতিটি ডায়নামিক পার্টিশন একটি আপডেট গ্রুপের অংশ হতে পারে। এইসব গ্রুপ, সেই গ্রুপের পার্টিশন সর্বাধিক কতখানি জায়গা নিতে পারে তা সীমিত করে। যেমন, system এবং vendor এমন একটি গ্রুপের অংশ হতে পারে যা system এবং vendor-এর মোট সাইজ সীমাবদ্ধ করে।

নতুন ডিভাইসে ডায়নামিক পার্টিশন প্রয়োগ করা

Android 10 এবং তার পরবর্তী যেকোনও ভার্সন সহ লঞ্চ হওয়া নতুন ডিভাইসে কীভাবে ডায়নামিক পার্টিশন প্রয়োগ করতে হয় সেই বিষয়ে এই বিভাগে বিস্তারিত তথ্য দেওয়া হয়েছে। আগে থেকে থাকা ডিভাইস আপডেট করতে, Android ডিভাইস আপগ্রেড করা দেখুন।

পার্টিশনে পরিবর্তন

Android 10 ভার্সন সহ লঞ্চ করা ডিভাইসের জন্য, super নামের একটি পার্টিশন তৈরি করুন। super পার্টিশন ইন্টার্নালি A/B স্লট ম্যানেজ করে, তাই A/B ডিভাইসের জন্য আলাদা super_a এবং super_b পার্টিশনের প্রয়োজন হয় না। সব রিড-অনলি AOSP পার্টিশন যা বুটলোডার ব্যবহার করে না, সেগুলি অবশ্যই ডায়নামিক হতে হবে এবং GUID পার্টিশন টেবিল (GPT) থেকে সরিয়ে দিতে হবে। ভেন্ডর-নির্দিষ্ট পার্টিশন ডায়নামিক হতে হবে না এবং GPT-তে রাখা যেতে পারে।

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

পার্টিশন টেবিল লেআউট
ছবি ১. ডায়নামিক পার্টিশনে কনভার্ট করার সময় নতুন ফিজিক্যাল পার্টিশন টেবিল লেআউট

যেসব ডায়নামিক পার্টিশন কাজ করে:

  • সিস্টেম
  • ভেন্ডর
  • প্রোডাক্ট
  • সিস্টেম এক্সটেনশন
  • ODM

Android 10-এর সাথে লঞ্চ করা ডিভাইসের জন্য, কার্নেল কমান্ড লাইন বিকল্প androidboot.super_partition অবশ্যই খালি থাকতে হবে যাতে কমান্ড sysprop ro.boot.super_partition খালি থাকে।

পার্টিশন অ্যালাইনমেন্ট

super পার্টিশন সঠিকভাবে অ্যালাইন করা না থাকলে ডিভাইস-ম্যাপার মডিউল কম দক্ষতার সাথে কাজ করতে পারে। ব্লক লেয়ারের নির্ধারিত ন্যূনতম I/O অনুরোধের সাইজের সাথে super পার্টিশনকে অবশ্যই অ্যালাইন করতে হবে। ডিফল্ট হিসেবে, বিল্ড সিস্টেম (lpmake-এর মাধ্যমে, যা super পার্টিশন ইমেজ তৈরি করে) ধরে নেয় যে প্রতিটি ডায়নামিক পার্টিশনের জন্য ১ MiB অ্যালাইনমেন্ট যথেষ্ট। তবে, ভেন্ডরদের নিশ্চিত করতে হবে যে super পার্টিশনটি সঠিকভাবে অ্যালাইন করা আছে।

আপনি sysfs পরীক্ষা করে ব্লক ডিভাইসের ন্যূনতম অনুরোধের সাইজ নির্ধারণ করতে পারেন। যেমন:

# ls -l /dev/block/by-name/super
lrwxrwxrwx 1 root root 16 1970-04-05 01:41 /dev/block/by-name/super -> /dev/block/sda17
# cat /sys/block/sda/queue/minimum_io_size
786432

আপনি একই পদ্ধতিতে super পার্টিশনের অ্যালাইনমেন্ট যাচাই করতে পারবেন:

# cat /sys/block/sda/sda17/alignment_offset

অ্যালাইনমেন্ট অফসেট অবশ্যই ০ হতে হবে।

ডিভাইস কনফিগারেশনে পরিবর্তন

ডায়নামিক পার্টিশনিং চালু করতে, নিম্নলিখিত ফ্ল্যাগটি device.mk-এ যোগ করুন:

PRODUCT_USE_DYNAMIC_PARTITIONS := true

বোর্ড কনফিগারেশনে পরিবর্তন

আপনাকে super পার্টিশনের সাইজ সেট করতে হবে:

BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>

A/B ডিভাইসে, ডায়নামিক পার্টিশন ইমেজের মোট সাইজ super পার্টিশন সাইজের অর্ধেকের বেশি হলে, বিল্ড সিস্টেম একটি সমস্যা দেখায়।

আপনি নিম্নলিখিত উপায়ে ডায়নামিক পার্টিশনের তালিকা কনফিগার করতে পারবেন। আপডেট গ্রুপ ব্যবহার করা ডিভাইসের জন্য, BOARD_SUPER_PARTITION_GROUPS ভেরিয়েবলে গ্রুপগুলি তালিকাভুক্ত করুন। প্রতিটি গ্রুপের নামের পরে BOARD_group_SIZE এবং BOARD_group_PARTITION_LIST ভেরিয়েবল থাকে। A/B ডিভাইসের জন্য, একটি গ্রুপের সর্বাধিক সাইজ শুধুমাত্র একটি স্লট কভার করা উচিত, কারণ গ্রুপের নামগুলি ইন্টার্নালি স্লট-সাফিক্সড।

এখানে একটি ডিভাইসের উদাহরণ দেওয়া হল যা example_dynamic_partitions নামের একটি গ্রুপে সব পার্টিশন রাখে:

BOARD_SUPER_PARTITION_GROUPS := example_dynamic_partitions
BOARD_EXAMPLE_DYNAMIC_PARTITIONS_SIZE := 6442450944
BOARD_EXAMPLE_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product

এখানে একটি ডিভাইসের উদাহরণ দেওয়া হল যা সিস্টেম ও প্রোডাক্ট পরিষেবা group_foo-এ এবং vendor, product ও odm-কে group_bar-এ রাখে:

BOARD_SUPER_PARTITION_GROUPS := group_foo group_bar
BOARD_GROUP_FOO_SIZE := 4831838208
BOARD_GROUP_FOO_PARTITION_LIST := system product_services
BOARD_GROUP_BAR_SIZE := 1610612736
BOARD_GROUP_BAR_PARTITION_LIST := vendor product odm
  • ভার্চুয়াল A/B লঞ্চ ডিভাইসের জন্য, সব গ্রুপের সর্বাধিক সাইজের যোগফল অবশ্যই সর্বাধিক হতে হবে:
    BOARD_SUPER_PARTITION_SIZE - ওভারহেড
    ভার্চুয়াল A/B প্রয়োগ করা দেখুন।
  • A/B লঞ্চ ডিভাইসের ক্ষেত্রে, সব গ্রুপের সর্বাধিক সাইজের যোগফলকে অবশ্যই:
    BOARD_SUPER_PARTITION_SIZE / ২ - ওভারহেড হতে হবে
  • নন-A/B ডিভাইস ও রেট্রোফিট A/B ডিভাইসের ক্ষেত্রে, সব গ্রুপের সর্বাধিক সাইজের যোগফল অবশ্যই:
    BOARD_SUPER_PARTITION_SIZE - ওভারহেড হতে হবে
  • বিল্ড করার সময়, আপডেট গ্রুপের প্রতিটি পার্টিশনের ছবির সাইজের যোগফল গ্রুপের সর্বাধিক সাইজের বেশি হওয়া চলবে না।
  • মেটাডেটা, অ্যালাইনমেন্ট ইত্যাদি হিসেব করার জন্য কম্পিউটেশনে ওভারহেড প্রয়োজন। ৪ MiB হল যুক্তিসঙ্গত ওভারহেড, তবে আপনি ডিভাইসের প্রয়োজন অনুযায়ী আরও বড় ওভারহেড বেছে নিতে পারেন।

ডায়নামিক পার্টিশনের সাইজ নির্ধারণ করুন

ডায়নামিক পার্টিশনের আগে, পার্টিশনের সাইজ অতিরিক্ত বরাদ্দ করা হত যাতে ভবিষ্যতের আপডেটের জন্য পর্যাপ্ত জায়গা থাকে। আসল সাইজ যেমন ছিল তেমনই নেওয়া হয়েছে এবং বেশিরভাগ রিড-অনলি পার্টিশনের ফাইল সিস্টেমে কিছুটা জায়গা খালি ছিল। ডায়নামিক পার্টিশনে, সেই খালি জায়গাটি ব্যবহারযোগ্য নয় এবং OTA চলাকালীন পার্টিশনের সাইজ বাড়ানোর জন্য ব্যবহার করা যেতে পারে। পার্টিশন যাতে জায়গা নষ্ট না করে এবং সেগুলিকে সম্ভাব্য সবচেয়ে ছোট সাইজে অ্যালোকেট করা হয় তা নিশ্চিত করা অত্যন্ত গুরুত্বপূর্ণ।

শুধুমাত্র-পঠনযোগ্য ext4 ছবির জন্য, কোনও হার্ডকোড করা পার্টিশনের সাইজ নির্দিষ্ট করা না থাকলে, বিল্ড সিস্টেম অটোমেটিক ন্যূনতম সাইজ অ্যাসাইন করে। বিল্ড সিস্টেম ছবিটিকে এমনভাবে ফিট করে যাতে ফাইল সিস্টেমে যতটা সম্ভব কম অব্যবহৃত জায়গা থাকে। এটি নিশ্চিত করে যে ডিভাইসটি এমন জায়গা নষ্ট করে না যা OTA-এর জন্য ব্যবহার করা যেতে পারে।

এছাড়াও, ব্লক- লেভেল ডিডুপ্লিকেশন চালু করার মাধ্যমে ext4 ছবি আরও কম্প্রেস করা যেতে পারে। এটি চালু করতে, নিম্নলিখিত কনফিগারেশন ব্যবহার করুন:

BOARD_EXT4_SHARE_DUP_BLOCKS := true

পার্টিশনের ন্যূনতম সাইজ অটোমেটিক অ্যাসাইন করা অবাঞ্ছিত হলে, পার্টিশনের সাইজ কন্ট্রোল করার দুটি উপায় আছে। আপনি BOARD_partitionIMAGE_PARTITION_RESERVED_SIZE-এর মাধ্যমে ফাঁকা জায়গার ন্যূনতম পরিমাণ নির্দিষ্ট করতে পারেন অথবা আপনি BOARD_partitionIMAGE_PARTITION_SIZE নির্দিষ্ট করে ডায়নামিক পার্টিশনকে নির্দিষ্ট সাইজে সেট করতে পারেন। প্রয়োজন না হলে এর কোনওটিই সাজেস্ট করা হয় না।

যেমন:

BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800

এর ফলে product.img-এর ফাইল সিস্টেমে ৫০ MiB অব্যবহৃত জায়গা থাকতে বাধ্য হয়।

সিস্টেম-অ্যাজ-রুট পরিবর্তন

Android 10-এর সাথে লঞ্চ হওয়া ডিভাইসে system-as-root ব্যবহার করা যাবে না।

ডায়নামিক পার্টিশন (এটি ডায়নামিক পার্টিশন সহ লঞ্চ হোক বা রেট্রোফিট ডায়নামিক পার্টিশন হোক) সহ ডিভাইসকে অবশ্যই সিস্টেম-অ্যাজ-রুট ব্যবহার করা যাবে না। Linux কার্নেল super পার্টিশনকে ব্যাখ্যা করতে পারে না এবং তাই এটি নিজে থেকে মাউন্ট system করতে পারে না। system এখন ফার্স্ট-স্টেজ init-এর দ্বারা মাউন্ট করা হয়েছে, যা র‍্যামডিস্কে থাকে।

BOARD_BUILD_SYSTEM_ROOT_IMAGE সেট করবেন না। Android ১০-এ, BOARD_BUILD_SYSTEM_ROOT_IMAGE ফ্ল্যাগটি শুধুমাত্র সিস্টেমটি কার্নেল দ্বারা মাউন্ট করা হয়েছে নাকি রামডিস্কে প্রথম-পর্যায়ের init দ্বারা মাউন্ট করা হয়েছে তা আলাদা করতে ব্যবহৃত হয়।

BOARD_BUILD_SYSTEM_ROOT_IMAGE-কে true-এ সেট করলে বিল্ড সংক্রান্ত সমস্যা হয়, যখন PRODUCT_USE_DYNAMIC_PARTITIONS-ও true হয়।

BOARD_USES_RECOVERY_AS_BOOT-এর মান true হিসেবে সেট করা থাকলে, রিকভারি ইমেজটি boot.img হিসেবে তৈরি হয়, এতে রিকভারির ramdisk থাকে। আগে, কোন মোডে বুট করতে হবে তা নির্ধারণ করতে বুটলোডার skip_initramfs কার্নেল কমান্ড লাইন প্যারামিটার ব্যবহার করত। Android 10 ডিভাইসের জন্য, বুটলোডারকে অবশ্যই কার্নেল কমান্ড-লাইনে skip_initramfs পাস করা যাবে না। পরিবর্তে, রিকভারি এড়িয়ে যেতে বুটলোডারকে androidboot.force_normal_boot=1 পাস করতে হবে এবং স্বাভাবিক Android বুট করতে হবে। Android 12 বা এর পরের যেকোনও ভার্সন নিয়ে লঞ্চ করা ডিভাইসকে androidboot.force_normal_boot=1 পাস করার জন্য বুটকনফিগার ব্যবহার করতে হবে।

AVB কনফিগারেশনে পরিবর্তন

Android Verified Boot 2.0 ব্যবহার করার সময়, ডিভাইস চেনড পার্টিশন ডেসক্রিপ্টর ব্যবহার না করলে, কোনও পরিবর্তন করার প্রয়োজন নেই। তবে, চেইন করা পার্টিশন ব্যবহার করলে এবং যাচাই করা পার্টিশনের মধ্যে একটি ডায়নামিক হলে, পরিবর্তন করতে হবে।

এখানে একটি ডিভাইসের জন্য উদাহরণ কনফিগারেশন দেওয়া হল যা system এবং vendor পার্টিশনের জন্য vbmeta চেইন করে।

BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048
BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1

BOARD_AVB_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_VENDOR_ALGORITHM := SHA256_RSA2048
BOARD_AVB_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_VENDOR_ROLLBACK_INDEX_LOCATION := 1

এই কনফিগারেশনের মাধ্যমে, বুটলোডার system এবং vendor পার্টিশনের শেষে একটি vbmeta ফুটার খুঁজে পাওয়ার আশা করে। কারণ, এই পার্টিশনগুলি বুটলোডার আর দেখতে পায় না (এগুলি super-এ থাকে), দুটি পরিবর্তন করতে হবে।

  • ডিভাইসের পার্টিশন টেবিলে vbmeta_system এবং vbmeta_vendor পার্টিশন যোগ করুন। A/B ডিভাইসের জন্য, এগুলি যোগ করুন vbmeta_system_a, vbmeta_system_b, vbmeta_vendor_a এবং vbmeta_vendor_b. এইসব পার্টিশনের মধ্যে এক বা একাধিক যোগ করলে, সেগুলি vbmeta পার্টিশনের মতো একই সাইজের হতে হবে।
  • VBMETA_ যোগ করে কনফিগারেশন ফ্ল্যাগের নাম পরিবর্তন করুন এবং চেনিং কোন কোন পার্টিশন পর্যন্ত এক্সটেন্ড করে তা উল্লেখ করুন:
    BOARD_AVB_VBMETA_SYSTEM := system
    BOARD_AVB_VBMETA_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
    BOARD_AVB_VBMETA_SYSTEM_ALGORITHM := SHA256_RSA2048
    BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
    BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX_LOCATION := 1
    
    BOARD_AVB_VBMETA_VENDOR := vendor
    BOARD_AVB_VBMETA_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
    BOARD_AVB_VBMETA_VENDOR_ALGORITHM := SHA256_RSA2048
    BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
    BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX_LOCATION := 1

কোনও ডিভাইস একটি, দুটি বা কোনও পার্টিশনই ব্যবহার নাও করতে পারে। লজিক্যাল পার্টিশনে চেনিং করার সময় শুধু পরিবর্তন করতে হয়।

AVB বুটলোডারে পরিবর্তন

বুটলোডারে libavb এম্বেড করা থাকলে, নিম্নলিখিত প্যাচ অন্তর্ভুক্ত করুন:

চেন করা পার্টিশন ব্যবহার করলে, একটি অতিরিক্ত প্যাচ যোগ করুন:

  • 49936b4c0109411fdd38bd4ba3a32a01c40439a9 — "libavb: Support vbmeta blobs in beginning of partition."

কার্নেল কমান্ড লাইনে পরিবর্তন

কার্নেল কমান্ড লাইনে একটি নতুন প্যারামিটার, androidboot.boot_devices, যোগ করতে হবে । init এটি ব্যবহার করে /dev/block/by-name সিমলিঙ্ক চালু করে। এটি ueventd-এর তৈরি করা নাম-ভিত্তিক অন্তর্নিহিত সিমলিঙ্কের ডিভাইস পাথ কম্পোনেন্ট হতে হবে, অর্থাৎ, /dev/block/platform/device-path/by-name/partition-name. Android 12 বা এর পরবর্তী যেকোনও ভার্সন নিয়ে লঞ্চ করা ডিভাইসকে androidboot.boot_devices থেকে init-এ পাস করার জন্য bootconfig ব্যবহার করতে হবে।

যেমন, সুপার পার্টিশন বাই-নেম সিমলিঙ্ক /dev/block/platform/soc/100000.ufshc/by-name/super হলে, আপনি BoardConfig.mk ফাইলে কমান্ড লাইন প্যারামিটার এইভাবে যোগ করতে পারবেন:

BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc/100000.ufshc
আপনি BoardConfig.mk ফাইলে নিম্নলিখিত উপায়ে bootconfig প্যারামিটার যোগ করতে পারেন:
BOARD_BOOTCONFIG += androidboot.boot_devices=soc/100000.ufshc

fstab-এ পরিবর্তন

ডিভাইস ট্রি ও ডিভাইস ট্রি ওভারলেতে fstab এন্ট্রি থাকলে চলবে না। ramdisk-এর অংশ হবে এমন একটি fstab ফাইল ব্যবহার করুন।

লজিক্যাল পার্টিশনের জন্য fstab ফাইলে পরিবর্তন করতে হবে:

  • fs_mgr ফ্ল্যাগ ফিল্ডে অবশ্যই logical ফ্ল্যাগ এবং Android 10-এ ইনট্রোডিউস করা first_stage_mount ফ্ল্যাগ থাকতে হবে, যা থেকে বোঝা যায় যে প্রথম স্টেজে একটি পার্টিশন মাউন্ট করতে হবে।
  • একটি পার্টিশন avb=vbmeta partition name ফ্ল্যাগ হিসেবে fs_mgr নির্দিষ্ট করতে পারে এবং তারপরে কোনও ডিভাইস মাউন্ট করার চেষ্টা করার আগে প্রথম স্টেজ init নির্দিষ্ট করা vbmeta পার্টিশনকে ইনিশিয়ালাইজ করে।
  • dev ফিল্ডটি অবশ্যই পার্টিশনের নাম হতে হবে।

নিম্নলিখিত fstab এন্ট্রিগুলি উপরে উল্লিখিত নিয়ম মেনে সিস্টেম, ভেন্ডর ও প্রোডাক্টকে লজিক্যাল পার্টিশন হিসেবে সেট করে।

#<dev>  <mnt_point> <type>  <mnt_flags options> <fs_mgr_flags>
system   /system     ext4    ro,barrier=1        wait,slotselect,avb=vbmeta,logical,first_stage_mount
vendor   /vendor     ext4    ro,barrier=1        wait,slotselect,avb,logical,first_stage_mount
product  /product    ext4    ro,barrier=1        wait,slotselect,avb,logical,first_stage_mount

প্রথম পর্যায়ের র‍্যামডিস্কে fstab ফাইল কপি করুন।

SELinux-এ পরিবর্তন

সুপার পার্টিশন ব্লক ডিভাইসকে অবশ্যই লেবেল super_block_device দিয়ে চিহ্নিত করতে হবে। যেমন, সুপার পার্টিশন বাই-নেম সিমলিঙ্ক যদি /dev/block/platform/soc/100000.ufshc/by-name/super হয়, তাহলে file_contexts-এ নিম্নলিখিত লাইন যোগ করুন:

/dev/block/platform/soc/10000\.ufshc/by-name/super   u:object_r:super_block_device:s0

fastbootd

বুটলোডার (বা ব্যবহারকারী স্পেস নয় এমন কোনও ফ্ল্যাশিং টুল) ডায়নামিক পার্টিশন বোঝে না, তাই এটি ফ্ল্যাশ করতে পারে না। এটি সমাধান করতে, ডিভাইসগুলিকে অবশ্যই fastboot প্রোটোকলের একটি ইউজার-স্পেস ইমপ্লিমেন্টেশন ব্যবহার করতে হবে, যাকে fastbootd বলা হয়।

fastbootd কীভাবে প্রয়োগ করতে হয় সেই ব্যাপারে আরও তথ্য পেতে, ব্যবহারকারীর স্পেসে Fastboot সরানো দেখুন।

adb remount

eng বা userdebug বিল্ড ব্যবহার করা ডেভেলপারদের জন্য, adb remount দ্রুত আইটেরেশনের ক্ষেত্রে অত্যন্ত উপযোগী। ডায়নামিক পার্টিশন adb remount-এর জন্য একটি সমস্যা তৈরি করে কারণ প্রতিটি ফাইল সিস্টেমের মধ্যে আর কোনও ফ্রি স্পেস থাকে না। এই সমস্যার সমাধান করতে, ডিভাইস overlayfs চালু করতে পারে। সুপার পার্টিশনের মধ্যে যতক্ষণ পর্যন্ত খালি জায়গা থাকে, adb remount ততক্ষণ পর্যন্ত অটোমেটিক একটি অস্থায়ী ডাইনামিক পার্টিশন তৈরি করে এবং লেখার জন্য ওভারলেএফএস ব্যবহার করে। অস্থায়ী পার্টিশনের নাম হল scratch, তাই অন্য পার্টিশনের জন্য এই নাম ব্যবহার করবেন না।

overlayfs কীভাবে চালু করতে হয় সেই সম্পর্কে আরও জানতে, AOSP-তে overlayfs README দেখুন।

Android ডিভাইস আপগ্রেড করুন

আপনি কোনও ডিভাইস Android 10-এ আপগ্রেড করলে এবং OTA-তে ডায়নামিক পার্টিশন সাপোর্ট যোগ করতে চাইলে, আপনাকে বিল্ট-ইন পার্টিশন টেবিল পরিবর্তন করতে হবে না। কিছু অতিরিক্ত কনফিগারেশন প্রয়োজন।

ডিভাইস কনফিগারেশনে পরিবর্তন

ডায়নামিক পার্টিশনিং রেট্রোফিট করতে, নিম্নলিখিত ফ্ল্যাগগুলি device.mk-এ যোগ করুন:

PRODUCT_USE_DYNAMIC_PARTITIONS := true
PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true

বোর্ডের কনফিগারেশনে পরিবর্তন

আপনাকে নিম্নলিখিত বোর্ড ভেরিয়েবল সেট করতে হবে:

  • ডায়নামিক পার্টিশনের এক্সটেন্ট স্টোর করতে ব্যবহৃত ব্লক ডিভাইসের তালিকায় BOARD_SUPER_PARTITION_BLOCK_DEVICES সেট করুন। এটি ডিভাইসে আগে থেকে থাকা ফিজিক্যাল পার্টিশনের নামের তালিকা।
  • BOARD_SUPER_PARTITION_partition_DEVICE_SIZE-কে BOARD_SUPER_PARTITION_BLOCK_DEVICES-এর প্রতিটি ব্লক ডিভাইসের সাইজে সেট করুন। এটি ডিভাইসে থাকা ফিজিক্যাল পার্টিশনের সাইজের তালিকা। এটি সাধারণত BOARD_partitionIMAGE_PARTITION_SIZE আগে থেকেই থাকা বোর্ড কনফিগারেশনে থাকে।
  • BOARD_SUPER_PARTITION_BLOCK_DEVICES-এর সব পার্টিশনের জন্য আগে থেকে থাকা BOARD_partitionIMAGE_PARTITION_SIZE আনসেট করুন।
  • BOARD_SUPER_PARTITION_SIZE-এর ভ্যালু BOARD_SUPER_PARTITION_partition_DEVICE_SIZE-এর যোগফলের সমান সেট করুন।
  • BOARD_SUPER_PARTITION_METADATA_DEVICE-কে ব্লক ডিভাইসে সেট করুন যেখানে ডায়নামিক পার্টিশন মেটাডেটা স্টোর করা আছে। এটি অবশ্যই BOARD_SUPER_PARTITION_BLOCK_DEVICES-এর মধ্যে একটি হতে হবে। সাধারণত, এটি system-এ সেট করা থাকে।
  • যথাক্রমে BOARD_SUPER_PARTITION_GROUPS, BOARD_group_SIZE এবং BOARD_group_PARTITION_LIST সেট করুন। বিস্তারিত জানতে নতুন ডিভাইসে বোর্ড কনফিগারেশন পরিবর্তন দেখুন।

যেমন, ডিভাইসে আগে থেকেই সিস্টেম ও ভেন্ডর পার্টিশন থাকলে এবং আপনি সেগুলি ডায়নামিক পার্টিশনে কনভার্ট করতে চাইলে এবং আপডেট করার সময় নতুন প্রোডাক্ট পার্টিশন যোগ করতে চাইলে, এই বোর্ড কনফিগারেশন সেট করুন:

BOARD_SUPER_PARTITION_BLOCK_DEVICES := system vendor
BOARD_SUPER_PARTITION_METADATA_DEVICE := system

# Rename BOARD_SYSTEMIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE.
BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE := <size-in-bytes>

# Rename BOARD_VENDORIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE
BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE := <size-in-bytes>

# This is BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE + BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE
BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>

# Configuration for dynamic partitions. For example:
BOARD_SUPER_PARTITION_GROUPS := group_foo
BOARD_GROUP_FOO_SIZE := <size-in-bytes>
BOARD_GROUP_FOO_PARTITION_LIST := system vendor product

SELinux-এ পরিবর্তন

সুপার পার্টিশন ব্লক ডিভাইসগুলি অবশ্যই অ্যাট্রিবিউট super_block_device_type দিয়ে চিহ্নিত করতে হবে। যেমন, ডিভাইসে আগে থেকেই system এবং vendor পার্টিশন থাকলে, আপনি সেগুলিকে ব্লক ডিভাইস হিসেবে ব্যবহার করে ডায়নামিক পার্টিশনের এক্সটেন্ট স্টোর করতে চান এবং তাদের নাম অনুযায়ী সিমলিঙ্ক system_block_device হিসেবে চিহ্নিত করা আছে:

/dev/block/platform/soc/10000\.ufshc/by-name/system   u:object_r:system_block_device:s0
/dev/block/platform/soc/10000\.ufshc/by-name/vendor   u:object_r:system_block_device:s0

তারপর, device.te-এ নিম্নলিখিত লাইন যোগ করুন:

typeattribute system_block_device super_block_device_type;

অন্যান্য কনফিগারেশনের জন্য, নতুন ডিভাইসে ডায়নামিক পার্টিশন প্রয়োগ করা দেখুন।

রেট্রোফিট আপডেট সম্পর্কে আরও জানতে, ডায়নামিক পার্টিশন ছাড়া A/B ডিভাইসের জন্য OTAদেখুন।

ফ্যাক্টরি ইমেজ

ডায়নামিক পার্টিশন সাপোর্ট সহ লঞ্চ করা ডিভাইসের ক্ষেত্রে, ফ্যাক্টরি ইমেজ ফ্ল্যাশ করার জন্য ইউজারস্পেস ফাস্টবুট ব্যবহার করা এড়িয়ে চলুন, কারণ ইউজারস্পেসে বুট করা অন্যান্য ফ্ল্যাশিং পদ্ধতির চেয়ে ধীরগতির হয়।

এটি সমাধান করতে, make dist এখন একটি অতিরিক্ত super.img ছবি তৈরি করে যা সরাসরি সুপার পার্টিশনে ফ্ল্যাশ করা যেতে পারে। এটি অটোমেটিক লজিক্যাল পার্টিশনের কন্টেন্ট বান্ডেল করে, যার অর্থ হল, super পার্টিশন মেটাডেটা ছাড়াও এতে system.img, vendor.img এবং আরও অনেক কিছু থাকে। এই ছবি সরাসরি super পার্টিশনে ফ্ল্যাশ করা যেতে পারে, এর জন্য কোনও অতিরিক্ত টুলিং বা fastbootd ব্যবহার করার প্রয়োজন নেই। বিল্ডের পরে, super.img-কে ${ANDROID_PRODUCT_OUT}-এ রাখা হয়।

ডায়নামিক পার্টিশন সহ লঞ্চ হওয়া A/B ডিভাইসের জন্য, super.img-এ A স্লটে ইমেজ থাকে। সরাসরি সুপার ইমেজ ফ্ল্যাশ করার পরে, ডিভাইস রিবুট করার আগে স্লট A-কে বুটেবল হিসেবে চিহ্নিত করুন।

রেট্রোফিট ডিভাইসের জন্য, make dist একগুচ্ছ super_*.img ছবি তৈরি করে যা সরাসরি সংশ্লিষ্ট ফিজিক্যাল পার্টিশনে ফ্ল্যাশ করা যেতে পারে। যেমন, make dist super_system.img এবং super_vendor.img তৈরি করে যখন BOARD_SUPER_PARTITION_BLOCK_DEVICES হল সিস্টেম ভেন্ডর। এইসব ছবি target_files.zip-এ OTA ফোল্ডারে রাখা হয়।

ডিভাইস ম্যাপার স্টোরেজ-ডিভাইস টিউনিং

ডায়নামিক পার্টিশনিংয়ে একাধিক নন-ডিটারমিনিস্টিক ডিভাইস-ম্যাপার অবজেক্ট থাকে। এগুলি প্রত্যাশা অনুযায়ী ইনস্ট্যান্টিয়েট নাও হতে পারে, তাই আপনাকে সব মাউন্ট ট্র্যাক করতে হবে এবং সব সংশ্লিষ্ট পার্টিশনের Android প্রপার্টি তাদের অন্তর্নিহিত স্টোরেজ ডিভাইসের সাথে আপডেট করতে হবে।

init-এর মধ্যে একটি মেকানিজম মাউন্ট ট্র্যাক করে এবং অ্যাসিঙ্ক্রোনাসভাবে Android প্রপার্টি আপডেট করে। এটি করতে কতটা সময় লাগবে তা নির্দিষ্ট করে বলা যায় না, তাই সব on property ট্রিগার যাতে কাজ করতে পারে তার জন্য আপনাকে যথেষ্ট সময় দিতে হবে। প্রপার্টিগুলি হল dev.mnt.blk.<partition> যেখানে <partition> হল root, system, data, অথবা vendor, উদাহরণস্বরূপ। প্রতিটি প্রপার্টি বেস স্টোরেজ-ডিভাইসের নামের সাথে যুক্ত থাকে, যেমন এই উদাহরণে দেখানো হয়েছে:

taimen:/ % getprop | grep dev.mnt.blk
[dev.mnt.blk.data]: [sda]
[dev.mnt.blk.firmware]: [sde]
[dev.mnt.blk.metadata]: [sde]
[dev.mnt.blk.persist]: [sda]
[dev.mnt.blk.root]: [dm-0]
[dev.mnt.blk.vendor]: [dm-1]

blueline:/ $ getprop | grep dev.mnt.blk
[dev.mnt.blk.data]: [dm-4]
[dev.mnt.blk.metadata]: [sda]
[dev.mnt.blk.mnt.scratch]: [sda]
[dev.mnt.blk.mnt.vendor.persist]: [sdf]
[dev.mnt.blk.product]: [dm-2]
[dev.mnt.blk.root]: [dm-0]
[dev.mnt.blk.system_ext]: [dm-3]
[dev.mnt.blk.vendor]: [dm-1]
[dev.mnt.blk.vendor.firmware_mnt]: [sda]

init.rc ভাষা Android প্রপার্টিকে নিয়মের অংশ হিসেবে বড় করার অনুমতি দেয় এবং স্টোরেজ ডিভাইস প্ল্যাটফর্মের মাধ্যমে প্রয়োজন অনুযায়ী এই ধরনের কমান্ডের মাধ্যমে টিউন করা যেতে পারে:

write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb 128
write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb 128

সেকেন্ড-স্টেজে init কমান্ড প্রসেস করা শুরু হলে, epoll loop অ্যাক্টিভ হয়ে যায় এবং ভ্যালু আপডেট হতে শুরু করে। তবে, প্রপার্টি ট্রিগার যেহেতু লেট-init পর্যন্ত অ্যাক্টিভ থাকে না, তাই root, system বা vendor ম্যানেজ করার জন্য প্রাথমিক বুট স্টেজে এটি ব্যবহার করা যায় না। আপনি আশা করতে পারেন যে read_ahead_kb ডিফল্ট কার্নেল early-fs-এ init.rc স্ক্রিপ্ট ওভাররাইড না করা পর্যন্ত যথেষ্ট হবে (যখন বিভিন্ন ডেমোন ও সুবিধা শুরু হয়)। তাই, Google সাজেস্ট করে যে, অপারেশন টাইমিং এবং রেস কন্ডিশন প্রতিরোধ করার জন্য, আপনাকে on property ফিচার ব্যবহার করতে হবে, সাথে sys.read_ahead_kb-এর মতো init.rc-নিয়ন্ত্রিত প্রপার্টি ব্যবহার করতে হবে, যেমন এইসব উদাহরণে দেখানো হয়েছে:

on property:dev.mnt.blk.root=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.system=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.system}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.vendor=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.vendor}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.product=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.system_ext}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.oem=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.oem}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on property:dev.mnt.blk.data=* && property:sys.read_ahead_kb=*
    write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048}

on early-fs:
    setprop sys.read_ahead_kb ${ro.read_ahead_kb.boot:-2048}

on property:sys.boot_completed=1
   setprop sys.read_ahead_kb ${ro.read_ahead_kb.bootcomplete:-128}