הוספת מכשיר חדש

אפשר להשתמש במידע בדף הזה כדי ליצור את קובצי ה-makefile למכשיר ולמוצר.

לכל מודול חדש של Android צריך להיות קובץ תצורה כדי להנחות את מערכת ה-build לגבי המטא-נתונים של המודול, יחסי התלות בזמן הידור והוראות האריזה. ב-Android נעשה שימוש במערכת ה-build של Soong. מידע נוסף על מערכת ה-build של Android זמין במאמר יצירת Android.

הסבר על שכבות build

היררכיית ה-build כוללת את שכבות ההפשטה שתואמות למבנה הפיזי של המכשיר. השכבות האלה מתוארות בטבלה הבאה. כל שכבה קשורה לשכבה שמעליה בקשר מסוג 'אחד לרבים'. לדוגמה, לארכיטקטורה יכולה להיות יותר מלוח אחד, וכל לוח יכול לכלול יותר ממוצר אחד. אפשר להגדיר אלמנט בשכבה מסוימת כמיקוד של אלמנט באותה שכבה, וכך למנוע העתקה ולפשט את התחזוקה.

שכבה דוגמה תיאור
מוצר myProduct, ‏ myProduct_eu, ‏ myProduct_eu_fr, ‏ j2, ‏ sdk בשכבת המוצר מוגדר מפרט התכונות של המוצר ששולחים, כמו המודולים ליצירה, הלוקאלים הנתמכים וההגדרות של לוקאלים שונים. במילים אחרות, זהו השם של המוצר הכולל. משתנים ספציפיים למוצר מוגדרים בקובצי makefile של הגדרת המוצר. מוצר יכול לרשת הגדרות של מוצרים אחרים, וכך לפשט את התחזוקה. שיטה נפוצה היא ליצור מוצר בסיס שמכיל תכונות שחלות על כל המוצרים, ואז ליצור וריאציות של המוצר על סמך מוצר הבסיס. לדוגמה, שני מוצרים שונים רק ברדיו שלהם (CDMA לעומת GSM) יכולים לרשת מאותו מוצר בסיס שלא מוגדר בו רדיו.
לוח/מכשיר מקרל, כחול-קו, קורל השכבה של הלוח או המכשיר מייצגת את השכבה הפיזית של הפלסטיק במכשיר (כלומר, העיצוב התעשייתי של המכשיר). השכבה הזו מייצגת גם את הסכימה הבסיסית של המוצר. אלה כוללים את הציוד ההיקפי על הלוח ואת ההגדרות שלו. השמות משמשים רק כקודים להגדרות שונות של הלוח או המכשיר.
קשת arm, ‏ x86, ‏ arm64, ‏ x86_64 בשכבת הארכיטקטורה מתוארת הגדרת המעבד והממשק הבינארי של האפליקציה (ABI) שפועל בלוח.

שימוש בוריאנטים של build

כשמפתחים גרסה למוצר מסוים, כדאי ליצור וריאציות קלות בגרסה הסופית של המוצר. בהגדרת המודול, אפשר לציין תגים עם LOCAL_MODULE_TAGS, שיכול להיות ערך אחד או יותר מ-optional (ברירת המחדל), debug ו-eng.

אם לא צוין תג למודול (באמצעות LOCAL_MODULE_TAGS), הערך שמוגדר כברירת מחדל לתג הוא optional. מודול אופציונלי מותקן רק אם הוא נדרש בהגדרת המוצר באמצעות PRODUCT_PACKAGES.

אלה וריאציות ה-build שמוגדרות כרגע.

וריאנט תיאור
eng זהו הטעם שמוגדר כברירת מחדל.
  • התקנה של מודולים שמסומנים בתג eng או debug.
  • התקנת מודולים בהתאם לקובצי הגדרת המוצר, בנוסף למודולים המתויגים.
  • ro.secure=0
  • ro.debuggable=1
  • ro.kernel.android.checkjni=1
  • adb מופעל כברירת מחדל.
user הווריאנט שמיועד להיות הביטים הסופיים של הגרסה.
  • התקנה של מודולים שמתויגים ב-user.
  • התקנת מודולים בהתאם לקובצי הגדרת המוצר, בנוסף למודולים המתויגים.
  • ro.secure=1
  • ro.debuggable=0
  • כברירת מחדל, האפשרות adb מושבתת.
userdebug כמו user, למעט החריגים הבאים:
  • הקוד מתקין גם מודולים שמתויגים ב-debug.
  • ro.debuggable=1
  • adb מופעל כברירת מחדל.

הנחיות ל-userdebug

