فروشنده APEX

می توانید از فرمت فایل APEX برای بسته بندی و نصب ماژول های سطح پایین سیستم عامل اندروید استفاده کنید. این امکان ساخت و نصب مستقل اجزایی مانند خدمات و کتابخانه های بومی، پیاده سازی HAL، سیستم عامل، فایل های پیکربندی و غیره را فراهم می کند.

APEX های فروشنده توسط سیستم ساخت به طور خودکار در پارتیشن /vendor نصب می شوند و در زمان اجرا توسط apexd فعال می شوند درست مانند APEX ها در سایر پارتیشن ها.

موارد استفاده کنید

مدولار کردن تصاویر فروشنده

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

هنگامی که تصاویر فروشنده به عنوان ترکیبی از APEXهای فروشنده مستقل ساخته می شوند، سازندگان دستگاه می توانند به راحتی پیاده سازی های فروشنده خاصی را که در دستگاه خود می خواهند انتخاب و انتخاب کنند. حتی اگر هیچ یک از APEX های ارائه شده مطابق با نیاز آنها نباشد، یا سخت افزار سفارشی کاملاً جدیدی داشته باشند، حتی می توانند یک APEX فروشنده جدید ایجاد کنند.

به عنوان مثال، یک OEM ممکن است تصمیم بگیرد دستگاه خود را با اجرای وای فای AOSP APEX، APEX اجرای بلوتوث SoC و APEX پیاده سازی تلفنی OEM سفارشی بسازد.

بدون APEX های فروشنده، پیاده سازی با وابستگی های بسیار بین اجزای فروشنده نیاز به هماهنگی و ردیابی دقیق دارد. با قرار دادن تمام مؤلفه ها (از جمله فایل های پیکربندی و کتابخانه های اضافی) در APEX با رابط های واضح تعریف شده در هر نقطه از ارتباط بین ویژگی ها، اجزای مختلف قابل تعویض می شوند.

تکرار توسعه دهنده

APEXهای فروشنده به توسعه‌دهندگان کمک می‌کنند در حین توسعه ماژول‌های فروشنده، با یکپارچه‌سازی اجرای کامل ویژگی، مانند HAL وای فای، در داخل یک APEX فروشنده، سریع‌تر تکرار کنند. سپس توسعه دهندگان می توانند به جای بازسازی کل تصویر فروشنده، APEX فروشنده را بسازند و به صورت جداگانه فشار دهند تا تغییرات را آزمایش کند.

این چرخه تکرار توسعه‌دهنده را برای توسعه‌دهندگانی که عمدتاً در یک منطقه ویژگی کار می‌کنند و می‌خواهند فقط در آن منطقه ویژگی تکرار کنند، ساده و سرعت می‌بخشد.

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

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

نمونه گردش کار:

# Build the entire device and flash. OR, obtain an already-flashed device.
source build/envsetup.sh && lunch oem_device-userdebug
m
fastboot flashall -w

# Test the device.
... testing ...

# Check previous behavior using a vendor APEX from one week ago, downloaded from
# your continuous integration build.
... download command ...
adb install <path to downloaded APEX>
adb reboot
... testing ...

# Edit and rebuild just the APEX to change and test behavior.
... edit APEX source contents ...
m <apex module name>
adb install out/<path to built APEX>
adb reboot
... testing ...

نمونه ها

مبانی

برای اطلاعات عمومی APEX، از جمله الزامات دستگاه، جزئیات فرمت فایل و مراحل نصب، به صفحه اصلی فرمت فایل APEX مراجعه کنید.

در Android.bp ، تنظیم ویژگی vendor: true یک ماژول APEX را به یک فروشنده APEX تبدیل می کند.

apex {
  ..
  vendor: true,
  ..
}

باینری ها و کتابخانه های مشترک

یک APEX شامل وابستگی های گذرا در داخل محموله APEX است مگر اینکه رابط های پایداری داشته باشند.

