کد هسته را برای GKI توسعه دهید

تصویر هسته عمومی (GKI) با هماهنگی نزدیک با هسته لینوکس بالادستی، تکه‌تکه شدن هسته را کاهش می‌دهد. با این حال، دلایل معتبری وجود دارد که چرا برخی از وصله‌ها نمی‌توانند در بالادستی پذیرفته شوند، و برنامه‌های محصولی وجود دارد که باید رعایت شوند، بنابراین برخی از وصله‌ها در منابع هسته مشترک اندروید (ACK) که GKI از آنها ساخته شده است، نگهداری می‌شوند.

توسعه‌دهندگان باید تغییرات کد را به عنوان اولین انتخاب، با استفاده از فهرست پستی هسته لینوکس (LKML) به شاخه ACK android-mainline ارسال کنند، و تغییرات کد را فقط زمانی به شاخه ACK android-mainline ارسال کنند که دلیل محکمی برای عدم امکان استفاده از upstream وجود داشته باشد. نمونه‌هایی از دلایل معتبر و نحوه مدیریت آنها در زیر فهرست شده است.

  • این وصله به LKML ارسال شد، اما به موقع برای انتشار محصول پذیرفته نشد. برای مدیریت این وصله:

    • شواهدی ارائه دهید که نشان دهد وصله به LKML ارسال شده و نظراتی برای وصله دریافت شده است، یا زمان تخمینی که تا آن زمان وصله به بالادست ارسال می‌شود.
    • در مورد یک مسیر عملی برای قرار دادن پچ در ACK تصمیم بگیرید، آن را در بالادست تأیید کنید و سپس وقتی نسخه نهایی بالادست در ACK ادغام شد، آن را از ACK خارج کنید.
  • این وصله، تابع EXPORT_SYMBOLS_GPL() را برای یک ماژول فروشنده تعریف می‌کند، اما به دلیل عدم وجود ماژول‌های درون‌شاخه‌ای که از آن نماد استفاده کنند، امکان ارسال به بالادست وجود ندارد. برای مدیریت این وصله، جزئیات مربوط به دلیل عدم امکان ارسال ماژول به بالادست و گزینه‌هایی که قبل از ارائه این درخواست در نظر گرفته‌اید را ارائه دهید.

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

  • این وصله نمی‌تواند توسط آپ‌استریم پذیرفته شود زیرا... <دلیل را اینجا وارد کنید> . برای مدیریت این وصله، با تیم کرنل اندروید تماس بگیرید و با ما روی گزینه‌هایی برای بازسازی وصله همکاری کنید تا بتوان آن را برای بررسی ارسال کرد و آپ‌استریم آن را پذیرفت.

توجیهات بالقوه بسیار بیشتری وجود دارد. وقتی اشکال یا وصله خود را ارسال می‌کنید، یک توجیه معتبر نیز ارائه دهید و انتظار تکرار و بحث را داشته باشید. ما می‌دانیم که ACK شامل برخی وصله‌ها می‌شود، به خصوص در مراحل اولیه GKI، در حالی که همه در حال یادگیری نحوه کار در مراحل بالادستی هستند اما نمی‌توانند برنامه‌های محصول را برای انجام این کار کنار بگذارند. انتظار داشته باشید که الزامات بالادستی با گذشت زمان سختگیرانه‌تر شوند.

الزامات وصله

وصله‌ها باید با استانداردهای کدنویسی هسته لینوکس که در درخت منبع لینوکس شرح داده شده است، مطابقت داشته باشند، چه از طریق upstream ارسال شوند و چه از طریق ACK. اسکریپت scripts/checkpatch.pl به عنوان بخشی از آزمایش presubmit Gerrit اجرا می‌شود، بنابراین آن را از قبل اجرا کنید تا مطمئن شوید که با موفقیت انجام می‌شود. برای اجرای اسکریپت checkpatch با همان پیکربندی آزمایش presubmit، از //build/kernel/static_analysis:checkpatch_presubmit استفاده کنید. برای جزئیات بیشتر، به build/kernel/kleaf/docs/checkpatch.md مراجعه کنید.

وصله‌های ACK

