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 ให้ @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
จะไม่มีการดำเนินการ กล่าวคือ ทั้ง @nullable IBinder
และ IBinder
แมปกับ android::sp<IBinder>
อย่างเท่าๆ กัน ซึ่งเป็นค่าว่างอยู่แล้วเนื่องจากเป็นตัวชี้ที่แข็งแกร่ง (การอ่าน CPP ยังคงบังคับใช้ความสามารถในการเว้นว่าง แต่ประเภทยังคงเป็น 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
ความเสถียรของ Vintf
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
จะสร้างโดยใช้โมดูล Soong ประเภท aidl_interface
ได้เท่านั้น โดยตั้งค่าพร็อพเพอร์ตี้ stability
เป็น "vintf"
aidl_interface {
name: "my_interface",
srcs: [...],
stability: "vintf",
}
การใช้งานแอปที่ไม่รองรับ
คำอธิบายประกอบ 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
วิธีใช้พาร์เซลนี้
- คุณต้องระบุ
ndk_header
- คุณต้องมีไลบรารี NDK ที่ระบุแพ็กเกจที่แปลงได้ และไลบรารีดังกล่าวต้องมีการรวบรวมไว้ในไลบรารี เช่น ในระบบบิลด์หลักในโมดูล
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
สร้างเมธอด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 ไม่ได้พิจารณาค่าของพารามิเตอร์ หากมีข้อผิดพลาดทางไวยากรณ์ระดับ Java คอมไพเลอร์ AIDL จะไม่ตรวจจับข้อผิดพลาดนั้น แต่คอมไพเลอร์ Java
คำอธิบายประกอบนี้สามารถแนบกับเอนทิตี AIDL ใดก็ได้ คำอธิบายประกอบนี้ไม่มีการดำเนินการสำหรับ แบ็กเอนด์ที่ไม่ใช่ Java
ขนาดคงที่
FixedSize
จะทําเครื่องหมายพาร์เซลที่มีโครงสร้างเป็นขนาดคงที่ เมื่อทำเครื่องหมายแล้ว จะไม่สามารถเพิ่มฟิลด์ที่แปลงข้อมูลได้ ทุกช่องของพื้นที่เก็บข้อมูลต้องเป็นประเภทขนาดคงที่ เช่น ประเภทพื้นฐาน, enum, อาร์เรย์ขนาดคงที่ และพาร์เซลอื่นๆ ที่ทำเครื่องหมายด้วย FixedSize
ทั้งนี้ วิธีนี้ไม่ได้ให้การรับประกันใดๆ ในทุกบิต และไม่ควรนำไปใช้สำหรับการสื่อสารแบบผสม
ข้อบ่งชี้
Descriptor
บังคับให้ระบุตัวบ่งชี้อินเทอร์เฟซของอินเทอร์เฟซ
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
ข้อบ่งชี้ของอินเทอร์เฟซนี้คือ android.bar.IWorld
หากไม่มีคำอธิบายประกอบ Descriptor
ตัวบ่งชี้จะเป็น android.foo.IHello
ซึ่งมีประโยชน์ในการเปลี่ยนชื่ออินเทอร์เฟซที่เผยแพร่แล้ว การทำให้คำอธิบายของอินเทอร์เฟซที่เปลี่ยนชื่อใหม่เหมือนกับข้อบ่งชี้ของอินเทอร์เฟซก่อนการเปลี่ยนชื่อจะช่วยให้ทั้ง 2 อินเทอร์เฟซสื่อสารกันได้
@ซ่อน ในความคิดเห็น
คอมไพเลอร์ AIDL จะจดจำ @hide
ในความคิดเห็นและส่งไปยังเอาต์พุต Java สำหรับ Metalava เพื่อรับสินค้า ความคิดเห็นนี้ช่วยให้ระบบบิลด์ของ Android รู้ว่า AIDL API ไม่ใช่ SDK API
@เลิกใช้งานแล้วในความคิดเห็น
คอมไพเลอร์ AIDL จะถือว่า @deprecated
ในความคิดเห็นเป็นแท็กเพื่อระบุเอนทิตี AIDL ที่ไม่ควรใช้อีกต่อไป
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
แบ็กเอนด์แต่ละรายการจะทำเครื่องหมายเอนทิตีที่เลิกใช้งานแล้วด้วยคำอธิบายประกอบหรือแอตทริบิวต์เฉพาะแบ็กเอนด์ เพื่อให้ระบบเตือนโค้ดไคลเอ็นต์หากมีการอ้างอิงเอนทิตีที่เลิกใช้งานแล้ว ตัวอย่างเช่น คำอธิบายประกอบ @Deprecated
และแท็ก @deprecated
จะแนบไปกับโค้ดที่ Java สร้างขึ้น