Phát triển mã nhân cho GKI

Hình ảnh nhân chung (GKI) giúp giảm tình trạng phân mảnh nhân bằng cách điều chỉnh cho phù hợp với nhân Linux ở thượng nguồn. Tuy nhiên, có những lý do hợp lệ khiến một số bản vá không thể được chấp nhận ở thượng nguồn và có những lịch trình sản phẩm phải được đáp ứng, vì vậy, một số bản vá được duy trì trong các nguồn nhân kernel Android Common (ACK) mà từ đó GKI được tạo.

Nhà phát triển phải gửi các thay đổi về mã ở quá trình tải lên bằng cách sử dụng lựa chọn đầu tiên là Danh sách gửi thư hạt nhân Linux (LKML) và chỉ gửi các thay đổi mã đến nhánh ACK android-mainline khi có lý do rõ ràng về việc không thể thực hiện quá trình tải lên trên. Sau đây là ví dụ về các lý do hợp lệ và cách xử lý các lý do đó.

  • Bản vá đã được gửi đến LKML nhưng không được chấp nhận kịp thời để phát hành sản phẩm. Cách xử lý bản vá này:

    • Hãy cung cấp bằng chứng cho thấy bản vá đã được gửi tới LKML và các nhận xét nhận được cho bản vá, hoặc thời gian ước tính mà bản vá được gửi ngược dòng.
    • Quyết định một phương án hành động để đưa bản vá vào ACK, phê duyệt bản vá ở thượng nguồn, sau đó xoá bản vá đó khỏi ACK khi phiên bản thượng nguồn cuối cùng được hợp nhất vào ACK.
  • Bản vá xác định EXPORT_SYMBOLS_GPL() cho mô-đun nhà cung cấp, nhưng không thể gửi lên trên vì không có mô-đun nào trong cây sử dụng biểu tượng đó. Để xử lý bản vá này, hãy cung cấp thông tin chi tiết về lý do bạn không thể gửi mô-đun lên trên và các phương án thay thế mà bạn đã cân nhắc trước khi đưa ra yêu cầu này.

  • Bản vá không đủ chung chung cho phần trên nguồn và không có thời gian để tái cấu trúc bản vá trước khi phát hành sản phẩm. Để xử lý bản vá này, hãy cung cấp thời gian ước tính mà bản vá được tái cấu trúc được gửi ngược dòng (bản vá sẽ không được chấp nhận trong ACK nếu không có kế hoạch gửi bản vá được tái cấu trúc ngược dòng để xem xét).

  • Không thể chấp nhận bản vá này vì... <insert reason here>. Để xử lý bản vá này, hãy liên hệ với nhóm nhân kernel Android và cùng chúng tôi thảo luận về các lựa chọn để tái cấu trúc bản vá để có thể gửi bản vá đó cho chúng tôi xem xét và chấp nhận.

Có rất nhiều lý do khác có thể được đưa ra. Khi bạn gửi lỗi hoặc bản vá, hãy đưa ra lý do hợp lệ và dự kiến sẽ có một số lần lặp lại và thảo luận. Chúng tôi nhận thấy ACK mang theo một số bản vá, đặc biệt là trong các giai đoạn đầu của GKI, trong khi mọi người đang tìm hiểu cách làm việc ngược dòng nhưng không thể nới lỏng lịch trình sản phẩm để làm như vậy. Dự kiến các yêu cầu về việc chuyển ngược dòng sẽ trở nên nghiêm ngặt hơn theo thời gian.

Yêu cầu về bản vá

Các bản vá phải tuân thủ các tiêu chuẩn lập trình hạt nhân Linux được mô tả trong cây nguồn Linux, cho dù được gửi lên trên hay đến ACK. Tập lệnh scripts/checkpatch.pl được chạy trong quá trình kiểm thử trước khi gửi của Gerrit, vì vậy, hãy chạy trước để đảm bảo tập lệnh này vượt qua. Để chạy tập lệnh checkpatch có cùng cấu hình với kiểm thử trước khi gửi, hãy sử dụng //build/kernel/static_analysis:checkpatch_presubmit. Để biết thông tin chi tiết, hãy xem build/kernel/kleaf/docs/checkpatch.md.

Bản vá ACK

Bản vá được gửi tới ACK phải tuân thủ các tiêu chuẩn mã hoá hạt nhân của Linux và nguyên tắc đóng góp. Bạn phải thêm thẻ Change-Id vào thông báo cam kết; nếu gửi bản vá cho nhiều nhánh (ví dụ: android-mainlineandroid12-5.4), bạn phải sử dụng cùng một Change-Id cho tất cả các bản sao của bản vá.

