Dodawanie nowego urządzenia

Użyj informacji na tej stronie, aby utworzyć pliki make dla urządzenia i produktu.

Każde nowe moduł Androida musi mieć plik konfiguracji, który kieruje system kompilacji za pomocą metadanych modułu, zależności na etapie kompilacji i instrukcji pakowania. Android używa systemu kompilacji Soong. Więcej informacji o systemie kompilacji Androida znajdziesz w artykule Kompilowanie aplikacji na Androida.

Informacje o warstwach kompilacji

Hierarchia kompilacji obejmuje warstwy abstrakcji odpowiadające fizycznej budowie urządzenia. Te warstwy zostały opisane w tabeli poniżej. Każda warstwa jest powiązana z poprzednią relacją „jeden do wielu”. Na przykład architektura może mieć więcej niż 1 kartę, a każda karta może mieć więcej niż 1 produkt. Element w danej warstwie możesz zdefiniować jako specjalizację elementu w tej samej warstwie. Pozwala to uniknąć kopiowania i uproszcza konserwację.

Warstwa Przykład Opis
Produkt myProduct, myProduct_eu, myProduct_eu_fr, j2, sdk Warstwa produktu określa specyfikację funkcji usługi dostawy, w tym moduły do utworzenia, obsługiwane języki i konfigurację dla różnych języków. Innymi słowy, jest to nazwa całego produktu. Zmienne związane z poszczególnymi produktami są definiowane w makefile’ach definicji produktów. Produkt może dziedziczyć właściwości z innych definicji produktów, co upraszcza konserwację. Typową metodą jest utworzenie produktu podstawowego zawierającego funkcje, które mają zastosowanie do wszystkich produktów, a następnie utworzenie wersji produktu na podstawie tego produktu podstawowego. Na przykład 2 produkty, które różnią się tylko radiem (CDMA lub GSM), mogą dziedziczyć z tego samego produktu podstawowego, który nie definiuje radia.
Płytka/urządzenie marlin, niebieski, koralowy Warstwa płytki/urządzenia reprezentuje fizyczną warstwę plastiku na urządzeniu (czyli przemysłowy projekt urządzenia). Ta warstwa reprezentuje również puste schematy produktu. Obejmuje to urządzenia peryferyjne w płycie głównej i ich konfigurację. Nazwy są tylko kodami różnych konfiguracji płyty/urządzenia.
Łuk arm, x86, arm64, x86_64 Warstwowa architektura opisuje konfigurację procesora i interfejs binarny aplikacji (ABI) działający na płycie.

Używanie wariantów kompilacji

Podczas kompilowania wersji na potrzeby konkretnego produktu warto wprowadzić drobne zmiany w wersji finalnej. W definicji modułu moduł może określać tagi za pomocą parametru LOCAL_MODULE_TAGS, który może przyjmować co najmniej jedną z tych wartości: optional (domyślna), debugeng.

Jeśli moduł nie określa tagu (za pomocą parametru LOCAL_MODULE_TAGS), domyślnie jest używany tag optional. Opcjonalny moduł jest instalowany tylko wtedy, gdy jest wymagany przez konfigurację produktu z PRODUCT_PACKAGES.

Są to obecnie zdefiniowane warianty wersji.

Wariant Opis
eng Jest to domyślna wersja.
  • Instaluje moduły oznaczone tagiem eng lub debug.
  • Instaluje moduły zgodnie z plikami definicji produktów, a także otagowane moduły.
  • ro.secure=0
  • ro.debuggable=1
  • ro.kernel.android.checkjni=1
  • adb jest domyślnie włączona.
user wariant, który ma być ostateczną wersją,
  • Instaluje moduły oznaczone tagiem user.
  • Instaluje moduły zgodnie z plikami definicji produktów, a także otagowane moduły.
  • ro.secure=1
  • ro.debuggable=0
  • adb jest domyślnie wyłączona.
userdebug To samo co user, z tymi wyjątkami:
  • Instaluje też moduły z tagiem debug.
  • ro.debuggable=1
  • adb jest domyślnie włączona.

Wytyczne dotyczące userdebug

