AIDL תומך בהערות שנותנות לקומפיילר AIDL מידע נוסף על הרכיב שנוסף לו הערה, וזה משפיע גם על קוד ה-stub שנוצר.
התחביר דומה לזה של Java:
@AnnotationName(argument1=value, argument2=value) AidlEntity
כאן, AnnotationName
הוא שם ההערה ו-AidlEntity
הוא ישות AIDL כמו interface Foo
, void method()
או int arg
. ההערה מצורפת לישות שמופיעה אחריה.
לחלק מההערות יכולים להיות ארגומנטים שמוגדרים בתוך הסוגריים, כמו בדוגמה שלמעלה. אם הערה לא כוללת ארגומנט, לא צריך להוסיף לה סוגריים. לדוגמה:
@AnnotationName AidlEntity
ההערות האלה לא זהות להערות ב-Java, למרות שהן נראות דומות מאוד. המשתמשים לא יכולים להגדיר הערות AIDL מותאמות אישית, כי כל ההערות מוגדרות מראש. חלק מההערות משפיעות רק על קצה עורפי מסוים ולא עושות כלום בקצוות עורפיים אחרים. יש להם הגבלות שונות לגבי המקומות שאליהם אפשר לצרף אותם.
זוהי רשימה של הערות AIDL מוגדרות מראש:
הערות | נוספה בגרסת Android |
---|---|
nullable |
7 |
utf8InCpp |
7 |
VintfStability |
11 |
UnsupportedAppUsage |
10 |
Hide |
11 |
Backing |
11 |
NdkOnlyStableParcelable |
14 |
JavaOnlyStableParcelable |
11 |
JavaDerive |
12 |
JavaPassthrough |
12 |
FixedSize |
12 |
Descriptor |
12 |
יכול להיות ריק
nullable
מציין שאולי לא יסופק הערך של הישות שנוספה לה הערה.
אפשר לצרף את ההערה הזו רק לסוגי החזרה של שיטות, לפרמטרים של שיטות ולשדות שניתנים להעברה.
interface IFoo {
// method return types
@nullable Data method();
// method parameters
void method2(in @nullable Data d);
}
parcelable Data {
// parcelable fields
@nullable Data d;
}
אי אפשר לצרף הערות לסוגים פרימיטיביים. זו שגיאה.
void method(in @nullable int a); // int is a primitive type
ההערה הזו לא מבצעת פעולה בקצה העורפי של Java. הסיבה לכך היא שב-Java, כל הסוגים הלא פרימיטיביים מועברים באמצעות הפניה, שיכולה להיות null
.
ב-CPP backend, @nullable T
ממופה ל-std::unique_ptr<T>
ב-Android 11 ומטה, ול-std::optional<T>
ב-Android 12 ומעלה.
ב-NDK backend, @nullable T
תמיד ממופה ל-std::optional<T>
.
ב-backend של Rust, @nullable T
תמיד ממופה ל-Option<T>
.
בסוגים דמויי-רשימה L
כמו T[]
או List<T>
, @nullable L
ממופה ל-std::optional<std::vector<std::optional<T>>>
(או ל-std::unique_ptr<std::vector<std::unique_ptr<T>>>
במקרה של קצה העורפי של CPP ל-Android 11 ומטה).
יש חריג למיפוי הזה. אם T
הוא IBinder
או ממשק AIDL, @nullable
הוא no-op לכל קצוות העורף (backend) חוץ מ-Rust. במילים אחרות, גם @nullable IBinder
וגם IBinder
ממופים באופן שווה ל-android::sp<IBinder>
, שכבר יכול להיות null כי הוא מצביע חזק (קריאות CPP עדיין אוכפות אפשרות של null, אבל הסוג הוא עדיין android::sp<IBinder>
). ב-Rust, הסוגים האלה הם nullable
רק אם הם מסומנים ב-@nullable
. הם ממופים ל-Option<T>
אם הם כוללים הערות.
החל מ-Android 13, אפשר להשתמש ב-@nullable(heap=true)
בשדות מסוג Parcelable כדי ליצור מודלים של סוגים רקורסיביים. @nullable(heap=true)
אי אפשר להשתמש ב-method parameters או ב-return types. כשמוסיפים את ההערה הזו, השדה ממופה להפניה std::unique_ptr<T>
שהוקצתה ב-heap בקצה העורפי של CPP/NDK. הערך @nullable(heap=true)
הוא no-op בקצה העורפי של Java.
utf8InCpp
utf8InCpp
מכריז ש-String
מיוצג בפורמט UTF8 עבור ה-CPP backend. כפי שהשם שלה מציין, ההערה היא פעולה שלא מבצעת כלום (no-op) עבור קצה עורפי אחר.
באופן ספציפי, String
הוא תמיד UTF16 בקצה העורפי של Java ו-UTF8 בקצה העורפי של NDK.
אפשר להוסיף את ההערה הזו בכל מקום שבו אפשר להשתמש בסוג String
, כולל ערכי החזרה, פרמטרים, הצהרות קבועות ושדות שניתנים להעברה.
ב-CPP backend, @utf8InCpp String
ב-AIDL ממופה ל-std::string
, ואילו String
ללא ההערה ממופה ל-android::String16
שבו נעשה שימוש ב-UTF16.
חשוב לזכור שהקיום של ההערה utf8InCpp
לא משנה את האופן שבו מחרוזות מועברות דרך הרשת. מחרוזות תמיד מועברות כ-UTF16
בחיבור. מחרוזת עם הערות utf8InCpp
מומרת ל-UTF16 לפני שהיא מועברת. כשמתקבלת מחרוזת, היא מומרת מ-UTF16 ל-UTF8 אם היא
סומנה כ-utf8InCpp
.
VintfStability
VintfStability
מציין שאפשר להשתמש בסוג שהוגדר על ידי המשתמש (ממשק, parcelable ו-enum) בכל המערכת ובדומיינים של הספקים. מידע נוסף על יכולת פעולה הדדית בין מערכות של ספקים זמין במאמר בנושא AIDL עבור HAL.
ההערה לא משנה את החתימה של הסוג, אבל כשהיא מוגדרת, המופע של הסוג מסומן כיציב כדי שאפשר יהיה להעביר אותו בין תהליכים של הספק והמערכת.
אפשר לצרף את ההערה רק להצהרות על סוגים שהוגדרו על ידי המשתמש, כמו שמוצג כאן:
@VintfStability
interface IFoo {
....
}
@VintfStability
parcelable Data {
....
}
@VintfStability
enum Type {
....
}
כשסוג מסוים מסומן בהערה עם VintfStability
, כל סוג אחר שאליו מתייחסים בסוג צריך גם להיות מסומן בהערה כזו. בדוגמה הבאה, צריך להוסיף את ההערה VintfStability
גם ל-Data
וגם ל-IBar
.
@VintfStability
interface IFoo {
void doSomething(in IBar b); // references IBar
void doAnother(in Data d); // references Data
}
@VintfStability // required
interface IBar {...}
@VintfStability // required
parcelable Data {...}
בנוסף, אפשר ליצור את קובצי ה-AIDL שמגדירים סוגים עם הערה VintfStability
רק באמצעות סוג המודול aidl_interface
Soong, כשהמאפיין stability
מוגדר לערך "vintf"
.
aidl_interface {
name: "my_interface",
srcs: [...],
stability: "vintf",
}
UnsupportedAppUsage
ההערה UnsupportedAppUsage
מציינת שסוג ה-AIDL עם ההערה הוא חלק מממשק שאינו SDK, שהיה נגיש לאפליקציות מדור קודם.
מידע נוסף על ממשקי ה-API המוסתרים זמין במאמר בנושא הגבלות על ממשקים שאינם SDK.
ההערה UnsupportedAppUsage
לא משפיעה על ההתנהגות של הקוד שנוצר. האנוטציה מוסיפה אנוטציה רק למחלקת ה-Java שנוצרה עם אנוטציית ה-Java באותו שם.
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
זוהי פעולה שלא משפיעה על קצה העורף שאינו Java.
גיבוי
ההערה Backing
מציינת את סוג האחסון של סוג enum ב-AIDL.
@Backing(type="int")
enum Color { RED, BLUE, }
ב-CPP backend, הפונקציה הזו יוצרת מחלקה מסוג enum ב-C++ מסוג int32_t
.
enum class Color : int32_t {
RED = 0,
BLUE = 1,
}
אם משמיטים את ההערה, הפונקציה type
פועלת בהנחה שערכה byte
, שמופה ל-int8_t
עבור קצה העורפי של CPP.
אפשר להגדיר את הארגומנט type
רק לסוגי המספרים השלמים הבאים:
-
byte
(8 ביט) int
(רוחב 32 ביט)long
(64-bit wide)
NdkOnlyStableParcelable
NdkOnlyStableParcelable
מציין הצהרה (לא הגדרה) של parcelable כהצהרה יציבה, כדי שאפשר יהיה להפנות אליה מסוגי AIDL יציבים אחרים. זה כמו JavaOnlyStableParcelable
, אבל NdkOnlyStableParcelable
מסמן הצהרה על אובייקט שניתן להעברה כהצהרה יציבה עבור קצה העורפי של NDK במקום עבור Java.
כדי להשתמש ב-Parcelable הזה:
- חובה לציין את הערך
ndk_header
. - צריכה להיות לכם ספריית NDK שבה מוגדר parcelable, והספרייה צריכה להיות מהודרת לספרייה. לדוגמה, במערכת הליבה של build במודול
cc_*
, משתמשים ב-static_libs
או ב-shared_libs
. עבורaidl_interface
, מוסיפים את הספרייה בקטעadditional_shared_libraries
ב-Android.bp
.
JavaOnlyStableParcelable
JavaOnlyStableParcelable
מציין הצהרה (לא הגדרה) של parcelable כהצהרה יציבה, כדי שאפשר יהיה להפנות אליה מסוגי AIDL יציבים אחרים.
ב-AIDL יציב, כל הסוגים שמוגדרים על ידי המשתמש צריכים להיות יציבים. במקרה של parcelables, כדי שהם יהיו יציבים, השדות שלהם צריכים להיות מתוארים באופן מפורש בקובץ המקור של AIDL.
parcelable Data { // Data is a structured parcelable.
int x;
int y;
}
parcelable AnotherData { // AnotherData is also a structured parcelable
Data d; // OK, because Data is a structured parcelable
}
אם האובייקט מסוג Parcelable לא היה מובנה (או רק הוגדר), אי אפשר להפנות אליו.
parcelable Data; // Data is NOT a structured parcelable
parcelable AnotherData {
Data d; // Error
}
התג JavaOnlyStableParcelable
מאפשר לכם לבטל את הבדיקה כשחבילת הנתונים (parcelable) שאליה אתם מפנים כבר זמינה בצורה בטוחה כחלק מ-Android SDK.
@JavaOnlyStableParcelable
parcelable Data;
parcelable AnotherData {
Data d; // OK
}
JavaDerive
JavaDerive
יוצרת באופן אוטומטי שיטות לסוגים של parcelable ב-Java backend.
@JavaDerive(equals = true, toString = true)
parcelable Data {
int number;
String str;
}
ההערה דורשת פרמטרים נוספים כדי לשלוט במה שיווצר. הפרמטרים הנתמכים הם:
-
equals=true
יוצרת את השיטותequals
ו-hashCode
. -
toString=true
generatestoString
method שמדפיסה את השם של הסוג והשדות. לדוגמה:Data{number: 42, str: foo}
JavaDefault
המאפיין JavaDefault
, שנוסף ב-Android 13, קובע אם תמיכת ברירת המחדל בניהול גרסאות תיווצר (עבור setDefaultImpl
). התמיכה הזו כבר לא נוצרת כברירת מחדל כדי לחסוך במקום.
JavaPassthrough
JavaPassthrough
מאפשר להוסיף הערה ל-Java API שנוצר באמצעות הערה שרירותית של Java.
ההערות הבאות ב-AIDL
@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")
להפוך
@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)
בקוד ה-Java שנוצר.
הערך של הפרמטר annotation
מועבר ישירות. הקומפיילר של AIDL לא בודק את ערך הפרמטר. אם יש שגיאת תחביר ברמת Java, מהדר AIDL לא יזהה אותה, אבל מהדר Java יזהה אותה.
אפשר לצרף את ההערה הזו לכל ישות AIDL. ההערה הזו לא מבצעת פעולה כלשהי (no-op) במערכות קצה שאינן Java.
RustDerive
RustDerive
מטמיע באופן אוטומטי מאפיינים עבור סוגי Rust שנוצרו.
ההערה דורשת פרמטרים נוספים כדי לשלוט במה שיווצר. הפרמטרים הנתמכים הם:
Copy=true
Clone=true
Ord=true
PartialOrd=true
Eq=true
PartialEq=true
Hash=true
הסברים על המאפיינים האלה זמינים בכתובת https://doc.rust-lang.org.
FixedSize
FixedSize
מסמן אובייקט Parcelable מובנה כגודל קבוע. אחרי שמסמנים את האפשרות הזו, אי אפשר להוסיף שדות חדשים לאובייקט Parcelable. כל השדות של האובייקט שניתן להעברה צריכים להיות גם הם מסוגים בגודל קבוע, כולל סוגים פרימיטיביים, סוגי enum, מערכים בגודל קבוע ואובייקטים אחרים שניתנים להעברה ומסומנים ב-FixedSize
.
השיטה הזו לא מבטיחה שום דבר לגבי תקשורת בין מערכות עם רמות סיביות שונות, ולכן לא מומלץ להסתמך עליה.
תיאור
Descriptor
מציין בכוח את מתאר הממשק של ממשק.
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
רכיב ה-descriptor של הממשק הזה הוא android.bar.IWorld
. אם התג
Descriptor
חסר, התיאור יהיה
android.foo.IHello
.
האפשרות הזו שימושית לשינוי השם של ממשק שכבר פורסם. אם תגדירו את אותו תיאור לממשק ששמו שונה כמו לממשק לפני שינוי השם, שני הממשקים יוכלו לתקשר ביניהם.
@hide בתגובות
הקומפיילר של AIDL מזהה את @hide
בתגובות ומעביר אותו לפלט של Java כדי ש-metalava יאסוף אותו. ההערה הזו מוודאת שמערכת ה-build של Android יודעת שממשקי AIDL API הם לא ממשקי SDK API.
@deprecated בתגובות
הקומפיילר של AIDL מזהה את התג @deprecated
בתגובות כסימן לזיהוי ישות AIDL שכבר לא אמורה לשמש.
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
כל קצה עורפי מסמן ישויות שהוצאו משימוש בהערה או במאפיין ספציפיים לקצה העורפי, כדי שקוד הלקוח יקבל אזהרה אם הוא מתייחס לישויות שהוצאו משימוש. לדוגמה, ההערה @Deprecated
והתג @deprecated
מצורפים לקוד שנוצר ב-Java.