پچ‌های ارسالی به ACK باید با استانداردهای کدنویسی هسته لینوکس و دستورالعمل‌های مشارکت مطابقت داشته باشند. شما باید یک برچسب Change-Id در پیام کامیت قرار دهید؛ اگر پچ را به چندین شاخه (مثلاً android-mainline و android12-5.4 ) ارسال می‌کنید، باید از Change-Id یکسان برای همه نمونه‌های پچ استفاده کنید.

ابتدا وصله‌ها را برای بررسی اولیه به LKML ارسال کنید. اگر وصله:

  • در صورت پذیرش در بالادست، به طور خودکار در android-mainline ادغام می‌شود.
  • پذیرفته نشده در بالادست، آن را به android-mainline ارسال کنید و در آن به درخواست بالادست ارجاع دهید یا توضیح دهید که چرا به LKML ارسال نشده است.

پس از اینکه یک پچ چه در بالادست و چه در android-mainline پذیرفته شد، می‌توان آن را به ACK مبتنی بر LTS مناسب (مانند android12-5.4 و android11-5.4 برای پچ‌هایی که کد مخصوص اندروید را اصلاح می‌کنند) بک‌پورت کرد. ارسال به android-mainline امکان آزمایش با نامزدهای انتشار جدید بالادست را فراهم می‌کند و تضمین می‌کند که پچ در ACK مبتنی بر LTS بعدی قرار دارد. موارد استثنا شامل مواردی است که یک پچ بالادست به android12-5.4 بک‌پورت می‌شود (زیرا احتمالاً پچ از قبل در android-mainline وجود دارد).

وصله‌های بالادستی

همانطور که در دستورالعمل‌های مشارکت مشخص شده است، وصله‌های بالادستی که برای هسته‌های ACK در نظر گرفته شده‌اند، در گروه‌های زیر قرار می‌گیرند (به ترتیب احتمال پذیرش فهرست شده‌اند).

  • UPSTREAM: - پچ‌های گلچین‌شده از 'android-mainline' احتمالاً در صورت وجود کاربرد منطقی، در ACK پذیرفته می‌شوند.
  • BACKPORT: - وصله‌هایی از بالادست که به طور دقیق گزینش نمی‌شوند و نیاز به اصلاح دارند، در صورت وجود دلیل منطقی برای استفاده، احتمالاً پذیرفته می‌شوند.
  • FROMGIT: - وصله‌هایی که از شاخه‌ی نگهدارنده برای ارسال به لینوکس اصلی انتخاب می‌شوند، در صورت وجود مهلت زمانی نزدیک، ممکن است پذیرفته شوند. این وصله‌ها باید هم از نظر محتوا و هم از نظر زمان‌بندی توجیه شوند.
  • FROMLIST: - پچ‌هایی که به LKML ارسال شده‌اند اما هنوز در شاخه نگهدارنده پذیرفته نشده‌اند، بعید است پذیرفته شوند، مگر اینکه توجیه به اندازه کافی قانع‌کننده باشد که پچ چه در لینوکس بالادستی قرار بگیرد چه نگیرد، پذیرفته می‌شود (ما فرض می‌کنیم که پذیرفته نخواهد شد). باید مشکلی در رابطه با پچ‌های FROMLIST وجود داشته باشد تا بحث با تیم هسته اندروید تسهیل شود.

وصله‌های مخصوص اندروید

اگر نمی‌توانید تغییرات مورد نیاز را در بالادست اعمال کنید، می‌توانید سعی کنید وصله‌های خارج از درخت را مستقیماً به ACK ارسال کنید. ارسال وصله‌های خارج از درخت مستلزم آن است که شما در بخش فناوری اطلاعات، مسئله‌ای را مطرح کنید که در آن به وصله و دلیل عدم امکان ارسال وصله به بالادست اشاره شده باشد (برای مثال‌ها به لیست قبلی مراجعه کنید). با این حال، چند مورد وجود دارد که کد نمی‌تواند به بالادست ارسال شود. این موارد به شرح زیر پوشش داده می‌شوند و باید از دستورالعمل‌های مشارکت برای وصله‌های مخصوص اندروید پیروی کنند و با پیشوند ANDROID: در موضوع برچسب‌گذاری شوند.

تغییرات در gki_defconfig

