ב-Android 11 מתבטלת החבילה של המחיצה product
, וכך
ללא תלות במחיצות system
ו-vendor
. כחלק מהשינויים האלה,
עכשיו אפשר לשלוט בגישה של המחיצה product
ל-Native ול-Java
ממשקים (שדומה לאופן שבו אכיפת הממשק פועלת עבור vendor
)
מחיצות).
אכיפת ממשקים נייטיב
כדי להפעיל את האכיפה של הממשק המקורי, צריך להגדיר PRODUCT_PRODUCT_VNDK_VERSION
אל current
. (הגרסה מוגדרת אוטומטית לערך current
כשערך המשלוח)
רמת ה-API של היעד גדולה מ-29). האכיפה מאפשרת:
- מודולים מקוריים במחיצה
product
לקישור:- באופן סטטי או דינמי למודולים אחרים במחיצה
product
לכלול ספריות סטטיות, ספריות משותפות או ספריות של כותרות. - באופן דינמי לספריות VNDK במחיצה
system
.
- באופן סטטי או דינמי למודולים אחרים במחיצה
- ספריות JNI ב-APKs לא כלולים במחיצת
product
לקישור אל ב-/product/lib
או ב-/product/lib64
(בנוסף ל ספריות NDK).
האכיפה לא מתירה קישורים אחרים למחיצות מלבד product
מחיצה.
אכיפת זמן היצירה (Android.bp)
ב-Android 11, מודולים של המערכת יכולים ליצור מוצר
של וריאציית תמונה בנוסף לווריאציות התמונה של הליבה והספק. כשמודעות מותאמות
אכיפת הממשק מופעלת (PRODUCT_PRODUCT_VNDK_VERSION
מוגדרת לערך
current
):
במקום זאת, מודולים מקוריים של המחיצה
product
הם בווריאציית המוצר. של הווריאציה העיקרית.מודולים עם
product_available: true
ב-Android.bp
הקבצים שלהם לכל וריאציית המוצר.ספריות או ספריות בינאריות שמציינות את
product_specific: true
יכולות לקשר למכשירים אחרים ספריות שמציינות אתproduct_specific: true
אוproduct_available: true
בקבצים ב-Android.bp
.ספריות VNDK חייבות לכלול
product_available: true
בקובציAndroid.bp
כדי ש-product
קבצים בינאריים יכולים לקשר ל-VNDK libs.
הטבלה הבאה מסכמת את המאפיינים של Android.bp
ששימשו ליצירת התמונה
וריאציות של אותו מודל.
נכסים ב-Android.bp | נוצרו וריאציות | |
---|---|---|
לפני האכיפה | לאחר האכיפה | |
ברירת מחדל (ללא) | התוכן הקבוע
(כולל /system , /system_ext וגם
/product ) |
התוכן הקבוע
(כולל /system ו-/system_ext , אבל לא
/product ) |
system_ext_specific: true |
התוכן הקבוע | התוכן הקבוע |
product_specific: true |
התוכן הקבוע | מוצר |
vendor: true |
ספק | ספק |
vendor_available: true |
ליבה, ספק | ליבה, ספק |
product_available: true |
לא רלוונטי | ליבה, מוצר |
vendor_available: true וגם product_available:
true |
לא רלוונטי | ליבה, מוצר, ספק |
system_ext_specific: true וגם vendor_available:
true |
ליבה, ספק | ליבה, ספק |
product_specific: true וגם vendor_available:
true |
ליבה, ספק | מוצר, ספק |
אכיפת זמן build (Android.mk)
כאשר אכיפה של ממשק נייטיב מופעלת, מודולים מקוריים מותקנים
למחיצה product
יש סוג קישור native:product
שיכול לקשר רק אל
מודולים אחרים של native:product
או native:vndk
. מנסה לקשר אל כלשהו
מודולים אחרים מלבד אלה יגרמו למערכת ה-build ליצור בדיקה של סוג קישור
שגיאה.
אכיפה של זמן ריצה
כאשר אכיפה של ממשק נייטיב מופעלת, תצורת המקשר של
Bionic Linker לא מאפשר לתהליכי מערכת להשתמש בספריות product
,
יצירת קטע product
לתהליכי product
שלא יכולים לקשר אליהם
ספריות מחוץ למחיצה product
(עם זאת, תהליכים כאלה יכולים לקשר אל
ספריות VNDK). ניסיונות להפר את תצורת הקישור בסביבת זמן הריצה יגרמו
תיכשל ותיצור הודעת שגיאה CANNOT LINK EXECUTABLE
.
אכיפת ממשקי Java
כדי להפעיל את האכיפה של ממשק Java, צריך להגדיר
PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE
עד true
. (הערך הוא
מוגדר באופן אוטומטי לערך true
כשרמת ה-API של המשלוח ליעד היא
גדול מ-29.) כשהאכיפה מופעלת, הפעולות הבאות מאפשרות או אסורות.
access:
API | /system | /system_ext | /product | /vendor | /data |
---|---|---|---|---|---|
ממשק API ציבורי | |||||
@SystemApi | |||||
@הסתרה של API |
כמו במחיצה של vendor
, אפליקציה או ספריית Java ב-product
המחיצה מורשית להשתמש רק בממשקי API ציבוריים ובממשקי API של המערכת; קישור לספרייה
שאינו משתמש בממשקי API נסתרים. ההגבלה הזו חלה גם על קישור בזמן ה-build
בזמן הריצה ובזמן הריצה.
אכיפת זמן build
בזמן ה-build, חברת Make ו-Songg מאמתות את המודולים של Java בproduct
לא להשתמש בממשקי API נסתרים על ידי סימון של platform_apis
sdk_version
שדות. sdk_version
של האפליקציות במחיצה product
חייבות
ימולאו ב-current
, ב-system_current
או בגרסה מספרית של ה-API, וגם
השדה platform_apis
חייב להיות ריק.
אכיפה של זמן ריצה
סביבת זמן הריצה של Android מאמתת שהאפליקציות במחיצה product
לא משתמשות
ממשקי API נסתרים, כולל תהליך חשיבה. פרטים נוספים זמינים במאמר הגבלות על
לא SDK
ממשקים.
הפעלת אכיפה של ממשק המוצר
כדי להפעיל אכיפה של ממשק המוצר, צריך לבצע את השלבים שמפורטים בקטע הזה.
שלב | משימה | חובה |
---|---|---|
1 | להגדיר קובץ getfile של המערכת שלכם שמציין את החבילות עבור
מחיצה system , ולאחר מכן להגדיר את בדיקת הדרישות של נתיב פריטי המידע שנוצרו בתהליך הפיתוח (Artifact)
בdevice.mk (כדי למנוע התקנה של מודולים שאינם של המערכת
למחיצה system ). |
לא |
2 | למחיקת רשימת ההיתרים. | לא |
3 | אכיפת ממשקים נייטיב וזיהוי כשלים בקישור בסביבת זמן הריצה (אפשר להפעיל ב: במקביל לאכיפה של Java). | Y |
4 | לאכוף ממשקי Java ולאמת התנהגות בזמן ריצה (יכולה לפעול במקביל עם אכיפה מובנית). | Y |
5 | בדיקת התנהגויות של סביבת זמן ריצה. | Y |
6 | יש לעדכן את device.mk עם אכיפה של ממשק המוצר. |
Y |
שלב 1: יצירת קובץ makefile והפעלת בדיקת נתיב של ארטיפקט
בשלב הזה מגדירים את קובץ ה-Makefile system
.
יוצרים קובץ makefile שמגדיר את החבילות של המחיצה
system
. עבור לדוגמה, יוצרים קובץoem_system.mk
עם ההגדרות הבאות:$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk) # Applications PRODUCT_PACKAGES += \ CommonSystemApp1 \ CommonSystemApp2 \ CommonSystemApp3 \ # Binaries PRODUCT_PACKAGES += \ CommonSystemBin1 \ CommonSystemBin2 \ CommonSystemBin3 \ # Libraries PRODUCT_PACKAGES += \ CommonSystemLib1 \ CommonSystemLib2 \ CommonSystemLib3 \ PRODUCT_SYSTEM_NAME := oem_system PRODUCT_SYSTEM_BRAND := Android PRODUCT_SYSTEM_MANUFACTURER := Android PRODUCT_SYSTEM_MODEL := oem_system PRODUCT_SYSTEM_DEVICE := generic # For system-as-root devices, system.img should be mounted at /, so we # include ROOT here. _my_paths := \ $(TARGET_COPY_OUT_ROOT)/ \ $(TARGET_COPY_OUT_SYSTEM)/ \ $(call require-artifacts-in-path, $(_my_paths),)
בקובץ
device.mk
, מקבלים בירושה את קובץ ה-createfile שלsystem
מחיצה ולאפשר את בדיקת הדרישות של הנתיב של פריטי המידע שנוצרו בתהליך הפיתוח (Artifact). לדוגמה:$(call inherit-product, $(SRC_TARGET_DIR)/product/oem_system.mk) # Enable artifact path requirements checking PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := strict
מידע על הדרישות לגבי הנתיב של פריט המידע שנוצר בתהליך הפיתוח (Artifact)
כשהערך בשדה PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
הוא true
או strict
,
מערכת ה-build מונעת התקנה של חבילות שמוגדרות ב-createfiles אחרים
הנתיבים שמוגדרים ב-require-artifacts-in-path
וגם מונעים חבילות
מוגדר בקובץ ה-Makefile הנוכחי מהתקנת ארטיפקטים מחוץ לנתיבים
מוגדר ב-require-artifacts-in-path
.
בדוגמה שלמעלה, כאשר PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
מוגדר לערך
strict
, קבצים מחוץ ל-oem_system.mk
לא יכולים לכלול מודולים שהותקנו ב-
המחיצה root
או system
. כדי לכלול את המודולים האלה, צריך
מגדירים אותם בקובץ oem_system.mk
עצמו או בקובץ makefile כלול.
ניסיונות להתקין מודולים בנתיבים אסורים גורמים להפסקות ב-build. כדי לפתור את הבעיה
מבצעים אחת מהפעולות הבאות:
אפשרות 1: מכניסים את מודול המערכת לקובצי makefiles שכלולים ב-
oem_system.mk
. כתוצאה מכך, כתוצאה מכך יש עמידה בדרישה של נתיב פריטי המידע שנוצרו בתהליך הפיתוח (Artifact) קיימים עכשיו בקובץ makefile כלול) ולכן הם מאפשרים להתקין קבוצת נתיבים ב-'demand-artifacts-in-path'.אפשרות 2: התקנת מודולים במחיצה
system_ext
אוproduct
(ו אל תתקין מודולים במחיצהsystem
).אפשרות 3: הוספת מודולים
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
. כאן רשומים מודולים מורשים תותקן.
שלב 2: ניקוי של רשימת ההיתרים
בשלב הזה, PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
ריקה, כך שכל המכשירים שמשתפים את oem_system.mk
יכולים לשתף גם system
יחיד
תמונה. כדי לרוקן את רשימת המודולים המורשים, מעבירים את כל המודולים ברשימה אל
system_ext
או product
יוצרים חלוקה למחיצה, או מוסיפים אותם ל-system
. הזה
השלב הזה הוא אופציונלי כי הגדרת תמונה נפוצה של system
לא נדרשת כדי
להפעיל אכיפה של ממשק המוצר. עם זאת, ריקון רשימת ההיתרים
מועיל להגדרת הגבול system
עם system_ext
.
שלב 3: אכיפת ממשקים מותאמים
בשלב הזה מגדירים PRODUCT_PRODUCT_VNDK_VERSION := current
, ואז בודקים
כדי לאתר שגיאות build ושגיאות זמן ריצה, ולפתור אותן. כדי לבדוק את ההפעלה של המכשיר ואת היומנים
ולאתר ולתקן כשלים בקישור בסביבת זמן הריצה:
הגדרה של
PRODUCT_PRODUCT_VNDK_VERSION := current
.יוצרים את המכשיר ומחפשים שגיאות build. סביר להניח שתראו גרסאות build של וריאציות מוצר או וריאציות ליבה חסרים. הפסקות נפוצות כוללים:
- כל מודול של
hidl_interface
שמכילproduct_specific: true
לא יהיה זמין למודולים של המערכת. כדי לפתור את הבעיה, צריך להחליף אתproduct_specific: true
עםsystem_ext_specific: true
. - יכול להיות שבמודולים חסרה וריאציית המוצר שנדרשת למוצר
מודולים. כדי לפתור את הבעיה, צריך להפוך את המודול הזה לזמין למחיצה של
product
באמצעות הגדרה שלproduct_available: true
או העברת המודול אלproduct
מחיצה על ידי הגדרה שלproduct_specific: true
.
- כל מודול של
צריך לפתור שגיאות build ולוודא שתהליך ה-build של המכשיר הושלם בהצלחה.
צריך להעלות את התמונה להבהוב ולחפש שגיאות בזמן הריצה באתחול המכשיר וביומנים.
- אם בתג
linker
ביומן של מקרי הבדיקה מוצגCANNOT LINK EXECUTABLE
חסרה תלות בקובץ create, והוא לא תועד זמן build). - כדי לבדוק זאת ממערכת ה-build, צריך להוסיף את הספרייה הנדרשת
שדה
shared_libs:
אוrequired:
.
- אם בתג
פותרים את יחסי התלות החסרים בעזרת ההנחיות שלמעלה.
שלב 4: אכיפת ממשקי Java
בשלב הזה מגדירים PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true
,
אחר כך מאתרים ומתקנים שגיאות build כתוצאה מכך. חפשו שני סוגים ספציפיים של שגיאות:
שגיאות בסוג הקישור. השגיאה הזו מציינת שאפליקציה מקשרת למודולים של Java יש
sdk_version
רחב יותר. כדי לפתור את הבעיה, אפשר להרחיבsdk_version
או הגבלתsdk_version
של הספרייה. שגיאה לדוגמה:error: frameworks/base/packages/SystemUI/Android.bp:138:1: module "SystemUI" variant "android_common": compiles against system API, but dependency "telephony-common" is compiling against private API.Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.
שגיאות בסמלים. השגיאה הזו מציינת שלא ניתן למצוא את הסמל כי הוא ב-API נסתר. כדי לפתור את הבעיה, צריך להשתמש ב-API גלוי (לא מוסתר) או לחפש אחרת. שגיאה לדוגמה:
frameworks/opt/net/voip/src/java/com/android/server/sip/SipSessionGroup.java:1051: error: cannot find symbol ProxyAuthenticate proxyAuth = (ProxyAuthenticate)response.getHeader( ^ symbol: class ProxyAuthenticate location: class SipSessionGroup.SipSessionImpl
שלב 5: בדיקת התנהגויות של סביבת זמן ריצה
בשלב הזה מוודאים שההתנהגויות בסביבת זמן הריצה תקינות. לאפליקציות
ניתן לבצע ניפוי באגים, אפשר לעקוב אחרי השימוש המוסתר ב-API על ידי התחברות באמצעות
StrictMode.detectNonSdkApiUsage
(שיוצר יומן כשהאפליקציה משתמשת ב-
API מוסתר). לחלופין, אפשר להשתמש
veridex
בכלי לניתוח סטטי כדי לקבל את סוג השימוש (קישור או השתקפות),
רמת ההגבלה ותרצון השיחות.
תחביר Veridex:
./art/tools/veridex/appcompat.sh --dex-file={apk file}
דוגמה לתוצאה של וורידקס:
#1: Linking greylist-max-o Landroid/animation/AnimationHandler;-><init>()V use(s): Lcom/android/systemui/pip/phone/PipMotionHelper;-><init>(Landroid/content/Context;Landroid/app/IActivityManager;Landroid/app/IActivityTaskManager;Lcom/android/systemui/pip/phone/PipMenuActivityController;Lcom/android/internal/policy/PipSnapAlgorithm;Lcom/android/systemui/statusbar/FlingAnimationUtils;)V #1332: Reflection greylist Landroid/app/Activity;->mMainThread use(s): Landroidx/core/app/ActivityRecreator;->getMainThreadField()Ljava/lang/reflect/Field;
לפרטים על השימוש ב-veridex, עיינו בבדיקה של שימוש ב-veridex, הכלי.
שלב 6: מעדכנים את device.mk
אחרי תיקון כל הכשלים ב-build ובזמן הריצה, ואימות של זמן הריצה
כדי שההתנהגות תהיה תקינה צריך להגדיר את הדברים הבאים ב-device.mk
:
PRODUCT_PRODUCT_VNDK_VERSION := current
PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true