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
จะเป็น no-op กล่าวอีกนัยหนึ่ง ทั้ง @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
ประกาศว่าประเภทที่ผู้ใช้กำหนด (อินเทอร์เฟซ แบ่งแยกได้ และแจงนับ) สามารถใช้ข้ามระบบและโดเมนของผู้จำหน่าย ดู 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
ระบุว่าประเภท 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++ enum ประเภท 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}
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)")
กลายเป็น
@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)
ในโค้ด Java ที่สร้างขึ้น
ค่าของพารามิเตอร์ annotation
ประกอบจะถูกส่งออกมาโดยตรง คอมไพเลอร์ AIDL ไม่ได้ดูค่าของพารามิเตอร์ หากมีข้อผิดพลาดทางไวยากรณ์ระดับ Java คอมไพเลอร์ AIDL จะไม่ถูกจับ แต่จะจับโดยคอมไพเลอร์ Java
คำอธิบายประกอบนี้สามารถแนบไปกับเอนทิตี AIDL ใดก็ได้ คำอธิบายประกอบนี้ไม่สามารถใช้งานได้สำหรับแบ็กเอนด์ที่ไม่ใช่ Java
ขนาดคงที่
FixedSize
เครื่องหมายโครงสร้างพัสดุเป็นขนาดคงที่ เมื่อทำเครื่องหมายแล้ว พัสดุที่จัดส่งจะไม่ได้รับอนุญาตให้เพิ่มช่องใหม่ลงไป ฟิลด์ทั้งหมดของพัสดุได้ต้องเป็นประเภทที่มีขนาดคงที่ รวมถึงประเภทพื้นฐาน การแจงนับ อาร์เรย์ที่มีขนาดคงที่ และพัสดุอื่นๆ ที่มีเครื่องหมาย FixedSize
สิ่งนี้ไม่ได้ให้การรับประกันใดๆ เกี่ยวกับ bitness ต่างๆ และไม่ควรเชื่อถือในการสื่อสารแบบ bitness แบบผสม
คำอธิบาย
Descriptor
บังคับให้ระบุตัวอธิบายอินเทอร์เฟซของอินเทอร์เฟซ
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
descriptor ของอินเทอร์เฟซด้านบนคือ android.bar.IWorld
หากไม่มีคำอธิบายประกอบ Descriptor
descriptor จะเป็น android.foo.IHello
สิ่งนี้มีประโยชน์สำหรับการเปลี่ยนชื่ออินเทอร์เฟซที่เผยแพร่แล้ว การทำให้ descriptor ของอินเทอร์เฟซที่เปลี่ยนชื่อเหมือนกับ descriptor ของอินเทอร์เฟซก่อนการเปลี่ยนชื่อจะทำให้ทั้งสองอินเทอร์เฟซสามารถพูดคุยกัน
@ซ่อนในความคิดเห็น
คอมไพลเลอร์ AIDL จดจำ @hide
ในความคิดเห็นและส่งผ่านไปยังเอาต์พุต Java เพื่อให้ Metalava รับ ความคิดเห็นนี้ช่วยให้แน่ใจว่าระบบบิลด์ Android รู้ว่า AIDL API ไม่ใช่ SDK API
@deprecated ในความคิดเห็น
คอมไพเลอร์ AIDL รู้จัก @deprecated
ในความคิดเห็นว่าเป็นแท็กเพื่อระบุเอนทิตี AIDL ที่ไม่ควรใช้อีกต่อไป
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
แบ็กเอนด์แต่ละรายการจะทำเครื่องหมายเอนทิตีที่เลิกใช้แล้วด้วยคำอธิบายประกอบ/แอตทริบิวต์เฉพาะของแบ็กเอนด์ เพื่อเตือนรหัสไคลเอ็นต์หากอ้างถึงเอนทิตีที่เลิกใช้แล้ว ตัวอย่างเช่น คำอธิบายประกอบ @Deprecated
และแท็ก @deprecated
จะแนบไปกับโค้ดที่สร้างโดย Java