قالب فایل APEX

قالب محتوی Android Pony EXpress (APEX) در Android 10 معرفی شد و در جریان نصب برای واحدهای سیستم سطح پایین‌تر استفاده می‌شود. این قالب به‌روزرسانی‌های عناصر سیستم را که با مدل استاندارد برنامه Android سازگار نیستند تسهیل می‌کند. برخی‌از اجزای نمونه عبارت‌اند از سرویس‌ها و کتابخانه‌های بومی، لایه‌های انتزاع سخت‌افزار (HAL)، زمان اجرا (ART)، و کتابخانه‌های کلاس.

اصطلاح «APEX» می‌تواند به فایل APEX نیز اشاره داشته باشد.

پس‌زمینه

اگرچه Android از به‌روزرسانی‌های ماژول‌هایی که در مدل برنامه استاندارد قرار می‌گیرند (برای مثال، سرویس‌ها، فعالیت‌ها) ازطریق برنامه‌های نصب‌کننده بسته (مانند برنامه «فروشگاه Google Play») پشتیبانی می‌کند، استفاده از مدل مشابه برای مؤلفه‌های سیستم‌عامل سطح پایین‌تر معایب زیر را دارد:

  • از واحدهای مبتنی بر APK نمی‌توان در مراحل اولیه توالی راه‌اندازی استفاده کرد. مدیر بسته مخزن مرکزی اطلاعات درباره برنامه‌ها است و فقط می‌تواند از مدیر فعالیت شروع شود، که در مرحله بعدی فرایند راه‌اندازی آماده می‌شود.
  • قالب APK (به‌ویژه مانیفست) برای برنامه‌های Android طراحی شده است و مدول‌های سیستم همیشه مناسب نیستند.

طراحی

این بخش طراحی سطح بالای قالب فایل APEX و مدیر APEX را که سرویسی برای مدیریت فایل‌های APEX است شرح می‌دهد.

برای اطلاعات بیشتر درباره اینکه چرا این طراحی برای APEX انتخاب شده است، جایگزین‌های درنظرگرفته‌شده هنگام توسعه APEX را ببینید.

قالب APEX

این قالب فایل APEX است.

قالب فایل APEX

شکل ۱. قالب فایل APEX

در سطح بالا، فایل APEX یک فایل zip است که در آن فایل‌ها به‌صورت فشرده‌نشده ذخیره می‌شوند و در مرزهای ۴ کیلوبایتی قرار می‌گیرند.

چهار فایل موجود در فایل APEX عبارت‌اند از:

  • apex_manifest.json
  • AndroidManifest.xml
  • apex_payload.img
  • apex_pubkey

فایل apex_manifest.json حاوی نام بسته و نسخه است که فایل APEX را شناسایی می‌کند. این یک ApexManifest بافر پروتکل در قالب JSON است.

فایل AndroidManifest.xml به فایل APEX اجازه می‌دهد از ابزارها و زیرساخت‌های مرتبط با APK مانند ADB،‏ PackageManager، و برنامه‌های نصب‌کننده بسته (مانند «فروشگاه Play») استفاده کند. برای مثال، فایل APEX می‌تواند از ابزاری موجود مثل aapt برای بازرسی فراداده‌های پایه فایل استفاده کند. فایل حاوی نام بسته و اطلاعات نسخه است. این اطلاعات معمولاً به زبان apex_manifest.json نیز دردسترس است.

‫apex_manifest.json برای کد جدید و سیستم‌هایی که با APEX سروکار دارند در مقایسه با AndroidManifest.xml توصیه می‌شود. AndroidManifest.xml ممکن است حاوی اطلاعات هدف‌یابی بیشتری باشد که ابزارهای موجود انتشار برنامه می‌توانند از آن استفاده کنند.

‫apex_payload.img یک تصویر سیستم فایل ext4 است که توسط dm-verity پشتیبانی می‌شود. تصویر در زمان اجرا ازطریق دستگاه حلقه برگشتی سوار می‌شود. به‌طور خاص، درخت درهم‌سازی و بلوک فراداده بااستفاده از کتابخانه libavb ایجاد می‌شوند. بار سیستم فایل تجزیه نمی‌شود (زیرا تصویر باید در محل قابل‌نصب باشد). فایل‌های معمولی در فایل apex_payload.img گنجانده شده است.

‫apex_pubkey کلید عمومی است که برای امضا کردن تصویر سیستم فایل استفاده می‌شود. در زمان اجرا، این کلید تضمین می‌کند که APEX بارگیری‌شده با همان نهادی امضا شود که همان APEX را در پارتیشن‌های داخلی امضا می‌کند.

رهنمودهای نام‌گذاری APEX

برای کمک به جلوگیری از تداخل نام بین APEXهای جدید با پیشرفت پلاتفرم، از رهنمودهای نام‌گذاری زیر استفاده کنید:

  • com.android.*
    • برای APEXهای AOSP رزرو شده است. منحصر به فرد برای هیچ شرکت یا دستگاهی نیست.
  • com.<companyname>.*
    • برای شرکتی رزرو شده باشد. احتمالاً چند دستگاه از آن شرکت از آن استفاده می‌کنند.
  • com.<companyname>.<devicename>.*
    • برای APEXهای منحصربه‌فرد یک دستگاه خاص (یا زیرمجموعه‌ای از دستگاه‌ها) رزرو شده است.