הפעלת גרסאות build של userdebug בבדיקה עוזרת למפתחי המכשירים להבין את הביצועים והעוצמה של גרסאות שעדיין נמצאות בפיתוח. כדי לשמור על עקביות בין גרסאות build לשימוש משתמשים לבין גרסאות build לשימוש למטרות ניפוי באגים, וכדי לקבל מדדים מהימנים בגרסאות build שמשמשות לניפוי באגים, מפתחי המכשירים צריכים לפעול לפי ההנחיות הבאות:

  • userdebug מוגדר כגרסת build של משתמש עם הרשאת root מופעלת, למעט:
    • אפליקציות userdebug בלבד שפועלות רק על פי דרישה של המשתמש
    • פעולות שפועלות רק במהלך תחזוקה במצב חוסר פעילות (במטען/טעינה מלאה), למשל שימוש ב-dex2oatd במקום ב-dex2oat לצורך הידור ברקע
  • אין לכלול תכונות שמופעלות או מושבתות כברירת מחדל בהתאם לסוג ה-build. מומלץ למפתחים לא להשתמש בכל סוג של רישום ביומן שמשפיע על חיי הסוללה, כמו רישום ביומן לניפוי באגים או דמפ של אשכול.
  • צריך להגדיר בבירור את כל תכונות ניפוי הבאגים שמופעלות כברירת מחדל ב-userdebug, ולשתף אותן עם כל המפתחים שעובדים על הפרויקט. מומלץ להפעיל את תכונות ניפוי הבאגים רק לזמן מוגבל, עד שהבעיה שאתם מנסים לנפות תיפתר.

התאמה אישית של ה-build באמצעות שכבות-על של משאבים

מערכת ה-build של Android משתמשת בשכבות-על של משאבים כדי להתאים אישית מוצר בזמן ה-build. שכבות-על של משאבים מציינות קובצי משאבים שחלים מעל הגדרות ברירת המחדל. כדי להשתמש בשכבות-על של משאבים, משנים את קובץ ה-build של הפרויקט כך ש-PRODUCT_PACKAGE_OVERLAYS יהיה נתיב ביחס לספרייה ברמה העליונה. הנתיב הזה הופך לשורש צל שמערכת ה-build מחפשת בו משאבים יחד עם השורש הנוכחי.

ההגדרות הנפוצות ביותר בהתאמה אישית נמצאות בקובץ frameworks/base/core/res/res/values/config.xml.

כדי להגדיר שכבת-על של משאבים בקובץ הזה, מוסיפים את ספריית שכבת-העל לקובץ ה-build של הפרויקט באמצעות אחת מהשיטות הבאות:

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

או

PRODUCT_PACKAGE_OVERLAYS := vendor/vendor-name/overlay

לאחר מכן מוסיפים קובץ שכבת-על לספרייה, לדוגמה:

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

מחרוזות או מערכי מחרוזות שנמצאים בקובץ שכבת-העל config.xml מחליפים את אלה שנמצאים בקובץ המקורי.

פיתוח מוצר

יש הרבה דרכים לארגן את קובצי המקור של המכשיר. בהמשך מופיעה תיאור קצר של אחת מהדרכים לארגון הטמעת Pixel.

Pixel מיושם עם הגדרת מכשיר ראשית בשם marlin. מתצורת המכשיר הזו נוצר מוצר באמצעות קובץ makefile להגדרת המוצר, שמצהיר על מידע ספציפי למוצר לגבי המכשיר, כמו השם והדגם. אפשר לעיין בספרייה device/google/marlin כדי לראות איך כל זה מוגדר.

כתיבת קובצי makefile של מוצרים

