AIDL รองรับคำอธิบายประกอบที่ให้ข้อมูลเพิ่มเติมแก่คอมไพเลอร์ AIDL เกี่ยวกับองค์ประกอบที่มีคำอธิบายประกอบ ซึ่งจะส่งผลต่อโค้ด Stub ที่สร้างขึ้นด้วย
ไวยากรณ์จะคล้ายกับของ Java ดังนี้
@AnnotationName(argument1=value, argument2=value) AidlEntity
โดย AnnotationName คือชื่อของคำอธิบายประกอบ และ AidlEntity คือ
เอนทิตี AIDL เช่น interface Foo, void method() หรือ int arg โดย
คำอธิบายประกอบจะแนบไปกับเอนทิตีที่อยู่หลังคำอธิบายประกอบ
คำอธิบายประกอบบางรายการอาจมีอาร์กิวเมนต์ที่ตั้งค่าไว้ภายในวงเล็บ ดังที่แสดงใน ตัวอย่างก่อนหน้า คำอธิบายประกอบที่ไม่มีอาร์กิวเมนต์ไม่จำเป็นต้องมีวงเล็บ เช่น
@AnnotationName AidlEntity
หมายเหตุเหล่านี้ไม่เหมือนกับหมายเหตุ Java แม้ว่าจะมีลักษณะคล้ายกันก็ตาม คำอธิบายประกอบทั้งหมดได้รับการกำหนดไว้ล่วงหน้า และมีข้อจำกัดเกี่ยวกับตำแหน่งที่คุณจะแนบคำอธิบายประกอบได้ คำอธิบายประกอบบางรายการจะมีผลกับแบ็กเอนด์บางอย่างเท่านั้น และจะไม่มีผลในแบ็กเอนด์อื่นๆ
รายการคำอธิบายประกอบ 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 ประกาศว่าค่าของเอนทิตีที่อธิบายประกอบอาจเป็นค่า 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 @nullable T จะแมปกับ std::unique_ptr<T> ใน Android
11 หรือต่ำกว่า และกับ std::optional<T> ใน Android 12 ขึ้นไป
ในแบ็กเอนด์ NDK @nullable T จะแมปกับ std::optional<T>
ในแบ็กเอนด์ 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 จะไม่มีการดำเนินการใดๆ สำหรับแบ็กเอนด์ Java, CPP และ NDK ตัวอย่างเช่น ในแบ็กเอนด์ CPP ทั้ง @nullable IBinder และ IBinder จะแมปกับ android::sp<IBinder> เท่ากัน ซึ่งเป็นค่าที่อนุญาตให้เป็น Null ได้อยู่แล้วเนื่องจากเป็นพอยน์เตอร์ที่แข็งแกร่ง (การอ่าน CPP และ NDK ยังคงบังคับให้เป็น Null ได้ แต่ประเภทจะยังคงเป็น android::sp<IBinder> หรือ ndk::SpAIBinder)
ในแบ็กเอนด์ของ Rust ประเภทที่ไม่ได้ใช้ Default (IBinder, อินเทอร์เฟซ AIDL
, ParcelFileDescriptor และ Parcelable ที่ไม่มีโครงสร้าง) จะแมปกับ
Option<T> โดยขึ้นอยู่กับบริบทของประเภทนั้นๆ
- ประเภทการคืนค่าของเมธอด พารามิเตอร์
inและพารามิเตอร์inout: ประเภทเหล่านี้ จะเป็นค่า Null ได้ก็ต่อเมื่อมีการใส่คำอธิบายประกอบด้วย@nullableซึ่งแมปกับOption<T>(หรือOption<&T>สำหรับพารามิเตอร์inและ&mut Option<T>สำหรับ พารามิเตอร์inout) หากไม่มี@nullableระบบจะแมปกับTโดยตรง (หรือ&Tและ&mut T) - ฟิลด์ที่ส่งผ่านได้และพารามิเตอร์
out: เนื่องจาก Rust parcelable ที่สร้างขึ้นจะได้รับพารามิเตอร์Defaultและoutที่เริ่มต้นเป็นค่าเริ่มต้น ประเภทเหล่านี้จึงแมปกับOption<T>เสมอ (และอาร์เรย์ขนาดคงที่ในบริบทเหล่านี้จะแมปกับ[Option<T>; N]ในขณะที่อาร์เรย์แบบไดนามิกในพารามิเตอร์outจะแมปกับVec<Option<T>>) แม้ว่าจะไม่มี@nullableก็ตาม เมื่อไม่ได้ใส่คำอธิบายประกอบด้วย@nullableระบบจะยังคงบังคับใช้การไม่เป็นค่าว่างในรันไทม์ระหว่างการแยกวิเคราะห์ (แสดงผลStatusCode::UNEXPECTED_NULLหากค่าเป็นNone)
ตั้งแต่ 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
VintfStability
VintfStability ประกาศว่าสามารถใช้ประเภทที่ผู้ใช้กำหนด (อินเทอร์เฟซ, Parcelable
และ 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 จะไม่มีผลต่อลักษณะการทำงานของโค้ดที่สร้างขึ้น โดยคำอธิบายประกอบจะใส่คำอธิบายประกอบเฉพาะคลาส 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 จะมีการปล่อยคลาส 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 บิต)
NdkOnlyStableParcelable
NdkOnlyStableParcelable จะทำเครื่องหมายการประกาศ (ไม่ใช่คำจำกัดความ) ที่ส่งผ่านได้
ว่าเสถียรเพื่อให้สามารถอ้างอิงจากประเภท AIDL อื่นๆ ที่เสถียรได้ ซึ่งคล้ายกับ JavaOnlyStableParcelable แต่ NdkOnlyStableParcelable จะทำเครื่องหมายการประกาศที่ส่งผ่านได้เป็นแบบเสถียรสำหรับแบ็กเอนด์ NDK แทนที่จะเป็น Java
วิธีใช้ Parcelable นี้
- คุณต้องระบุ
ndk_header - คุณต้องมีไลบรารี NDK ที่ระบุ Parcelable และต้องคอมไพล์ไลบรารี
ลงในไลบรารี เช่น ในระบบบิลด์หลักในโมดูล
cc_*ให้ใช้static_libsหรือshared_libsสำหรับaidl_interfaceให้เพิ่ม ไลบรารีในส่วนadditional_shared_librariesในAndroid.bp
JavaOnlyStableParcelable
JavaOnlyStableParcelable จะทำเครื่องหมายการประกาศ (ไม่ใช่คำจำกัดความ) ที่ส่งผ่านได้
ว่าเสถียรเพื่อให้สามารถอ้างอิงจากประเภท AIDL อื่นๆ ที่เสถียรได้
AIDL ที่เสถียรกำหนดให้ประเภทที่ผู้ใช้กำหนดทั้งหมดต้องเสถียร สำหรับ Parcelable การมีเสถียรภาพกำหนดให้ต้องอธิบายฟิลด์อย่างชัดเจนใน ไฟล์ต้นฉบับ 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 จะสร้างเมธอดสำหรับประเภทที่ส่งผ่านได้ในแบ็กเอนด์ Java โดยอัตโนมัติ ดังนี้
@JavaDerive(equals = true, toString = true)
parcelable Data {
int number;
String str;
}
คำอธิบายประกอบต้องมีพารามิเตอร์เพิ่มเติมเพื่อควบคุมสิ่งที่ต้อง สร้าง พารามิเตอร์ที่รองรับมีดังนี้
equals=trueสร้างequalsและhashCodetoString=trueจะสร้างเมธอด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=trueClone=trueOrd=truePartialOrd=trueEq=truePartialEq=trueHash=true
ดูคำอธิบายลักษณะเหล่านี้ได้ที่เอกสารประกอบของ Rust
FixedSize
FixedSize ทำเครื่องหมาย StructuredParcelable ว่าเป็นขนาดคงที่ หลังจากทำเครื่องหมายแล้ว คุณจะเพิ่มฟิลด์ใหม่ลงใน Parcelable ไม่ได้ ฟิลด์ทั้งหมดของ
Parcelable ต้องเป็นประเภทขนาดคงที่ รวมถึงประเภทดั้งเดิม
การแจงนับ อาร์เรย์ขนาดคงที่ และ Parcelable อื่นๆ ที่ทำเครื่องหมายด้วย FixedSize
ออบเจ็กต์ FixedSize มีขนาดและการจัดแนวที่เสถียรในแบ็กเอนด์ 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 {...}
ตัวอธิบายของอินเทอร์เฟซนี้คือ android.bar.IWorld หากไม่มี
Descriptorคำอธิบายประกอบ ข้อบ่งชี้จะเป็น
android.foo.IHello
ซึ่งมีประโยชน์สำหรับการเปลี่ยนชื่ออินเทอร์เฟซที่เผยแพร่ไปแล้ว การทำให้ ตัวอธิบายของอินเทอร์เฟซที่เปลี่ยนชื่อแล้วเหมือนกับตัวอธิบายของอินเทอร์เฟซ ก่อนการเปลี่ยนชื่อจะช่วยให้อินเทอร์เฟซทั้ง 2 สื่อสารกันได้
@hide ในความคิดเห็น
คอมไพเลอร์ AIDL จะจดจำ @hide ในความคิดเห็นและส่งผ่านไปยังเอาต์พุต Java เพื่อให้ Metalava รับไป ความคิดเห็นนี้ช่วยให้มั่นใจได้ว่า
ระบบบิลด์ของ Android จะรับรู้ว่า API ของ AIDL ไม่ใช่ API ของ SDK
@deprecated ในความคิดเห็น
คอมไพเลอร์ AIDL จะรับรู้ @deprecated ในความคิดเห็นเป็นแท็กเพื่อระบุเอนทิตี AIDL ที่ไม่ควรใช้อีกต่อไป ดังนี้
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
แบ็กเอนด์แต่ละรายการจะทำเครื่องหมายเอนทิตีที่เลิกใช้งานแล้วด้วยคำอธิบายประกอบหรือ
แอตทริบิวต์เฉพาะแบ็กเอนด์ เพื่อให้โค้ดไคลเอ็นต์ได้รับการเตือนหากอ้างอิงถึงเอนทิตีที่เลิกใช้งานแล้ว
เช่น ระบบจะแนบคำอธิบายประกอบ @Deprecated และแท็ก @deprecated
ไว้กับโค้ด Java ที่สร้างขึ้น