Dodanie nowego urządzenia

Skorzystaj z informacji zawartych na tej stronie, aby utworzyć pliki make dla swojego urządzenia i produktu.

Każdy nowy moduł Androida musi mieć plik konfiguracyjny, który będzie sterował systemem kompilacji za pomocą metadanych modułu, zależności w czasie kompilacji i instrukcji pakowania. Android korzysta z systemu kompilacji Soong . Aby uzyskać więcej informacji na temat systemu kompilacji systemu Android, zobacz Tworzenie systemu Android.

Zrozumienie warstw kompilacji

Hierarchia kompilacji obejmuje warstwy abstrakcji odpowiadające fizycznemu składowi urządzenia. Warstwy te opisano w poniższej tabeli. Każda warstwa jest powiązana z warstwą znajdującą się nad nią w relacji jeden do wielu. Na przykład architektura może mieć więcej niż jedną płytkę, a każda płytka może zawierać więcej niż jeden produkt. Można zdefiniować element w danej warstwie jako specjalizację elementu w tej samej warstwie, co eliminuje kopiowanie i ułatwia konserwację.

Warstwa Przykład Opis
Produkt mójProdukt, mójProdukt_eu, mójProdukt_eu_fr, j2, sdk Warstwa produktu definiuje specyfikację funkcji produktu wysyłkowego, taką jak moduły do ​​zbudowania, obsługiwane lokalizacje i konfiguracja dla różnych lokalizacji. Innymi słowy, jest to nazwa całego produktu. Zmienne specyficzne dla produktu są zdefiniowane w plikach makefile definicji produktu. Produkt może dziedziczyć z innych definicji produktu, co upraszcza konserwację. Powszechną metodą jest utworzenie produktu podstawowego zawierającego funkcje mające zastosowanie do wszystkich produktów, a następnie utworzenie wariantów produktu w oparciu o ten produkt podstawowy. Na przykład dwa produkty różniące się jedynie radiem (CDMA i GSM) mogą dziedziczyć po tym samym produkcie podstawowym, który nie definiuje radia.
Płyta/urządzenie marlin, niebieska linia, koral Warstwa płytki/urządzenia reprezentuje fizyczną warstwę plastiku na urządzeniu (czyli wzór przemysłowy urządzenia). Warstwa ta reprezentuje również gołe schematy produktu. Należą do nich urządzenia peryferyjne na płycie i ich konfiguracja. Użyte nazwy są jedynie kodami dla różnych konfiguracji płyty/urządzenia.
Łuk ramię, x86, ramię64, x86_64 Warstwa architektury opisuje konfigurację procesora i interfejs binarny aplikacji (ABI) działający na płycie.

Korzystanie z wariantów kompilacji

Kiedy tworzysz dla konkretnego produktu, przydatne jest posiadanie niewielkich zmian w ostatecznej wersji. W definicji modułu moduł może określić znaczniki z LOCAL_MODULE_TAGS , które mogą być jedną lub większą liczbą wartości optional (domyślnych), debug i eng .

Jeśli moduł nie określa tagu (przez LOCAL_MODULE_TAGS ), jego tag jest domyślnie optional . Moduł opcjonalny jest instalowany tylko wtedy, gdy wymaga tego konfiguracja produktu z PRODUCT_PACKAGES .

Są to obecnie zdefiniowane warianty kompilacji.

Wariant Opis
eng To jest domyślny smak.
  • Instaluje moduły oznaczone tagiem eng lub debug .
  • Instaluje moduły zgodnie z plikami definicji produktu, oprócz modułów oznaczonych.
  • ro.secure=0
  • ro.debuggable=1
  • ro.kernel.android.checkjni=1
  • adb jest domyślnie włączone.
user Wariant, który miał być ostatecznym wydaniem.
  • Instaluje moduły oznaczone user .
  • Instaluje moduły zgodnie z plikami definicji produktu, oprócz modułów oznaczonych.
  • ro.secure=1
  • ro.debuggable=0
  • adb jest domyślnie wyłączony.
