حاشیه نویسی در AIDL

AIDL از حاشیه‌نویسی‌هایی پشتیبانی می‌کند که به کامپایلر AIDL اطلاعات بیشتری در مورد عنصر حاشیه‌نویسی می‌دهد، که بر کد خرد تولید شده نیز تأثیر می‌گذارد.

سینتکس شبیه به جاوا است:

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

در اینجا AnnotationName نام حاشیه‌نویسی است و AidlEntity یک موجودیت AIDL مانند interface Foo ، void method() یا int arg است. یک حاشیه نویسی به موجودی که آن را دنبال می کند پیوست می شود.

برخی از حاشیه نویسی ها می توانند آرگومان هایی را در داخل پرانتز قرار دهند، همانطور که در بالا نشان داده شده است. حاشیه نویسی هایی که استدلال ندارند نیازی به پرانتز ندارند. مثلا:

@AnnotationName AidlEntity

این حاشیه نویسی ها با حاشیه نویسی های جاوا یکسان نیستند، اگرچه بسیار شبیه به هم هستند. کاربران نمی توانند حاشیه نویسی های سفارشی AIDL را تعریف کنند. حاشیه نویسی ها همه از پیش تعریف شده اند. برخی از حاشیه نویسی ها فقط بر یک باطن خاص تأثیر می گذارند و در سایر باطن ها بدون عملیات هستند. آنها محدودیت های مختلفی دارند که می توان به آنها متصل شد.

در زیر لیستی از حاشیه نویسی های از پیش تعریف شده AIDL آمده است:

حاشیه نویسی ها در نسخه اندروید اضافه شد
nullable 7
utf8InCpp 7
VintfStability 11
UnsupportedAppUsage 10
Hide 11
Backing 11
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

این حاشیه نویسی برای باطن جاوا بدون عملیات است. این به این دلیل است که در جاوا، همه انواع غیر ابتدایی با مرجع ارسال می شوند که می تواند null .

در پشتیبان CPP، @nullable T به std::unique_ptr<T> در اندروید 11 یا پایین‌تر و به std::optional<T> در اندروید 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 backend برای اندروید 11 یا پایین تر).

یک استثنا برای این نقشه برداری وجود دارد. وقتی T IBinder یا یک رابط AIDL باشد، @nullable no-op است. به عبارت دیگر، هر دو @nullable IBinder و IBinder به طور مساوی به android::sp<IBinder> نگاشت می شوند، که در حال حاضر nullable است زیرا یک اشاره گر قوی است (CPP می خواند همچنان nullability را اعمال می کند، اما نوع آن هنوز android::sp<IBinder> ).

با شروع Android T (AOSP تجربی)، @nullable(heap=true) می‌تواند برای فیلدهای parcelable برای مدل‌سازی انواع بازگشتی استفاده شود. @nullable(heap=true) را نمی توان با پارامترهای متد یا انواع برگشتی استفاده کرد. هنگامی که با آن حاشیه نویسی می شود، این فیلد به یک مرجع تخصیص داده شده پشته ای std::unique_ptr<T> در پشتیبان های CPP/NDK نگاشت می شود. @nullable(heap=true) در باطن جاوا no-op است.

utf8InCpp

utf8InCpp اعلام می کند که یک String در قالب UTF8 برای باطن CPP نشان داده شده است. همانطور که از نام آن مشخص است، حاشیه نویسی برای سایر باطن ها یک عملیات بدون عملیات است. به طور خاص، String همیشه UTF16 در باطن جاوا و UTF8 در باطن NDK است.

این حاشیه نویسی را می توان در هر جایی که بتوان از نوع String استفاده کرد، از جمله مقادیر بازگشتی، پارامترها، اعلان های ثابت و فیلدهای قابل بسته بندی پیوست کرد.

برای باطن CPP، @utf8InCpp String در نقشه های AIDL به std::string ، در حالی که String بدون حاشیه نویسی به android::String16 که در آن از UTF16 استفاده می شود، نقشه می دهد.

توجه داشته باشید که وجود حاشیه نویسی utf8InCpp نحوه انتقال رشته ها از طریق سیم را تغییر نمی دهد. رشته ها همیشه به صورت UTF16 از طریق سیم منتقل می شوند. یک رشته حاشیه نویسی utf8InCpp قبل از انتقال به UTF16 تبدیل می شود. هنگامی که یک رشته دریافت می شود، اگر به عنوان utf8InCpp حاشیه نویسی شده باشد، از UTF16 به UTF8 تبدیل می شود.

VintfStability

VintfStability اعلام می کند که یک نوع تعریف شده توسط کاربر (رابط، بسته پذیر، و enum) می تواند در سراسر سیستم و دامنه های فروشنده استفاده شود. برای اطلاعات بیشتر در مورد قابلیت همکاری سیستم و فروشنده به AIDL برای HAL ها مراجعه کنید.

حاشیه‌نویسی امضای نوع را تغییر نمی‌دهد، اما وقتی تنظیم می‌شود، نمونه نوع به‌عنوان پایدار علامت‌گذاری می‌شود تا بتواند در سراسر فرآیندهای فروشنده و سیستم حرکت کند.

حاشیه نویسی فقط می تواند به اعلان های نوع تعریف شده توسط کاربر مطابق شکل زیر پیوست شود:

@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 Soong ساخته شوند، با ویژگی stability روی "vintf" تنظیم شده است.

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

UnsupportedAppUsage

