Thêm thiết bị mới

Sử dụng thông tin trong trang này để tạo tệp makefile cho thiết bị và sản phẩm của bạn.

Mỗi mô-đun Android mới phải có một tệp cấu hình để hướng dẫn hệ thống xây dựng bằng siêu dữ liệu mô-đun, phần phụ thuộc tại thời điểm biên dịch và hướng dẫn đóng gói. Android sử dụng hệ thống xây dựng Soong. Hãy xem bài viết Tạo bản dựng Android để biết thêm thông tin về hệ thống xây dựng Android.

Tìm hiểu về các lớp bản dựng

Hệ phân cấp bản dựng bao gồm các lớp trừu tượng tương ứng với cấu trúc vật lý của thiết bị. Các lớp này được mô tả trong bảng dưới đây. Mỗi lớp liên quan đến lớp phía trên theo mối quan hệ một với nhiều. Ví dụ: một cấu trúc có thể có nhiều bảng và mỗi bảng có thể có nhiều sản phẩm. Bạn có thể xác định một phần tử trong một lớp nhất định là một phần tử chuyên biệt của một phần tử trong cùng lớp, giúp loại bỏ việc sao chép và đơn giản hoá việc bảo trì.

Lớp Ví dụ Mô tả
Sản phẩm myProduct, myProduct_eu, myProduct_eu_fr, j2, sdk Lớp sản phẩm xác định thông số kỹ thuật của tính năng của một sản phẩm vận chuyển, chẳng hạn như các mô-đun cần tạo, ngôn ngữ được hỗ trợ và cấu hình cho nhiều ngôn ngữ. Nói cách khác, đây là tên của sản phẩm tổng thể. Các biến dành riêng cho sản phẩm được xác định trong các tệp makefile định nghĩa sản phẩm. Một sản phẩm có thể kế thừa từ các định nghĩa sản phẩm khác, giúp đơn giản hoá việc bảo trì. Một phương pháp phổ biến là tạo một sản phẩm cơ sở chứa các tính năng áp dụng cho tất cả sản phẩm, sau đó tạo các biến thể sản phẩm dựa trên sản phẩm cơ sở đó. Ví dụ: hai sản phẩm chỉ khác nhau về radio (CDMA so với GSM) có thể kế thừa từ cùng một sản phẩm cơ sở không xác định radio.
Bảng/thiết bị cá thu ngừ, xanh dương, san hô Lớp bo mạch/thiết bị đại diện cho lớp nhựa thực tế trên thiết bị (tức là thiết kế công nghiệp của thiết bị). Lớp này cũng thể hiện sơ đồ cơ bản của một sản phẩm. Các thành phần này bao gồm cả thiết bị ngoại vi trên bo mạch và cấu hình của các thiết bị đó. Tên được sử dụng chỉ là mã cho các cấu hình bảng/thiết bị khác nhau.
Hình vòng cung arm, x86, arm64, x86_64 Lớp cấu trúc mô tả cấu hình bộ xử lý và giao diện nhị phân của ứng dụng (ABI) chạy trên bo mạch.

Sử dụng biến thể bản dựng

Khi xây dựng cho một sản phẩm cụ thể, bạn nên có các biến thể nhỏ trên bản phát hành cuối cùng. Trong định nghĩa mô-đun, mô-đun có thể chỉ định thẻ bằng LOCAL_MODULE_TAGS, có thể là một hoặc nhiều giá trị của optional (mặc định), debugeng.

Nếu một mô-đun không chỉ định thẻ (bằng LOCAL_MODULE_TAGS), thì thẻ của mô-đun đó sẽ mặc định là optional. Mô-đun không bắt buộc chỉ được cài đặt nếu cấu hình sản phẩm yêu cầu bằng PRODUCT_PACKAGES.

Đây là các biến thể bản dựng hiện được xác định.

Biến thể Mô tả
eng Đây là phiên bản mặc định.
  • Cài đặt các mô-đun được gắn thẻ eng hoặc debug.
  • Cài đặt các mô-đun theo tệp định nghĩa sản phẩm, ngoài các mô-đun được gắn thẻ.
  • ro.secure=0
  • ro.debuggable=1
  • ro.kernel.android.checkjni=1
  • adb được bật theo mặc định.