Uruchamianie wersji userdebug w ramach testów pomaga deweloperom urządzeń lepiej poznać wydajność i możliwości wersji w trakcie tworzenia. Aby zachować spójność między wersjami przeznaczonymi dla użytkowników i użytkowników w celu debugowania oraz uzyskać wiarygodne dane w wersjach używanych do debugowania, deweloperzy urządzeń powinni przestrzegać tych wytycznych:

  • userdebug to kompilacja użytkownika z włączonym dostępem roota, z wyjątkiem:
    • aplikacje przeznaczone tylko do testowania, które są uruchamiane tylko na żądanie przez użytkownika;
    • operacje wykonywane tylko podczas konserwacji w trybie bezczynności (na ładowarce lub w pełni naładowanej baterii), np. użycie dex2oatd zamiast dex2oat do kompilacji w tle;
  • Nie uwzględniaj funkcji, które są domyślnie włączone lub wyłączone na podstawie typu kompilacji. Nie zalecamy używania żadnych form rejestrowania, które mają wpływ na czas pracy na baterii, takich jak rejestrowanie debugowania czy zrzuty stosu.
  • Wszystkie funkcje debugowania, które są domyślnie włączone w userdebug, powinny być jasno zdefiniowane i udostępnione wszystkim deweloperom pracującym nad projektem. Funkcje debugowania należy włączać tylko na ograniczony czas, dopóki nie rozwiążesz problemu, który próbujesz rozwiązać.

Dostosowywanie wersji za pomocą nakładek zasobów

System kompilacji Androida używa nakładek zasobów do dostosowywania produktu w momencie kompilacji. Nakładki zasobów określają pliki zasobów, które są stosowane na wierzchu domyślnych. Aby używać nakładek zasobów, zmodyfikuj plik build projektu, aby ustawić wartość PRODUCT_PACKAGE_OVERLAYS na ścieżkę względną do katalogu najwyższego poziomu. Ta ścieżka staje się katalogiem głównym cienia, który jest przeszukiwany wraz z bieżącym katalogiem głównym, gdy system kompilacji szuka zasobów.

Najczęściej dostosowywane ustawienia znajdują się w pliku frameworks/base/core/res/res/values/config.xml.

Aby skonfigurować nakładkę zasobów w tym pliku, dodaj katalog nakładki do pliku kompilacji projektu za pomocą jednej z tych opcji:

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

lub

PRODUCT_PACKAGE_OVERLAYS := vendor/vendor-name/overlay

Następnie dodaj do katalogu plik nakładki, na przykład:

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

Wszystkie ciągi znaków lub tablice ciągów znaków znalezione w pliku nakładki config.xml zastępują te znalezione w pliku oryginalnym.

Tworzenie produktu

Pliki źródłowe na urządzeniu możesz porządkować na wiele sposobów. Oto krótki opis jednej z metod organizacji implementacji pikselu.

Pixel jest implementowany z główną konfiguracją urządzenia o nazwie marlin. Na podstawie tej konfiguracji urządzenia tworzony jest produkt z makefile definicji produktu, który deklaruje informacje o produkcie, takie jak nazwa i model. Aby zobaczyć, jak to wszystko jest skonfigurowane, otwórz katalog device/google/marlin.

Tworzenie makefile’ów produktów