Trước tiên, hãy gửi các bản vá cho LKML để xem xét ngược dòng. Nếu bản vá là:

  • Được chấp nhận ở thượng nguồn, mã này sẽ tự động được hợp nhất vào android-mainline.
  • Không được chấp nhận trong luồng tải lên, hãy gửi tệp này tới android-mainline kèm theo thông tin tham chiếu đến nội dung đã gửi ở trên hoặc nội dung giải thích lý do tệp không được gửi tới LKML.

Sau khi bản vá được chấp nhận ở trạng thái ngược dòng (upstream) hoặc trong android-mainline, bản vá đó có thể được điều chỉnh cho phiên bản cũ sang ACK dựa trên LTS thích hợp (chẳng hạn như android12-5.4android11-5.4 đối với các bản vá giúp sửa mã dành riêng cho Android). Việc gửi đến android-mainline cho phép kiểm thử với các đề xuất bản phát hành ngược dòng (upstream) mới và đảm bảo rằng bản vá sẽ nằm trong ACK dựa trên LTS tiếp theo. Ngoại lệ là những trường hợp mà bản vá ngược dòng được điều chỉnh cho phiên bản cũ về android12-5.4 (vì bản vá này có thể đã nằm trong android-mainline).

Bản vá ngược dòng (upstream)

Như đã chỉ định trong nguyên tắc đóng góp, các bản vá ngược dòng dành cho nhân ACK thuộc các nhóm sau (liệt kê theo thứ tự khả năng được chấp nhận).

  • UPSTREAM: – Các bản vá được chọn từ "android-mainline" có thể được chấp nhận đưa vào ACK nếu có trường hợp sử dụng hợp lý.
  • BACKPORT: – Bản vá từ thượng nguồn không được chọn sạch và cần sửa đổi cũng có thể được chấp nhận nếu có trường hợp sử dụng hợp lý.
  • FROMGIT: – Các bản vá được chọn lọc từ một nhánh của trình bảo trì để chuẩn bị gửi đến dòng chính của Linux có thể được chấp nhận nếu có thời hạn sắp tới. Những thay đổi này phải được lý giải cả về nội dung và lịch phát sóng.
  • FROMLIST: – Bản vá đã được gửi tới LKML nhưng chưa được chấp nhận vào nhánh nhà bảo trì ít có khả năng được chấp nhận, trừ phi có lý do đủ thuyết phục để bản vá đó được chấp nhận cho dù bản vá đó có rơi vào Linux ngược dòng hay không (chúng tôi giả định rằng bản vá đó sẽ không được chấp nhận). Phải có vấn đề liên quan đến các bản vá FROMLIST để tạo điều kiện thảo luận với nhóm nhân kernel Android.

Bản vá dành riêng cho Android

Nếu không thể tải các thay đổi bắt buộc ở thượng nguồn, bạn có thể thử gửi trực tiếp các bản vá ngoài cây tới ACK. Việc gửi các bản vá ngoài cây yêu cầu bạn gặp phải một vấn đề trong bộ phận CNTT có trích dẫn bản vá và giải thích lý do không thể gửi bản vá ngược dòng (xem danh sách trước đó để tham khảo ví dụ). Tuy nhiên, có một số trường hợp bạn không thể gửi mã lên trên. Những trường hợp này được đề cập như sau và phải tuân thủ nguyên tắc đóng góp cho bản vá dành riêng cho Android, đồng thời được gắn thẻ bằng tiền tố ANDROID: trong chủ đề.

Thay đổi đối với gki_defconfig

Tất cả thay đổi CONFIG đối với gki_defconfig phải được áp dụng cho cả phiên bản arm64 và x86, trừ phi CONFIG dành riêng cho cấu trúc. Để yêu cầu thay đổi chế độ cài đặt CONFIG, hãy tạo một vấn đề trong nhóm CNTT để thảo luận về thay đổi đó. Mọi thay đổi CONFIG ảnh hưởng đến Giao diện mô-đun hạt nhân (KMI) sau khi giao diện này bị đóng băng sẽ bị từ chối. Trong trường hợp đối tác yêu cầu các chế độ cài đặt xung đột cho một cấu hình, chúng tôi sẽ giải quyết xung đột thông qua thảo luận về các lỗi liên quan.

Mã không tồn tại ở thượng nguồn