user Biến thể dự kiến sẽ là các bit phát hành cuối cùng.
  • Cài đặt các mô-đun được gắn thẻ user.
  • Cài đặt các mô-đun theo tệp định nghĩa sản phẩm, ngoài các mô-đun được gắn thẻ.
  • ro.secure=1
  • ro.debuggable=0
  • adb bị tắt theo mặc định.
userdebug Tương tự như user, ngoại trừ các trường hợp sau:
  • Ngoài ra, còn cài đặt các mô-đun được gắn thẻ debug.
  • ro.debuggable=1
  • adb được bật theo mặc định.

Nguyên tắc về userdebug

Việc chạy các bản dựng userdebug trong quá trình kiểm thử giúp các nhà phát triển thiết bị hiểu được hiệu suất và sức mạnh của các bản phát hành đang trong quá trình phát triển. Để duy trì tính nhất quán giữa bản dựng người dùng và bản dựng userdebug, cũng như để đạt được các chỉ số đáng tin cậy trong các bản dựng dùng để gỡ lỗi, nhà phát triển thiết bị nên tuân theo các nguyên tắc sau:

  • userdebug được xác định là bản dựng người dùng có bật quyền truy cập gốc, ngoại trừ:
    • các ứng dụng chỉ dành cho userdebug mà người dùng chỉ chạy theo yêu cầu
    • Các hoạt động chỉ chạy trong quá trình bảo trì ở trạng thái rảnh (khi sạc/đã sạc đầy), chẳng hạn như sử dụng dex2oatd thay vì dex2oat để biên dịch ở chế độ nền
  • Không đưa vào các tính năng được bật/tắt theo mặc định dựa trên loại bản dựng. Nhà phát triển không nên sử dụng bất kỳ hình thức ghi nhật ký nào ảnh hưởng đến thời lượng pin, chẳng hạn như ghi nhật ký gỡ lỗi hoặc kết xuất vùng nhớ khối xếp.
  • Mọi tính năng gỡ lỗi được bật theo mặc định trong userdebug phải được xác định rõ ràng và chia sẻ với tất cả nhà phát triển đang làm việc trên dự án. Bạn chỉ nên bật các tính năng gỡ lỗi trong một khoảng thời gian có hạn cho đến khi giải quyết được vấn đề mà bạn đang cố gắng gỡ lỗi.

Tuỳ chỉnh bản dựng bằng lớp phủ tài nguyên

Hệ thống xây dựng Android sử dụng lớp phủ tài nguyên để tuỳ chỉnh sản phẩm tại thời điểm tạo bản dựng. Lớp phủ tài nguyên chỉ định các tệp tài nguyên được áp dụng trên các tệp mặc định. Để sử dụng lớp phủ tài nguyên, hãy sửa đổi tệp bản dựng dự án để đặt PRODUCT_PACKAGE_OVERLAYS thành một đường dẫn tương ứng với thư mục cấp cao nhất. Đường dẫn đó trở thành thư mục gốc bóng được tìm kiếm cùng với thư mục gốc hiện tại khi hệ thống xây dựng tìm kiếm tài nguyên.

Các chế độ cài đặt được tuỳ chỉnh phổ biến nhất nằm trong tệp frameworks/base/core/res/res/values/config.xml.

Để thiết lập lớp phủ tài nguyên trên tệp này, hãy thêm thư mục lớp phủ vào tệp bản dựng dự án bằng một trong các cách sau:

PRODUCT_PACKAGE_OVERLAYS := device/device-implementer/device-name/overlay

hoặc

PRODUCT_PACKAGE_OVERLAYS := vendor/vendor-name/overlay

Sau đó, hãy thêm tệp lớp phủ vào thư mục, ví dụ:

vendor/foobar/overlay/frameworks/base/core/res/res/values/config.xml

Mọi chuỗi hoặc mảng chuỗi tìm thấy trong tệp config.xml lớp phủ sẽ thay thế những chuỗi hoặc mảng chuỗi tìm thấy trong tệp gốc.

Tạo sản phẩm

Bạn có thể sắp xếp các tệp nguồn cho thiết bị theo nhiều cách. Dưới đây là nội dung mô tả ngắn gọn về một cách để sắp xếp việc triển khai Pixel.

