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 ประกาศว่าค่าของเอนทิตีที่อธิบายประกอบอาจเป็นค่าว่างได้
คุณแนบคำอธิบายประกอบนี้ได้เฉพาะกับประเภทการคืนค่าของเมธอด พารามิเตอร์ของเมธอด และฟิลด์ที่ส่งผ่านได้:
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>อย่างเท่าเทียมกัน ซึ่ง
เป็นค่าที่กำหนดให้เป็น Null ได้อยู่แล้วเนื่องจากเป็นพอยน์เตอร์ที่เข้มงวด (CPP ยังคง
บังคับให้กำหนดค่าเป็น Null ได้ แต่ประเภทก็ยังคงเป็น 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
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 ทำเครื่องหมาย Structured Parcelable เป็นขนาดคงที่ หลังจากทำเครื่องหมายแล้ว คุณจะเพิ่มฟิลด์ใหม่ลงใน Parcelable ไม่ได้ ฟิลด์ทั้งหมดของ
Parcelable ต้องเป็นประเภทขนาดคงที่ รวมถึงประเภทดั้งเดิม
การแจงนับ อาร์เรย์ขนาดคงที่ และ Parcelable อื่นๆ ที่ทำเครื่องหมายด้วย FixedSize
ข้อบ่งชี้
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 จะรับรู้ว่า AIDL API ไม่ใช่ SDK API
@deprecated ในความคิดเห็น
คอมไพเลอร์ AIDL จะรับรู้ @deprecated ในความคิดเห็นเป็นแท็กเพื่อระบุเอนทิตี AIDL ที่ไม่ควรใช้อีกต่อไป ดังนี้
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
แบ็กเอนด์แต่ละรายการจะทำเครื่องหมายเอนทิตีที่เลิกใช้งานแล้วด้วยคำอธิบายประกอบหรือ
แอตทริบิวต์เฉพาะแบ็กเอนด์ เพื่อให้โค้ดไคลเอ็นต์ได้รับคำเตือนหากอ้างอิงถึงเอนทิตีที่เลิกใช้งานแล้ว
เช่น ระบบจะแนบคำอธิบายประกอบ @Deprecated และแท็ก @deprecated
ไว้กับโค้ดที่สร้างด้วย Java