คำอธิบายประกอบใน AIDL

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
JavaOnlyStableParcelable 11
JavaDerive 12
JavaPassthrough 12
FixedSize 12
Descriptor 12

nullable

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 IBinder และ IBinder คู่กับ android::sp<IBinder> เท่ากันซึ่งเป็นโมฆะเพราะเป็น ตัวชี้ ที่แข็งแกร่ง (CPP อ่านยังคงบังคับใช้ nullability แต่ประเภทยังคงเป็น android::sp<IBinder> ).

เริ่มต้นด้วย Android T (รุ่นทดลอง AOSP) @nullable(heap=true) สามารถใช้สำหรับฟิลด์ที่แยกพัสดุได้เพื่อสร้างแบบจำลองประเภทเรียกซ้ำ @nullable(heap=true) ใช้กับพารามิเตอร์เมธอดหรือประเภทการส่งคืนไม่ได้ เมื่อใส่คำอธิบายประกอบ ฟิลด์จะถูกแมปกับการอ้างอิงที่จัดสรรแบบฮีป std::unique_ptr<T> ในแบ็กเอนด์ CPP/NDK @nullable(heap=true) เป็น no-op ในแบ็กเอนด์ Java

utf8InCpp

utf8InCpp ประกาศว่า String แสดงในรูปแบบ UTF8 สำหรับแบ็กเอนด์ CPP ตามชื่อที่ระบุไว้ คำอธิบายประกอบเป็นแบบไม่มีการดำเนินการสำหรับแบ็กเอนด์อื่นๆ โดยเฉพาะ String เป็น UTF16 เสมอใน Java backend และ UTF8 ใน NDK backend

สามารถแนบคำอธิบายประกอบนี้ได้ทุกที่ที่สามารถใช้ประเภท 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 สามารถสร้างได้โดยใช้ประเภทโมดูล aidl_interface Soong เท่านั้น โดยตั้งค่าคุณสมบัติ stability เป็น "vintf"

aidl_interface {
    name: "my_interface",
    srcs: [...],
    stability: "vintf",
}

ไม่รองรับAppUsage

คำอธิบายประกอบ UnsupportedAppUsage ระบุว่าประเภท AIDL ที่มีคำอธิบายประกอบเป็นส่วนหนึ่งของอินเทอร์เฟซที่ไม่ใช่ SDK ที่สามารถเข้าถึงได้สำหรับแอปรุ่นเก่า ดู ข้อจำกัดบนอินเทอร์เฟซที่ไม่ใช่ SDK สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ API ที่ซ่อนอยู่

คำอธิบายประกอบ 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 บิต)

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 T (รุ่นทดลอง AOSP) จะควบคุมว่าจะมีการสร้างการสนับสนุนการกำหนดเวอร์ชันการใช้งานเริ่มต้นหรือไม่ (สำหรับ 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 ทำเครื่องหมายพัสดุที่มีโครงสร้างเป็นขนาดคงที่ เมื่อทำเครื่องหมายแล้ว พัสดุภัณฑ์จะไม่ได้รับอนุญาตให้เพิ่มช่องใหม่เข้าไป ฟิลด์ทั้งหมดของพัสดุต้องเป็นประเภทขนาดคงที่ ซึ่งรวมถึงประเภทดั้งเดิม enums อาร์เรย์ขนาดคงที่ และพัสดุอื่นๆ ที่ทำเครื่องหมายด้วย FixedSize ที่

สิ่งนี้ไม่ได้ให้การรับประกันใด ๆ สำหรับ bitnesses ที่แตกต่างกันและไม่ควรพึ่งพาการสื่อสารแบบผสม

คำอธิบาย

Descriptor บังคับให้ระบุอินเทอร์เฟซของอินเทอร์เฟซ

package android.foo;

@Descriptor(value="android.bar.IWorld")
interface IHello {...}

คำอธิบายของอินเทอร์เฟซข้างต้นคือ 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