Không thể gửi nội dung sửa đổi đối với mã đã dành riêng cho Android. Ví dụ: mặc dù trình điều khiển liên kết được duy trì ở thượng nguồn, nhưng bạn không thể gửi các nội dung sửa đổi đối với các tính năng kế thừa ưu tiên của trình điều khiển liên kết lên thượng nguồn vì các tính năng này dành riêng cho Android. Hãy nêu rõ trong lỗi và vá lý do không thể gửi mã ngược dòng. Nếu có thể, hãy chia các bản vá thành các phần có thể được gửi ngược dòng và các phần dành riêng cho Android không thể gửi ngược dòng để giảm thiểu số lượng mã ngoài cây được duy trì trong ACK.

Các thay đổi khác trong danh mục này là nội dung cập nhật cho tệp trình bày KMI, danh sách ký hiệu KMI, gki_defconfig, tập lệnh bản dựng hoặc cấu hình hoặc các tập lệnh khác không tồn tại ở thượng nguồn.

Mô-đun ngoài cây

Linux Upstream chủ động không khuyến khích hỗ trợ xây dựng các mô-đun ngoài cây. Đây là một quan điểm hợp lý vì các nhà bảo trì Linux không đảm bảo về khả năng tương thích của tệp nhị phân hoặc nguồn trong hạt nhân và không muốn hỗ trợ mã không có trong cây. Tuy nhiên, GKI đưa ra các đảm bảo ABI cho các mô-đun của nhà cung cấp, đảm bảo rằng giao diện KMI ổn định trong suốt thời gian hoạt động được hỗ trợ của hạt nhân. Do đó, có một lớp thay đổi để hỗ trợ các mô-đun nhà cung cấp được chấp nhận cho ACK nhưng không được chấp nhận cho thượng nguồn.

Ví dụ: hãy xem xét một bản vá thêm các macro EXPORT_SYMBOL_GPL() trong đó các mô-đun sử dụng tính năng xuất không có trong cây nguồn. Mặc dù bạn phải cố gắng yêu cầu EXPORT_SYMBOL_GPL() ở thượng nguồn và cung cấp một mô-đun sử dụng biểu tượng mới xuất, nhưng nếu có lý do hợp lệ cho việc tại sao mô-đun không được gửi lên thượng nguồn, thì bạn có thể gửi bản vá cho ACK. Bạn cần đưa ra lý do giải thích tại sao không thể chuyển lên trên trong vấn đề. (Đừng yêu cầu biến thể không phải GPL, EXPORT_SYMBOL().)

Cấu hình ẩn

Một số mô-đun trong cây tự động chọn các cấu hình ẩn không thể chỉ định trong gki_defconfig. Ví dụ: CONFIG_SND_SOC_TOPOLOGY được chọn tự động khi bạn định cấu hình CONFIG_SND_SOC_SOF=y. Để hỗ trợ việc xây dựng mô-đun ngoài cây, GKI có một cơ chế để bật các cấu hình ẩn.

Để bật cấu hình ẩn, hãy thêm câu lệnh select vào init/Kconfig.gki để cấu hình này được chọn tự động dựa trên cấu hình hạt nhân CONFIG_GKI_HACKS_TO_FIX (đã bật trong gki_defconfig). Chỉ sử dụng cơ chế này cho các cấu hình ẩn; nếu cấu hình không bị ẩn, bạn phải chỉ định cấu hình đó trong gki_defconfig một cách rõ ràng hoặc dưới dạng phần phụ thuộc.

Trình quản lý có thể tải

Đối với các khung hạt nhân (chẳng hạn như cpufreq) hỗ trợ trình quản lý có thể tải, bạn có thể ghi đè trình quản lý mặc định (chẳng hạn như trình quản lý schedutil của cpufreq). Đối với các khung (chẳng hạn như khung nhiệt) không hỗ trợ các trình điều khiển hoặc trình điều khiển có thể tải nhưng vẫn yêu cầu triển khai theo từng nhà cung cấp, hãy tạo một vấn đề trong bộ phận CNTT và tham khảo ý kiến của nhóm phụ trách nhân hệ điều hành Android.

Chúng tôi sẽ làm việc với bạn và các nhà bảo trì cấp trên để thêm các tính năng hỗ trợ cần thiết.

Lệnh gọi của nhà cung cấp

Trong các bản phát hành trước, bạn có thể thêm các nội dung sửa đổi dành riêng cho nhà cung cấp trực tiếp vào hạt nhân lõi. Điều này không thể thực hiện được với GKI 2.0 vì mã dành riêng cho sản phẩm phải được triển khai trong các mô-đun và sẽ không được chấp nhận trong các hạt nhân cốt lõi ở thượng nguồn hoặc trong ACK. Để bật các tính năng giá trị gia tăng mà đối tác dựa vào mà không gây ảnh hưởng lớn đến mã nhân hệ điều hành cốt lõi, GKI chấp nhận các hook của nhà cung cấp cho phép gọi các mô-đun từ mã nhân hệ điều hành cốt lõi. Ngoài ra, các cấu trúc dữ liệu chính có thể được đệm bằng các trường dữ liệu của nhà cung cấp có sẵn để lưu trữ dữ liệu dành riêng cho nhà cung cấp nhằm triển khai các tính năng này.