בשלבים הבאים מוסבר איך להגדיר קובצי make של מוצרים באופן דומה לזה של קו מוצרי Pixel:

  1. יוצרים ספרייה device/<company-name>/<device-name> למוצר. לדוגמה, device/google/marlin. הספרייה הזו תכיל את קוד המקור של המכשיר ואת קובצי ה-makefile ליצירת ה-build.
  2. יוצרים קובץ makefile ‏device.mk שמצהיר על הקבצים והמודולים הנדרשים למכשיר. דוגמה מופיעה בקטע device/google/marlin/device-marlin.mk.
  3. יוצרים קובץ makefile להגדרת המוצר כדי ליצור מוצר ספציפי על סמך המכשיר. קובץ ה-makefile הבא לקוח מ-device/google/marlin/aosp_marlin.mk לדוגמה. שימו לב שהמוצר עובר בירושה מהקבצים device/google/marlin/device-marlin.mk ו-vendor/google/marlin/device-vendor-marlin.mk דרך קובץ ה-makefile, וגם מכריז על המידע הספציפי למוצר, כמו שם, מותג ודגם.
    # 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
    

    במאמר הגדרת משתני הגדרת המוצר מפורטים משתנים נוספים ספציפיים למוצר שאפשר להוסיף לקובצי ה-make.

  4. יוצרים קובץ AndroidProducts.mk שמצביע על קובצי ה-makefile של המוצר. בדוגמה הזו, נדרש רק קובץ ה-makefile של הגדרת המוצר. הדוגמה הבאה היא מ-device/google/marlin/AndroidProducts.mk (שמכיל גם את marlin, ‏ Pixel, וגם את sailfish, ‏ Pixel XL, שחלקו את רוב ההגדרות):
    PRODUCT_MAKEFILES := \
    	$(LOCAL_DIR)/aosp_marlin.mk \
    	$(LOCAL_DIR)/aosp_sailfish.mk
    
    COMMON_LUNCH_CHOICES := \
    	aosp_marlin-userdebug \
    	aosp_sailfish-userdebug
    
  5. יוצרים קובץ makefile ‏BoardConfig.mk שמכיל הגדרות ספציפיות ללוח. דוגמה מופיעה בקטע device/google/marlin/BoardConfig.mk.
  6. ב-Android מגרסה 9 ומטה בלבד, יוצרים קובץ vendorsetup.sh כדי להוסיף את המוצר ('ארוחת צהריים משולבת') לגרסה המאוחדת, יחד עם גרסה של הגרסה המאוחדת, ומופרדים ביניהם באמצעות מקף. לדוגמה:
    add_lunch_combo <product-name>-userdebug
    
  7. בשלב הזה, אפשר ליצור עוד וריאנטים של מוצרים על סמך אותו מכשיר.

הגדרת משתנים של הגדרת המוצר

משתנים ספציפיים למוצר מוגדרים בקובץ ה-makefile של המוצר. בטבלה מוצגים חלק מהמשתנים שמתוחזקים בקובץ הגדרת המוצר.

משתנה תיאור דוגמה
PRODUCT_AAPT_CONFIG הגדרות aapt לשימוש ביצירת חבילות.
PRODUCT_BRAND המותג (למשל, ספק) שהתוכנה מותאמת אישית עבורו.
PRODUCT_CHARACTERISTICS מאפייני aapt כדי לאפשר הוספה של משאבים ספציפיים לווריאציה לחבילה. tablet, nosdcard
PRODUCT_COPY_FILES רשימה של מילים כמו source_path:destination_path. צריך להעתיק את הקובץ בנתיב המקור לנתיב היעד כשמפתחים את המוצר הזה. הכללים של שלבי ההעתקה מוגדרים ב-config/makefile.
PRODUCT_DEVICE השם של העיצוב התעשייתי. זהו גם שם הלוח, ומערכת ה-build משתמשת בו כדי לאתר את BoardConfig.mk. tuna
PRODUCT_LOCALES רשימה מופרדת בפסיקים של זוגות של קוד שפה בן שתי אותיות וקוד מדינה בן שתי אותיות שמתארים כמה הגדרות של המשתמש, כמו שפת ממשק המשתמש, הזמן, התאריך וסימון המטבע. הלוקאל הראשון שמופיע ב-PRODUCT_LOCALES משמש כלוקאל ברירת המחדל של המוצר. en_GB, de_DE, es_ES, fr_CA
PRODUCT_MANUFACTURER שם היצרן. acme
PRODUCT_MODEL השם של המוצר הסופי שגלוי למשתמש הקצה.
PRODUCT_NAME השם של המוצר הכולל שגלוי למשתמשי הקצה. מופיע במסך הגדרות > מידע כללי.
PRODUCT_OTA_PUBLIC_KEYS רשימת מפתחות ציבוריים של המוצר לשידור אוויר (OTA).
PRODUCT_PACKAGES רשימת קובצי ה-APK והמודולים להתקנה. אנשי קשר ביומן
PRODUCT_PACKAGE_OVERLAYS מציין אם להשתמש במשאבים שמוגדרים כברירת מחדל או להוסיף שכבות-על ספציפיות למוצר. vendor/acme/overlay
PRODUCT_SYSTEM_PROPERTIES רשימה של הקצאות של מאפייני המערכת בפורמט "key=value" למחיצה של המערכת. אפשר להגדיר מאפייני מערכת למחיצות אחרות באמצעות PRODUCT_<PARTITION>_PROPERTIES, כמו ב-PRODUCT_VENDOR_PROPERTIES למחיצה של הספק. שמות המחיצות הנתמכים: SYSTEM,‏ VENDOR,‏ ODM,‏ SYSTEM_EXT ו-PRODUCT.

הגדרת שפת ברירת המחדל של המערכת ומסנן של אזור גיאוגרפי