مدیر APEX

مدیر APEX (یا apexd) فرایندی بومی و مستقل است که مسئول تأیید، نصب، و حذف نصب فایل‌های APEX است. این فرایند راه‌اندازی می‌شود و در مراحل اولیه توالی راه‌اندازی آماده است. فایل‌های APEX معمولاً ازپیش در دستگاه تحت /system/apex نصب شده‌اند. اگر به‌روزرسانی‌ای دردسترس نباشد، مدیر APEX به‌طور پیش‌فرض از این بسته‌ها استفاده می‌کند.

ترتیب به‌روزرسانی APEX از کلاس «مدیر بسته» استفاده می‌کند و به این صورت است.

  1. فایل APEX ازطریق برنامه نصب‌کننده بسته، ADB، یا منبع دیگری بارگیری می‌شود.
  2. مدیر بسته فرایند نصب را شروع می‌کند. پس‌از تشخیص اینکه فایل APEX است، مدیر بسته کنترل را به مدیر APEX منتقل می‌کند.
  3. مدیر APEX فایل APEX را درستی‌سنجی می‌کند.
  4. اگر فایل APEX درستی‌سنجی شود، پایگاه داده داخلی مدیر APEX به‌روز می‌شود تا نشان دهد که فایل APEX در بوت بعدی فعال می‌شود.
  5. درخواست‌کننده نصب پس‌از درستی‌سنجی موفق بسته، یک پخش دریافت می‌کند.
  6. برای ادامه نصب، سیستم باید بازراه‌اندازی شود.
  7. در راه‌اندازی بعدی، مدیر APEX شروع می‌شود، پایگاه داده داخلی را می‌خواند، و برای هر فایل APEX فهرست‌شده کارهای زیر را انجام می‌دهد:

    1. فایل APEX را درستی‌سنجی می‌کند.
    2. دستگاه بازگردان را از فایل APEX ایجاد می‌کند.
    3. دستگاه بلوک نگاشت‌گر دستگاه را در بالای دستگاه حلقه برگشتی ایجاد می‌کند.
    4. دستگاه بلوک نگاشت دستگاه را در مسیر یکتایی (برای نمونه، /apex/name@ver) نصب می‌کند.

وقتی همه فایل‌های APEX فهرست‌شده در پایگاه داده داخلی نصب می‌شوند، مدیر APEX خدمات چسباننده‌ای برای دیگر عناصر سیستم فراهم می‌کند تا اطلاعات مربوط به فایل‌های APEX نصب‌شده را پُرسمان کنند. برای مثال، دیگر عناصر سیستم می‌توانند فهرست فایل‌های APEX نصب‌شده در دستگاه یا مسیر دقیق محل نصب APEX خاصی را پُرسمان کنند تا بتوان به فایل‌ها دسترسی داشت.

فایل‌های APEX همان فایل‌های APK هستند

فایل‌های APEX فایل‌های APK معتبری هستند زیرا بایگانی‌های zip امضاشده‌ای هستند (بااستفاده از طرح امضای APK) که حاوی فایل AndroidManifest.xml هستند. این کار به فایل‌های APEX اجازه می‌دهد از زیرساخت فایل‌های APK، مثل برنامه نصب‌کننده بسته، ابزار کمکی امضا، و مدیر بسته استفاده کنند.

فایل AndroidManifest.xml درون فایل APEX حداقل است و شامل بسته name، versionCode، و targetSdkVersion، minSdkVersion اختیاری، و maxSdkVersion برای هدف‌یابی دقیق است. این اطلاعات به فایل‌های APEX اجازه می‌دهد ازطریق کانال‌های موجود مثل برنامه‌های نصب‌کننده بسته و ADB ارائه شوند.

انواع فایل‌های پشتیبانی‌شده

قالب APEX از این نوع فایل‌ها پشتیبانی می‌کند:

  • کتابخانه‌های مشترک بومی
  • فایل‌های اجرایی بومی
  • فایل‌های JAR
  • فایل‌های داده
  • فایل‌های پیکربندی

این بدان معنا نیست که APEX می‌تواند همه این انواع فایل را به‌روز کند. امکان به‌روزرسانی نوع فایل به پلاتفرم و میزان پایدار بودن تعریف‌های رابط‌های انواع فایل بستگی دارد.

گزینه‌های امضا کردن

فایل‌های APEX به دو روش امضا می‌شوند. ابتدا، فایل apex_payload.img (به‌طور دقیق، توصیف‌گر vbmeta پیوست‌شده به apex_payload.img) با کلیدی امضا می‌شود. سپس، کل APEX بااستفاده از طرح امضای APK نسخه ۳ امضا می‌شود. در این فرایند از دو کلید متفاوت استفاده می‌شود.

در سمت دستگاه، کلید عمومی مربوط به کلید خصوصی استفاده‌شده برای امضا کردن توصیفگر vbmeta نصب می‌شود. مدیر APEX از کلید عمومی برای درستی‌سنجی APEXهایی که درخواست نصب آن‌ها شده است استفاده می‌کند. هر APEX باید با کلیدهای متفاوتی امضا شود و هم در زمان ساخت و هم در زمان اجرا اعمال می‌شود.