حاشیه نویسی UnsupportedAppUsage نشان می دهد که نوع AIDL حاشیه نویسی شده بخشی از رابط غیر SDK است که برای برنامه های قدیمی در دسترس بوده است. برای اطلاعات بیشتر در مورد APIهای پنهان، به محدودیت‌های رابط‌های غیر SDK مراجعه کنید.

حاشیه نویسی UnsupportedAppUsage بر رفتار کد تولید شده تأثیر نمی گذارد. حاشیه نویسی فقط کلاس جاوای تولید شده را با حاشیه نویسی جاوا به همین نام حاشیه نویسی می کند.

// in AIDL
@UnsupportedAppUsage
interface IFoo {...}

// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}

این یک برنامه بدون عملیات برای پشتیبان های غیر جاوا است.

پشتیبان گیری

حاشیه نویسی Backing نوع ذخیره سازی یک نوع AIDL enum را مشخص می کند.

@Backing(type="int")
enum Color { RED, BLUE, }

در باطن CPP، کلاس فوق یک کلاس enum C++ از نوع int32_t می کند.

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

اگر حاشیه‌نویسی حذف شود، type byte در نظر گرفته می‌شود که برای backend CPP به int8_t .

آرگومان type را می توان فقط برای انواع انتگرال زیر تنظیم کرد:

  • byte (عرض 8 بیت)
  • int (عرض 32 بیت)
  • long (64 بیت عرض)

JavaOnlyStableParcelable

JavaOnlyStableParcelable یک اعلان parcelable (نه تعریف) را به عنوان پایدار علامت گذاری می کند تا بتوان آن را از سایر انواع 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 به طور خودکار متدهایی را برای انواع قابل بسته بندی در باطن جاوا تولید می کند.

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

حاشیه نویسی به پارامترهای اضافی برای کنترل آنچه تولید می شود نیاز دارد. پارامترهای پشتیبانی شده عبارتند از:

  • equals=true متدهای equals و hashCode را تولید می کند.
  • toString=true toString را ایجاد می کند که نام نوع و فیلدها را چاپ می کند. به عنوان مثال: Data{number: 42, str: foo}

JavaDefault

JavaDefault ، اضافه شده در Android T (آزمایشی AOSP)، کنترل می‌کند که آیا پشتیبانی از نسخه‌سازی پیاده‌سازی پیش‌فرض ایجاد شود (برای setDefaultImpl ). این پشتیبانی دیگر به صورت پیش فرض برای صرفه جویی در فضا ایجاد نمی شود.

JavaPassthrough

JavaPassthrough اجازه می دهد تا API جاوا ایجاد شده با یک حاشیه نویسی دلخواه جاوا حاشیه نویسی شود.

حاشیه نویسی زیر در 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)

در کد جاوای تولید شده

مقدار پارامتر annotation مستقیماً منتشر می شود. کامپایلر AIDL به مقدار پارامتر نگاه نمی کند. اگر هر گونه خطای نحوی در سطح جاوا وجود داشته باشد، توسط کامپایلر AIDL شناسایی نمی شود، بلکه توسط کامپایلر جاوا شناسایی می شود.

این حاشیه نویسی را می توان به هر موجودیت AIDL پیوست. این حاشیه نویسی برای برنامه های پشتیبان غیر جاوا، بدون عملیات است.

سایز ثابت

FixedSize یک بسته بندی ساختار یافته را به عنوان اندازه ثابت علامت گذاری می کند. پس از علامت گذاری، بسته بندی مجاز به افزودن فیلدهای جدید به آن نخواهد بود. تمام فیلدهای parcelable نیز باید دارای انواع با اندازه ثابت باشند، از جمله انواع اولیه، enums، آرایه‌های با اندازه ثابت، و دیگر parcelableهایی که با FixedSize مشخص شده‌اند.

این هیچ تضمینی برای بیت های مختلف ارائه نمی دهد و نباید برای ارتباط با بیت های مختلف به آن اعتماد کرد.

توصیفگر

Descriptor به اجبار توصیفگر رابط یک رابط را مشخص می کند.

package android.foo;

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

توصیف کننده رابط فوق android.bar.IWorld است. اگر حاشیه‌نویسی Descriptor وجود نداشته باشد، توصیف‌گر android.foo.IHello خواهد بود.IHello.

این برای تغییر نام یک رابط از قبل منتشر شده مفید است. قبل از تغییر نام، توصیف کننده رابط تغییر نام یافته مشابه با توصیف کننده رابط کاربری قبل از تغییر نام، به دو رابط اجازه می دهد تا با یکدیگر صحبت کنند.

@hide در نظرات

کامپایلر AIDL، @hide را در کامنت‌ها تشخیص می‌دهد و آن را به خروجی جاوا می‌فرستد تا metalava را دریافت کند. این نظر تضمین می کند که سیستم ساخت اندروید می داند که APIهای AIDL APIهای SDK نیستند.

@ منسوخ شده در نظرات

کامپایلر AIDL، @deprecated را در نظرات به عنوان برچسبی برای شناسایی موجودیت AIDL که دیگر نباید استفاده شود، می شناسد.

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

هر بک‌اند موجودیت‌های منسوخ‌شده را با یک حاشیه‌نویسی/ویژگی خاص باطن علامت‌گذاری می‌کند تا در صورت ارجاع به موجودیت‌های منسوخ، به کد کلاینت هشدار داده شود. به عنوان مثال، حاشیه نویسی @Deprecated و تگ @deprecated به کد تولید شده جاوا متصل می شوند.