تمام تغییرات CONFIG در gki_defconfig باید روی هر دو نسخه arm64 و x86 اعمال شود، مگر اینکه CONFIG مختص معماری خاصی باشد. برای درخواست تغییر در تنظیمات CONFIG ، در بخش فناوری اطلاعات یک موضوع ایجاد کنید تا در مورد تغییر بحث شود. هر تغییر CONFIG که پس از فریز شدن، رابط ماژول هسته (KMI) را تحت تأثیر قرار دهد، رد می‌شود. در مواردی که شرکا درخواست تنظیمات متناقض برای یک پیکربندی واحد را دارند، ما از طریق بحث در مورد اشکالات مرتبط، اختلافات را حل می‌کنیم.

کدی که در بالادست وجود ندارد

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

سایر تغییرات در این دسته شامل به‌روزرسانی‌هایی در فایل‌های نمایشی KMI، فهرست نمادهای KMI، gki_defconfig ، اسکریپت‌های ساخت یا پیکربندی یا سایر اسکریپت‌هایی است که در بالادست وجود ندارند.

ماژول‌های خارج از درخت

لینوکس بالادستی (Upstream Linux) به طور فعال از پشتیبانی از ساخت ماژول‌های خارج از درخت پشتیبانی نمی‌کند. این یک موضع منطقی است با توجه به اینکه توسعه‌دهندگان لینوکس تضمینی در مورد سازگاری منبع درون هسته یا باینری ارائه نمی‌دهند و نمی‌خواهند از کدی که در درخت نیست پشتیبانی کنند. با این حال، GKI تضمین‌های ABI را برای ماژول‌های فروشنده ارائه می‌دهد و تضمین می‌کند که رابط‌های KMI برای طول عمر پشتیبانی شده یک هسته پایدار باشند. بنابراین، دسته‌ای از تغییرات برای پشتیبانی از ماژول‌های فروشنده وجود دارد که برای ACK قابل قبول هستند اما برای بالادستی قابل قبول نیستند.

برای مثال، وصله‌ای را در نظر بگیرید که ماکروهای EXPORT_SYMBOL_GPL() را اضافه می‌کند، در حالی که ماژول‌هایی که از export استفاده می‌کنند در درخت منبع نیستند. در حالی که شما باید سعی کنید EXPORT_SYMBOL_GPL() در بالادست درخواست کنید و ماژولی را ارائه دهید که از نماد تازه صادر شده استفاده می‌کند، اگر توجیه معتبری برای عدم ارسال ماژول به بالادست وجود دارد، می‌توانید وصله را به جای آن برای ACK ارسال کنید. شما باید توجیه عدم امکان ارسال ماژول به بالادست را در این مسئله ذکر کنید. (نوع غیر GPL، EXPORT_SYMBOL() را درخواست نکنید.)

پیکربندی‌های پنهان

برخی از ماژول‌های درون‌شاخه‌ای به‌طور خودکار پیکربندی‌های پنهانی را انتخاب می‌کنند که نمی‌توان آن‌ها را در gki_defconfig مشخص کرد. برای مثال، CONFIG_SND_SOC_TOPOLOGY به‌طور خودکار هنگام پیکربندی CONFIG_SND_SOC_SOF=y انتخاب می‌شود. برای سازگاری با ساخت ماژول برون‌شاخه‌ای، GKI شامل مکانیزمی برای فعال کردن پیکربندی‌های پنهان است.

برای فعال کردن یک پیکربندی پنهان، یک دستور select در init/Kconfig.gki اضافه کنید تا به طور خودکار بر اساس پیکربندی هسته CONFIG_GKI_HACKS_TO_FIX که در gki_defconfig فعال شده است، انتخاب شود. از این مکانیزم فقط برای پیکربندی‌های پنهان استفاده کنید. اگر پیکربندی پنهان نیست، باید به طور صریح یا به عنوان یک وابستگی در gki_defconfig مشخص شود.

گاورنر های قابل بارگذاری

برای چارچوب‌های هسته (مانند cpufreq ) که از فرمان‌های قابل بارگذاری پشتیبانی می‌کنند، می‌توانید فرمان پیش‌فرض (مانند فرمان schedutil مربوط به cpufreq ) را لغو کنید. برای چارچوب‌هایی (مانند چارچوب حرارتی) که از فرمان‌ها یا درایورهای قابل بارگذاری پشتیبانی نمی‌کنند اما همچنان به پیاده‌سازی خاص فروشنده نیاز دارند، در بخش فناوری اطلاعات مشکلی ایجاد کنید و با تیم هسته اندروید مشورت کنید.

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

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