Các trình bổ trợ của nhà cung cấp có hai biến thể (bình thường và bị hạn chế) dựa trên các điểm theo dõi (không phải sự kiện theo dõi) mà các mô-đun của nhà cung cấp có thể đính kèm. Ví dụ: thay vì thêm một hàm sched_exit() mới để tính toán khi thoát tác vụ, nhà cung cấp có thể thêm một trình nối trong do_exit() mà mô-đun nhà cung cấp có thể đính kèm để xử lý. Ví dụ về cách triển khai bao gồm các trình bổ trợ của nhà cung cấp sau.

  • Các trình bổ trợ nhà cung cấp thông thường sử dụng DECLARE_HOOK() để tạo hàm điểm theo dõi với tên trace_name, trong đó name là giá trị nhận dạng duy nhất cho dấu vết. Theo quy ước, tên của trình bổ trợ nhà cung cấp thông thường bắt đầu bằng android_vh, vì vậy, tên của trình bổ trợ sched_exit() sẽ là android_vh_sched_exit.
  • Bạn cần có các trình bổ trợ của nhà cung cấp bị hạn chế cho các trường hợp như trình bổ trợ của trình lập lịch biểu, trong đó hàm đính kèm phải được gọi ngay cả khi CPU đang ngoại tuyến hoặc yêu cầu ngữ cảnh không nguyên tử. Không thể tách các trình bổ trợ của nhà cung cấp bị hạn chế, vì vậy, các mô-đun gắn với trình bổ trợ bị hạn chế không bao giờ có thể tải xuống. Tên lệnh gọi của nhà cung cấp bị hạn chế bắt đầu bằng android_rvh.

Để thêm một điểm bắt buộc của nhà cung cấp, hãy báo cáo sự cố trong bộ phận CNTT và gửi bản vá (cũng như với tất cả các bản vá dành riêng cho Android, phải có vấn đề và bạn phải đưa ra lý do). Hỗ trợ cho các trình bổ trợ của nhà cung cấp chỉ có trong ACK, vì vậy, đừng gửi các bản vá này đến Linux ngược dòng.

Thêm trường nhà cung cấp vào cấu trúc

Bạn có thể liên kết dữ liệu nhà cung cấp với các cấu trúc dữ liệu chính bằng cách thêm các trường android_vendor_data bằng cách sử dụng macro ANDROID_VENDOR_DATA(). Ví dụ: để hỗ trợ các tính năng gia tăng giá trị, hãy thêm các trường vào cấu trúc như minh hoạ trong mã mẫu sau.

Để tránh xung đột tiềm ẩn giữa các trường mà nhà cung cấp cần và các trường mà OEM cần, OEM không được sử dụng các trường được khai báo bằng macro ANDROID_VENDOR_DATA(). Thay vào đó, OEM (Nhà sản xuất thiết bị gốc) phải sử dụng ANDROID_OEM_DATA() để khai báo các trường 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 */
}

Xác định trình bổ trợ của nhà cung cấp

Thêm các hook của nhà cung cấp vào mã hạt nhân làm điểm theo dõi bằng cách khai báo chúng bằng cách sử dụng DECLARE_HOOK() hoặc DECLARE_RESTRICTED_HOOK(), sau đó thêm chúng vào mã làm điểm theo dõi. Ví dụ: để thêm trace_android_vh_sched_exit() vào hàm hạt nhân do_exit() hiện có:

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

Ban đầu, hàm trace_android_vh_sched_exit() chỉ kiểm tra xem có nội dung nào được đính kèm hay không. Tuy nhiên, nếu mô-đun nhà cung cấp đăng ký một trình xử lý bằng cách sử dụng register_trace_android_vh_sched_exit(), thì hàm đã đăng ký sẽ được gọi. Trình xử lý phải nhận biết được ngữ cảnh liên quan đến các khoá đang giữ, trạng thái RCS và các yếu tố khác. Bạn phải xác định hook trong tệp tiêu đề ở thư mục include/trace/hooks.

Ví dụ: Mã sau đây đưa ra một nội dung khai báo có thể áp dụng cho trace_android_vh_sched_exit() trong tệp 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>