رابط‌های بومی پایدار برای وابستگی‌های APEX فروشنده شامل cc_library با stubs و کتابخانه‌های LLNDK است. این وابستگی ها از بسته بندی حذف می شوند و وابستگی ها در مانیفست APEX ثبت می شوند. مانیفست توسط linkerconfig پردازش می‌شود تا وابستگی‌های بومی خارجی در زمان اجرا در دسترس باشند.

در قطعه زیر، APEX هم شامل باینری ( my_service ) و هم وابستگی های ناپایدار آن (فایل *.so ) است.

apex {
  ..
  vendor: true,
  binaries: ["my_service"],
  ..
}

در قطعه زیر، APEX حاوی کتابخانه مشترک my_standalone_lib و هر یک از وابستگی‌های ناپایدار آن (همانطور که در بالا توضیح داده شد) است.

apex {
  ..
  vendor: true,
  native_shared_libs: ["my_standalone_lib"],
  ..
}

APEX را کوچکتر کنید

APEX ممکن است بزرگ‌تر شود زیرا وابستگی‌های ناپایدار را بسته‌بندی می‌کند. توصیه می کنیم از پیوند استاتیک استفاده کنید. کتابخانه های رایج مانند libc++.so و libbase.so می توان به صورت ایستا به باینری های HAL پیوند داد. ایجاد وابستگی برای ارائه یک رابط پایدار می تواند گزینه دیگری باشد. وابستگی در APEX همراه نخواهد بود.

پیاده سازی HAL

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

برای کپسوله‌سازی کامل اجرای HAL، APEX باید هر قطعه VINTF مربوطه و اسکریپت‌های init را نیز مشخص کند.

قطعات VINTF

وقتی قطعات در etc/vintf APEX قرار دارند، قطعات VINTF را می توان از یک APEX فروشنده ارائه کرد.

از ویژگی prebuilts برای جاسازی قطعات VINTF در APEX استفاده کنید.

apex {
  ..
  vendor: true,
  prebuilts: ["fragment.xml"],
  ..
}

prebuilt_etc {
  name: "fragment.xml",
  src: "fragment.xml",
  sub_dir: "vintf",
}

Query APIs

وقتی قطعات VINTF به APEX اضافه می‌شوند، از APIهای libbinder_ndk برای دریافت نگاشت رابط‌های HAL و نام‌های APEX استفاده کنید.

  • AServiceManager_isUpdatableViaApex("com.android.foo.IFoo/default") : اگر نمونه HAL در APEX تعریف شده باشد true .
  • AServiceManager_getUpdatableApexName("com.android.foo.IFoo/default", ...) : نام APEX را دریافت می کند که نمونه HAL را تعریف می کند.
  • AServiceManager_openDeclaredPassthroughHal("mapper", "instance", ...) : از این برای باز کردن یک HAL گذرگاهی استفاده کنید.

اسکریپت های Init

APEX ها می توانند اسکریپت های init را به دو صورت شامل شوند: (الف) یک فایل متنی از پیش ساخته شده در APEX payload، یا (ب) یک اسکریپت init معمولی در /vendor/etc . می توانید هر دو را برای یک APEX تنظیم کنید.

شروع اسکریپت در APEX:

prebuilt_etc {
  name: "myinit.rc",
  src: "myinit.rc"
}

apex {
  ..
  vendor: true,
  prebuilts: ["myinit.rc"],
  ..
}

اسکریپت های Init در APEX های فروشنده می توانند تعاریف service و دستورالعمل های on <property or event> داشته باشند.

مطمئن شوید که یک تعریف service به یک باینری در همان APEX اشاره می کند. برای مثال، com.android.foo APEX ممکن است سرویسی به نام foo-service تعریف کند.

on foo-service /apex/com.android.foo/bin/foo
  ...

هنگام استفاده on دستورالعمل ها مراقب باشید. از آنجایی که اسکریپت های init در APEX ها پس از فعال شدن APEX ها تجزیه و اجرا می شوند، برخی رویدادها یا ویژگی ها را نمی توان استفاده کرد. در اسرع وقت از apex.all.ready=true استفاده کنید. APEX های بوت استرپ می توانند on init استفاده کنند، اما نه on early-init .