userdebug To samo co user , z tymi wyjątkami:
  • Instaluje także moduły oznaczone debug .
  • ro.debuggable=1
  • adb jest domyślnie włączone.

Wytyczne dotyczące debugowania użytkownika

Uruchamianie kompilacji debugowania użytkownika podczas testów pomaga twórcom urządzeń zrozumieć wydajność i możliwości wydań w fazie rozwoju. Aby zachować spójność między kompilacjami użytkownika i debugowania użytkownika oraz aby uzyskać wiarygodne metryki w kompilacjach używanych do debugowania, twórcy urządzeń powinni przestrzegać następujących wskazówek:

  • userdebug definiuje się jako kompilację użytkownika z włączonym dostępem roota, z wyjątkiem:
    • aplikacje typu userdebug-only, które są uruchamiane wyłącznie na żądanie użytkownika
    • Operacje wykonywane tylko podczas bezczynności (na ładowarce/w pełni naładowany), takie jak używanie dex2oatd w porównaniu z dex2oat do kompilacji w tle
  • Nie uwzględniaj funkcji, które są domyślnie włączone/wyłączone w zależności od typu kompilacji. Odradza się programistom korzystanie z jakichkolwiek form rejestrowania wpływających na żywotność baterii, takich jak rejestrowanie debugowania lub zrzucanie sterty.
  • Wszelkie funkcje debugowania, które są domyślnie włączone w userdebug, powinny być jasno zdefiniowane i udostępnione wszystkim programistom pracującym nad projektem. Funkcje debugowania należy włączać tylko na ograniczony czas, do czasu rozwiązania problemu, który próbujesz debugować.

Dostosowywanie kompilacji za pomocą nakładek zasobów

System kompilacji Androida wykorzystuje nakładki zasobów, aby dostosować produkt na etapie kompilacji. Nakładki zasobów określają pliki zasobów, które są stosowane zamiast ustawień domyślnych. Aby użyć nakładek zasobów, zmodyfikuj plik kompilacji projektu, aby ustawić PRODUCT_PACKAGE_OVERLAYS na ścieżkę względem katalogu najwyższego poziomu. Ścieżka ta staje się cieniem katalogu głównego przeszukiwanym 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 na tym pliku, dodaj katalog nakładki do pliku kompilacji projektu, korzystając z jednej z poniższych opcji:

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

Lub

PRODUCT_PACKAGE_OVERLAYS := vendor/vendor-name/overlay

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

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

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

Budowanie produktu

Pliki źródłowe urządzenia możesz porządkować na wiele różnych sposobów. Oto krótki opis jednego ze sposobów organizacji implementacji Pixela.

Pixel jest zaimplementowany z główną konfiguracją urządzenia o nazwie marlin . Na podstawie tej konfiguracji urządzenia tworzony jest produkt z plikiem makefile definicji produktu, który deklaruje informacje o urządzeniu specyficzne dla produktu, takie jak nazwa i model. Możesz wyświetlić katalog device/google/marlin aby zobaczyć, jak to wszystko jest skonfigurowane.

Pisanie plików makefile produktów