Poniżej znajdziesz instrukcje konfigurowania plików make podobnych do tych używanych w linii produktów Pixel:

  1. Utwórz device/<company-name>/<device-name>katalog dla produktu. Na przykład: device/google/marlin. Katalog ten będzie zawierać kod źródłowy Twojego urządzenia wraz z plikami make służącymi do jego kompilacji.
  2. Utwórz plik makefile device.mk, który deklaruje pliki i moduły potrzebne na urządzeniu. Przykład znajdziesz w sekcji device/google/marlin/device-marlin.mk.
  3. Utwórz makefile definicji produktu, aby utworzyć konkretny produkt na podstawie urządzenia. Poniżej znajduje się przykładowy plik makefile pochodzący z device/google/marlin/aosp_marlin.mk. Zwróć uwagę, że produkt dziedziczy z plików device/google/marlin/device-marlin.mkvendor/google/marlin/device-vendor-marlin.mk za pomocą makefile, deklarując jednocześnie informacje o produkcie, takie jak nazwa, marka i model.
    # 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
    

    Aby dowiedzieć się więcej o dodatkowych zmiennych dotyczących produktów, które możesz dodać do plików make, zapoznaj się z artykułem Ustawianie zmiennych definicji produktu.

  4. Utwórz plik AndroidProducts.mk, który wskazuje pliki make produktu. W tym przykładzie wymagany jest tylko plik make z definicją produktu. Przykład poniżej pochodzi z device/google/marlin/AndroidProducts.mk (który zawiera zarówno model marlin, czyli Pixel, jak i model sailfish, czyli Pixel XL, które mają identyczną konfigurację):
    PRODUCT_MAKEFILES := \
    	$(LOCAL_DIR)/aosp_marlin.mk \
    	$(LOCAL_DIR)/aosp_sailfish.mk
    
    COMMON_LUNCH_CHOICES := \
    	aosp_marlin-userdebug \
    	aosp_sailfish-userdebug
    
  5. Utwórz plik make BoardConfig.mk zawierający konfiguracje specyficzne dla danej płytki. Przykład znajdziesz w sekcji device/google/marlin/BoardConfig.mk.
  6. Tylko w przypadku Androida 9 i starszych: utwórz plik vendorsetup.sh, aby dodać produkt (np. „lunch combo”) do wersji wraz z wersją wersji, oddzieloną myślnikiem. Przykład:
    add_lunch_combo <product-name>-userdebug
    
  7. W tym momencie możesz utworzyć więcej wersji produktu na podstawie tego samego urządzenia.

Konfigurowanie zmiennych definicji produktu

Zmienne związane z poszczególnymi produktami są definiowane w pliku make. Tabela zawiera niektóre zmienne przechowywane w pliku definicji produktu.

Zmienna Opis Przykład
PRODUCT_AAPT_CONFIG aapt konfiguracji do użycia podczas tworzenia pakietów.
PRODUCT_BRAND Marka (np. operator), dla której oprogramowanie jest dostosowane.
PRODUCT_CHARACTERISTICS aapt, aby umożliwić dodawanie do pakietu zasobów związanych z poszczególnymi wariantami. tablet, nosdcard
PRODUCT_COPY_FILES Lista słów takich jak source_path:destination_path. Podczas tworzenia tego produktu plik na ścieżce źródłowej należy skopiować na ścieżkę docelową. Reguły dotyczące kopiowania kroków są zdefiniowane w config/makefile.
PRODUCT_DEVICE Nazwa projektu przemysłowego. Jest to też nazwa płyty głównej, której system kompilacji używa do znajdowania BoardConfig.mk. tuna
PRODUCT_LOCALES Lista oddzielonych spacjami par dwuliterowych kodów języka i dwuliterowych kodów kraju, które opisują różne ustawienia dla użytkownika, takie jak język interfejsu użytkownika oraz formatowanie czasu, daty i waluty. Pierwszy język na liście w pliku PRODUCT_LOCALES jest używany jako domyślny język produktu. en_GB, de_DE, es_ES, fr_CA
PRODUCT_MANUFACTURER Nazwa producenta. acme
PRODUCT_MODEL Nazwa produktu widoczna dla użytkowników.
PRODUCT_NAME Nazwa produktu widoczna dla użytkowników. Wyświetla się na ekranie Ustawienia > Informacje.
PRODUCT_OTA_PUBLIC_KEYS Lista kluczy publicznych OTA dla usługi.
PRODUCT_PACKAGES Lista plików APK i modułów do zainstalowania. Kontakty w kalendarzu
PRODUCT_PACKAGE_OVERLAYS Określa, czy należy użyć zasobów domyślnych, czy dodać nakładki dla poszczególnych produktów. vendor/acme/overlay
PRODUCT_SYSTEM_PROPERTIES Lista przypisań właściwości systemowych w formacie "key=value" dla partycji systemowej. Właściwości systemowe innych partycji można ustawiać za pomocą funkcji PRODUCT_<PARTITION>_PROPERTIES, tak jak w przypadku funkcji PRODUCT_VENDOR_PROPERTIES dla partycji dostawcy. Obsługiwane nazwy partycji: SYSTEM, VENDOR, ODM, SYSTEM_EXT i PRODUCT.

Konfigurowanie domyślnego języka systemu i filtra lokalizacji

Użyj tych informacji, aby skonfigurować domyślny język i filtr systemu, a następnie włącz filtr języka dla nowego typu urządzenia.