در نسخه‌های گذشته، می‌توانستید تغییرات خاص فروشنده را مستقیماً به هسته اصلی اضافه کنید. این کار با GKI 2.0 امکان‌پذیر نیست زیرا کد خاص محصول باید در ماژول‌ها پیاده‌سازی شود و در هسته‌های اصلی بالادست یا در ACK پذیرفته نمی‌شود. برای فعال کردن ویژگی‌های ارزش افزوده‌ای که شرکا با حداقل تأثیر بر کد هسته اصلی به آنها متکی هستند، GKI قلاب‌های فروشنده را می‌پذیرد که به ماژول‌ها اجازه می‌دهد از کد هسته اصلی فراخوانی شوند. علاوه بر این، ساختارهای داده کلیدی را می‌توان با فیلدهای داده فروشنده که برای ذخیره داده‌های خاص فروشنده برای پیاده‌سازی این ویژگی‌ها در دسترس هستند، پر کرد.

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

  • هوک‌های فروشنده‌ی معمولی DECLARE_HOOK() برای ایجاد یک تابع tracepoint با نام trace_ name استفاده می‌کنند که در آن name شناسه‌ی منحصر به فرد برای ردیابی است. طبق قرارداد، نام هوک‌های فروشنده‌ی معمولی با android_vh شروع می‌شود، بنابراین نام هوک sched_exit() به android_vh_sched_exit خواهد بود.
  • قلاب‌های فروشنده‌ی محدود برای مواردی مانند قلاب‌های زمان‌بندی مورد نیاز هستند که در آن‌ها تابع متصل شده باید حتی اگر CPU آفلاین باشد یا به یک زمینه‌ی غیراتمی نیاز داشته باشد، فراخوانی شود. قلاب‌های فروشنده‌ی محدود را نمی‌توان جدا کرد، بنابراین ماژول‌هایی که به یک قلاب محدود متصل می‌شوند هرگز نمی‌توانند بارگیری شوند. نام قلاب‌های فروشنده‌ی محدود با android_rvh شروع می‌شود.

برای افزودن قلاب فروشنده، یک مشکل را در بخش فناوری اطلاعات ثبت کنید و وصله‌ها را ارسال کنید (مانند تمام وصله‌های مخصوص اندروید، باید یک مشکل وجود داشته باشد و شما باید توجیهی ارائه دهید). پشتیبانی از قلاب‌های فروشنده فقط در ACK انجام می‌شود، بنابراین این وصله‌ها را به لینوکس بالادستی ارسال نکنید.

فیلدهای فروشنده را به ساختارها اضافه کنید

شما می‌توانید با اضافه کردن فیلدهای android_vendor_data با استفاده از ماکروهای ANDROID_VENDOR_DATA() ، داده‌های فروشنده را با ساختارهای داده کلیدی مرتبط کنید. به عنوان مثال، برای پشتیبانی از ویژگی‌های ارزش افزوده، فیلدها را همانطور که در نمونه کد زیر نشان داده شده است، به ساختارها اضافه کنید.

برای جلوگیری از تداخل‌های احتمالی بین فیلدهای مورد نیاز فروشندگان و فیلدهای مورد نیاز تولیدکنندگان اصلی تجهیزات (OEM)، تولیدکنندگان اصلی تجهیزات هرگز نباید از فیلدهای اعلام‌شده با استفاده از ماکروهای ANDROID_VENDOR_DATA() استفاده کنند. در عوض، تولیدکنندگان اصلی تجهیزات باید ANDROID_OEM_DATA() برای اعلام فیلدهای android_oem_data استفاده کنند.

#include <linux/android_vendor.h>
...
struct important_kernel_data {
  [all the standard fields];
  /* Create vendor data for use by hook implementations. The
   * size of vendor data is based on vendor input. Vendor data
   * can be defined as single u64 fields like the following that
   * declares a single u64 field named "android_vendor_data1" :
   */
  ANDROID_VENDOR_DATA(1);

  /*
   * ...or an array can be declared. The following is equivalent to
   * u64 android_vendor_data2[20]:
   */
  ANDROID_VENDOR_DATA_ARRAY(2, 20);

  /*
   * SoC vendors must not use fields declared for OEMs and
   * OEMs must not use fields declared for SoC vendors.
   */
  ANDROID_OEM_DATA(1);

  /* no further fields */
}

