הערות ב-AIDL

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

ערך null

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, @nullable T ממופה אל std::unique_ptr<T> ב-Android 11 ומטה, ולstd::optional<T> ב-Android 12 ומעלה.

בקצה העורפי של NDK, @nullable T תמיד ממופה ל-std::optional<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 אינו פעיל. במילים אחרות, גם @nullable IBinder ו-IBinder ממופים באופן שווה ל-android::sp<IBinder>, כבר ניתן לאפס כי הוא מצביע חזק (CPP עדיין קורא לאכוף יכולת null אבל הסוג עדיין android::sp<IBinder>).

החל מ-Android 13, אפשר להשתמש ב-@nullable(heap=true) בשביל שדות שניתן למיין כדי לבנות מודלים של סוגים רקורסיביים. לא ניתן להשתמש באפליקציה @nullable(heap=true) עם פרמטרים של שיטה או סוגי החזרה. כשמוסיפים לו הערות, השדה ממופה לקובץ עזר של std::unique_ptr<T> שהוקצה בשביל הזיכרון ב-CPP/NDK בקצה העורפי. השירות @nullable(heap=true) לא פעיל בקצה העורפי של Java.

utf8InCpp

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

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

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

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

יציבות וינטג'

VintfStability מצהיר/ה שסוג מוגדר על ידי המשתמש (ממשק, מגרש, ו-enum) יכולים לשמש בדומיינים של המערכת ושל הספקים. צפייה מידע נוסף על AIDL ל-HALs יכולת פעולה הדדית של ספק מערכת.

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

אפשר לצרף את ההערה רק להצהרות סוג שהוגדרו על ידי המשתמש, כפי שמוצג כאן:

@VintfStability
interface IFoo {
    ....
}

@VintfStability
parcelable Data {
    ....
}

@VintfStability
enum Type {
    ....
}

כשמוסיפים הערות לסוג מסוים עם VintfStability, כל סוג אחר ש צריך להוסיף הערות כאלה גם בסוג הזה. בתוך לדוגמה, צריך להוסיף הערות גם ל-Data וגם ל-IBar באמצעות VintfStability.

@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, עם הנכס stability שהוגדר הוא "vintf".

aidl_interface {
    name: "my_interface",
    srcs: [...],
    stability: "vintf",
}

שימוש באפליקציה לא נתמך

ההערה UnsupportedAppUsage מציינת שסוג AIDL עם ההערות הוא חלק מהממשק שאינו SDK, שהיה נגיש לאפליקציות מדור קודם. למידע נוסף, ניתן לעיין בקטע הגבלות על אפליקציות שאינן SDK ממשקים לקבלת מידע נוסף על ממשקי ה-API המוסתרים.

ההערה 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, נוצר סיווג C++ מסוג int32_t.

enum class Color : int32_t {
    RED = 0,
    BLUE = 1,
}

אם משמיטים את ההערה, ההנחה היא ש-type הוא byte, שממפה ל-int8_t עבור הקצה העורפי של CPP.

אפשר להגדיר את הארגומנט type רק לסוגי האינטגרל הבאים:

  • byte (ברוחב 8 ביט)
  • int (ברוחב 32 ביט)
  • long (רוחב 64 ביט)

NdkOnlyStableParcelable

NdkOnlyStableParcelable מסמן הצהרה בנוגע למגרש (לא הגדרה) יציבה, כך שאפשר יהיה להפנות אליה מסוגי AIDL יציבים אחרים. הזה הוא כמו JavaOnlyStableParcelable, אבל NdkOnlyStableParcelable מסמן הצהרה שניתן לשלוח כיציב ל-NDK את הקצה העורפי במקום ל-Java.

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

  • צריך לציין ndk_header.
  • צריכה להיות לכם ספריית NDK שמציינת את החבילה, והספרייה חייבת יקובצו בספרייה. לדוגמה, במערכת הליבה של גרסת ה-build המודול cc_*, יש להשתמש ב-static_libs או ב-shared_libs. צריך להוסיף את aidl_interface הספרייה בקטע additional_shared_libraries ב-Android.bp.

JavaOnlyStableParcelable

JavaOnlyStableParcelable מסמן הצהרה בנוגע למגרש (לא הגדרה) יציבה, כך שאפשר יהיה להפנות אליה מסוגי AIDL יציבים אחרים.

כדי להשתמש ב-AIDL יציב, כל הסוגים שהוגדרו על ידי המשתמש צריכים להיות יציבים. עבור כדי שתהיה יציבות, צריך לתאר את השדות שלה במפורש את קובץ המקור ה-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 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 יוצרת באופן אוטומטי שיטות לסוגים של מגרשים הקצה העורפי של Java.

@JavaDerive(equals = true, toString = true)
parcelable Data {
  int number;
  String str;
}

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

  • הפונקציה equals=true יוצרת method equals ו-hashCode.
  • toString=true יוצרת שיטת toString שמדפיסה את שם הסוג ושדות. לדוגמה: Data{number: 42, str: foo}

ברירת מחדל של Java

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 מהדר (compiler) לא בודק את הערך של הפרמטר. אם קיים שגיאת תחביר ברמת Java, היא לא תזוהה על ידי המהדר של AIDL אלא על ידי מהדר (compiler) Java.

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

גודל קבוע

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

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

מתאר

Descriptor מציין בכוח את מתאר הממשק של הממשק.

package android.foo;

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

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

האפשרות הזו שימושית כשמשנים שם של ממשק שכבר פורסם. להפוך את מתאר של הממשק עם השם החדש זהה לתיאור של הממשק לפני שהשינוי מאפשר לשני הממשקים לדבר זה עם זה.

@הסתרה בתגובות

המהדר של AIDL מזהה את @hide בתגובות ומעביר אותו לפלט Java של Metalava לאיסוף. הערה זו מבטיחה ש-Android מערכת ה-build יודעת שממשקי API של AIDL אינם ממשקי API של SDK.

@הוצא משימוש בתגובות

המהדר של AIDL מזהה את @deprecated בתגובות כתג כדי לזהות ישות AIDL שלא צריכה יותר להשתמש בה.

interface IFoo {
  /** @deprecated use bar() instead */
  void foo();
  void bar();
}

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