APEX در پارتیشن‌های داخلی

فایل‌های APEX می‌توانند در پارتیشن‌های داخلی مثل /system قرار بگیرند. بخش ازقبل روی dm-verity است، بنابراین فایل‌های APEX مستقیماً روی دستگاه حلقه نصب می‌شوند.

اگر APEX در پارتیشن داخلی وجود داشته باشد، APEX را می‌توان با ارائه بسته APEX با همان نام بسته و کد نسخه بزرگ‌تر یا مساوی به‌روز کرد. ‫APEX جدید در /data ذخیره می‌شود و، مشابه APK، نسخه جدیداً نصب‌شده نسخه موجود در پارتیشن داخلی را سایه می‌اندازد. اما برخلاف APK، نسخه جدید نصب‌شده APEX فقط پس‌از بازراه‌اندازی فعال می‌شود.

الزامات هسته

برای پشتیبانی از واحدهای اصلی APEX در دستگاه Android، ویژگی‌های زیر در هسته Linux لازم است: درایور loopback و dm-verity. گرداننده حلقه برگشتی تصویر سیستم فایل را در واحد APEX نصب می‌کند و dm-verity واحد APEX را درستی‌سنجی می‌کند.

عملکرد درایور حلقه برگشتی و dm-verity در دستیابی به عملکرد خوب سیستم هنگام استفاده از واحدهای APEX مهم است.

نسخه‌های پشتیبانی‌شده هسته

ماژول‌های خط اصلی APEX در دستگاه‌هایی که از نسخه هسته ۴.۴ یا بالاتر استفاده می‌کنند پشتیبانی می‌شود. دستگاه‌های جدیدی که با Android 10 یا بالاتر عرضه می‌شوند باید از نسخه هسته ۴.۹ یا بالاتر استفاده کنند تا از ماژول‌های APEX پشتیبانی کنند.

وصله‌های هسته الزامی

وصله‌های هسته موردنیاز برای پشتیبانی از واحدهای APEX در درخت مشترک Android گنجانده شده است. برای دریافت وصله‌های پشتیبانی از APEX، از جدیدترین نسخه درخت مشترک Android استفاده کنید.

نسخه هسته ۴.۴

این نسخه فقط برای دستگاه‌هایی پشتیبانی می‌شود که از Android 9 به Android 10 ارتقا یافته‌اند و می‌خواهند از ماژول‌های APEX پشتیبانی کنند. برای دریافت وصله‌های لازم، اکیداً توصیه می‌شود از شاخه android-4.4 ادغام نزولی انجام دهید. در زیر فهرستی از وصله‌های فردی موردنیاز برای نسخه ۴.۴ هسته آورده شده است.

  • UPSTREAM: loop: add ioctl for changing logical block size (4.4)
  • ‫BACKPORT: block/loop: set hw_sectors (4.4)
  • UPSTREAM: loop: Add LOOP_SET_BLOCK_SIZE in compat ioctl (4.4)
  • ANDROID: mnt: Fix next_descendent (4.4)
  • ANDROID: mnt: remount باید به برده‌های برده‌ها منتقل شود (۴.۴)
  • ANDROID: mnt: Propagate remount correctly (4.4)
  • Revert "ANDROID: dm verity: add minimum prefetch size" (4.4)
  • بالادستی: حلقه: اگر افست یا block_size تغییر کرد، حافظه‌های نهان را حذف کنید (۴.۴)

نسخه‌های هسته ۴.۹/۴.۱۴/۴.۱۹

برای دریافت وصله‌های موردنیاز برای نسخه‌های هسته ۴.۹/۴.۱۴/۴.۱۹، از شاخه android-common ادغام نزولی انجام دهید.

گزینه‌های پیکربندی هسته موردنیاز

فهرست زیر الزامات پیکربندی پایه برای پشتیبانی از واحدهای APEX را که در Android 10 معرفی شده‌اند نشان می‌دهد. موارد دارای ستاره (*) الزامات موجود از Android 9 و پایین‌تر هستند.

(*) CONFIG_AIO=Y # AIO support (for direct I/O on loop devices)
CONFIG_BLK_DEV_LOOP=Y # for loop device support
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 # pre-create 16 loop devices
(*) CONFIG_CRYPTO_SHA1=Y # SHA1 hash for DM-verity
(*) CONFIG_CRYPTO_SHA256=Y # SHA256 hash for DM-verity
CONFIG_DM_VERITY=Y # DM-verity support

الزامات پارامتر خط فرمان هسته

برای پشتیبانی از APEX، مطمئن شوید که پارامترهای خط فرمان هسته الزامات زیر را برآورده می‌کنند:

  • ‫loop.max_loop نباید تنظیم شود
  • ‫loop.max_part باید <= 8 باشد

ساختن APEX

این بخش نحوه ساختن APEX بااستفاده از سیستم ساخت Android را شرح می‌دهد. در زیر نمونه‌ای از Android.bp برای APEX به‌نام apex.test آمده است.

apex {
    name: "apex.test",
    manifest: "apex_manifest.json",
    file_contexts: "file_contexts",
    // libc.so and libcutils.so are included in the apex
    native_shared_libs: ["libc", "libcutils"],
    binaries: ["vold"],
    java_libs: ["core-all"],
    prebuilts: ["my_prebuilt"],
    compile_multilib: "both",
    key: "apex.test.key",
    certificate: "platform",
}