قلاب‌های فروشنده را تعریف کنید

با استفاده از DECLARE_HOOK() یا DECLARE_RESTRICTED_HOOK() هوک‌های فروشنده را به عنوان نقاط ردیابی به کد هسته اضافه کنید و سپس آنها را به عنوان یک نقطه ردیابی به کد اضافه کنید. به عنوان مثال، برای اضافه کردن trace_android_vh_sched_exit() به تابع هسته do_exit() موجود:

#include <trace/hooks/exit.h>
void do_exit(long code)
{
    struct task_struct *tsk = current;
    ...
    trace_android_vh_sched_exit(tsk);
    ...
}

تابع trace_android_vh_sched_exit() در ابتدا فقط بررسی می‌کند که آیا چیزی پیوست شده است یا خیر. با این حال، اگر یک ماژول فروشنده با استفاده از register_trace_android_vh_sched_exit() یک هندلر ثبت کند، تابع ثبت شده فراخوانی می‌شود. هندلر باید از زمینه مربوط به قفل‌های نگهداری شده، وضعیت RCS و سایر عوامل آگاه باشد. هوک باید در یک فایل هدر در دایرکتوری include/trace/hooks تعریف شود.

برای مثال، کد زیر یک اعلان احتمالی برای trace_android_vh_sched_exit() در فایل include/trace/hooks/exit.h ارائه می‌دهد.

/* SPDX-License-Identifier: GPL-2.0 */
#undef TRACE_SYSTEM
#define TRACE_SYSTEM sched
#define TRACE_INCLUDE_PATH trace/hooks

#if !defined(_TRACE_HOOK_SCHED_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_HOOK_SCHED_H
#include <trace/hooks/vendor_hooks.h>
/*
 * Following tracepoints are not exported in tracefs and provide a
 * mechanism for vendor modules to hook and extend functionality
 */

struct task_struct;

DECLARE_HOOK(android_vh_sched_exit,
             TP_PROTO(struct task_struct *p),
             TP_ARGS(p));

#endif /* _TRACE_HOOK_SCHED_H */

/* This part must be outside protection */
#include <trace/define_trace.h>

برای نمونه‌سازی رابط‌های مورد نیاز برای قلاب فروشنده، فایل هدر را با اعلان قلاب به drivers/android/vendor_hooks.c اضافه کنید و نمادها را export کنید. برای مثال، کد زیر اعلان قلاب android_vh_sched_exit() را کامل می‌کند.

#ifndef __GENKSYMS__
/* struct task_struct */
#include <linux/sched.h>
#endif

#define CREATE_TRACE_POINTS
#include <trace/hooks/vendor_hooks.h>
#include <trace/hooks/exit.h>
/*
 * Export tracepoints that act as a bare tracehook (i.e. have no trace
 * event associated with them) to allow external modules to probe
 * them.
 */
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_sched_exit);

نکته : ساختارهای داده‌ای که در اعلان هوک استفاده می‌شوند، باید به طور کامل تعریف شوند تا پایداری ABI تضمین شود. در غیر این صورت، ارجاع مجدد به اشاره‌گرهای مبهم یا استفاده از ساختار در زمینه‌های با اندازه مشخص، ناامن است. include که تعریف کامل چنین ساختارهای داده‌ای را ارائه می‌دهد، باید در بخش #ifndef __GENKSYMS__ از drivers/android/vendor_hooks.c قرار گیرد. فایل‌های هدر در include/trace/hooks نباید شامل فایل هدر هسته با تعاریف نوع باشند تا از تغییرات CRC که KMI را خراب می‌کنند، جلوگیری شود. در عوض، انواع را به جلو اعلام کنید.

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

برای استفاده از قلاب‌های فروشنده، ماژول فروشنده باید یک هندلر برای قلاب ثبت کند (که معمولاً در حین مقداردهی اولیه ماژول انجام می‌شود). برای مثال، کد زیر هندلر ماژول foo.ko را برای trace_android_vh_sched_exit() نشان می‌دهد.

#include <trace/hooks/sched.h>
...
static void foo_sched_exit_handler(void *data, struct task_struct *p)
{
    foo_do_exit_accounting(p);
}
...
static int foo_probe(..)
{
    ...
    rc = register_trace_android_vh_sched_exit(foo_sched_exit_handler, NULL);
    ...
}

استفاده از قلاب‌های فروشنده از فایل‌های هدر