Pixel được triển khai bằng cấu hình thiết bị chính có tên là marlin. Từ cấu hình thiết bị này, một sản phẩm được tạo bằng một tệp makefile định nghĩa sản phẩm khai báo thông tin dành riêng cho sản phẩm về thiết bị, chẳng hạn như tên và kiểu máy. Bạn có thể xem thư mục device/google/marlin để xem cách thiết lập tất cả các thành phần này.

Viết tệp makefile của sản phẩm

Các bước sau đây mô tả cách thiết lập tệp make của sản phẩm theo cách tương tự như dòng sản phẩm Pixel:

  1. Tạo thư mục device/<company-name>/<device-name> cho sản phẩm. Ví dụ: device/google/marlin. Thư mục này sẽ chứa mã nguồn cho thiết bị của bạn cùng với các tệp makefile để tạo mã nguồn.
  2. Tạo một tệp makefile device.mk khai báo các tệp và mô-đun cần thiết cho thiết bị. Để biết ví dụ, hãy xem device/google/marlin/device-marlin.mk.
  3. Tạo tệp makefile định nghĩa sản phẩm để tạo một sản phẩm cụ thể dựa trên thiết bị. Sau đây là ví dụ về tệp makefile được lấy từ device/google/marlin/aosp_marlin.mk. Lưu ý rằng sản phẩm kế thừa từ các tệp device/google/marlin/device-marlin.mkvendor/google/marlin/device-vendor-marlin.mk thông qua tệp makefile, đồng thời khai báo thông tin cụ thể về sản phẩm như tên, thương hiệu và kiểu máy.
    # Inherit from the common Open Source product configuration
    $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
    $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
    
    PRODUCT_NAME := aosp_marlin
    PRODUCT_DEVICE := marlin
    PRODUCT_BRAND := Android
    PRODUCT_MODEL := AOSP on msm8996
    PRODUCT_MANUFACTURER := Google
    PRODUCT_RESTRICT_VENDOR_FILES := true
    
    PRODUCT_COPY_FILES += device/google/marlin/fstab.common:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.marlin
    
    $(call inherit-product, device/google/marlin/device-marlin.mk)
    $(call inherit-product-if-exists, vendor/google_devices/marlin/device-vendor-marlin.mk)
    
    PRODUCT_PACKAGES += \
        Launcher3QuickStep \
        WallpaperPicker
    

    Hãy xem phần Đặt biến định nghĩa sản phẩm để biết thêm các biến dành riêng cho sản phẩm mà bạn có thể thêm vào tệp makefile.

  4. Tạo tệp AndroidProducts.mk trỏ đến tệp makefile của sản phẩm. Trong ví dụ này, bạn chỉ cần tệp makefile định nghĩa sản phẩm. Ví dụ bên dưới là từ device/google/marlin/AndroidProducts.mk (chứa cả marlin, Pixel và sailfish, Pixel XL, có chung hầu hết cấu hình):
    PRODUCT_MAKEFILES := \
    	$(LOCAL_DIR)/aosp_marlin.mk \
    	$(LOCAL_DIR)/aosp_sailfish.mk
    
    COMMON_LUNCH_CHOICES := \
    	aosp_marlin-userdebug \
    	aosp_sailfish-userdebug
    
  5. Tạo một tệp makefile BoardConfig.mk chứa các cấu hình dành riêng cho bo mạch. Để biết ví dụ, hãy xem device/google/marlin/BoardConfig.mk.
  6. Chỉ dành cho Android 9 trở xuống, hãy tạo một tệp vendorsetup.sh để thêm sản phẩm của bạn ("bữa ăn trưa kết hợp") vào bản dựng cùng với một biến thể bản dựng được phân tách bằng dấu gạch ngang. Ví dụ:
    add_lunch_combo <product-name>-userdebug
    
  7. Tại thời điểm này, bạn có thể tạo thêm biến thể sản phẩm dựa trên cùng một thiết bị.

Đặt biến định nghĩa sản phẩm

Các biến dành riêng cho sản phẩm được xác định trong tệp makefile của sản phẩm. Bảng này cho thấy một số biến được duy trì trong tệp định nghĩa sản phẩm.