Poniższe kroki opisują sposób konfigurowania plików makefile produktów w sposób podobny do linii produktów Pixel:

  1. Utwórz katalog device/ <company-name> / <device-name> dla swojego produktu. Na przykład device/google/marlin . Ten katalog będzie zawierał kod źródłowy Twojego urządzenia wraz z plikami make do ich zbudowania.
  2. Utwórz plik makefile device.mk , który deklaruje pliki i moduły potrzebne dla urządzenia. Na przykład zobacz device/google/marlin/device-marlin.mk .
  3. Utwórz plik makefile definicji produktu, aby utworzyć konkretny produkt na podstawie urządzenia. Następujący plik makefile został pobrany jako przykład z device/google/marlin/aosp_marlin.mk . Zwróć uwagę, że produkt dziedziczy z plików device/google/marlin/device-marlin.mk i vendor/google/marlin/device-vendor-marlin.mk poprzez plik makefile, deklarując jednocześnie informacje specyficzne dla produktu, takie jak nazwa, marka, i modelka.
    # 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
    

    Zobacz Ustawianie zmiennych definicji produktu , aby zapoznać się z dodatkowymi zmiennymi specyficznymi dla produktu, które możesz dodać do plików makefile.

  4. Utwórz plik AndroidProducts.mk wskazujący pliki makefile produktu. W tym przykładzie potrzebny jest tylko plik makefile definicji produktu. Poniższy przykład pochodzi z device/google/marlin/AndroidProducts.mk (który zawiera zarówno Marlin, Pixel, jak i Sailfish, Pixel XL, które mają najwięcej wspólnych konfiguracji):
    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 makefile BoardConfig.mk zawierający konfiguracje specyficzne dla płyty. Na przykład zobacz device/google/marlin/BoardConfig.mk .
  6. Tylko w przypadku Androida 9 i starszych wersji utwórz plik vendorsetup.sh , aby dodać swój produkt („zestaw lunchowy”) do kompilacji wraz z wariantem kompilacji oddzielonym myślnikiem. Na przykład:
    add_lunch_combo <product-name>-userdebug
    
  7. W tym momencie możesz stworzyć więcej wariantów produktu w oparciu o to samo urządzenie.

Ustawianie zmiennych definicji produktu

Zmienne specyficzne dla produktu są zdefiniowane w pliku makefile produktu. W tabeli przedstawiono niektóre zmienne przechowywane w pliku definicji produktu.

Zmienny Opis Przykład
PRODUCT_AAPT_CONFIG aapt konfiguracje do użycia podczas tworzenia pakietów.
PRODUCT_BRAND Marka (np. przewoźnik), dla której dostosowane jest oprogramowanie.
PRODUCT_CHARACTERISTICS aapt , aby umożliwić dodanie zasobów specyficznych dla wariantu do pakietu. tablet , nosdcard
PRODUCT_COPY_FILES Lista słów takich jak source_path:destination_path . Podczas tworzenia tego produktu plik w ścieżce źródłowej powinien zostać skopiowany do ścieżki docelowej. Reguły dotyczące kroków kopiowania są zdefiniowane w config/makefile .
PRODUCT_DEVICE Nazwa wzoru przemysłowego. Jest to również nazwa płytki i system kompilacji używa jej do zlokalizowania BoardConfig.mk . tuna
PRODUCT_LOCALES Oddzielona spacjami lista dwuliterowych kodów języka i par dwuliterowych kodów krajów opisujących kilka ustawień użytkownika, takich jak język interfejsu użytkownika oraz formatowanie godziny, daty i waluty. Pierwsze ustawienie regionalne wymienione w PRODUCT_LOCALES jest używane jako domyślne ustawienie regionalne produktu. en_GB , de_DE , es_ES , fr_CA
PRODUCT_MANUFACTURER Nazwa producenta. acme
PRODUCT_MODEL Widoczna dla użytkownika końcowego nazwa produktu końcowego.
PRODUCT_NAME Widoczna dla użytkownika końcowego nazwa całego produktu. Pojawia się na ekranie Ustawienia > Informacje .
PRODUCT_OTA_PUBLIC_KEYS Lista kluczy publicznych OTA dla produktu.
PRODUCT_PACKAGES Lista plików APK i modułów do zainstalowania. Kontakty kalendarza
PRODUCT_PACKAGE_OVERLAYS Wskazuje, czy użyć zasobów domyślnych, czy dodać nakładki specyficzne dla produktu. vendor/acme/overlay
PRODUCT_SYSTEM_PROPERTIES Lista przypisań właściwości systemu w formacie "key=value" dla partycji systemowej. Właściwości systemu dla innych partycji można ustawić poprzez PRODUCT_<PARTITION>_PROPERTIES tak jak w 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 ustawień regionalnych