مثال apex_manifest.json:

{
  "name": "com.android.example.apex",
  "version": 1
}

نمونه file_contexts:

(/.*)?           u:object_r:system_file:s0
/sub(/.*)?       u:object_r:sub_file:s0
/sub/file3       u:object_r:file3_file:s0

انواع فایل و مکان‌ها در APEX

نوع فایل مکان در APEX
کتابخانه‌های مشترک /lib و /lib64 (/lib/arm برای arm ترجمه‌شده در x86)
فایل‌های اجرایی /bin
کتابخانه‌های جاوا /javalib
ساختمان‌های پیش‌ساخته /etc

وابستگی‌های انتقالی

فایل‌های APEX به‌طور خودکار شامل وابستگی‌های انتقالی کتابخانه‌های مشترک بومی یا فایل‌های اجرایی می‌شود. برای مثال، اگر libFoo به libBar وابسته باشد، وقتی فقط libFoo در دارایی native_shared_libs فهرست شده باشد، این دو کتابخانه اضافه می‌شوند.

چندین ABI را مدیریت کنید

ویژگی native_shared_libs را برای هر دو میانای دودویی کاربردی (ABI) اصلی و فرعی دستگاه نصب کنید. اگر APEX دستگاه‌هایی را هدف‌گیری کند که دارای یک ABI واحد هستند (یعنی فقط ۳۲ بیتی یا فقط ۶۴ بیتی)، فقط کتابخانه‌های دارای ABI متناظر نصب می‌شوند.

دارایی binaries را فقط برای ABI اصلی دستگاه نصب کنید، همان‌طور که در زیر توضیح داده شده است:

  • اگر دستگاه فقط ۳۲ بیتی باشد، فقط گونه ۳۲ بیتی فایل باینری نصب می‌شود.
  • اگر دستگاه فقط ۶۴ بیتی باشد، فقط گونه ۶۴ بیتی باینری نصب می‌شود.

برای افزودن کنترل دقیق بر «واسط‌های برنامه‌سازی کاربردی» کتابخانه‌ها و فایل‌های اجرایی بومی، از multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries] خصوصیت‌ها استفاده کنید.

  • first: با ABI اصلی دستگاه مطابقت دارد. این گزینه پیش‌فرض برای باینری‌ها است.
  • ‫lib32: درصورت پشتیبانی، با ABI ۳۲ بیتی دستگاه مطابقت دارد.
  • ‫lib64: با ABI‏ ۶۴ بیتی دستگاه مطابقت دارد، پشتیبانی می‌شود.
  • ‫prefer32: درصورت پشتیبانی، با ABI ۳۲ بیتی دستگاه مطابقت دارد. اگر ‫ABI ۳۲ بیتی پشتیبانی نمی‌شود، با ABI ۶۴ بیتی مطابقت دارد.
  • ‫both: با هر دو ABI مطابقت دارد. این گزینه پیش‌فرض برای native_shared_libraries است.

مشخصه‌های java،‏ libraries، و prebuilts مستقل از رابط دودویی نرم‌افزار هستند.

این مثال برای دستگاهی است که از ۳۲/۶۴ پشتیبانی می‌کند و ۳۲ را ترجیح نمی‌دهد:

apex {
    // other properties are omitted
    native_shared_libs: ["libFoo"], // installed for 32 and 64
    binaries: ["exec1"], // installed for 64, but not for 32
    multilib: {
        first: {
            native_shared_libs: ["libBar"], // installed for 64, but not for 32
            binaries: ["exec2"], // same as binaries without multilib.first
        },
        both: {
            native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib
            binaries: ["exec3"], // installed for 32 and 64
        },
        prefer32: {
            native_shared_libs: ["libX"], // installed for 32, but not for 64
        },
        lib64: {
            native_shared_libs: ["libY"], // installed for 64, but not for 32
        },
    },
}

امضای vbmeta

هر APEX را با کلیدهای مختلف امضا کنید. وقتی کلید جدیدی لازم باشد، جفت کلید عمومی-خصوصی ایجاد کنید و واحد apex_key بسازید. از دارایی key برای امضا کردن APEX بااستفاده از کلید استفاده کنید. کلید عمومی به‌طور خودکار در APEX با نام avb_pubkey گنجانده می‌شود.

# create an rsa key pair
openssl genrsa -out foo.pem 4096

# extract the public key from the key pair
avbtool extract_public_key --key foo.pem --output foo.avbpubkey

# in Android.bp
apex_key {
    name: "apex.test.key",
    public_key: "foo.avbpubkey",
    private_key: "foo.pem",
}

در مثال بالا، نام کلید عمومی (foo) به شناسه کلید تبدیل می‌شود. شناسه کلید استفاده‌شده برای امضای APEX در APEX نوشته می‌شود. در زمان اجرا، apexd APEX را بااستفاده از کلید عمومی با همان شناسه در دستگاه تأیید می‌کند.

امضای APEX

فایل‌های APEX را به همان روشی که فایل‌های APK را امضا می‌کنید امضا کنید. APEXها را دو بار امضا کنید؛ یک بار برای سیستم فایل کوچک (فایل apex_payload.img) و یک بار برای کل فایل.