Właściwości

Skonfiguruj domyślny język i filtr języka systemu za pomocą specjalnych właściwości systemu:

  • ro.product.locale: do ustawienia domyślnego języka. Jest on początkowo ustawiany na pierwszy region językowy w zmiennej PRODUCT_LOCALES. Możesz jednak zastąpić tę wartość. (Więcej informacji znajdziesz w tabeli Ustawianie zmiennych definicji produktu).
  • ro.localization.locale_filter: do ustawienia filtra lokalizacji za pomocą wyrażenia regularnego zastosowanego do nazw lokalizacji. Na przykład:
    • Filtr uwzględniający: ^(de-AT|de-DE|en|uk).* – pozwala na wyświetlanie tylko wersji niemieckich (austriackich i niemieckich), wszystkich wariantów języka angielskiego oraz języka ukraińskiego.
    • Filtr wykluczeń: ^(?!de-IT|es).* – wyklucza język niemiecki (wariant włoski) i wszystkie warianty języka hiszpańskiego.

Włączanie filtra języka

Aby włączyć filtr, ustaw wartość ciągu znaków właściwości systemowej ro.localization.locale_filter.

Ustawiając wartość właściwości filtra i język domyślny za pomocą oem/oem.prop podczas kalibracji fabrycznej, możesz skonfigurować ograniczenia bez wprowadzania filtra do obrazu systemu. Aby te właściwości były pobierane z partycji OEM, dodaj je do zmiennej PRODUCT_OEM_PROPERTIES w ten sposób:

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

Następnie w wersji produkcyjnej do pliku oem/oem.prop zapisywane są rzeczywiste wartości, które odpowiadają wymaganiom docelowym. Dzięki temu podczas przywracania ustawień fabrycznych wartości domyślne są zachowywane, dzięki czemu początkowe ustawienia wyglądają dla użytkownika tak samo jak podczas pierwszej konfiguracji.

Ustaw ADB_VENDOR_KEYS, aby połączyć się przez USB

Zmienna środowiskowa ADB_VENDOR_KEYS umożliwia producentom urządzeń dostęp do wersji umożliwiających debugowanie (-userdebug i -eng, ale nie -user) za pomocą adb bez ręcznego autoryzowania. Zazwyczaj adb generuje niepowtarzalny klucz uwierzytelniający RSA dla każdego komputera klienta i wysyła go do każdego podłączonego urządzenia. To klucz RSA wyświetlany w oknie autoryzacji adb. Alternatywnie możesz wbudować znane klucze w obrazie systemu i udostępnić je klientowi adb. Jest to przydatne podczas tworzenia i szczególnie testowania systemu operacyjnego, ponieważ eliminuje konieczność ręcznego otwierania okna autoryzacji adb.

Aby utworzyć klucze dostawcy, jedna osoba (zazwyczaj menedżer wersji) powinna:

  1. Wygeneruj parę kluczy za pomocą adb keygen. W przypadku urządzeń Google Google generuje nową parę kluczy dla każdej nowej wersji systemu operacyjnego.
  2. Sprawdź pary kluczy gdzieś w drzewie źródeł. Google przechowuje je na przykład w vendor/google/security/adb/.
  3. Ustaw zmienną kompilacji PRODUCT_ADB_KEYS tak, aby wskazywała katalog kluczy. Google robi to, dodając do katalogu kluczy plik Android.mk o nazwie PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub. Pomaga to pamiętać o generowaniu nowego klucza pary dla każdej wersji systemu operacyjnego.

Oto plik makefile używany przez Google w katalogu, w którym przechowujemy pary kluczy przesłane w ramach każdej wersji:

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

Aby używać tych kluczy dostawcy, inżynier musi tylko ustawić zmienną środowiskową ADB_VENDOR_KEYS tak, aby wskazywała katalog, w którym są przechowywane pary kluczy. To powoduje, że adb najpierw próbuje użyć tych kluczy kanonicznych, a potem, jeśli to nie zadziała, używa wygenerowanego klucza hosta, który wymaga ręcznego zatwierdzenia. Gdy adb nie może połączyć się z nieautoryzowanym urządzeniem, komunikat o błędzie zasugeruje, aby ustawić ADB_VENDOR_KEYS, jeśli nie jest już ustawiony.