Biến Mô tả Ví dụ
PRODUCT_AAPT_CONFIG Cấu hình aapt để sử dụng khi tạo gói.
PRODUCT_BRAND Thương hiệu (ví dụ: nhà mạng) mà phần mềm được tuỳ chỉnh.
PRODUCT_CHARACTERISTICS Đặc điểm aapt để cho phép thêm tài nguyên dành riêng cho biến thể vào một gói. tablet, nosdcard
PRODUCT_COPY_FILES Danh sách các từ như source_path:destination_path. Bạn nên sao chép tệp ở đường dẫn nguồn vào đường dẫn đích khi tạo sản phẩm này. Các quy tắc cho các bước sao chép được xác định trong config/makefile.
PRODUCT_DEVICE Tên của kiểu dáng công nghiệp. Đây cũng là tên bảng và hệ thống xây dựng sử dụng tên này để xác định vị trí BoardConfig.mk. tuna
PRODUCT_LOCALES Danh sách các cặp mã ngôn ngữ gồm hai chữ cái, mã quốc gia gồm hai chữ cái được phân tách bằng dấu cách, mô tả một số chế độ cài đặt cho người dùng, chẳng hạn như ngôn ngữ giao diện người dùng, thời gian, ngày và định dạng tiền tệ. Ngôn ngữ đầu tiên được liệt kê trong PRODUCT_LOCALES được dùng làm ngôn ngữ mặc định của sản phẩm. en_GB, de_DE, es_ES, fr_CA
PRODUCT_MANUFACTURER Tên của nhà sản xuất. acme
PRODUCT_MODEL Tên hiển thị cho người dùng cuối của sản phẩm cuối cùng.
PRODUCT_NAME Tên hiển thị cho người dùng cuối của sản phẩm tổng thể. Xuất hiện trong màn hình Cài đặt > Giới thiệu.
PRODUCT_OTA_PUBLIC_KEYS Danh sách khoá công khai truyền hình không dây (OTA) cho sản phẩm.
PRODUCT_PACKAGES Danh sách các tệp APK và mô-đun cần cài đặt. Danh bạ trong Lịch
PRODUCT_PACKAGE_OVERLAYS Cho biết liệu có sử dụng tài nguyên mặc định hay thêm bất kỳ lớp phủ nào dành riêng cho sản phẩm hay không. vendor/acme/overlay
PRODUCT_SYSTEM_PROPERTIES Danh sách các lượt chỉ định thuộc tính hệ thống ở định dạng "key=value" cho phân vùng hệ thống. Bạn có thể đặt thuộc tính hệ thống cho các phân vùng khác thông qua PRODUCT_<PARTITION>_PROPERTIES như trong PRODUCT_VENDOR_PROPERTIES cho phân vùng của nhà cung cấp. Tên phân vùng được hỗ trợ: SYSTEM, VENDOR, ODM, SYSTEM_EXTPRODUCT.

Định cấu hình bộ lọc ngôn ngữ và ngôn ngữ mặc định của hệ thống

Sử dụng thông tin này để định cấu hình bộ lọc ngôn ngữ mặc định và bộ lọc ngôn ngữ hệ thống, sau đó bật bộ lọc ngôn ngữ cho một loại thiết bị mới.

Thuộc tính

Định cấu hình cả ngôn ngữ mặc định và bộ lọc ngôn ngữ hệ thống bằng cách sử dụng các thuộc tính hệ thống chuyên dụng:

  • ro.product.locale: để đặt ngôn ngữ mặc định. Ban đầu, giá trị này được đặt thành ngôn ngữ đầu tiên trong biến PRODUCT_LOCALES; bạn có thể ghi đè giá trị đó. (Để biết thêm thông tin, hãy xem bảng Đặt biến định nghĩa sản phẩm.)
  • ro.localization.locale_filter: để đặt bộ lọc ngôn ngữ, sử dụng biểu thức chính quy áp dụng cho tên ngôn ngữ. Ví dụ:
    • Bộ lọc bao gồm: ^(de-AT|de-DE|en|uk).* – chỉ cho phép tiếng Đức (các biến thể tiếng Đức ở Áo và Đức), tất cả biến thể tiếng Anh và tiếng Ukraina
    • Bộ lọc độc quyền: ^(?!de-IT|es).* – loại trừ tiếng Đức (biến thể Ý) và tất cả biến thể tiếng Tây Ban Nha.

Bật bộ lọc ngôn ngữ

Để bật bộ lọc, hãy đặt giá trị chuỗi thuộc tính hệ thống ro.localization.locale_filter.

