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

אפשר להשתמש במידע שבדף הזה כדי ליצור את קובצי ה-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 שכבת הארכיטקטורה מתארת את הגדרות המעבד ואת הממשק Application Binary Interface ‏ (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

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

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

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

מערכת ה-Build של Android משתמשת בשכבות-על של משאבים כדי להתאים אישית מוצר בזמן ה-Build. שכבות-על של משאבים מציינות קובצי משאבים שמוחלים על ברירות המחדל. כדי להשתמש בשכבות-על של משאבים, משנים את קובץ ה-build של הפרויקט כדי להגדיר את PRODUCT_PACKAGE_OVERLAYS לנתיב יחסי לספרייה ברמה העליונה. הנתיב הזה הופך ל-shadow root שמחפשים בו יחד עם ה-root הנוכחי כשמערכת ה-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.

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

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

  1. יוצרים ספרייה בשם device/<company-name>/<device-name> למוצר. לדוגמה, device/google/marlin. הספרייה הזו תכיל קוד מקור למכשיר שלכם, יחד עם קובצי ה-Makefile לבנייתם.
  2. יוצרים device.mk makefile שמצהיר על הקבצים והמודולים שנדרשים למכשיר. לדוגמה, אפשר לעיין ב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
    

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

  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. יוצרים קובץ BoardConfig.mk makefile שמכיל הגדרות ספציפיות ללוח. לדוגמה, אפשר לעיין בdevice/google/marlin/BoardConfig.mk.
  6. ב-Android מגרסה 9 ומטה בלבד, יוצרים קובץ vendorsetup.sh כדי להוסיף את המוצר (ארוחת צהריים משולבת) אל ה-build, יחד עם וריאנט build, כשהם מופרדים באמצעות מקף. לדוגמה:
    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. הקובץ בנתיב המקור צריך להיות מועתק לנתיב היעד כשמבצעים build של המוצר הזה. הכללים לשלבי ההעתקה מוגדרים ב-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 במהלך כיול המפעל, אפשר להגדיר הגבלות בלי להטמיע את המסנן בתמונת המערכת. כדי לוודא שהמאפיינים האלה נאספים מהמחיצה של יצרן הציוד המקורי, מוסיפים אותם למשתנה 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 מאפשר ליצרני מכשירים לגשת לבנייה שניתן לנפות בה באגים (‎-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 אם הוא עדיין לא מוגדר.