Để tạo bản sao các giao diện cần thiết cho trình bổ trợ của nhà cung cấp, hãy thêm tệp tiêu đề có nội dung khai báo trình bổ trợ vào drivers/android/vendor_hooks.c và xuất các biểu tượng. Ví dụ: mã sau đây hoàn tất việc khai báo lệnh gọi lại 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);

LƯU Ý: Bạn cần xác định đầy đủ các cấu trúc dữ liệu được sử dụng trong phần khai báo lệnh gọi lại để đảm bảo ABI ổn định. Nếu không, việc tham chiếu giá trị của con trỏ mờ hoặc sử dụng cấu trúc trong ngữ cảnh có kích thước sẽ không an toàn. Phần bao gồm cung cấp định nghĩa đầy đủ về các cấu trúc dữ liệu như vậy phải nằm bên trong phần #ifndef __GENKSYMS__ của drivers/android/vendor_hooks.c. Các tệp tiêu đề trong include/trace/hooks không nên bao gồm tệp tiêu đề hạt nhân với các định nghĩa loại để tránh những thay đổi CRC làm hỏng KMI. Thay vào đó, hãy khai báo chuyển tiếp các loại.

Đính kèm vào các trình bổ trợ của nhà cung cấp

Để sử dụng các trình bổ trợ của nhà cung cấp, mô-đun của nhà cung cấp cần đăng ký một trình xử lý cho trình bổ trợ (thường được thực hiện trong quá trình khởi chạy mô-đun). Ví dụ: mã sau đây cho thấy trình xử lý mô-đun foo.ko cho 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);
    ...
}

Sử dụng trình bổ trợ của nhà cung cấp từ tệp tiêu đề

Để sử dụng hook của nhà cung cấp từ tệp tiêu đề, bạn có thể cần phải cập nhật tệp tiêu đề hook của nhà cung cấp để không xác định TRACE_INCLUDE_PATH nhằm tránh các lỗi bản dựng cho biết không tìm thấy tệp tiêu đề điểm theo dõi. Ví dụ:

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.

Để khắc phục loại lỗi bản dựng này, hãy áp dụng biện pháp khắc phục tương đương cho tệp tiêu đề lệnh gọi của nhà cung cấp mà bạn đang đưa vào. Để biết thêm thông tin, hãy tham khảo 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

Việc xác định UNDEF_TRACE_INCLUDE_PATH sẽ yêu cầu include/trace/define_trace.h huỷ xác định TRACE_INCLUDE_PATH sau khi tạo các điểm theo dõi.

Các tính năng cốt lõi của nhân

Nếu không có kỹ thuật nào trước đó cho phép bạn triển khai một tính năng từ một mô-đun, thì bạn phải thêm tính năng đó dưới dạng nội dung sửa đổi dành riêng cho Android vào hạt nhân cốt lõi. Tạo một vấn đề trong công cụ theo dõi lỗi (IT) để bắt đầu cuộc trò chuyện.

Giao diện lập trình ứng dụng người dùng (UAPI)

  • Tệp tiêu đề UAPI. Các thay đổi đối với tệp tiêu đề UAPI phải xảy ra ở thượng nguồn, trừ phi các thay đổi đó là đối với giao diện dành riêng cho Android. Sử dụng các tệp tiêu đề dành riêng cho nhà cung cấp để xác định giao diện giữa các mô-đun nhà cung cấp và mã không gian người dùng của nhà cung cấp.
  • Các nút sysfs. Không thêm nút sysfs mới vào hạt nhân GKI (những phần bổ sung này chỉ hợp lệ trong mô-đun của nhà cung cấp). Các nút sysfs mà thư viện SoC và thư viện không phân biệt thiết bị cũng như mã Java bao gồm khung Android sử dụng chỉ có thể được thay đổi theo cách tương thích và phải được thay đổi ở thượng nguồn nếu không phải là nút sysfs dành riêng cho Android. Bạn có thể tạo các nút sysfs dành riêng cho nhà cung cấp để không gian người dùng của nhà cung cấp sử dụng. Theo mặc định, quyền truy cập vào các nút sysfs của không gian người dùng sẽ bị từ chối bằng SELinux. Nhà cung cấp có thể thêm các nhãn SELinux thích hợp để cho phép phần mềm của nhà cung cấp được uỷ quyền truy cập.
  • Các nút DebugFS. Các mô-đun của nhà cung cấp có thể xác định các nút trong debugfs chỉ để gỡ lỗi (vì debugfs không được gắn trong quá trình hoạt động bình thường của thiết bị).