برای امضا کردن APEX در سطح فایل، ویژگی certificate را به یکی از این سه روش تنظیم کنید:

  • تنظیم نشده: اگر مقداری تنظیم نشده باشد، APEX با گواهینامه موجود در PRODUCT_DEFAULT_DEV_CERTIFICATE امضا می‌شود. اگر پرچمی تنظیم نشده باشد، مسیر پیش‌فرض build/target/product/security/testkey خواهد بود.
  • <name>: APEX با گواهی <name> در همان دایرکتوری PRODUCT_DEFAULT_DEV_CERTIFICATE امضا شده است.
  • :<name>: «ای‌پی‌اکس» با گواهینامه‌ای که توسط واحد Soong به‌نام <name> تعریف شده است امضا می‌شود. واحد گواهینامه را می‌توان به‌صورت زیر تعریف کرد.
android_app_certificate {
    name: "my_key_name",
    certificate: "dir/cert",
    // this will use dir/cert.x509.pem (the cert) and dir/cert.pk8 (the private key)
}

مدیریت کلید

از کلیدهای آزمایشی برای ساخت‌های توسعه استفاده می‌شود، درحالی‌که از کلیدهای انتشار برای امضای ساخت‌های عمومی استفاده می‌شود. همان‌طور که در جایگزینی کلید امضای APEX شرح داده شده است، همه کلیدهای آزمایشی باید قبل‌از انتشار عمومی با کلیدهای انتشار مربوطه جایگزین شوند. سرورهای ساخت OEM می‌توانند ابزار میزبان sign_target_files_apks را ادغام کنند، که هم تصویر سیستم فایل و هم کل فایل APEX را برای همه فایل‌های APEX موجود در بایگانی Zip فایل‌های هدف دوباره امضا می‌کند.

برای حفظ امنیت، رعایت روال‌های مطلوب زیر برای عملیات مدیریت کلید و امضای نسخه پخش بسیار مهم است:

  • کلیدهای انتشار را در محیطی امن نگهداری کنید تا دسترسی به آن‌ها را محدود کنید.

  • یک ACL باید شروع عملیات امضای انتشار را کنترل کند.

  • فقط پس‌از اینکه آرتیفکت‌ها برای انتشار آزمایش و تأیید شدند، آن‌ها را با کلید انتشار امضا کنید.

  • یک شخص باید کنش‌های امضای انتشار را راه‌اندازی کند؛ این فرایند را خودکارسازی نکنید.

  • آرتیفکت‌های امضاشده با کلید انتشار باید در محیطی امن ذخیره شوند.

  • دسترسی به آرتیفکت‌های امضاشده با کلید انتشار باید به دلایل تجاری معتبر محدود شود.

  • کارساز ساخت OEM باید سابقه هر درخواست امضا را در پایگاه داده امضا نگهداری کند.

نصب APEX

برای نصب APEX، از ADB استفاده کنید.

adb install apex_file_name
adb reboot

اگر supportsRebootlessUpdate روی true در apex_manifest.json تنظیم شده باشد و APEX نصب‌شده فعلی استفاده‌نشده باشد (برای مثال، هر سرویسی که دربردارد متوقف شده باشد)، دراین‌صورت APEX جدید را می‌توان بدون بازراه‌اندازی با پرچم --force-non-staged نصب کرد.

adb install --force-non-staged apex_file_name

استفاده از APEX

پس‌از بازراه‌اندازی، APEX در دایرکتوری /apex/<apex_name>@<version> نصب می‌شود. چندین نسخه از یک APEX را می‌توان به‌طور هم‌زمان سوار کرد. از میان مسیرهای نصب، مسیری که مربوط به جدیدترین نسخه است در /apex/<apex_name> نصب شده است.

کارخواه‌ها می‌توانند از مسیر bind-mounted برای خواندن یا اجرای فایل‌ها از APEX استفاده کنند.

APEXها معمولاً به این صورت استفاده می‌شوند:

  1. وقتی دستگاه ارسال می‌شود، سازنده اصلی یا سازنده طراحی اصلی APEX را در /system/apex ازپیش بار می‌کند.
  2. فایل‌های موجود در APEX ازطریق مسیر /apex/<apex_name>/ دردسترس هستند.
  3. وقتی نسخه به‌روزشده APEX در /data/apex نصب می‌شود، مسیر پس‌از بازراه‌اندازی به APEX جدید اشاره می‌کند.

به‌روزرسانی سرویس با APEX

برای به‌روزرسانی سرویس بااستفاده از APEX:

  1. خدمات را در پارتیشن سیستم به‌عنوان قابل‌به‌روزرسانی علامت‌گذاری کنید. گزینه updatable را به تعریف سرویس اضافه کنید.

    /system/etc/init/myservice.rc:
    
    service myservice /system/bin/myservice
        class core
        user system
        ...
        updatable
    
  2. فایل .rc جدیدی برای سرویس به‌روزشده ایجاد کنید. برای تعریف مجدد سرویس موجود، از گزینه override استفاده کنید.

    /apex/my.apex/etc/init.rc:
    
    service myservice /apex/my.apex/bin/myservice
        class core
        user system
        ...
        override
    

