Android 10 เพิ่มการรองรับภาษาคำจำกัดความสำหรับอินเทอร์เฟซ Android (AIDL) ที่มีความเสถียร ซึ่งเป็นวิธีใหม่ในการติดตามอินเทอร์เฟซโปรแกรมแอปพลิเคชัน (API) และอินเทอร์เฟซไบนารีของแอปพลิเคชัน (ABI) ที่ให้บริการโดยอินเทอร์เฟซ AIDL AIDL เวอร์ชันเสถียรมีความแตกต่างที่สำคัญจาก AIDL ดังนี้
- อินเทอร์เฟซจะกำหนดไว้ในระบบบิลด์ด้วย
aidl_interfaces
- อินเทอร์เฟซมีได้เฉพาะข้อมูลที่มีโครงสร้าง ระบบจะสร้างพาร์เซลที่แสดงประเภทที่ต้องการโดยอัตโนมัติตามคำจำกัดความของ AIDL และจะสร้างขึ้นมาแบบมาร์แชลล์และไม่ใส่มาร์ชออกโดยอัตโนมัติ
- อินเทอร์เฟซอาจประกาศได้ว่าเสถียร (เข้ากันได้แบบย้อนหลัง) เมื่อเกิดเหตุการณ์นี้ขึ้น API ดังกล่าวจะได้รับการติดตามและกำหนดเวอร์ชันในไฟล์ข้างอินเทอร์เฟซ AIDL
AIDL แบบมีโครงสร้างกับแบบเสถียร
AIDL ที่มีโครงสร้างหมายถึงประเภทที่กำหนดไว้ใน AIDL เพียงอย่างเดียว เช่น ประกาศที่จัดกลุ่มได้ (Parcelable ที่กำหนดเอง) ไม่ใช่ AIDL แบบมีโครงสร้าง พัสดุที่มีฟิลด์ซึ่งระบุไว้ใน AIDL จะเรียกว่าพัสดุที่มีโครงสร้าง
AIDL เวอร์ชันเสถียรต้องใช้ AIDL ที่มีโครงสร้างเพื่อให้ระบบบิลด์และคอมไพเลอร์เข้าใจว่าการเปลี่ยนแปลงที่ทำกับพาร์เซลนั้นเข้ากันได้แบบย้อนหลังหรือไม่
อย่างไรก็ตาม อินเทอร์เฟซที่มีโครงสร้างบางรายการอาจไม่เสถียร อินเทอร์เฟซต้องใช้ประเภทที่มีโครงสร้างเท่านั้น รวมถึงต้องใช้ฟีเจอร์การกำหนดเวอร์ชันต่อไปนี้เพื่อให้มีความเสถียร ในทางกลับกัน อินเทอร์เฟซจะไม่เสถียรหากใช้ระบบบิลด์หลักในการสร้างหรือมีการตั้งค่า unstable:true
ไว้
กำหนดอินเทอร์เฟซ AIDL
คำจำกัดความของ aidl_interface
มีลักษณะดังนี้
aidl_interface {
name: "my-aidl",
srcs: ["srcs/aidl/**/*.aidl"],
local_include_dir: "srcs/aidl",
imports: ["other-aidl"],
versions_with_info: [
{
version: "1",
imports: ["other-aidl-V1"],
},
{
version: "2",
imports: ["other-aidl-V3"],
}
],
stability: "vintf",
backend: {
java: {
enabled: true,
platform_apis: true,
},
cpp: {
enabled: true,
},
ndk: {
enabled: true,
},
rust: {
enabled: true,
},
},
}
name
: ชื่อของโมดูลอินเทอร์เฟซ AIDL ที่ระบุอินเทอร์เฟซ AIDL แบบไม่ซ้ำsrcs
: รายการไฟล์ต้นทางของ AIDL ที่เขียนอินเทอร์เฟซ เส้นทางสำหรับ AIDL ประเภทFoo
ที่กำหนดไว้ในแพ็กเกจcom.acme
ควรอยู่ที่<base_path>/com/acme/Foo.aidl
โดยที่<base_path>
อาจเป็นไดเรกทอรีใดก็ได้ที่เกี่ยวข้องกับไดเรกทอรีที่Android.bp
อยู่ ในตัวอย่างก่อนหน้านี้<base_path>
คือsrcs/aidl
local_include_dir
: เส้นทางจากจุดเริ่มต้นของชื่อแพ็กเกจ ซึ่งสอดคล้องกับ<base_path>
ที่อธิบายไว้ข้างต้นimports
: รายการaidl_interface
โมดูลที่ใช้ หากอินเทอร์เฟซ AIDL อันใดอันหนึ่งใช้อินเทอร์เฟซหรือไฟล์พาร์ทจากaidl_interface
อีกตัวหนึ่ง ให้ใส่ชื่อของอินเทอร์เฟซนั้นที่นี่ ซึ่งอาจเป็นชื่อเฉพาะ ใช้อ้างอิงถึงเวอร์ชันล่าสุด หรือชื่อที่มีคำต่อท้ายเวอร์ชัน (เช่น-V1
) เพื่อหมายถึงเวอร์ชันที่เจาะจง รองรับการระบุเวอร์ชันตั้งแต่ Android 12versions
: อินเทอร์เฟซเวอร์ชันก่อนหน้าที่ตรึงไว้ภายใต้api_dir
ตั้งแต่ Android 11 เป็นต้นไปversions
จะตรึงชั่วคราวอยู่ภายใต้aidl_api/name
หากไม่มีเวอร์ชันใดที่หยุดนิ่งของอินเทอร์เฟซ ก็ไม่ควรระบุไว้ และจะไม่มีการตรวจสอบความเข้ากันได้ เราได้แทนที่ช่องนี้ด้วยversions_with_info
สำหรับ Android 13 ขึ้นไปversions_with_info
: รายการ tuples แต่ละรายชื่อมีชื่อของเวอร์ชันที่ถูกตรึง และรายการที่มีการนำเข้าเวอร์ชันของโมดูล aidl_interface อื่นๆ ที่ aidl_interface เวอร์ชันนี้นำเข้ามา ดูคำจำกัดความของเวอร์ชัน V ของ IFACE ของอินเทอร์เฟซ AIDL ได้ที่aidl_api/IFACE/V
ช่องนี้เกิดขึ้นใน Android 13 และไม่ควรทำการแก้ไขในAndroid.bp
โดยตรง เพิ่มหรืออัปเดตช่องนี้โดยการเรียกใช้*-update-api
หรือ*-freeze-api
นอกจากนี้ ระบบจะย้ายข้อมูลช่องversions
ไปยังversions_with_info
โดยอัตโนมัติเมื่อผู้ใช้เรียกใช้*-update-api
หรือ*-freeze-api
stability
: ธงที่ไม่บังคับเพื่อรับประกันความเสถียรของอินเทอร์เฟซนี้ ฟีเจอร์นี้รองรับเฉพาะ"vintf"
หากไม่ได้ตั้งค่าstability
ไว้ ระบบบิลด์จะตรวจสอบว่าอินเทอร์เฟซใช้งานร่วมกันได้แบบย้อนหลัง เว้นแต่จะมีการระบุunstable
ไว้ การไม่ได้ตั้งค่าจะสอดคล้องกับอินเทอร์เฟซที่มีความเสถียรในบริบทการคอมไพล์นี้ (ดังนั้น ไม่ว่าจะเป็นทุกสิ่งของระบบ เช่น สิ่งต่างๆ ในsystem.img
และพาร์ติชันที่เกี่ยวข้อง หรือสิ่งของผู้ให้บริการทั้งหมด เช่น สิ่งต่างๆ ในvendor.img
และพาร์ติชันที่เกี่ยวข้อง) หากตั้งค่าstability
เป็น"vintf"
กรณีนี้จะสอดคล้องกับข้อกำหนดด้านความเสถียร กล่าวคือ อินเทอร์เฟซต้องเสถียรตราบเท่าที่ใช้งานgen_trace
: Flag ที่ไม่บังคับสำหรับเปิดหรือปิดการติดตาม ตั้งแต่ Android 14 เป็นต้นไป ค่าเริ่มต้นคือtrue
สำหรับแบ็กเอนด์cpp
และjava
host_supported
: แฟล็กที่ไม่บังคับซึ่งเมื่อตั้งค่าเป็นtrue
จะทำให้ไลบรารีที่สร้างขึ้นพร้อมใช้งานกับสภาพแวดล้อมของโฮสต์unstable
: แฟล็กที่ไม่บังคับซึ่งใช้เพื่อทำเครื่องหมายว่าอินเทอร์เฟซนี้ไม่จำเป็นต้องเสถียร เมื่อตั้งค่าเป็นtrue
ระบบบิลด์จะไม่สร้างดัมพ์ API สำหรับอินเทอร์เฟซและไม่ต้องมีการอัปเดตfrozen
: แฟล็กที่ไม่บังคับซึ่งเมื่อตั้งค่าเป็นtrue
หมายความว่าอินเทอร์เฟซไม่มีการเปลี่ยนแปลงนับตั้งแต่อินเทอร์เฟซเวอร์ชันก่อนหน้า ซึ่งจะทำให้มีการตรวจสอบเวลาบิลด์มากยิ่งขึ้น เมื่อตั้งค่าเป็นfalse
หมายความว่าอินเทอร์เฟซอยู่ระหว่างการพัฒนาและมีการเปลี่ยนแปลงใหม่ ดังนั้นการเรียกใช้foo-freeze-api
จะสร้างเวอร์ชันใหม่และเปลี่ยนค่าเป็นtrue
โดยอัตโนมัติ เปิดตัวใน Android 14backend.<type>.enabled
: แฟล็กเหล่านี้จะสลับแบ็กเอนด์แต่ละรายการที่คอมไพเลอร์ AIDL สร้างโค้ดให้ ระบบรองรับแบ็กเอนด์ 4 แบบ ได้แก่ Java, C++, NDK และ Rust แบ็กเอนด์ Java, C++ และ NDK จะเปิดใช้โดยค่าเริ่มต้น หากไม่จำเป็นต้องใช้แบ็กเอนด์ใดๆ ใน 3 รายการเหล่านี้ คุณต้องปิดใช้อย่างชัดเจน Rust จะปิดใช้โดยค่าเริ่มต้นจนถึง Android 15 (เวอร์ชันทดลอง AOSP)backend.<type>.apex_available
: รายการชื่อ APEX ที่ไลบรารีสตับที่สร้างขึ้นพร้อมใช้งานbackend.[cpp|java].gen_log
: แฟล็กที่ไม่บังคับซึ่งควบคุมว่าจะสร้างโค้ดเพิ่มเติมสำหรับรวบรวมข้อมูลเกี่ยวกับธุรกรรมหรือไม่backend.[cpp|java].vndk.enabled
: Flag (ไม่บังคับ) ที่จะทำให้อินเทอร์เฟซนี้เป็นส่วนหนึ่งของ VNDK ค่าเริ่มต้นคือfalse
backend.[cpp|ndk].additional_shared_libraries
: Flag นี้เปิดตัวใน Android 14 และจะเพิ่มทรัพยากร Dependency ไปยังไลบรารีเนทีฟ การตั้งค่าสถานะนี้มีประโยชน์กับndk_header
และcpp_header
backend.java.sdk_version
: แฟล็กที่ไม่บังคับสำหรับระบุเวอร์ชันของ SDK ที่ใช้ไลบรารี Java Stub สร้างขึ้น โดยมีค่าเริ่มต้นเป็น"system_current"
ไม่ควรตั้งค่านี้เมื่อbackend.java.platform_apis
คือtrue
backend.java.platform_apis
: Flag ที่ไม่บังคับที่ควรตั้งค่าเป็นtrue
เมื่อไลบรารีที่สร้างขึ้นต้องสร้างเทียบกับ API ของแพลตฟอร์มแทน SDK
ระบบจะสร้างไลบรารี Stub สำหรับชุดค่าผสมของเวอร์ชันและแบ็กเอนด์ที่เปิดใช้แต่ละชุด ดูวิธีอ้างถึงเวอร์ชันเฉพาะของไลบรารี Stub สำหรับแบ็กเอนด์ที่เจาะจงได้ที่กฎการตั้งชื่อโมดูล
เขียนไฟล์ AIDL
อินเทอร์เฟซใน AIDL เวอร์ชันเสถียรนั้นคล้ายกับอินเทอร์เฟซแบบดั้งเดิม โดยมีข้อยกเว้นว่าไม่ได้รับอนุญาตให้ใช้พื้นที่ซึ่งไม่มีโครงสร้าง (เนื่องจากหน้าเหล่านี้ไม่เสถียร โปรดดู AIDL ที่มีโครงสร้างกับเสถียร) ความแตกต่างหลักๆ ใน AIDL แบบคงที่คือวิธีกำหนดพัสดุ ก่อนหน้านี้ไฟล์พาร์เซลมีการประกาศการส่งต่อ ดังนั้น AIDL ที่เสถียร (จึงเป็นโครงสร้าง) จะมีการกำหนดช่องและตัวแปรของพาร์เซลอย่างชัดเจน
// in a file like 'some/package/Thing.aidl'
package some.package;
parcelable SubThing {
String a = "foo";
int b;
}
ระบบรองรับค่าเริ่มต้น (แต่ไม่บังคับ) สำหรับ boolean
, char
,
float
, double
, byte
, int
, long
และ String
ใน Android 12 รองรับค่าเริ่มต้นสำหรับการแจงนับที่กำหนดโดยผู้ใช้ด้วย เมื่อไม่ได้ระบุค่าเริ่มต้น ระบบจะใช้ค่าที่เหมือน 0 หรือว่างเปล่า
การแจงนับที่ไม่มีค่าเริ่มต้นจะเริ่มต้นเป็น 0 แม้ว่าจะไม่มีตัวระบุที่เป็น 0 ก็ตาม
ใช้ไลบรารีต้นขั้ว
หลังจากเพิ่มไลบรารี Stub เป็นทรัพยากร Dependency ของโมดูลแล้ว คุณจะรวมไลบรารีดังกล่าวลงในไฟล์ได้ ต่อไปนี้คือตัวอย่างไลบรารี Stub ในระบบบิลด์ (ใช้ Android.mk
สำหรับการกำหนดโมดูลเดิมได้ด้วย)
cc_... {
name: ...,
shared_libs: ["my-module-name-cpp"],
...
}
# or
java_... {
name: ...,
// can also be shared_libs if your preference is to load a library and share
// it among multiple users or if you only need access to constants
static_libs: ["my-module-name-java"],
...
}
# or
rust_... {
name: ...,
rustlibs: ["my-module-name-rust"],
...
}
ตัวอย่างใน C++
#include "some/package/IFoo.h"
#include "some/package/Thing.h"
...
// use just like traditional AIDL
ตัวอย่างใน Java
import some.package.IFoo;
import some.package.Thing;
...
// use just like traditional AIDL
ตัวอย่างใน Rust
use aidl_interface_name::aidl::some::package::{IFoo, Thing};
...
// use just like traditional AIDL
อินเทอร์เฟซการกำหนดเวอร์ชัน
การประกาศโมดูลโดยใช้ชื่อ foo จะเป็นการสร้างเป้าหมายในระบบบิลด์ที่คุณใช้จัดการ API ของโมดูลได้ด้วย เมื่อสร้างแล้ว foo-freeze-api
จะเพิ่มคำจำกัดความ API ใหม่ภายใต้ api_dir
หรือ
aidl_api/name
ทั้งนี้ขึ้นอยู่กับเวอร์ชัน Android และเพิ่มไฟล์ .hash
ซึ่งทั้ง 2 ไฟล์จะแสดงอินเทอร์เฟซเวอร์ชันแช่แข็งใหม่ foo-freeze-api จะอัปเดตพร็อพเพอร์ตี้ versions_with_info
เพื่อแสดงเวอร์ชันเพิ่มเติมและ imports
สำหรับเวอร์ชันนั้นด้วย โดยทั่วไปแล้ว imports
ใน versions_with_info
จะคัดลอกมาจากช่อง imports
แต่มีการระบุเวอร์ชันเสถียรล่าสุดใน imports
ใน versions_with_info
สำหรับการนำเข้า ซึ่งไม่มีเวอร์ชันที่ชัดเจน
หลังจากระบุพร็อพเพอร์ตี้ versions_with_info
แล้ว ระบบบิลด์จะทำการตรวจสอบความเข้ากันได้ระหว่างเวอร์ชันที่ตรึงไว้และระหว่าง Top of Tree (ToT) กับเวอร์ชันล่าสุดที่ตรึงไว้
นอกจากนี้ คุณจำเป็นต้องจัดการคำจำกัดความ API ของเวอร์ชัน ToT ทุกครั้งที่มีการอัปเดต API ให้เรียกใช้ foo-update-api เพื่ออัปเดต
aidl_api/name/current
ซึ่งมีคำจำกัดความ API ของเวอร์ชัน ToT
เจ้าของสามารถเพิ่มรายการต่อไปนี้ได้เพื่อรักษาความเสถียรของอินเทอร์เฟซ
- เมธอดต่อท้ายอินเทอร์เฟซ (หรือเมธอดที่มีหมายเลขซีเรียลใหม่กำหนดไว้อย่างชัดเจน)
- องค์ประกอบที่อยู่ท้ายไฟล์พาร์เซล (ต้องมีค่าเริ่มต้นเพื่อเพิ่มสำหรับแต่ละองค์ประกอบ)
- ค่าคงที่
- ใน Android 11 ตัวระบุ
- ใน Android 12 ช่องที่อยู่ท้ายสุดของสหภาพ
ไม่อนุญาตให้ดำเนินการอื่นๆ และไม่มีใครสามารถแก้ไขอินเทอร์เฟซได้ (มิเช่นนั้นอาจทำให้เกิดความขัดแย้งกับการเปลี่ยนแปลงที่เจ้าของทำ)
หากต้องการทดสอบว่าอินเทอร์เฟซทั้งหมดหยุดนิ่งสำหรับการเปิดตัว คุณสามารถสร้างด้วยชุดตัวแปรสภาพแวดล้อมต่อไปนี้
AIDL_FROZEN_REL=true m ...
- บิลด์กำหนดให้หยุดอินเทอร์เฟซ AIDL ที่เสถียรทั้งหมดซึ่งไม่ได้ระบุช่องowner:
AIDL_FROZEN_OWNERS="aosp test"
- บิลด์กำหนดให้หยุดอินเทอร์เฟซ AIDL ที่เสถียรทั้งหมดโดยระบุช่องowner:
เป็น "aosp" หรือ "test"
ความเสถียรของการนำเข้า
การอัปเดตเวอร์ชันของการนำเข้าสำหรับอินเทอร์เฟซเวอร์ชันที่ตรึงไว้จะเข้ากันได้แบบย้อนหลังที่เลเยอร์ AIDL เวอร์ชันเสถียร แต่การอัปเดตเหล่านี้จำเป็นต้องอัปเดตเซิร์ฟเวอร์และไคลเอ็นต์ทั้งหมดที่ใช้อินเทอร์เฟซเวอร์ชันก่อนหน้า และบางแอปอาจสับสนระหว่างเวอร์ชันต่างๆ ที่มีหลายเวอร์ชัน โดยทั่วไป วิธีนี้ปลอดภัยสำหรับแพ็กเกจประเภทเท่านั้นหรือแพ็กเกจทั่วไป เนื่องจากต้องมีการเขียนโค้ดไว้จัดการประเภทที่ไม่รู้จักจากธุรกรรม IPC แล้ว
ในโค้ดแพลตฟอร์ม Android android.hardware.graphics.common
คือตัวอย่าง
ที่ใหญ่ที่สุดของการอัปเกรดเวอร์ชันประเภทนี้
ใช้อินเทอร์เฟซที่มีเวอร์ชัน
วิธีการเชื่อมต่อ
ขณะรันไทม์ เมื่อพยายามเรียกใช้เมธอดใหม่ในเซิร์ฟเวอร์เก่า ไคลเอ็นต์ใหม่จะได้รับข้อผิดพลาดหรือข้อยกเว้น ทั้งนี้ขึ้นอยู่กับแบ็กเอนด์
- แบ็กเอนด์
cpp
ได้รับ::android::UNKNOWN_TRANSACTION
- แบ็กเอนด์
ndk
ได้รับSTATUS_UNKNOWN_TRANSACTION
- แบ็กเอนด์
java
ได้รับandroid.os.RemoteException
พร้อมข้อความแจ้งว่ายังไม่ได้ใช้ API
สำหรับกลยุทธ์ในการจัดการปัญหานี้ โปรดดูที่เวอร์ชันการค้นหาและการใช้ค่าเริ่มต้น
พาร์เซล
เมื่อมีการเพิ่มช่องใหม่ลงในพาร์เซล ไคลเอ็นต์และเซิร์ฟเวอร์เก่าจะทิ้งช่องนั้นไป เมื่อไคลเอ็นต์และเซิร์ฟเวอร์ใหม่ได้รับพาร์เซลเก่า ระบบจะกรอกค่าเริ่มต้นสำหรับช่องใหม่โดยอัตโนมัติ ซึ่งหมายความว่าจำเป็นต้องระบุค่าเริ่มต้นสำหรับช่องใหม่ทุกช่องในพื้นที่เก็บข้อมูล
ไคลเอ็นต์ไม่ควรคาดหวังให้เซิร์ฟเวอร์ใช้ช่องใหม่ เว้นแต่จะรู้ว่าเซิร์ฟเวอร์ใช้เวอร์ชันที่มีการกำหนดช่องเอาไว้ (ดูเวอร์ชันการค้นหา)
ค่าแจกแจงและค่าคงที่
ในทํานองเดียวกัน ไคลเอ็นต์และเซิร์ฟเวอร์ควรปฏิเสธหรือเพิกเฉยต่อค่าคงที่ที่ไม่รู้จักและตัวแจกแจงตามความเหมาะสม เนื่องจากอาจมีการเพิ่มเข้ามาในอนาคต เช่น เซิร์ฟเวอร์ไม่ควรล้มเลิกเมื่อได้รับเครื่องมือแจกแจงที่ไม่รู้จัก เซิร์ฟเวอร์ควรเพิกเฉยต่อโปรแกรมแจกแจง หรือแสดงผลบางอย่างเพื่อให้ไคลเอ็นต์ทราบว่าไม่ได้รับการรองรับในการใช้งานนี้
สหภาพ
การพยายามส่งการรวมที่มีช่องใหม่จะล้มเหลวหากผู้รับเป็นรุ่นเก่าและไม่ทราบข้อมูลเกี่ยวกับช่องนั้น การใช้งานจะไม่มีวันรวมที่อยู่กับฟิลด์ใหม่ ระบบจะไม่สนใจความล้มเหลวหากเป็นธุรกรรมทางเดียว มิเช่นนั้น ข้อผิดพลาดจะเป็น BAD_VALUE
(สำหรับแบ็กเอนด์ C++ หรือ NDK) หรือ IllegalArgumentException
(สำหรับแบ็กเอนด์ Java) ระบบจะได้รับข้อผิดพลาดหากไคลเอ็นต์ส่งชุดการรวมข้อมูลไปยังฟิลด์ใหม่ไปยังเซิร์ฟเวอร์เก่า หรือเมื่อไคลเอ็นต์เป็นไคลเอ็นต์เก่าที่ได้รับการรวมดังกล่าวจากเซิร์ฟเวอร์ใหม่
การพัฒนาที่อิงตาม Flag
อินเทอร์เฟซที่อยู่ระหว่างการพัฒนา (ยกเลิกการตรึง) จะใช้กับอุปกรณ์ที่เผยแพร่ไม่ได้ เนื่องจากไม่มีการรับประกันว่าจะใช้งานร่วมกันได้แบบย้อนหลัง
AIDL รองรับรันไทม์สำรองสำหรับไลบรารีอินเทอร์เฟซที่ไม่ได้ตรึงเหล่านี้เพื่อเขียนโค้ดเทียบกับเวอร์ชันล่าสุดที่ไม่ได้ตรึงไว้และยังคงใช้งานในอุปกรณ์ที่เผยแพร่ได้ ลักษณะการทำงานที่เข้ากันได้กับไคลเอ็นต์แบบย้อนหลังนั้นคล้ายกับลักษณะการทำงานที่มีอยู่ และเมื่อใช้วิดีโอสำรอง การติดตั้งใช้งานจะต้องเป็นไปตามลักษณะการทำงานเหล่านั้นด้วย โปรดดูหัวข้อใช้อินเทอร์เฟซที่มีเวอร์ชัน
Flag บิลด์ AIDL
แฟล็กที่ควบคุมลักษณะการทำงานนี้มีการกำหนด RELEASE_AIDL_USE_UNFROZEN
ใน build/release/build_flags.bzl
true
หมายความว่าจะมีการใช้อินเทอร์เฟซเวอร์ชันที่ไม่ได้ตรึงไว้ในขณะรันไทม์ และ false
หมายความว่าไลบรารีของเวอร์ชันที่ไม่ได้ตรึงไว้ทำงานเหมือนกับเวอร์ชันที่ตรึงไว้ล่าสุด
คุณลบล้าง Flag เป็น true
สำหรับการพัฒนาในเครื่องได้ แต่ต้องเปลี่ยนกลับไปเป็น false
ก่อนการเปิดตัว โดยปกติแล้วการพัฒนาจะเสร็จสิ้นด้วยการกำหนดค่าที่มีการตั้งค่า Flag เป็น true
เมทริกซ์ความเข้ากันได้และไฟล์ Manifest
ออบเจ็กต์อินเทอร์เฟซผู้ให้บริการ (ออบเจ็กต์ VINTF) กำหนดเวอร์ชันที่คาดไว้และเวอร์ชันที่จะแสดงที่ด้านข้างของอินเทอร์เฟซผู้ให้บริการ
อุปกรณ์ที่ไม่ใช่ Cuttlefish ส่วนใหญ่จะกําหนดเป้าหมายเมทริกซ์ความเข้ากันได้ล่าสุดหลังจากที่อินเทอร์เฟซค้างเท่านั้น ไลบรารี AIDL ที่ใช้ RELEASE_AIDL_USE_UNFROZEN
จึงไม่มีความแตกต่าง
เมทริกซ์
ระบบจะเพิ่มอินเทอร์เฟซที่พาร์ทเนอร์เป็นเจ้าของลงในเมทริกซ์ความเข้ากันได้เฉพาะอุปกรณ์หรือเมทริกซ์ความเข้ากันได้เฉพาะผลิตภัณฑ์ที่อุปกรณ์กำหนดเป้าหมายระหว่างการพัฒนา ดังนั้นเมื่อมีการเพิ่มอินเทอร์เฟซเวอร์ชันใหม่ที่ไม่ได้ตรึงไว้ลงในเมทริกซ์ความเข้ากันได้ เวอร์ชันที่ตรึงไว้ก่อนหน้านี้จะยังคงต้องใช้เวอร์ชัน RELEASE_AIDL_USE_UNFROZEN=false
ต่อไป ซึ่งจัดการได้โดยใช้ไฟล์เมทริกซ์ความเข้ากันได้ที่ต่างกันสำหรับการกำหนดค่า RELEASE_AIDL_USE_UNFROZEN
ที่แตกต่างกัน หรืออนุญาตให้ใช้ทั้ง 2 เวอร์ชันในไฟล์เมทริกซ์ความเข้ากันได้ไฟล์เดียวซึ่งใช้ในการกำหนดค่าทั้งหมด
เช่น เมื่อเพิ่มเวอร์ชัน 4 ที่ไม่ได้ตรึงไว้ ให้ใช้ <version>3-4</version>
เมื่อเวอร์ชัน 4 ถูกระงับชั่วคราว คุณสามารถนำเวอร์ชัน 3 ออกจากเมทริกซ์ความเข้ากันได้ เนื่องจากจะมีการใช้เวอร์ชัน 4 ที่ตรึงไว้เมื่อ RELEASE_AIDL_USE_UNFROZEN
คือ false
Manifest
ใน Android 15 (เวอร์ชันทดลอง AOSP) มีการเปลี่ยนแปลงใน libvintf
เพื่อแก้ไขไฟล์ Manifest ในเวลาบิลด์โดยอิงตามค่าของ RELEASE_AIDL_USE_UNFROZEN
ไฟล์ Manifest และส่วนย่อยของไฟล์ Manifest จะประกาศเวอร์ชันของอินเทอร์เฟซที่บริการใช้ เมื่อใช้อินเทอร์เฟซเวอร์ชันล่าสุดที่ไม่ได้ตรึงไว้ คุณจะต้องอัปเดตไฟล์ Manifest ให้สอดคล้องกับเวอร์ชันใหม่นี้ เมื่อ
RELEASE_AIDL_USE_UNFROZEN=false
รายการไฟล์ Manifest ได้รับการปรับเปลี่ยนโดย
libvintf
เพื่อแสดงการเปลี่ยนแปลงในไลบรารี AIDL ที่สร้างขึ้น เวอร์ชันนี้มีการแก้ไขจากเวอร์ชันที่ไม่ได้ตรึงไว้ N
เป็นเวอร์ชัน N - 1
ที่ตรึงไว้ล่าสุด ดังนั้น ผู้ใช้ไม่จำเป็นต้องจัดการไฟล์ Manifest หรือไฟล์ Manifest หลายรายการสำหรับบริการแต่ละรายการ
การเปลี่ยนแปลงไคลเอ็นต์ HAL
รหัสไคลเอ็นต์ HAL ต้องเข้ากันได้กับเวอร์ชันเก่าที่ตรึงเวอร์ชันที่รองรับก่อนหน้านี้ เมื่อ RELEASE_AIDL_USE_UNFROZEN
มีค่าเป็น false
บริการจะมีลักษณะเหมือนเวอร์ชันที่ตรึงไว้ล่าสุดหรือก่อนหน้านี้เสมอ (ตัวอย่างเช่น การเรียกใช้เมธอดที่ไม่ได้ตรึงใหม่จะแสดงผล UNKNOWN_TRANSACTION
หรือฟิลด์ parcelable
ใหม่จะมีค่าเริ่มต้น) ไคลเอ็นต์เฟรมเวิร์ก Android จะต้องเข้ากันได้แบบย้อนหลังกับเวอร์ชันก่อนหน้าเพิ่มเติม แต่รายละเอียดนี้เป็นรายละเอียดใหม่สำหรับไคลเอ็นต์ของผู้ให้บริการและไคลเอ็นต์ของอินเทอร์เฟซที่พาร์ทเนอร์เป็นเจ้าของ
การเปลี่ยนแปลงการใช้ HAL
ความแตกต่างที่สําคัญที่สุดของการพัฒนา HAL กับการพัฒนาที่อิงตาม Flag คือต้องมีการติดตั้งใช้งาน HAL เพื่อความเข้ากันได้แบบย้อนหลังกับเวอร์ชันที่ตรึงไว้ล่าสุดเพื่อให้ทำงานได้เมื่อ RELEASE_AIDL_USE_UNFROZEN
คือ false
การพิจารณาความเข้ากันได้แบบย้อนหลังในการใช้งานและโค้ดของอุปกรณ์เป็นแบบฝึกหัดใหม่ โปรดดูหัวข้อใช้อินเทอร์เฟซ
ที่มีเวอร์ชัน
โดยทั่วไปแล้ว การพิจารณาความเข้ากันได้แบบย้อนหลังนั้นเหมือนกันสำหรับไคลเอ็นต์และเซิร์ฟเวอร์ และสำหรับโค้ดเฟรมเวิร์กและโค้ดของผู้ให้บริการ แต่มีความแตกต่างเล็กๆ น้อยๆ ที่คุณต้องทราบ เนื่องจากตอนนี้คุณกำลังใช้ 2 เวอร์ชันที่ใช้ซอร์สโค้ดเดียวกัน (เวอร์ชันปัจจุบันที่ไม่ได้ตรึงไว้) อย่างมีประสิทธิภาพ
ตัวอย่าง: อินเทอร์เฟซมีเวอร์ชันที่ตรึงไว้ 3 เวอร์ชัน อินเทอร์เฟซมีการอัปเดต
ด้วยวิธีการใหม่ ทั้งไคลเอ็นต์และบริการได้รับการอัปเดตให้ใช้ไลบรารีเวอร์ชันใหม่ 4 เนื่องจากไลบรารี V4 อิงตามอินเทอร์เฟซเวอร์ชันที่ไม่ได้ตรึงไว้ จึงมีลักษณะการทำงานเหมือนเวอร์ชัน 3 ที่ตรึงไว้ล่าสุดเมื่อ RELEASE_AIDL_USE_UNFROZEN
คือ false
และป้องกันไม่ให้ใช้วิธีการใหม่นี้
เมื่ออินเทอร์เฟซถูกระงับ ค่าทั้งหมดของ RELEASE_AIDL_USE_UNFROZEN
จะใช้เวอร์ชันที่ถูกตรึงไว้ และจะนำโค้ดที่จัดการความเข้ากันได้แบบย้อนหลังออกได้
เมื่อเรียกใช้เมธอดใน Callback คุณต้องจัดการเคสอย่างระมัดระวังเมื่อมีการแสดง UNKNOWN_TRANSACTION
ไคลเอ็นต์อาจใช้ Callback 2 เวอร์ชันที่ต่างกันตามการกำหนดค่ารุ่น คุณจึงสันนิษฐานว่าไคลเอ็นต์ส่งเวอร์ชันใหม่ล่าสุดไม่ได้ และเมธอดใหม่อาจแสดงผลแบบนี้ ซึ่งคล้ายกับวิธีที่ไคลเอ็นต์ AIDL เวอร์ชันเสถียรยังคงรักษาความสามารถในการใช้งานร่วมกันแบบย้อนหลังกับเซิร์ฟเวอร์ไว้ในหัวข้อใช้อินเทอร์เฟซที่มีเวอร์ชัน
// Get the callback along with the version of the callback
ScopedAStatus RegisterMyCallback(const std::shared_ptr<IMyCallback>& cb) override {
mMyCallback = cb;
// Get the version of the callback for later when we call methods on it
auto status = mMyCallback->getInterfaceVersion(&mMyCallbackVersion);
return status;
}
// Example of using the callback later
void NotifyCallbackLater() {
// From the latest frozen version (V2)
mMyCallback->foo();
// Call this method from the unfrozen V3 only if the callback is at least V3
if (mMyCallbackVersion >= 3) {
mMyCallback->bar();
}
}
ช่องใหม่ในประเภทที่มีอยู่ (parcelable
, enum
, union
) อาจไม่มีอยู่หรือมีค่าเริ่มต้นเมื่อ RELEASE_AIDL_USE_UNFROZEN
เป็น false
และค่าของช่องใหม่ที่บริการพยายามส่งจะถูกตัดออกขณะออกจากกระบวนการ
ประเภทใหม่ที่เพิ่มเข้ามาในเวอร์ชันที่ไม่ได้ตรึงไว้นี้จะไม่สามารถส่งหรือรับผ่านอินเทอร์เฟซได้
การติดตั้งใช้งานนี้ไม่ได้รับการเรียกเมธอดใหม่ๆ จากลูกค้าเมื่อ RELEASE_AIDL_USE_UNFROZEN
เท่ากับ false
โปรดใช้ตัวระบุใหม่เฉพาะกับเวอร์ชันที่เปิดตัวเท่านั้น ไม่ใช่เวอร์ชันก่อนหน้า
โดยปกติคุณจะใช้ foo->getInterfaceVersion()
เพื่อดูเวอร์ชันอินเทอร์เฟซระยะไกล อย่างไรก็ตาม การรองรับการกำหนดเวอร์ชันตามแฟล็กหมายความว่าคุณใช้งาน 2 เวอร์ชันที่แตกต่างกัน คุณจึงอาจต้องการรับเวอร์ชันของอินเทอร์เฟซปัจจุบัน ซึ่งทำได้โดยการรับเวอร์ชันอินเทอร์เฟซของออบเจ็กต์ปัจจุบัน เช่น this->getInterfaceVersion()
หรือวิธีอื่นๆ สำหรับ my_ver
ดูการค้นหาเวอร์ชันอินเทอร์เฟซของออบเจ็กต์ระยะไกล
สำหรับข้อมูลเพิ่มเติม
อินเทอร์เฟซ VINTF เวอร์ชันเสถียรใหม่
เมื่อเพิ่มแพ็กเกจอินเทอร์เฟซ AIDL ใหม่ จะไม่มีเวอร์ชันที่ตรึงไว้ล่าสุด จึงจะไม่มีลักษณะการทำงานที่จะกลับไปใช้เวลาที่ RELEASE_AIDL_USE_UNFROZEN
เป็น false
อย่าใช้อินเทอร์เฟซเหล่านี้ เมื่อ RELEASE_AIDL_USE_UNFROZEN
เป็น false
ผู้จัดการบริการจะไม่อนุญาตให้บริการลงทะเบียนอินเทอร์เฟซ
และลูกค้าจะหาอินเทอร์เฟซไม่พบ
คุณเพิ่มบริการแบบมีเงื่อนไขได้โดยอิงตามค่าของ Flag RELEASE_AIDL_USE_UNFROZEN
ในไฟล์บิลด์ของอุปกรณ์
ifeq ($(RELEASE_AIDL_USE_UNFROZEN),true)
PRODUCT_PACKAGES += \
android.hardware.health.storage-service
endif
หากบริการเป็นส่วนหนึ่งของกระบวนการที่ใหญ่กว่า คุณจึงเพิ่มบริการลงในอุปกรณ์อย่างมีเงื่อนไขไม่ได้ ให้ตรวจสอบเพื่อดูว่ามีการประกาศบริการด้วย IServiceManager::isDeclared()
หรือไม่ หากประกาศแล้วแต่ลงทะเบียนไม่สำเร็จ ให้ล้มเลิกกระบวนการ หากไม่ได้ประกาศไว้ การลงทะเบียนอาจล้มเหลว
หมึกกระดองเป็นเครื่องมือพัฒนา
ทุกปีหลังจากที่ VINTF หยุดทํางาน เราจะปรับเมทริกซ์ความเข้ากันได้ของเฟรมเวิร์ก (FCM) target-level
และ PRODUCT_SHIPPING_API_LEVEL
ของ Cuttlefish เพื่อแสดงอุปกรณ์ที่จะเปิดตัวพร้อมกับการเปิดตัวในปีหน้า เราปรับเปลี่ยน target-level
และ PRODUCT_SHIPPING_API_LEVEL
เพื่อให้มีอุปกรณ์บางรุ่นที่เปิดตัวที่ได้รับการทดสอบและเป็นไปตามข้อกำหนดใหม่สำหรับรุ่นปีหน้า
เมื่อ RELEASE_AIDL_USE_UNFROZEN
คือ true
ระบบจะใช้ Cuttlefish
เพื่อพัฒนา Android รุ่นต่อๆ ไป โดยกำหนดเป้าหมายเป็นระดับ FCM สำหรับการเปิดตัว Android ของปีหน้าและ PRODUCT_SHIPPING_API_LEVEL
ซึ่งกำหนดให้ต้องเป็นไปตามข้อกำหนดเกี่ยวกับซอฟต์แวร์ของผู้ให้บริการ (VSR) สำหรับรุ่นถัดไป
เมื่อ RELEASE_AIDL_USE_UNFROZEN
อายุ false
ปี Cuttlefish จะมีtarget-level
และPRODUCT_SHIPPING_API_LEVEL
ก่อนหน้าเพื่อแสดงอุปกรณ์ที่เปิดตัว
ใน Android 14 และต่ำกว่า การสร้างความแตกต่างนี้จะทำร่วมกับ Git ต่างๆ ที่ไม่ได้รับการเปลี่ยนแปลงไปยัง FCM, target-level
, ระดับ API การจัดส่ง หรือโค้ดอื่นๆ ที่กำหนดเป้าหมายไปยังรุ่นถัดไป
กฎการตั้งชื่อโมดูล
ใน Android 11 ระบบจะสร้างโมดูลไลบรารี Stub โดยอัตโนมัติสำหรับชุดค่าผสมของเวอร์ชันและแบ็กเอนด์ที่เปิดใช้แต่ละเวอร์ชัน หากต้องการอ้างอิงโมดูลไลบรารีต้นขั้วเฉพาะเพื่อการลิงก์ อย่าใช้ชื่อของโมดูล aidl_interface
แต่เป็นชื่อของโมดูลคลังสตับ ซึ่งก็คือ ifacename-version-backend โดยที่
ifacename
: ชื่อของโมดูลaidl_interface
version
เป็นอย่างใดอย่างหนึ่งVversion-number
สำหรับเวอร์ชันที่ตรึงไว้Vlatest-frozen-version-number + 1
สำหรับเวอร์ชันต้นๆ (ยังแข็ง)
backend
เป็นอย่างใดอย่างหนึ่งjava
สำหรับแบ็กเอนด์ Javacpp
สำหรับแบ็กเอนด์ C++ndk
หรือndk_platform
สำหรับแบ็กเอนด์ NDK ตัวเลือกแรกมีไว้สำหรับแอป ส่วนหลังจะใช้สำหรับการใช้งานแพลตฟอร์มจนถึง Android 13 ใน Android 13 ขึ้นไป โปรดใช้ndk
เท่านั้นrust
สำหรับแบ็กเอนด์ของ Rust
สมมติว่ามีโมดูลชื่อ foo และเวอร์ชันล่าสุดคือ 2 และรองรับทั้ง NDK และ C++ ในกรณีนี้ AIDL จะสร้างโมดูลต่อไปนี้
- อิงตามเวอร์ชัน 1
foo-V1-(java|cpp|ndk|ndk_platform|rust)
- อิงตามเวอร์ชัน 2 (เวอร์ชันที่เสถียรล่าสุด)
foo-V2-(java|cpp|ndk|ndk_platform|rust)
- ตามเวอร์ชันของข้อกำหนดในการให้บริการ
foo-V3-(java|cpp|ndk|ndk_platform|rust)
เทียบกับ Android 11
foo-backend
ซึ่งอ้างถึงเวอร์ชันเสถียรล่าสุด ได้กลายเป็นfoo-V2-backend
foo-unstable-backend
ซึ่งอ้างถึงเวอร์ชัน ToT จะกลายเป็นfoo-V3-backend
ชื่อไฟล์เอาต์พุตจะเหมือนกับชื่อโมดูลเสมอ
- จากเวอร์ชัน 1:
foo-V1-(cpp|ndk|ndk_platform|rust).so
- จากเวอร์ชัน 2:
foo-V2-(cpp|ndk|ndk_platform|rust).so
- ตามเวอร์ชันข้อกำหนดในการให้บริการ:
foo-V3-(cpp|ndk|ndk_platform|rust).so
โปรดทราบว่าคอมไพเลอร์ AIDL จะไม่สร้างโมดูลเวอร์ชัน unstable
หรือโมดูลที่ไม่มีเวอร์ชันสำหรับอินเทอร์เฟซ AIDL ที่เสถียร
ใน Android 12 ชื่อโมดูลที่สร้างจากอินเทอร์เฟซ AIDL ที่เสถียรจะมีเวอร์ชันเสมอ
วิธีการใหม่สำหรับอินเทอร์เฟซเมตา
Android 10 เพิ่มเมธอดอินเทอร์เฟซเมตาหลายวิธีสำหรับ AIDL เวอร์ชันเสถียร
ค้นหาเวอร์ชันอินเทอร์เฟซของออบเจ็กต์ระยะไกล
ไคลเอ็นต์สามารถค้นหาเวอร์ชันและแฮชของอินเทอร์เฟซที่ออบเจ็กต์ระยะไกลใช้งานอยู่ และเปรียบเทียบค่าที่แสดงผลกับค่าของอินเทอร์เฟซที่ไคลเอ็นต์ใช้อยู่
ตัวอย่างที่มีแบ็กเอนด์ cpp
sp<IFoo> foo = ... // the remote object
int32_t my_ver = IFoo::VERSION;
int32_t remote_ver = foo->getInterfaceVersion();
if (remote_ver < my_ver) {
// the remote side is using an older interface
}
std::string my_hash = IFoo::HASH;
std::string remote_hash = foo->getInterfaceHash();
ตัวอย่างที่มีแบ็กเอนด์ ndk
(และ ndk_platform
)
IFoo* foo = ... // the remote object
int32_t my_ver = IFoo::version;
int32_t remote_ver = 0;
if (foo->getInterfaceVersion(&remote_ver).isOk() && remote_ver < my_ver) {
// the remote side is using an older interface
}
std::string my_hash = IFoo::hash;
std::string remote_hash;
foo->getInterfaceHash(&remote_hash);
ตัวอย่างที่มีแบ็กเอนด์ java
IFoo foo = ... // the remote object
int myVer = IFoo.VERSION;
int remoteVer = foo.getInterfaceVersion();
if (remoteVer < myVer) {
// the remote side is using an older interface
}
String myHash = IFoo.HASH;
String remoteHash = foo.getInterfaceHash();
สำหรับภาษา Java ฝั่งระยะไกลต้องใช้ getInterfaceVersion()
และ getInterfaceHash()
ดังนี้ (ใช้ super
แทน IFoo
เพื่อหลีกเลี่ยงข้อผิดพลาดในการคัดลอกและวาง อาจต้องใช้คำอธิบายประกอบ @SuppressWarnings("static")
เพื่อปิดใช้คำเตือน ทั้งนี้ขึ้นอยู่กับการกำหนดค่า javac
) ดังนี้
class MyFoo extends IFoo.Stub {
@Override
public final int getInterfaceVersion() { return super.VERSION; }
@Override
public final String getInterfaceHash() { return super.HASH; }
}
นั่นเป็นเพราะระบบแชร์คลาสที่สร้างขึ้น (IFoo
, IFoo.Stub
ฯลฯ) ระหว่างไคลเอ็นต์และเซิร์ฟเวอร์ (เช่น คลาสอาจอยู่ใน Bootclasspath) เมื่อมีการแชร์ชั้นเรียน เซิร์ฟเวอร์จะลิงก์กับชั้นเรียนเวอร์ชันล่าสุดด้วย แม้ว่าระบบอาจสร้างด้วยอินเทอร์เฟซเวอร์ชันเก่าก็ตาม หากใช้อินเทอร์เฟซเมตานี้ในชั้นเรียนที่แชร์ อินเทอร์เฟซเมตาก็จะเป็นเวอร์ชันล่าสุดเสมอ แต่ด้วยการใช้วิธีการดังกล่าวข้างต้น หมายเลขเวอร์ชันของอินเทอร์เฟซจะฝังอยู่ในโค้ดของเซิร์ฟเวอร์ (เนื่องจาก IFoo.VERSION
เป็น static final int
ที่มีการแทรกในบรรทัดเมื่อมีการอ้างอิง) วิธีนี้จึงแสดงเวอร์ชันเดียวกับที่เซิร์ฟเวอร์สร้างขึ้นได้
จัดการกับอินเทอร์เฟซรุ่นเก่า
เป็นไปได้ว่าไคลเอ็นต์จะได้รับการอัปเดตด้วยอินเทอร์เฟซ AIDL เวอร์ชันใหม่ แต่เซิร์ฟเวอร์ใช้อินเทอร์เฟซ AIDL แบบเก่า ในกรณีดังกล่าว การเรียกใช้เมธอดในอินเทอร์เฟซเก่าจะส่งคืนค่า UNKNOWN_TRANSACTION
เมื่อใช้ AIDL เวอร์ชันเสถียร ไคลเอ็นต์จะควบคุมสิ่งต่างๆ ได้มากขึ้น ในฝั่งไคลเอ็นต์ คุณสามารถตั้งค่าการใช้งานเริ่มต้นให้กับอินเทอร์เฟซ AIDL ระบบจะเรียกใช้เมธอดในการติดตั้งใช้งานเริ่มต้นเฉพาะเมื่อไม่มีการติดตั้งใช้งานเมธอดดังกล่าวในด้านระยะไกล (เนื่องจากสร้างขึ้นด้วยอินเทอร์เฟซเวอร์ชันเก่า) เนื่องจากค่าเริ่มต้นได้รับการตั้งค่าไว้ทั่วโลก จึงไม่ควรใช้ค่าเริ่มต้นจากบริบทที่อาจมีการแชร์
ตัวอย่างใน C++ ใน Android 13 ขึ้นไป
class MyDefault : public IFooDefault {
Status anAddedMethod(...) {
// do something default
}
};
// once per an interface in a process
IFoo::setDefaultImpl(::android::sp<MyDefault>::make());
foo->anAddedMethod(...); // MyDefault::anAddedMethod() will be called if the
// remote side is not implementing it
ตัวอย่างใน Java
IFoo.Stub.setDefaultImpl(new IFoo.Default() {
@Override
public xxx anAddedMethod(...) throws RemoteException {
// do something default
}
}); // once per an interface in a process
foo.anAddedMethod(...);
คุณไม่จำเป็นต้องติดตั้งใช้งานเริ่มต้นของเมธอดทั้งหมดในอินเทอร์เฟซ AIDL เมธอดที่รับประกันว่าจะใช้งานในด้านระยะไกล
(เนื่องจากคุณมั่นใจว่ารีโมตสร้างขึ้นเมื่อเมธอดอยู่ในคำอธิบายอินเทอร์เฟซ AIDL) ไม่จำเป็นต้องลบล้างในคลาส impl
เริ่มต้น
แปลง AIDL ที่มีอยู่เป็น AIDL ที่มีโครงสร้างหรือเสถียร
หากคุณมีอินเทอร์เฟซ AIDL และโค้ดที่ใช้อินเทอร์เฟซดังกล่าวอยู่แล้ว ให้ใช้ขั้นตอนต่อไปนี้เพื่อแปลงอินเทอร์เฟซเป็นอินเทอร์เฟซ AIDL เวอร์ชันเสถียร
ระบุทรัพยากร Dependency ทั้งหมดในอินเทอร์เฟซ สำหรับทุกแพ็กเกจที่อินเทอร์เฟซจะใช้อยู่ ให้พิจารณาว่าแพ็กเกจนั้นได้รับการกำหนดใน AIDL แบบคงที่หรือไม่ หากไม่ได้กำหนด ต้องแปลงแพ็กเกจ
แปลง Parcelable ทั้งหมดในอินเทอร์เฟซให้เป็น Parcelable ที่เสถียร (ตัวไฟล์อินเทอร์เฟซจะไม่มีการเปลี่ยนแปลง) โดยการแสดงโครงสร้างของผู้ใช้โดยตรงในไฟล์ AIDL ชั้นเรียนการจัดการจึงต้องเขียนใหม่ เพื่อใช้ประเภทใหม่เหล่านี้ ซึ่งทำได้ก่อนสร้างแพ็กเกจ
aidl_interface
(ด้านล่าง)สร้างแพ็กเกจ
aidl_interface
(ตามที่อธิบายไว้ข้างต้น) ที่มีชื่อโมดูล ทรัพยากร Dependency และข้อมูลอื่นๆ ที่คุณต้องการ นอกจากนี้ ยังต้องมีเวอร์ชันเพื่อให้มีความเสถียร (ไม่ใช่แค่มีโครงสร้าง) ด้วย ดูข้อมูลเพิ่มเติมได้ที่การกำหนดเวอร์ชันอินเทอร์เฟซ