Dodawanie nowego urządzenia

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

Każdy nowy moduł systemu Android musi mieć plik konfiguracyjny, aby kierować system kompilacji z metadanymi modułu, zależnościami czasu kompilacji i instrukcjami pakowania. Android korzysta z systemu kompilacji Soong . Zobacz Budowanie systemu Android , aby uzyskać więcej informacji o systemie kompilacji Androida.

Zrozumienie warstw kompilacji

Hierarchia kompilacji obejmuje warstwy abstrakcji, które odpowiadają fizycznej budowie urządzenia. Warstwy te są opisane w poniższej tabeli. Każda warstwa odnosi się do warstwy nad nią w relacji jeden-do-wielu. Na przykład architektura może mieć więcej niż jedną tablicę, a każda tablica może mieć więcej niż jeden produkt. Możesz zdefiniować element w danej warstwie jako specjalizację elementu w tej samej warstwie, co eliminuje kopiowanie i ułatwia konserwację.

Warstwa Przykład Opis
Produkt myProduct, myProduct_eu, myProduct_eu_fr, j2, sdk Warstwa produktu definiuje specyfikację funkcji produktu wysyłkowego, taką jak moduły do ​​zbudowania, obsługiwane języki 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 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 wariantów produktu na podstawie tego produktu podstawowego. Na przykład dwa produkty, które różnią się tylko radiotelefonami (CDMA w porównaniu z GSM), mogą dziedziczyć z tego samego produktu podstawowego, który nie definiuje radia.
Tablica/urządzenie marlin, niebieska linia, koral Warstwa płyty/urządzenia reprezentuje fizyczną warstwę tworzywa sztucznego na urządzeniu (tj. wzór przemysłowy urządzenia). Ta warstwa reprezentuje również sam schemat 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 binarny interfejs aplikacji (ABI) działający na płycie.

Korzystanie z wariantów kompilacji

Podczas kompilowania dla konkretnego produktu warto mieć niewielkie różnice w ostatecznej kompilacji wydania. W definicji modułu moduł może określać tagi z LOCAL_MODULE_TAGS , które mogą mieć jedną lub więcej wartości optional (domyślnie), debug i eng .

Jeśli moduł nie określa tagu (przez LOCAL_MODULE_TAGS ), jego tag jest domyślnie optional . Opcjonalny moduł jest instalowany tylko wtedy, gdy jest to wymagane przez konfigurację 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łączony.
user Wariant miał być bitami ostatecznego wydania.
  • Instaluje moduły oznaczone tagiem 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łączone.
userdebug Tak samo jak user , z tymi wyjątkami:
  • Instaluje również moduły oznaczone tagiem debug .
  • ro.debuggable=1
  • adb jest domyślnie włączony.

Wytyczne dotyczące debugowania użytkowników

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

  • userdebug jest zdefiniowany jako kompilacja użytkownika z włączonym dostępem administratora, z wyjątkiem:
    • aplikacje tylko do debugowania użytkownika, które są uruchamiane tylko na żądanie przez użytkownika
    • Operacje, które działają tylko podczas bezczynności konserwacji (na ładowarce/w pełni naładowanej), takie jak używanie dex2oatd lub dex2oat do kompilacji w tle
  • Nie uwzględniaj funkcji, które są domyślnie włączone/wyłączone na podstawie typu kompilacji. Deweloperzy są zniechęceni do korzystania z jakiejkolwiek formy rejestrowania, która wpływa na żywotność baterii, takiej jak rejestrowanie debugowania lub zrzucanie sterty.
  • Wszelkie funkcje debugowania, które są domyślnie włączone w userdebug, powinny być jasno zdefiniowane i udostępniane wszystkim deweloperom pracującym nad projektem. Funkcje debugowania należy włączać tylko przez ograniczony czas, dopóki problem, który próbujesz debugować, nie zostanie rozwiązany.

Dostosowywanie kompilacji za pomocą nakładek zasobów

System kompilacji Android używa nakładek zasobów, aby dostosować produkt w czasie kompilacji. Nakładki zasobów określają pliki zasobów, które są stosowane poza wartościami domyślnymi. Aby korzystać z nakładek zasobów, zmodyfikuj plik budowy projektu, ustawiając PRODUCT_PACKAGE_OVERLAYS na ścieżkę względną do katalogu najwyższego poziomu. Ta ścieżka staje się ukrytym katalogiem głównym przeszukiwanym wraz z bieżącym katalogiem głównym, gdy system kompilacji szuka zasobów.