تعریف‌های سرویس فقط در فایل .rc در APEX تعریف می‌شود. کنش محرک‌ها در APEX پشتیبانی نمی‌شوند.

اگر سرویسی که به‌عنوان قابل‌به‌روزرسانی علامت‌گذاری شده است قبل‌از فعال شدن APEXها شروع شود، شروع آن تا زمان تکمیل فعال‌سازی APEXها به‌تأخیر می‌افتد.

پیکربندی سیستم برای پشتیبانی از به‌روزرسانی‌های APEX

برای پشتیبانی از به‌روزرسانی‌های فایل APEX، ویژگی سیستم زیر را روی true تنظیم کنید.

<device.mk>:

PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true

BoardConfig.mk:
TARGET_FLATTEN_APEX := false

یا فقط

<device.mk>:

$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)

‫APEX مسطح

برای دستگاه‌های قدیمی، گاهی اوقات به‌روزرسانی هسته قدیمی برای پشتیبانی کامل از APEX غیرممکن یا غیرقابل‌اجرا است. برای مثال، ممکن است هسته بدون CONFIG_BLK_DEV_LOOP=Y ساخته شده باشد، که برای سوار کردن تصویر سیستم فایل در APEX حیاتی است.

‫APEX مسطح‌شده یک APEX ویژه است که می‌تواند در دستگاه‌های دارای هسته قدیمی فعال شود. فایل‌های موجود در APEX مسطح‌شده مستقیماً در دایرکتوری زیر پارتیشن داخلی نصب می‌شوند. برای مثال، lib/libFoo.so در APEX مسطح‌شده my.apex در /system/apex/my.apex/lib/libFoo.so نصب می‌شود.

فعال کردن APEX مسطح‌شده شامل دستگاه حلقه نمی‌شود. کل دایرکتوری /system/apex/my.apex مستقیماً به /apex/name@ver پیوند-نصب می‌شود.

نمی‌توان APEXهای مسطح‌شده را با بارگیری نسخه‌های به‌روزرسانی‌شده از شبکه به‌روزرسانی کرد زیرا APEXهای بارگیری‌شده را نمی‌توان مسطح کرد. «ای‌پی‌اکس»های مسطح‌شده فقط ازطریق «به‌روزرسانی ازطریق شبکه» معمولی قابل به‌روزرسانی هستند.

«APEX مسطح» پیکربندی پیش‌فرض است. این یعنی همه APEXها به‌طور پیش‌فرض مسطح می‌شوند، مگراینکه دستگاهتان را به‌طور صریح پیکربندی کنید تا APEXهای غیرمسطح برای پشتیبانی از به‌روزرسانی‌های APEX ساخته شوند (همان‌طور که در بالا توضیح داده شد).

ترکیب کردن APEXهای مسطح و غیرمسطح در یک دستگاه پشتیبانی نمی‌شود. ‫APEXهای موجود در یک دستگاه باید یا همه غیرمسطح یا همه مسطح باشند. این موضوع به‌ویژه هنگام ارسال پیش‌ساخت‌های APEX پیش‌امضاشده برای پروژه‌هایی مثل Mainline اهمیت دارد. ‫APEXهایی که ازقبل امضا نشده‌اند (یعنی از منبع ساخته شده‌اند) نیز باید غیرمسطح باشند و با کلیدهای مناسب امضا شوند. دستگاه باید از updatable_apex.mk ارث ببرد، همان‌طور که در به‌روزرسانی سرویس با APEX توضیح داده شده است.

APEXهای فشرده‌شده

‫Android 12 و نسخه‌های بالاتر از فشرده‌سازی APEX برای کاهش تأثیر فضای ذخیره‌سازی بسته‌های APEX به‌روزرسانی‌شدنی استفاده می‌کنند. پس‌از نصب به‌روزرسانی APEX، اگرچه دیگر از نسخه پیش‌نصب‌شده آن استفاده نمی‌شود، اما همچنان همان مقدار فضا را اشغال می‌کند. آن فضای اشغال‌شده همچنان دردسترس نخواهد بود.

فشرده‌سازی APEX بااستفاده از مجموعه بسیار فشرده‌ای از فایل‌های APEX در پارتیشن‌های فقط‌خواندنی (مثل پارتیشن /system) این تأثیر بر فضای ذخیره‌سازی را به‌حداقل می‌رساند. ‫Android 12 و نسخه‌های بالاتر از الگوریتم فشرده‌سازی Deflate zip استفاده می‌کنند.

فشرده‌سازی بهینه‌سازی را برای موارد زیر ارائه نمی‌دهد:

  • APEXهای راه‌اندازی که باید در مراحل اولیه توالی راه‌اندازی سوار شوند.

  • ‫APEXهای غیرقابل‌به‌روزرسانی. فشرده‌سازی فقط درصورتی مفید است که نسخه به‌روزشده APEX در بخش /data نصب شده باشد. فهرست کامل APEXهای به‌روزرسانی‌شدنی در صفحه اجزای سیستم واحد دردسترس است.

  • APEXهای کتابخانه‌های مشترک پویا. ازآنجایی‌که apexd همیشه هر دو نسخه این نوع APEX را فعال می‌کند (ازپیش نصب‌شده و ارتقایافته)، فشرده کردن آن‌ها ارزشی اضافه نمی‌کند.