برای استفاده از قلاب‌های فروشنده از فایل‌های هدر، ممکن است لازم باشد فایل هدر قلاب فروشنده را به undefine TRACE_INCLUDE_PATH به‌روزرسانی کنید تا از خطاهای ساخت که نشان می‌دهد فایل هدر نقطه ردیابی یافت نمی‌شود، جلوگیری شود. برای مثال،

In file included from .../common/init/main.c:111:
In file included from .../common/include/trace/events/initcall.h:74:
.../common/include/trace/define_trace.h:95:10: fatal error: 'trace/hooks/initcall.h' file not found
   95 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.../common/include/trace/define_trace.h:90:32: note: expanded from macro 'TRACE_INCLUDE'
   90 | # define TRACE_INCLUDE(system) __TRACE_INCLUDE(system)
      |                                ^~~~~~~~~~~~~~~~~~~~~~~
.../common/include/trace/define_trace.h:87:34: note: expanded from macro '__TRACE_INCLUDE'
   87 | # define __TRACE_INCLUDE(system) __stringify(TRACE_INCLUDE_PATH/system.h)
      |                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.../common/include/linux/stringify.h:10:27: note: expanded from macro '__stringify'
   10 | #define __stringify(x...)       __stringify_1(x)
      |                                 ^~~~~~~~~~~~~~~~
.../common/include/linux/stringify.h:9:29: note: expanded from macro '__stringify_1'
    9 | #define __stringify_1(x...)     #x
      |                                 ^~
<scratch space>:14:1: note: expanded from here
   14 | "trace/hooks/initcall.h"
      | ^~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

برای رفع این نوع خطای ساخت، اصلاحیه معادل را روی فایل هدر هوک فروشنده‌ای که اضافه می‌کنید اعمال کنید. برای اطلاعات بیشتر، به https://r.android.com/3066703 مراجعه کنید.

diff --git a/include/trace/hooks/mm.h b/include/trace/hooks/mm.h
index bc6de7e53d66..039926f7701d 100644
--- a/include/trace/hooks/mm.h
+++ b/include/trace/hooks/mm.h
@@ -2,7 +2,10 @@
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM mm

+#ifdef CREATE_TRACE_POINTS
 #define TRACE_INCLUDE_PATH trace/hooks
+#define UNDEF_TRACE_INCLUDE_PATH
+#endif

تعریف UNDEF_TRACE_INCLUDE_PATH include/trace/define_trace.h می‌گوید که TRACE_INCLUDE_PATH پس از ایجاد نقاط ردیابی، undefine کند.

ویژگی‌های هسته اصلی

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

رابط برنامه‌نویسی کاربردی کاربر (UAPI)

  • فایل‌های هدر UAPI. تغییرات در فایل‌های هدر UAPI باید در بالادست رخ دهد، مگر اینکه تغییرات مربوط به رابط‌های مخصوص اندروید باشند. از فایل‌های هدر مخصوص فروشنده برای تعریف رابط‌های بین ماژول‌های فروشنده و کد فضای کاربری فروشنده استفاده کنید.
  • گره‌های sysfs. گره‌های sysfs جدید را به هسته GKI اضافه نکنید (چنین اضافات فقط در ماژول‌های فروشنده معتبر هستند). گره‌های sysfs که توسط کتابخانه‌های SoC و device-agnostic و کد جاوا که چارچوب اندروید را تشکیل می‌دهند، استفاده می‌شوند، فقط به روش‌های سازگار قابل تغییر هستند و اگر گره‌های sysfs مخصوص اندروید نباشند، باید در بالادست تغییر کنند. می‌توانید گره‌های sysfs مخصوص فروشنده ایجاد کنید تا توسط فضای کاربری فروشنده استفاده شوند. به طور پیش‌فرض، دسترسی به گره‌های sysfs توسط فضای کاربری با استفاده از SELinux رد می‌شود. این به فروشنده بستگی دارد که برچسب‌های SELinux مناسب را اضافه کند تا امکان دسترسی توسط نرم‌افزار فروشنده مجاز فراهم شود.
  • گره‌های DebugFS. ماژول‌های فروشنده می‌توانند گره‌هایی را در debugfs فقط برای اشکال‌زدایی تعریف کنند (زیرا debugfs در حین عملکرد عادی دستگاه نصب نمی‌شود).