אפשר להשתמש במידע הזה כדי להגדיר את שפת ברירת המחדל ואת מסנן האזור של המערכת, ואז להפעיל את מסנן האזור לסוג מכשיר חדש.

מאפיינים

מגדירים את שפת ברירת המחדל ואת מסנן הלוקאל של המערכת באמצעות מאפייני מערכת ייעודיים:

  • ro.product.locale: להגדרת לוקאל ברירת המחדל. הערך הזה מוגדר בהתחלה ללוקאל הראשון במשתנה PRODUCT_LOCALES. אפשר לשנות את הערך הזה. (מידע נוסף זמין בטבלה הגדרת משתני הגדרת המוצר).
  • ro.localization.locale_filter: להגדרת מסנן אזור גיאוגרפי, באמצעות ביטוי רגולרי שחלים על שמות של אזורים גיאוגרפיים. לדוגמה:
    • מסנן כולל: ^(de-AT|de-DE|en|uk).* – מאפשר רק גרמנית (הגרסאות של אוסטריה וגרמניה), את כל הגרסאות של אנגלית ואוקראינית
    • מסנן בלעדי: ^(?!de-IT|es).* – לא כולל גרמנית (גרסה לאיטליה) וכל הגרסאות של הספרדית.

הפעלת המסנן של אזור הזמן

כדי להפעיל את המסנן, מגדירים את ערך המחרוזת של מאפיין המערכת ro.localization.locale_filter.

הגדרת ערך מאפיין הסינון ושפת ברירת המחדל באמצעות oem/oem.prop במהלך כיול המפעל מאפשרת להגדיר הגבלות בלי להטמיע את המסנן בתמונת המערכת. כדי לוודא שהמאפיינים האלה ייאספו מהמחיצה של ה-OEM, מוסיפים אותם למשתנה PRODUCT_OEM_PROPERTIES כפי שמתואר בהמשך:

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

לאחר מכן, הערכים בפועל נכתבים ב-oem/oem.prop בסביבת הייצור כדי לשקף את דרישות היעד. בגישה הזו, ערכי ברירת המחדל נשמרים במהלך האיפוס להגדרות המקוריות, כך שההגדרות הראשוניות נראות למשתמש בדיוק כמו הגדרה ראשונית.

הגדרת ADB_VENDOR_KEYS כדי להתחבר דרך USB

משתנה הסביבה ADB_VENDOR_KEYS מאפשר ליצרני המכשירים לגשת ל-builds שניתן לנפות באגים בהם (-userdebug ו--eng, אבל לא -user) דרך adb ללא הרשאה ידנית. בדרך כלל, adb יוצר מפתח אימות RSA ייחודי לכל מחשב לקוח, ושולח אותו לכל מכשיר מחובר. זהו מפתח ה-RSA שמוצג בתיבת הדו-שיח של הרשאת adb. לחלופין, אפשר להטמיע מפתחות ידועים בתמונת המערכת ולשתף אותם עם לקוח adb. האפשרות הזו שימושית לפיתוח מערכת הפעלה ובמיוחד לבדיקה, כי היא מונעת את הצורך לבצע אינטראקציה ידנית עם תיבת הדו-שיח של הרשאת adb.

כדי ליצור מפתחות של ספקים, אדם אחד (בדרך כלל מנהל גרסאות) צריך:

  1. יוצרים זוג מפתחות באמצעות adb keygen. במכשירי Google, ‏ Google יוצרת זוג מפתחות חדש לכל גרסה חדשה של מערכת ההפעלה.
  2. בודקים את זוגות המפתחות במקום כלשהו בעץ המקור. Google שומרת אותם, לדוגמה, ב-vendor/google/security/adb/.
  3. מגדירים את משתנה ה-build PRODUCT_ADB_KEYS כך שיצביע על ספריית המפתחות. Google עושה זאת על ידי הוספת קובץ Android.mk בספריית המפתחות עם הערך PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub, כדי לוודא שנזכור ליצור זוג מפתחות חדש לכל גרסה של מערכת ההפעלה.

זהו קובץ ה-makefile שבו Google משתמשת בספרייה שבה אנחנו מאחסנים את זוגות המפתחות שאנחנו שומרים בכל גרסה:

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

כדי להשתמש במפתחות של הספקים האלה, מהנדס צריך רק להגדיר את משתנה הסביבה ADB_VENDOR_KEYS כך שיצביע על הספרייה שבה זוגות המפתחות מאוחסנים. כך adb ינסו קודם את המפתחות הקנוניים האלה, לפני שיחזרו למפתח המארח שנוצר שדורש הרשאה ידנית. אם adb לא יכול להתחבר למכשיר לא מורשה, הודעת השגיאה תציע להגדיר את ADB_VENDOR_KEYS אם הוא עדיין לא מוגדר.