قالب فایل APEX فشرده‌شده

این قالب فایل فشرده APEX است.

نمودار قالب فایل APEX فشرده را نشان می‌دهد

شکل ۲. قالب فایل فشرده APEX

در سطح بالا، فایل APEX فشرده‌شده یک فایل zip است که حاوی فایل apex اصلی در شکل فشرده با سطح فشرده‌سازی ۹ و فایل‌های دیگر ذخیره‌شده به‌صورت فشرده‌نشده است.

فایل APEX از چهار فایل تشکیل شده است:

  • original_apex: با سطح فشرده‌سازی ۹ فشرده شده است این فایل APEX اصلی و فشرده‌نشده است.
  • apex_manifest.pb: فقط ذخیره‌شده
  • ‫AndroidManifest.xml: فقط ذخیره شد
  • ‫apex_pubkey: فقط ذخیره شد

فایل‌های apex_manifest.pb، AndroidManifest.xml، و apex_pubkey کپی فایل‌های مربوطه در original_apex هستند.

ساختن APEX فشرده

‫APEX فشرده را می‌توان بااستفاده از ابزار apex_compression_tool.py واقع در system/apex/tools ساخت.

چندین پارامتر مربوط به فشرده‌سازی APEX در سیستم ساخت دردسترس است.

در Android.bp، اینکه فایل APEX فشرده‌شدنی باشد یا نه با دارایی compressible کنترل می‌شود:

apex {
    name: "apex.test",
    manifest: "apex_manifest.json",
    file_contexts: "file_contexts",
    compressible: true,
}

پرچم محصول PRODUCT_COMPRESSED_APEX کنترل می‌کند که آیا تصویر سیستم ساخته‌شده از منبع باید حاوی فایل‌های APEX فشرده‌شده باشد یا نه.

برای آزمایش محلی، می‌توانید با تنظیم کردن OVERRIDE_PRODUCT_COMPRESSED_APEX= روی true، ساختمانی را مجبور کنید APEXها را فشرده کند.

فایل‌های APEX فشرده‌شده تولیدشده توسط سیستم ساخت دارای پسوند .capex هستند. این افزونه تشخیص نسخه‌های فشرده و فشرده‌نشده فایل APEX را آسان‌تر می‌کند.

الگوریتم‌های فشرده‌سازی پشتیبانی‌شده

Android 12 فقط از فشرده‌سازی zip Deflate پشتیبانی می‌کند.

فعال کردن فایل APEX فشرده درطول راه‌اندازی

قبل‌از اینکه APEX فشرده‌شده فعال شود، فایل original_apex داخل آن در دایرکتوری /data/apex/decompressed از حالت فشرده خارج می‌شود. فایل APEX ازفشرده‌سازی خارج‌شده حاصل به‌صورت پیوند سخت به فهرست راهنمای /data/apex/active پیوند داده می‌شود.

مثال زیر را به‌عنوان نمونه‌ای از فرایند شرح‌داده‌شده در بالا درنظر بگیرید.

‫/system/apex/com.android.foo.capex را به‌عنوان APEX فشرده‌ای که با versionCode 37 فعال می‌شود درنظر بگیرید.

  1. فایل original_apex در /system/apex/com.android.foo.capex به /data/apex/decompressed/com.android.foo@37.apex از حالت فشرده خارج می‌شود.
  2. restorecon /data/apex/decompressed/com.android.foo@37.apex برای تأیید اینکه برچسب SELinux صحیح دارد انجام می‌شود.
  3. بررسی‌های درستی‌سنجی روی /data/apex/decompressed/com.android.foo@37.apex انجام می‌شود تا از معتبر بودن آن مطمئن شویم: apexd کلید عمومی دسته‌بندی‌شده در /data/apex/decompressed/com.android.foo@37.apex را بررسی می‌کند تا تأیید کند که با کلید عمومی دسته‌بندی‌شده در /system/apex/com.android.foo.capex یکسان است.
  4. فایل /data/apex/decompressed/com.android.foo@37.apex به دایرکتوری /data/apex/active/com.android.foo@37.apex پیوند سخت دارد.
  5. منطق فعال‌سازی معمول برای فایل‌های APEX فشرده‌نشده در /data/apex/active/com.android.foo@37.apex اجرا می‌شود.

تعامل با OTA

فایل‌های فشرده APEX بر ارائه و کاربرد OTA تأثیر می‌گذارند. ازآنجایی‌که به‌روزرسانی OTA ممکن است حاوی فایل APEX فشرده‌شده با سطح نسخه بالاتری نسبت‌به آنچه در دستگاه فعال است باشد، باید مقدار مشخصی فضای خالی قبل‌از راه‌اندازی مجدد دستگاه برای اعمال به‌روزرسانی OTA رزرو شود.

برای پشتیبانی از سیستم OTA،‏ apexd این دو میانای برنامه‌سازی کاربردی binder را نمایش می‌دهد:

  • ‫calculateSizeForCompressedApex - اندازه موردنیاز برای ازحالت فشرده خارج کردن فایل‌های APEX در بسته OTA را محاسبه می‌کند. از این می‌توان برای درستی‌سنجی اینکه دستگاه قبل‌از بارگیری OTA فضای کافی دارد یا نه استفاده کرد.
  • ‫reserveSpaceForCompressedApex - فضایی را در دیسک برای استفاده‌های بعدی توسط apexd برای ازهم فشرده کردن فایل‌های فشرده APEX در بسته OTA رزرو می‌کند.