Skorzystaj z tych informacji, aby skonfigurować domyślny język i systemowy filtr ustawień regionalnych, a następnie włącz filtr ustawień regionalnych dla nowego typu urządzenia.

Nieruchomości

Skonfiguruj zarówno domyślny język, jak i filtr ustawień regionalnych systemu, korzystając z dedykowanych właściwości systemu:

  • ro.product.locale : do ustawiania domyślnych ustawień regionalnych. Początkowo jest to ustawione na pierwsze ustawienia regionalne w zmiennej PRODUCT_LOCALES ; możesz zastąpić tę wartość. (Aby uzyskać więcej informacji, zobacz tabelę Ustawianie zmiennych definicji produktu .)
  • ro.localization.locale_filter : do ustawiania filtru ustawień regionalnych przy użyciu wyrażenia regularnego stosowanego do nazw ustawień regionalnych. Na przykład:
    • Filtr włączający: ^(de-AT|de-DE|en|uk).* - dopuszcza tylko język niemiecki (warianty austriackie i niemieckie), wszystkie angielskie warianty języka angielskiego i ukraińskiego
    • Ekskluzywny filtr: ^(?!de-IT|es).* - wyklucza język niemiecki (wariant włoski) i wszystkie warianty języka hiszpańskiego.

Włączanie filtru regionalnego

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

Ustawiając wartość właściwości filtra i domyślny język w oem/oem.prop podczas kalibracji fabrycznej, możesz skonfigurować ograniczenia bez wypalania filtra w obrazie systemu. Upewnij się, że te właściwości zostaną pobrane z partycji OEM, dodając je do zmiennej PRODUCT_OEM_PROPERTIES , jak wskazano poniżej:

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

Następnie podczas produkcji rzeczywiste wartości są zapisywane w oem/oem.prop , aby odzwierciedlić wymagania docelowe. Dzięki takiemu podejściu wartości domyślne są zachowywane podczas przywracania ustawień fabrycznych, więc ustawienia początkowe wyglądają dla użytkownika dokładnie tak samo, jak pierwsza konfiguracja.

Ustawianie ADB_VENDOR_KEYS do połączenia przez USB

Zmienna środowiskowa ADB_VENDOR_KEYS umożliwia producentom urządzeń dostęp do debugowalnych kompilacji (-userdebug i -eng, ale nie -user) za pośrednictwem adb bez ręcznej autoryzacji. Zwykle adb generuje unikalny klucz uwierzytelniający RSA dla każdego komputera klienckiego, który wysyła do dowolnego podłączonego urządzenia. To jest klucz RSA pokazany w oknie dialogowym autoryzacji adb. Alternatywnie możesz wbudować znane klucze w obraz systemu i udostępnić je klientowi adb. Jest to przydatne przy opracowywaniu systemu operacyjnego, a zwłaszcza podczas testowania, ponieważ pozwala uniknąć konieczności ręcznej interakcji z oknem dialogowym autoryzacji adb.

Aby utworzyć klucze dostawcy, jedna osoba (zwykle menedżer ds. 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ódłowym. 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 plik Android.mk do katalogu kluczy o treści PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub , co pomaga pamiętać o wygenerowaniu nowej pary kluczy dla każdej wersji systemu operacyjnego.

Oto plik makefile, którego Google używa w katalogu, w którym przechowujemy nasze sprawdzone pary kluczy dla 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żyć tych kluczy dostawcy, inżynier musi jedynie ustawić zmienną środowiskową ADB_VENDOR_KEYS tak, aby wskazywała katalog, w którym przechowywane są pary kluczy. To mówi adb , aby najpierw wypróbował te klucze kanoniczne, zanim wróci do wygenerowanego klucza hosta, który wymaga ręcznej autoryzacji. Gdy adb nie może połączyć się z nieautoryzowanym urządzeniem, komunikat o błędzie zasugeruje ustawienie ADB_VENDOR_KEYS , jeśli nie jest jeszcze ustawione.