Bằng cách đặt giá trị thuộc tính bộ lọc và ngôn ngữ mặc định thông qua oem/oem.prop trong quá trình hiệu chuẩn ban đầu, bạn có thể định cấu hình các quy tắc hạn chế mà không cần đưa bộ lọc vào hình ảnh hệ thống. Bạn đảm bảo rằng các thuộc tính này được lấy từ phân vùng OEM bằng cách thêm các thuộc tính đó vào biến PRODUCT_OEM_PROPERTIES như được chỉ định dưới đây:

# Delegation for OEM customization
PRODUCT_OEM_PROPERTIES += \
    ro.product.locale \
    ro.localization.locale_filter

Sau đó, trong quá trình phát hành chính thức, các giá trị thực tế sẽ được ghi vào oem/oem.prop để phản ánh các yêu cầu mục tiêu. Với phương pháp này, các giá trị mặc định được giữ lại trong quá trình đặt lại về trạng thái ban đầu, vì vậy, chế độ cài đặt ban đầu sẽ giống hệt như chế độ thiết lập đầu tiên đối với người dùng.

Đặt ADB_VENDOR_KEYS để kết nối qua USB

Biến môi trường ADB_VENDOR_KEYS cho phép nhà sản xuất thiết bị truy cập vào các bản dựng có thể gỡ lỗi (-userdebug và -eng, nhưng không phải -user) qua adb mà không cần uỷ quyền thủ công. Thông thường, adb sẽ tạo một khoá xác thực RSA duy nhất cho mỗi máy tính khách và gửi khoá này đến mọi thiết bị đã kết nối. Đây là khoá RSA xuất hiện trong hộp thoại uỷ quyền adb. Ngoài ra, bạn có thể tạo các khoá đã biết vào hình ảnh hệ thống và chia sẻ các khoá đó với ứng dụng adb. Điều này hữu ích cho việc phát triển hệ điều hành và đặc biệt là cho việc kiểm thử vì bạn không cần phải tương tác theo cách thủ công với hộp thoại uỷ quyền adb.

Để tạo khoá nhà cung cấp, một người (thường là người quản lý bản phát hành) phải:

  1. Tạo một cặp khoá bằng adb keygen. Đối với các thiết bị của Google, Google sẽ tạo một cặp khoá mới cho mỗi phiên bản hệ điều hành mới.
  2. Kiểm tra các cặp khoá ở đâu đó trong cây nguồn. Ví dụ: Google lưu trữ các tệp này trong vendor/google/security/adb/.
  3. Đặt biến bản dựng PRODUCT_ADB_KEYS để trỏ đến thư mục khoá. Google thực hiện việc này bằng cách thêm một tệp Android.mk vào thư mục khoá có tên là PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub. Thao tác này giúp đảm bảo rằng chúng ta nhớ tạo một cặp khoá mới cho mỗi phiên bản hệ điều hành.

Dưới đây là tệp makefile mà Google sử dụng trong thư mục lưu trữ các cặp khoá đã kiểm tra cho mỗi bản phát hành:

PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub

ifeq ($(wildcard $(PRODUCT_ADB_KEYS)),)
  $(warning ========================)
  $(warning The adb key for this release)
  $(warning )
  $(warning   $(PRODUCT_ADB_KEYS))
  $(warning )
  $(warning does not exist. Most likely PLATFORM_VERSION in build/core/version_defaults.mk)
  $(warning has changed and a new adb key needs to be generated.)
  $(warning )
  $(warning Please run the following commands to create a new key:)
  $(warning )
  $(warning   make -j8 adb)
  $(warning   LOGNAME=android-eng HOSTNAME=google.com adb keygen $(patsubst %.pub,%,$(PRODUCT_ADB_KEYS)))
  $(warning )
  $(warning and upload/review/submit the changes)
  $(warning ========================)
  $(error done)
endif

Để sử dụng các khoá nhà cung cấp này, kỹ sư chỉ cần đặt biến môi trường ADB_VENDOR_KEYS để trỏ đến thư mục lưu trữ các cặp khoá. Thao tác này yêu cầu adb thử các khoá chuẩn hoá này trước, trước khi quay lại khoá máy chủ đã tạo và yêu cầu uỷ quyền thủ công. Khi adb không thể kết nối với một thiết bị không được uỷ quyền, thông báo lỗi sẽ đề xuất bạn đặt ADB_VENDOR_KEYS nếu bạn chưa đặt.