در به‌روزرسانی OTA نوع A/B، apexd فشرده‌سازی را در پس‌زمینه به‌عنوان بخشی از روال OTA پس‌از نصب انجام می‌دهد. اگر فشرده‌سازی ناموفق باشد، apexd فشرده‌سازی را درحین بوت که به‌روزرسانی OTA را اعمال می‌کند انجام می‌دهد.

جایگزین‌های درنظر گرفته‌شده هنگام توسعه APEX

در اینجا چند گزینه وجود دارد که AOSP هنگام طراحی قالب فایل APEX درنظر گرفته است، و دلیل گنجاندن یا حذف آن‌ها.

سیستم‌های مدیریت بسته معمولی

توزیع‌های Linux سیستم‌های مدیریت بسته مانند dpkg و rpm دارند که قدرتمند، کامل، و قوی هستند. بااین‌حال، برای APEX پذیرفته نشدند زیرا نمی‌توانند از بسته‌ها پس‌از نصب محافظت کنند. درستی‌سنجی فقط هنگام نصب بسته‌ها انجام می‌شود. مهاجمان می‌توانند بدون اینکه متوجه شوید تمامیت بسته‌های نصب‌شده را نقض کنند. این یک رگرسیون برای Android است که در آن همه مؤلفه‌های سیستم در سیستم‌های فایل فقط خواندنی ذخیره می‌شدند و یکپارچگی آن‌ها توسط dm-verity برای هر I/O محافظت می‌شد. هرگونه دستکاری در اجزای سیستم باید ممنوع باشد یا قابل‌شناسایی باشد تا درصورت به‌خطر افتادن دستگاه، دستگاه از راه‌اندازی خودداری کند.

‫dm-crypt برای تمامیت

فایل‌های موجود در محفظه APEX از پارتیشن‌های داخلی (برای مثال، پارتیشن /system) هستند که توسط dm-verity محافظت می‌شوند، جایی که هرگونه تغییر در فایل‌ها حتی پس‌از سوار شدن پارتیشن‌ها ممنوع است. برای ارائه همان سطح امنیت به فایل‌ها، همه فایل‌ها در APEX در یک تصویر سیستم فایل ذخیره می‌شوند که با یک درخت درهم‌ساز و یک توصیف‌گر vbmeta جفت شده است. بدون dm-verity، یک APEX در پارتیشن /data دربرابر تغییرات ناخواسته که پس‌از درستی‌سنجی و نصب آن انجام می‌شود آسیب‌پذیر است.

درواقع، پارتیشن /data نیز با لایه‌های رمزگذاری مانند dm-crypt محافظت می‌شود. اگرچه این کار تا حدی از دستکاری جلوگیری می‌کند، هدف اصلی آن حفظ حریم خصوصی است، نه یکپارچگی. وقتی مهاجمی به /data پارتیشن دسترسی پیدا می‌کند، دیگر هیچ محافظتی وجود ندارد و این دوباره پس‌رفت در مقایسه با زمانی است که همه اجزای سیستم در پارتیشن /system قرار دارند. درخت درهم‌سازی داخل فایل APEX به‌همراه dm-verity همان سطح از محافظت از محتوا را ارائه می‌دهد.

تغییر مسیر دادن مسیرها از system /به apex/

فایل‌های عنصر سیستم که در APEX بسته‌بندی شده‌اند ازطریق مسیرهای جدیدی مثل /apex/<name>/lib/libfoo.so قابل‌دسترس هستند. وقتی فایل‌ها بخشی از پارتیشن /system بودند، ازطریق مسیرهایی مثل /system/lib/libfoo.so دردسترس بودند. کلاینت فایل APEX (فایل‌های APEX دیگر یا پلاتفرم) باید از مسیرهای جدید استفاده کند. ممکن است لازم باشد کد موجود را درنتیجه تغییر مسیر به‌روزرسانی کنید.

اگرچه یک راه برای جلوگیری از تغییر مسیر، هم‌پوشانی محتویات فایل در یک فایل APEX روی پارتیشن /system است، تیم Android تصمیم گرفت فایل‌ها را روی پارتیشن /system هم‌پوشانی نکند زیرا این کار می‌تواند بر عملکرد تأثیر بگذارد، زیرا تعداد فایل‌هایی که هم‌پوشانی می‌شوند (احتمالاً حتی یکی پس‌از دیگری روی هم قرار می‌گیرند) افزایش می‌یابد.

گزینه دیگر ربودن کارکردهای دسترسی به فایل مثل open، stat، و readlink بود، به‌طوری‌که مسیرهای شروع‌شده با /system به مسیرهای متناظرشان در /apex هدایت می‌شدند. تیم Android این گزینه را کنار گذاشت زیرا تغییر دادن همه عملکردهایی که مسیرها را می‌پذیرند غیرممکن است. برای مثال، برخی‌از برنامه‌ها به‌صورت ایستا به Bionic پیوند می‌دهند که عملکردها را پیاده‌سازی می‌کند. در چنین مواردی، آن برنامه‌ها هدایت نمی‌شوند.