سیستم عامل

مثال:

سیستم عامل را در یک فروشنده APEX با نوع ماژول prebuilt_firmware ، به شرح زیر قرار دهید.

prebuilt_firmware {
  name: "my.bin",
  src: "path_to_prebuilt_firmware",
  vendor: true,
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.bin"],  // installed inside APEX as /etc/firmware/my.bin
  ..
}

ماژول‌های prebuilt_firmware در فهرست <apex name>/etc/firmware APEX نصب می‌شوند. ueventd دایرکتوری های /apex/*/etc/firmware را اسکن می کند تا ماژول های سیستم عامل را پیدا کند.

file_contexts APEX باید هر ورودی بارگذاری سیستم عامل را به درستی برچسب گذاری کند تا اطمینان حاصل شود که این فایل ها توسط ueventd در زمان اجرا قابل دسترسی هستند. معمولاً برچسب vendor_file کافی است. به عنوان مثال:

(/.*)? u:object_r:vendor_file:s0

ماژول های هسته

ماژول های هسته را در یک فروشنده APEX به عنوان ماژول های از پیش ساخته شده به شرح زیر قرار دهید.

prebuilt_etc {
  name: "my.ko",
  src: "my.ko",
  vendor: true,
  sub_dir: "modules"
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.ko"],  // installed inside APEX as /etc/modules/my.ko
  ..
}

file_contexts APEX باید هر ورودی بارگذاری ماژول هسته را به درستی برچسب گذاری کند. به عنوان مثال:

/etc/modules(/.*)? u:object_r:vendor_kernel_modules:s0

ماژول های کرنل باید به صراحت نصب شوند. مثال زیر اسکریپت init در پارتیشن فروشنده، نصب از طریق insmod را نشان می دهد:

my_init.rc :

on early-boot
  insmod /apex/myapex/etc/modules/my.ko
  ..

همپوشانی منابع زمان اجرا

مثال:

با استفاده از ویژگی rros ، پوشش‌های منابع زمان اجرا را در APEX فروشنده جاسازی کنید.

runtime_resource_overlay {
    name: "my_rro",
    soc_specific: true,
}


apex {
  ..
  vendor: true,
  rros: ["my_rro"],  // installed inside APEX as /overlay/my_rro.apk
  ..
}

فایل های پیکربندی دیگر

APEX های فروشنده از فایل های پیکربندی مختلف دیگری که معمولاً در پارتیشن فروشنده به عنوان پیش ساخته در داخل APEX های فروشنده یافت می شوند، پشتیبانی می کنند و موارد بیشتری در حال اضافه شدن هستند.

مثال ها:

Bootstrap Vendor APEXs

برخی از خدمات HAL مانند keymint باید قبل از فعال شدن APEX در دسترس باشند. آن HAL ها معمولا early_hal در تعریف سرویس خود در اسکریپت init قرار می دهند. مثال دیگر کلاس animation است که معمولاً زودتر از رویداد post-fs-data شروع می شود. هنگامی که چنین سرویس HAL اولیه در APEX فروشنده بسته بندی می شود، apex را "vendorBootstrap": true کنید تا زودتر فعال شود. توجه داشته باشید که APEX های بوت استرپ را می توان فقط از مکان از پیش ساخته شده مانند /vendor/apex فعال کرد، نه از /data/apex .

ویژگی های سیستم

اینها ویژگی های سیستمی هستند که چارچوب برای پشتیبانی از APEX های فروشنده می خواند:

  • input_device.config_file.apex=<apex name> - وقتی تنظیم شود، فایل های پیکربندی ورودی ( *.idc ، *.kl ، و *.kcm ) از دایرکتوری /etc/usr APEX/ جستجو می شوند.
  • ro.vulkan.apex=<apex name> - وقتی تنظیم شود، درایور Vulkan از APEX بارگیری می شود. از آنجایی که درایور Vulkan توسط HAL های اولیه استفاده می شود، APEX Bootstrap APEX را ایجاد کرده و فضای نام پیوند دهنده را قابل مشاهده پیکربندی کنید.

ویژگی های سیستم را در اسکریپت های init با استفاده از دستور setprop تنظیم کنید.

ویژگی های توسعه اضافی

انتخاب APEX در هنگام راه اندازی

مثال:

توسعه‌دهندگان همچنین می‌توانند چندین نسخه از APEXهای فروشنده را نصب کنند که نام و کلید APEX یکسانی دارند، و سپس انتخاب کنند که کدام نسخه در طول هر بار راه‌اندازی با استفاده از sysprops دائمی فعال شود. برای برخی موارد استفاده از توسعه دهندگان، این ممکن است ساده تر از نصب یک نسخه جدید از APEX با استفاده از adb install باشد.

موارد استفاده مثال:

  • نصب 3 نسخه از APEX فروشنده وای فای HAL: تیم‌های QA می‌توانند آزمایش دستی یا خودکار را با استفاده از یک نسخه انجام دهند، سپس در نسخه دیگری راه‌اندازی مجدد کنند و آزمایش‌ها را دوباره اجرا کنند، سپس نتایج نهایی را مقایسه کنند.
  • نصب 2 نسخه از دوربین HAL فروشنده APEX، فعلی و آزمایشی : Dogfooders می‌توانند از نسخه آزمایشی بدون دانلود و نصب فایل اضافی استفاده کنند، بنابراین می‌توانند به راحتی آن را تعویض کنند.

در طول راه‌اندازی، apexd به دنبال sysprops با فرمت خاصی می‌گردد تا نسخه مناسب APEX را فعال کند.

فرمت های مورد انتظار برای کلید ویژگی عبارتند از:

  • بوت کانفیگ
    • برای تنظیم مقدار پیش فرض در BoardConfig.mk استفاده می شود.
    • androidboot.vendor.apex.<apex name>
  • سیسپروپ ماندگار
    • برای تغییر مقدار پیش‌فرض استفاده می‌شود که روی دستگاهی که از قبل راه‌اندازی شده تنظیم شده است.
    • در صورت وجود، مقدار bootconfig را لغو می کند.
    • persist.vendor.apex.<apex name>

مقدار ویژگی باید نام فایل APEX باشد که باید فعال شود.

// Default version.
apex {
  name: "com.oem.camera.hal.my_apex_default",
  vendor: true,
  ..
}

// Non-default version.
apex {
  name: "com.oem.camera.hal.my_apex_experimental",
  vendor: true,
  ..
}

نسخه پیش فرض نیز باید با استفاده از bootconfig در BoardConfig.mk پیکربندی شود:

# Example for APEX "com.oem.camera.hal" with the default above:
BOARD_BOOTCONFIG += \
    androidboot.vendor.apex.com.oem.camera.hal=com.oem.camera.hal.my_apex_default

پس از بوت شدن دستگاه، نسخه فعال شده را با تنظیم sysprop دائمی تغییر دهید:

$ adb root;
$ adb shell setprop \
    persist.vendor.apex.com.oem.camera.hal \
    com.oem.camera.hal.my_apex_experimental;
$ adb reboot;

اگر دستگاه از به‌روزرسانی bootconfig پس از فلش کردن (مانند دستورات fastboot oem ) پشتیبانی می‌کند، سپس با تغییر ویژگی bootconfig برای APEX چند نصب‌شده، نسخه فعال‌شده در راه‌اندازی نیز تغییر می‌کند.

برای دستگاه‌های مرجع مجازی مبتنی بر Cuttlefish ، می‌توانید از دستور --extra_bootconfig_args برای تنظیم مستقیم ویژگی bootconfig هنگام راه‌اندازی استفاده کنید. به عنوان مثال:

launch_cvd --noresume \
  --extra_bootconfig_args "androidboot.vendor.apex.com.oem.camera.hal:=com.oem.camera.hal.my_apex_experimental";