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>
เสมอ
ในแบ็กเอนด์ 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
โปรดทราบว่าการมีคำอธิบายประกอบ utf8InCpp
ไม่ได้เปลี่ยนวิธี
การส่งสตริงผ่านสาย ระบบจะส่งสตริงเป็น UTF16
ผ่านสายเสมอ ระบบจะแปลงสตริงที่มีคำอธิบายประกอบเป็น UTF16 ก่อนที่จะส่ง
utf8InCpp
เมื่อได้รับสตริง ระบบจะแปลงจาก UTF16 เป็น UTF8 หากมีการ
ใส่คำอธิบายประกอบเป็น utf8InCpp
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: &
quot;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
และ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.Al
ice.Value.A)")
กลายเป็น
@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)
ในโค้ด Java ที่สร้างขึ้น
ระบบจะส่งค่าของพารามิเตอร์ annotation
โดยตรง คอมไพเลอร์ AIDL
จะไม่ดูค่าของพารามิเตอร์ หากมีข้อผิดพลาดทางไวยากรณ์ระดับ Java คอมไพเลอร์ AIDL จะไม่ตรวจพบ แต่คอมไพเลอร์ Java จะตรวจพบ
คำอธิบายประกอบนี้สามารถแนบกับเอนทิตี AIDL ใดก็ได้ คำอธิบายประกอบนี้ไม่มีผล สำหรับแบ็กเอนด์ที่ไม่ใช่ Java
RustDerive
RustDerive
จะใช้ลักษณะสำหรับประเภท Rust ที่สร้างขึ้นโดยอัตโนมัติ
คำอธิบายประกอบต้องมีพารามิเตอร์เพิ่มเติมเพื่อควบคุมสิ่งที่ต้อง สร้าง พารามิเตอร์ที่รองรับมีดังนี้
Copy=true
Clone=true
Ord=true
PartialOrd=true
Eq=true
PartialEq=true
Hash=true
ดูคำอธิบายลักษณะเหล่านี้ได้ที่ https://doc.rust-lang.org
FixedSize
FixedSize
ทำเครื่องหมาย Structured Parcelable เป็นขนาดคงที่ เมื่อทำเครื่องหมายแล้ว ระบบจะไม่อนุญาตให้เพิ่มฟิลด์ใหม่ลงใน
Parcelable ฟิลด์ทั้งหมดของ
Parcelable ต้องเป็นประเภทขนาดคงที่ด้วย รวมถึงประเภทดั้งเดิม
การแจงนับ อาร์เรย์ขนาดคงที่ และ Parcelable อื่นๆ ที่ทำเครื่องหมายด้วย FixedSize
ซึ่งไม่ได้เป็นการรับประกันสำหรับบิตเนสต่างๆ และไม่ควรใช้ ในการสื่อสารแบบผสมบิตเนส
ข้อบ่งชี้
Descriptor
ระบุตัวอธิบายอินเทอร์เฟซของอินเทอร์เฟซอย่างชัดเจน
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHe
llo {...}
ตัวอธิบายของอินเทอร์เฟซนี้คือ 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