AIDL รองรับคําอธิบายประกอบที่ให้ข้อมูลเพิ่มเติมแก่คอมไพเลอร์ AIDL เกี่ยวกับองค์ประกอบที่มีคําอธิบายประกอบ ซึ่งส่งผลต่อโค้ดสแต็บที่สร้างขึ้นด้วย
ไวยากรณ์จะคล้ายกับ 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>
เสมอ
ในแบ็กเอนด์ 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
จะไม่มีผลกับแบ็กเอนด์ทั้งหมดยกเว้น Rust กล่าวคือ ทั้ง @nullable IBinder
และ IBinder
จะแมปกับ android::sp<IBinder>
เท่าๆ กัน ซึ่งจะเป็น Nullable อยู่แล้วเนื่องจากเป็น pointer แบบ Strong (การอ่าน CPP จะยังคงบังคับใช้ Nullable แต่ประเภทจะยังคงเป็น android::sp<IBinder>
) ใน Rust ประเภทเหล่านี้จะเป็น nullable
ก็ต่อเมื่อมีการทำเครื่องหมายกำกับด้วย @nullable
เท่านั้น โดยจะแมปกับ Option<T>
หากมีคำอธิบายประกอบ
ตั้งแต่ 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
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
คําอธิบายประกอบ UnsupportedAppUsage
บ่งบอกว่าประเภท AIDL ที่มีคําอธิบายประกอบเป็นส่วนหนึ่งของอินเทอร์เฟซที่ไม่ใช่ SDK ซึ่งแอปเดิมเข้าถึงได้
ดูข้อมูลเพิ่มเติมเกี่ยวกับ API ที่ซ่อนอยู่ได้ที่ข้อจํากัดเกี่ยวกับอินเทอร์เฟซที่ไม่ใช่ SDK
คำอธิบายประกอบ UnsupportedAppUsage
ไม่ส่งผลต่อลักษณะการทำงานของโค้ดที่สร้างขึ้น คำอธิบายประกอบนี้จะใส่คำอธิบายประกอบคลาส Java ที่สร้างขึ้นด้วยคำอธิบายประกอบ Java ที่มีชื่อเดียวกันเท่านั้น
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
การดำเนินการนี้จะใช้งานไม่ได้กับแบ็กเอนด์ที่ไม่ใช่ Java
พื้นหลัง
คําอธิบายประกอบ Backing
จะระบุประเภทพื้นที่เก็บข้อมูลของประเภท AIDL enum
@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
วิธีใช้ Parcelable นี้
- คุณต้องระบุ
ndk_header
- คุณต้องมีไลบรารี NDK ที่ระบุ Parcelable และไลบรารีต้องได้รับการคอมไพล์ลงในไลบรารี เช่น ในระบบบิลด์หลักของข้อบังคับ
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
ช่วยให้คุณลบล้างการตรวจสอบได้เมื่อ 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
และ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
ทำเครื่องหมาย Structured Parcelable เป็นขนาดคงที่ เมื่อทำเครื่องหมายแล้ว ระบบจะไม่อนุญาตให้เพิ่มช่องใหม่ในแปลงที่ดิน ทุกช่องของพื้นที่เก็บข้อมูลต้องเป็นประเภทขนาดคงที่ด้วย เช่น ประเภทพื้นฐาน, enum, อาร์เรย์ขนาดคงที่ และพาร์เซลอื่นๆ ที่ทำเครื่องหมายด้วย FixedSize
การดำเนินการนี้ไม่ได้รับประกันอะไรเลยสำหรับบิตที่แตกต่างกัน และไม่ควรใช้เพื่อการสื่อสารแบบผสมบิต
ข้อบ่งชี้
Descriptor
ระบุตัวบ่งชี้อินเทอร์เฟซของอินเทอร์เฟซอย่างบังคับ
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
ข้อบ่งชี้ของอินเทอร์เฟซนี้คือ android.bar.IWorld
หากไม่มีANNOTATION Descriptor
ข้อบ่งชี้จะเป็นandroid.foo.IHello
ซึ่งมีประโยชน์สำหรับการเปลี่ยนชื่ออินเทอร์เฟซที่เผยแพร่ไปแล้ว การกำหนดข้อบ่งชี้ของอินเทอร์เฟซที่เปลี่ยนชื่อให้เหมือนกับข้อบ่งชี้ของอินเทอร์เฟซก่อนเปลี่ยนชื่อจะช่วยให้อินเทอร์เฟซทั้งสองสื่อสารกันได้
@hide ในความคิดเห็น
คอมไพเลอร์ 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 สร้างขึ้น