Najczęściej dostosowywane ustawienia są zawarte w plikach frameworks/base/core/res/res/values/config.xml .

Aby skonfigurować nakładkę zasobów w tym pliku, dodaj katalog nakładek do pliku budowania projektu, korzystając z jednej z następujących czynności:

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 nakładki config.xml zastępują te znalezione w oryginalnym pliku.

Budowanie produktu

Pliki źródłowe urządzenia można organizować 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 specyficzne dla produktu dotyczące urządzenia, 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ą, jak skonfigurować pliki makefile produktów w sposób podobny do tego w 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 urządzenia wraz z plikami makefile 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ć określony produkt na podstawie urządzenia. Poniższy plik makefile jest pobierany z device/google/marlin/aosp_marlin.mk jako przykład. Zwróć uwagę, że produkt dziedziczy z plików device/google/marlin/device-marlin.mk i vendor/google/marlin/device-vendor-marlin.mk przez plik makefile, jednocześnie deklarując informacje dotyczące produktu, 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
    

    Zobacz Ustawianie zmiennych definicji produktu, aby uzyskać dodatkowe zmienne specyficzne dla produktu, które możesz dodać do swoich plików makefile.

  4. Utwórz plik AndroidProducts.mk , który wskazuje 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óry współdzielił większość 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 , który zawiera konfiguracje specyficzne dla tablicy. Na przykład zobacz device/google/marlin/BoardConfig.mk .
  6. Tylko w przypadku systemu Android 9 i starszych , utwórz plik vendorsetup.sh , aby dodać swój produkt („zestaw obiadowy”) 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 (na przykład przewoźnik), do której oprogramowanie jest dostosowane, jeśli istnieje.
PRODUCT_CHARACTERISTICS cechy aapt umożliwiające dodawanie zasobów specyficznych dla wariantu do pakietu. tablet , nosdcard
PRODUCT_COPY_FILES Lista słów, takich jak source_path:destination_path . Plik w ścieżce źródłowej należy skopiować do ścieżki docelowej podczas tworzenia tego produktu. Reguły kroków kopiowania są zdefiniowane w config/makefile .
PRODUCT_DEVICE Nazwa wzoru przemysłowego. Jest to również nazwa płyty, a system kompilacji używa jej do zlokalizowania BoardConfig.mk . tuna
PRODUCT_LOCALES Rozdzielona spacjami lista dwuliterowych kodów języka i dwuliterowych par kodów krajów, które opisują kilka ustawień użytkownika, takich jak język interfejsu użytkownika i godzina, data i formatowanie waluty. Pierwszy język wymieniony w 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 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 bezprzewodowych kluczy publicznych (OTA) dla produktu.
PRODUCT_PACKAGES Lista pakietów APK i modułów do zainstalowania. Kontakty z 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 systemowych w formacie "key=value" dla partycji systemowej. Właściwości systemu dla innych partycji można ustawić za pomocą 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

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

Nieruchomości

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

  • ro.product.locale : do ustawiania domyślnych ustawień regionalnych. Jest to początkowo 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 niemieckie (warianty austriackie i niemieckie), wszystkie angielskie warianty angielskiego i ukraińskie
    • Filtr wykluczający: ^(?!de-IT|es).* - wyklucza niemiecki (wariant włoski) i wszystkie warianty hiszpańskiego.

Włączenie filtra ustawień regionalnych

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 za pomocą oem/oem.prop podczas kalibracji fabrycznej, można skonfigurować ograniczenia bez umieszczania filtra w obrazie systemu. Możesz upewnić się, że te właściwości są pobierane 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 w 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 początkowe ustawienia wyglądają dokładnie tak, jak pierwsza konfiguracja dla użytkownika.

Ustawianie ADB_VENDOR_KEYS do połączenia przez USB

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

Aby utworzyć klucze dostawcy, jedna osoba (zazwyczaj menedżer ds. wydania) 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 w 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 zarejestrowane 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 tylko ustawić zmienną środowiskową ADB_VENDOR_KEYS , aby wskazywała katalog, w którym przechowywane są pary kluczy. To mówi adb , aby najpierw wypróbował te klucze kanoniczne, zanim powró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.