הערות ב-AIDL

‫AIDL תומך בהערות שנותנות לקומפיילר AIDL מידע נוסף על הרכיב עם ההערה, וזה משפיע גם על קוד ה-stub שנוצר.

התחביר דומה לזה של Java:

@AnnotationName(argument1=value, argument2=value) AidlEntity

כאן, AnnotationName הוא שם ההערה ו-AidlEntity הוא ישות AIDL כמו interface Foo,‏ void method() או int arg. ההערה מצורפת לישות שמופיעה אחריה.

לחלק מההערות יכולים להיות ארגומנטים שמוגדרים בתוך הסוגריים, כמו בדוגמה הקודמת. אם הערה לא כוללת ארגומנט, לא צריך להוסיף סוגריים. לדוגמה:

@AnnotationName AidlEntity

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

זוהי רשימה של הערות AIDL מוגדרות מראש:

הערותנוספה בגרסת Android
nullable7
utf8InCpp7
VintfStability11
UnsupportedAppUsage10
Hide11
Backing11
NdkOnlyStableParcelable14
JavaOnlyStableParcelable11
JavaDerive12
JavaPassthrough12
FixedSize12
Descriptor12

יכול להיות ריק

nullable מציין שהערך של הישות עם ההערה יכול להיות null.

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

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>.

ב-Rust backend, ‏ @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 לכל ה-backends חוץ מ-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> בקצה העורפי של CPP ו-NDK. השיטה @nullable(heap=true) לא מבצעת פעולה בבק-אנד של Java.

utf8InCpp

ההצהרה utf8InCpp מציינת שהערך String מיוצג בפורמט UTF8 עבור קצה העורפי של ה-CPP. כפי שהשם שלה מציין, האנוטציה לא מבצעת פעולה כלשהי בשרתי קצה אחרים. באופן ספציפי, String הוא תמיד UTF16 בקצה העורפי של Java ו-UTF8 בקצה העורפי של NDK.

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

ב-CPP backend, ‏ @utf8InCpp String ב-AIDL ממופה ל-std::string, כאשר String ללא ההערה ממופה ל-android::String16 במקומות שבהם נעשה שימוש ב-UTF16.

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 מאפשרת לכם לבטל את הבדיקה כשחבילת הנתונים שאתם מפנים אליה זמינה בבטחה כחלק מ-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 יוצרת את ה-method toString שמדפיסה את השם של הסוג והשדות, למשל 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)")

הופכים לקוד הבא בקוד ה-Java שנוצר:

@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)

הערך של הפרמטר annotation מועבר ישירות. הקומפיילר של AIDL לא בודק את הערך של הפרמטר. אם יש שגיאת תחביר ברמת Java, היא לא תזוהה על ידי מהדר AIDL אלא על ידי מהדר Java.

אפשר לצרף את ההערה הזו לכל ישות AIDL. ההערה הזו לא מבצעת פעולה כלשהי בשרתי קצה שאינם Java.

RustDerive

RustDerive מטמיע באופן אוטומטי מאפיינים עבור סוגי Rust שנוצרו.

ההערה דורשת פרמטרים נוספים כדי לשלוט במה שיווצר. הפרמטרים הנתמכים הם:

  • Copy=true
  • Clone=true
  • Ord=true
  • PartialOrd=true
  • Eq=true
  • PartialEq=true
  • Hash=true

הסברים על התכונות האלה מופיעים במאמרי העזרה של Rust.

FixedSize

FixedSize מסמן אובייקט Parcelable מובנה כגודל קבוע. אחרי שמסמנים אותו, אי אפשר להוסיף שדות חדשים ל-parcelable. כל השדות של האובייקט שניתן להעברה צריכים להיות מסוגים בגודל קבוע, כולל סוגים פשוטים, סוגי enum, מערכים בגודל קבוע ואובייקטים אחרים שניתנים להעברה ומסומנים ב-FixedSize.

לאובייקטים מסוג FixedSize יש גדלים ומיקומים יציבים ב-backend של ndk.

סוג גודל (בייטים) התאמה (בייטים)
boolean 1 1
byte 1 1
char 2 2
int 4 4
long 8 8
float 4 4
double 8 8
parcelable הגודל הכולל של כל השדות היישור הכי גדול של כל השדות
union הגודל הכי גדול של כל השדות היישור הכי גדול של כל השדות
enum גודל סוג הגיבוי התאמה של סוג הגיבוי
T[N] (מערך בגודל קבוע) גודל של T * N התאמה של T
String, IBinder, FileDescriptor, ParcelFileDescriptor N/A N/A

תיאור

Descriptor מציין בכפייה את מתאר הממשק של ממשק:

package android.foo;

@Descriptor(value="android.bar.IWorld")
interface IHello {...}

ה-descriptor של הממשק הזה הוא android.bar.IWorld. אם חסרה ההערה Descriptor, התיאור יהיה android.foo.IHello.

האפשרות הזו שימושית לשינוי השם של ממשק שכבר פורסם. אם תתנו לממשק ששיניתם את השם שלו את אותו תיאור שהיה לו לפני שינוי השם, שני הממשקים יוכלו לתקשר ביניהם.

‫@hide in comments

הקומפיילר של 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.