Android 10 เพิ่มการรองรับภาษาคำจำกัดความอินเทอร์เฟซ Android (AIDL) ที่เสถียร ซึ่งเป็นวิธีใหม่ในการตรวจสอบ Application Programming Interface (API) และ Application Binary Interface (ABI) ที่อินเทอร์เฟซ AIDL ระบุ AIDL เวอร์ชันเสถียรทํางานเหมือนกับ AIDL ทุกประการ แต่ระบบบิลด์จะติดตามความเข้ากันได้ของอินเทอร์เฟซ และมีข้อจํากัดในสิ่งที่คุณทําได้ ดังนี้
- อินเทอร์เฟซจะกำหนดไว้ในระบบบิลด์ด้วย
aidl_interfaces
- อินเทอร์เฟซมีได้เฉพาะ Structured Data เท่านั้น ระบบจะสร้าง Parcelable ที่แสดงถึงประเภทที่ต้องการโดยอัตโนมัติตามคำจำกัดความ AIDL และจะทำการจัดเรียงและการจัดเรียงใหม่โดยอัตโนมัติ
- อินเทอร์เฟซสามารถประกาศว่าเสถียร (เข้ากันได้แบบย้อนหลัง) เมื่อเกิดกรณีนี้ ระบบจะติดตามและกำหนดเวอร์ชัน API ไว้ในไฟล์ข้างอินเทอร์เฟซ AIDL
AIDL แบบมีโครงสร้างกับแบบเสถียร
AIDL ที่มีโครงสร้างหมายถึงประเภทที่กำหนดไว้ใน AIDL เพียงอย่างเดียว เช่น การประกาศที่แยกย่อยได้ (การแยกย่อยที่กําหนดเอง) ไม่ใช่ AIDL ที่มีโครงสร้าง Parcelable ที่มีการกำหนดช่องใน AIDL จะเรียกว่า Structured Parcelable
AIDL เวอร์ชันเสถียรต้องใช้ AIDL ที่มีโครงสร้างเพื่อให้ระบบบิลด์และคอมไพเลอร์เข้าใจว่าการเปลี่ยนแปลงที่ทำกับพาร์เซลนั้นเข้ากันได้แบบย้อนหลังหรือไม่
อย่างไรก็ตาม อินเทอร์เฟซที่มีโครงสร้างบางรายการอาจไม่เสถียร อินเทอร์เฟซต้องใช้เฉพาะ Structured Type และต้องใช้ฟีเจอร์การจัดรุ่นต่อไปนี้ด้วยจึงจะทำงานได้อย่างเสถียร ในทางกลับกัน อินเทอร์เฟซจะไม่เสถียรหากใช้ระบบบิลด์หลักเพื่อสร้างหรือหากตั้งค่า 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 รายการใดรายการหนึ่งใช้อินเทอร์เฟซหรือ Parcelable จากaidl_interface
รายการอื่น ให้ใส่ชื่อของอินเทอร์เฟซนั้นที่นี่ ซึ่งอาจเป็นชื่อเพียงอย่างเดียวเพื่ออ้างอิงถึงเวอร์ชันล่าสุด หรือชื่อที่มีส่วนต่อท้ายเวอร์ชัน (เช่น-V1
) เพื่ออ้างอิงถึงเวอร์ชันที่เฉพาะเจาะจง ระบบรองรับการระบุเวอร์ชันตั้งแต่ Android 12versions
: อินเทอร์เฟซเวอร์ชันก่อนหน้าที่ตรึงไว้ภายใต้api_dir
ตั้งแต่ Android 11 เป็นต้นไปversions
จะตรึงชั่วคราวอยู่ภายใต้aidl_api/name
หากไม่มีเวอร์ชันใดที่หยุดนิ่งของอินเทอร์เฟซ ก็ไม่ควรระบุไว้ และจะไม่มีการตรวจสอบความเข้ากันได้ ช่องนี้มีการแทนที่ด้วยversions_with_info
สำหรับ Android 13 ขึ้นไปversions_with_info
: รายการทูเพลตแต่ละรายการมีชื่อของเวอร์ชันที่หยุดทำงานและรายการที่มีการนําเข้าเวอร์ชันของโมดูล aidl_interface อื่นๆ ที่ aidl_interface เวอร์ชันนี้นําเข้า คําจํากัดความของเวอร์ชัน V ของอินเทอร์เฟซ AIDL IFACE อยู่ที่aidl_api/IFACE/V
ช่องนี้เปิดตัวใน Android 13 และไม่ควรแก้ไขในAndroid.bp
โดยตรง ระบบจะเพิ่มหรืออัปเดตช่องโดยการเรียกใช้*-update-api
หรือ*-freeze-api
นอกจากนี้ ระบบจะย้ายข้อมูลช่องversions
ไปยังversions_with_info
โดยอัตโนมัติเมื่อผู้ใช้เรียกใช้*-update-api
หรือ*-freeze-api
stability
: Flag ไม่บังคับสำหรับสัญญาความเสถียรของอินเทอร์เฟซนี้ การดำเนินการนี้รองรับเฉพาะ"vintf"
หากไม่ได้ตั้งค่าstability
ไว้ ระบบบิลด์จะตรวจสอบว่าอินเทอร์เฟซสามารถใช้งานร่วมกันได้แบบย้อนหลัง เว้นแต่จะมีการระบุunstable
ไว้ การตั้งค่าเป็น "ไม่ตั้งค่า" สอดคล้องกับอินเทอร์เฟซที่มีความเสถียรภายในบริบทการคอมไพล์นี้ (ดังนั้น สิ่งต่างๆ ทั้งหมดของระบบ เช่น สิ่งต่างๆ ในsystem.img
และพาร์ติชันที่เกี่ยวข้อง หรือสิ่งต่างๆ ทั้งหมดของผู้ให้บริการ เช่น สิ่งต่างๆ ในvendor.img
และพาร์ติชันที่เกี่ยวข้อง) หากตั้งค่าstability
เป็น"vintf"
แสดงว่าสอดคล้องกับสัญญาความเสถียร ซึ่งหมายความว่าอินเทอร์เฟซต้องมีความเสถียรตราบใดที่มีการใช้งานgen_trace
: แฟล็กที่ไม่บังคับสำหรับเปิดหรือปิดการติดตาม โดยตั้งแต่ Android 14 เป็นต้นไป ค่าเริ่มต้นคือtrue
สำหรับแบ็กเอนด์cpp
และjava
host_supported
: Flag ไม่บังคับซึ่งเมื่อตั้งค่าเป็นtrue
จะทำให้ไลบรารีที่สร้างขึ้นพร้อมใช้งานสำหรับสภาพแวดล้อมโฮสต์unstable
: Flag ที่ไม่บังคับซึ่งใช้ทำเครื่องหมายว่าอินเทอร์เฟซนี้ไม่จำเป็นต้องเสถียร เมื่อตั้งค่าเป็นtrue
ระบบบิลด์จะไม่สร้างการดัมพ์ API สําหรับอินเทอร์เฟซหรือกําหนดให้อัปเดตfrozen
: แฟล็กที่ไม่บังคับซึ่งเมื่อตั้งค่าเป็นtrue
หมายความว่าอินเทอร์เฟซไม่มีการเปลี่ยนแปลงนับตั้งแต่อินเทอร์เฟซเวอร์ชันก่อนหน้า ซึ่งจะทำให้มีการตรวจสอบเวลาบิลด์มากยิ่งขึ้น เมื่อตั้งค่าเป็นfalse
หมายความว่าอินเทอร์เฟซอยู่ระหว่างการพัฒนาและมีการเปลี่ยนแปลงใหม่ ดังนั้นการเรียกใช้foo-freeze-api
จะสร้างเวอร์ชันใหม่และเปลี่ยนค่าเป็นtrue
โดยอัตโนมัติ เปิดตัวใน Android 14backend.<type>.enabled
: Flag เหล่านี้จะเปิด/ปิดแบ็กเอนด์แต่ละรายการที่คอมไพเลอร์ AIDL สร้างขึ้น ระบบรองรับแบ็กเอนด์ 4 รายการ ได้แก่ Java, C++, NDK และ Rust แบ็กเอนด์ Java, C++ และ NDK จะเปิดใช้โดยค่าเริ่มต้น หากไม่จำเป็นต้องใช้แบ็กเอนด์ใดเลย จะต้องปิดใช้แบ็กเอนด์นั้นอย่างชัดเจน ระบบจะปิดใช้ Rust โดยค่าเริ่มต้นจนกว่า Android 15 จะพร้อมให้บริการbackend.<type>.apex_available
: รายการชื่อ APEX ที่ไลบรารีสแต็บที่สร้างขึ้นใช้ได้backend.[cpp|java].gen_log
: Flag ไม่บังคับที่ใช้ควบคุมว่าจะสร้างโค้ดเพิ่มเติมเพื่อรวบรวมข้อมูลเกี่ยวกับธุรกรรมหรือไม่backend.[cpp|java].vndk.enabled
: Flag ที่ไม่บังคับเพื่อทำให้อินเทอร์เฟซนี้เป็นส่วนหนึ่งของ VNDK ค่าเริ่มต้นคือfalse
backend.[cpp|ndk].additional_shared_libraries
: เปิดตัวใน Android 14 โดย Flag นี้จะเพิ่มการพึ่งพาไปยังไลบรารีแบบเนทีฟ ธงนี้มีประโยชน์กับ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 สำหรับแบ็กเอนด์ที่เจาะจงได้ที่กฎการตั้งชื่อโมดูล
เขียนไฟล์ AIDL
อินเทอร์เฟซใน AIDL ที่เสถียรจะคล้ายกับอินเทอร์เฟซแบบดั้งเดิม ยกเว้นว่าไม่อนุญาตให้ใช้ Parcelable ที่ไม่มีโครงสร้าง (เนื่องจากไม่เสถียร โปรดดูAIDL แบบมีโครงสร้างเทียบกับ AIDL ที่เสถียร) ความแตกต่างหลักๆ ใน AIDL ที่เสถียรคือวิธีกำหนดพัสดุ ก่อนหน้านี้ Parcelable มีการประกาศล่วงหน้า แต่ใน AIDL เวอร์ชันเสถียร (และเป็นแบบ Structured) ฟิลด์และตัวแปร Parcelable จะได้รับการกําหนดไว้อย่างชัดเจน
// 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 ก็ตาม
ใช้ไลบรารีสแต็บ
หลังจากเพิ่มไลบรารีสแต็บเป็นข้อกำหนดของโมดูลแล้ว คุณจะรวมไลบรารีเหล่านั้นไว้ในไฟล์ได้ ตัวอย่างไลบรารีสแต็บในระบบบิลด์มีดังนี้ (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
เจ้าของสามารถเพิ่มรายการต่อไปนี้ได้เพื่อรักษาเสถียรภาพของอินเทอร์เฟซ
- เมธอดที่อยู่ที่ส่วนท้ายของอินเทอร์เฟซ (หรือเมธอดที่มีนิพจน์ใหม่ซึ่งระบุไว้อย่างชัดเจน)
- องค์ประกอบที่ท้ายของ Parcelable (ต้องเพิ่มค่าเริ่มต้นสำหรับแต่ละองค์ประกอบ)
- ค่าคงที่
- ใน 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
backend ได้รับSTATUS_UNKNOWN_TRANSACTION
- แบ็กเอนด์
java
ได้รับandroid.os.RemoteException
พร้อมข้อความว่าไม่ได้ติดตั้งใช้งาน API
ดูกลยุทธ์ในการจัดการปัญหานี้ได้ที่หัวข้อการค้นหาเวอร์ชันและการใช้ค่าเริ่มต้น
พาร์เซล
เมื่อมีการเพิ่มช่องใหม่ลงในพาร์เซล ไคลเอ็นต์และเซิร์ฟเวอร์เก่าจะทิ้งช่องนั้นไป เมื่อไคลเอ็นต์และเซิร์ฟเวอร์ใหม่ได้รับพาร์เซลที่เก่า ระบบจะป้อนค่าเริ่มต้นสำหรับช่องใหม่โดยอัตโนมัติ ซึ่งหมายความว่าต้องระบุค่าเริ่มต้นสำหรับช่องใหม่ทั้งหมดใน Parcelable
ลูกค้าไม่ควรคาดหวังว่าเซิร์ฟเวอร์จะใช้ช่องใหม่ เว้นแต่ว่าลูกค้าจะทราบว่าเซิร์ฟเวอร์กำลังใช้งานเวอร์ชันที่มีการกําหนดช่อง (ดูการค้นหาเวอร์ชัน)
ค่าแจกแจงและค่าคงที่
ในทํานองเดียวกัน ไคลเอ็นต์และเซิร์ฟเวอร์ควรปฏิเสธหรือเพิกเฉยต่อค่าคงที่ที่ไม่รู้จักและตัวแจกแจงตามความเหมาะสม เนื่องจากอาจมีการเพิ่มเข้ามาในอนาคต เช่น เซิร์ฟเวอร์ไม่ควรหยุดดำเนินการเมื่อได้รับตัวนับที่ไม่ทราบ เซิร์ฟเวอร์ควรละเว้นตัวนับ หรือแสดงผลบางอย่างเพื่อให้ไคลเอ็นต์ทราบว่าการใช้งานนี้ไม่รองรับ
สหภาพแรงงาน
การพยายามส่งการรวมที่มีช่องใหม่จะล้มเหลวหากผู้รับเป็นรุ่นเก่าและไม่ทราบข้อมูลเกี่ยวกับช่องนั้น การใช้งานจะไม่เห็นการรวมช่องใหม่ ระบบจะไม่สนใจความล้มเหลวหากเป็นธุรกรรมแบบทางเดียว มิฉะนั้นข้อผิดพลาดคือ BAD_VALUE
(สําหรับแบ็กเอนด์ C++ หรือ NDK) หรือ IllegalArgumentException
(สําหรับแบ็กเอนด์ Java) ระบบจะได้รับข้อผิดพลาดหากไคลเอ็นต์ส่งชุดการรวมข้อมูลไปยังฟิลด์ใหม่ไปยังเซิร์ฟเวอร์เก่า หรือเมื่อไคลเอ็นต์เป็นไคลเอ็นต์เก่าที่ได้รับการรวมดังกล่าวจากเซิร์ฟเวอร์ใหม่
จัดการหลายเวอร์ชัน
เนมสเปซ Linker ใน Android มีอินเทอร์เฟซ aidl
ที่เฉพาะเจาะจงได้เพียง 1 เวอร์ชันเท่านั้น เพื่อหลีกเลี่ยงสถานการณ์ที่ประเภท aidl
ที่สร้างขึ้นมีคำจำกัดความหลายรายการ C++ มีกฎคำจำกัดความเดียวที่กำหนดให้มีคำจำกัดความของสัญลักษณ์แต่ละรายการเพียงรายการเดียว
บิลด์ Android จะแสดงข้อผิดพลาดเมื่อโมดูลใช้aidl_interface
คลังเดียวกันในเวอร์ชันที่แตกต่างกัน โมดูลอาจขึ้นต่อกันกับไลบรารีเหล่านี้โดยตรงหรือโดยอ้อมผ่านทรัพยากร Dependency ของไลบรารีเหล่านั้น ข้อผิดพลาดเหล่านี้แสดงกราฟทรัพยากร Dependency จากโมดูลที่ล้มเหลวไปยังไลบรารี aidl_interface
เวอร์ชันที่ขัดแย้งกัน คุณต้องอัปเดตไลบรารีทั้งหมดที่ใช้ร่วมกันให้ใช้เวอร์ชันเดียวกัน (โดยปกติจะเป็นเวอร์ชันล่าสุด)
หากมีการใช้ไลบรารีอินเทอร์เฟซโดยโมดูลต่างๆ หลายรายการ คุณอาจต้องสร้าง cc_defaults
, java_defaults
และ rust_defaults
สำหรับกลุ่มไลบรารีและกระบวนการที่ต้องใช้เวอร์ชันเดียวกัน เมื่อเริ่มใช้อินเทอร์เฟซเวอร์ชันใหม่ คุณจะอัปเดตค่าเริ่มต้นเหล่านั้นได้และโมดูลทั้งหมดที่ใช้อินเทอร์เฟซเหล่านั้นได้รับการอัปเดตพร้อมกันเพื่อให้มั่นใจว่าไม่ได้ใช้อินเทอร์เฟซเวอร์ชันอื่น
cc_defaults {
name: "my.aidl.my-process-group-ndk-shared",
shared_libs: ["my.aidl-V3-ndk"],
...
}
cc_library {
name: "foo",
defaults: ["my.aidl.my-process-group-ndk-shared"],
...
}
cc_binary {
name: "bar",
defaults: ["my.aidl.my-process-group-ndk-shared"],
...
}
เมื่อโมดูล aidl_interface
นําเข้าโมดูล aidl_interface
อื่นๆ การดำเนินการนี้จะสร้างข้อกําหนดเพิ่มเติมที่ต้องใช้เวอร์ชันที่เฉพาะเจาะจงร่วมกัน สถานการณ์นี้อาจจัดการได้ยากเมื่อมีaidl_interface
โมดูลทั่วไปที่นําเข้าในaidl_interface
โมดูลหลายรายการที่ใช้ร่วมกันในกระบวนการเดียวกัน
aidl_interfaces_defaults
สามารถใช้เพื่อเก็บคำจำกัดความของข้อกำหนดเวอร์ชันล่าสุดสำหรับ aidl_interface
ไว้ 1 รายการ ซึ่งอัปเดตได้ในที่เดียว และโมดูล aidl_interface
ทั้งหมดที่ต้องการนำเข้าอินเทอร์เฟซทั่วไปนั้นจะใช้ได้
aidl_interface_defaults {
name: "android.popular.common-latest-defaults",
imports: ["android.popular.common-V3"],
...
}
aidl_interface {
name: "android.foo",
defaults: ["my.aidl.latest-ndk-shared"],
...
}
aidl_interface {
name: "android.bar",
defaults: ["my.aidl.latest-ndk-shared"],
...
}
การพัฒนาตามธง
อินเทอร์เฟซเวอร์ชันที่พัฒนาอยู่ (ไม่ได้หยุดทำงานชั่วคราว) จะใช้กับอุปกรณ์รุ่นต่างๆ ไม่ได้เนื่องจากไม่มีการรับประกันว่าจะใช้งานร่วมกันได้ย้อนหลัง
AIDL รองรับการสำรองรันไทม์สำหรับไลบรารีอินเทอร์เฟซที่เลิกตรึงเหล่านี้เพื่อให้เขียนโค้ดกับเวอร์ชันล่าสุดที่เลิกตรึงและยังคงใช้งานได้ในอุปกรณ์รุ่นที่เผยแพร่ ลักษณะการทำงานที่เข้ากันได้แบบย้อนหลังของไคลเอ็นต์จะคล้ายกับลักษณะการทำงานที่มีอยู่ และการใช้ฟีเจอร์สำรองยังต้องเป็นไปตามลักษณะการทำงานเหล่านั้นด้วย ดูหัวข้อใช้อินเทอร์เฟซเวอร์ชัน
Flag การสร้าง AIDL
Flag ที่ควบคุมลักษณะการทำงานนี้มี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 จะมีการเปลี่ยนแปลง 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
อย่างเหมาะสม ไคลเอ็นต์อาจใช้การเรียกกลับ 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()
เพื่อดูว่าอินเทอร์เฟซระยะไกลใช้เวอร์ชันใด อย่างไรก็ตาม เมื่อใช้การรองรับการแยกเวอร์ชันตาม Flag คุณจะใช้งาน 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 ระดับ PRODUCT_SHIPPING_API_LEVEL
ของ Android รุ่นปีหน้า โดยต้องเป็นไปตามข้อกำหนดซอฟต์แวร์ของผู้ให้บริการ (VSR) ของรุ่นถัดไป
เมื่อ RELEASE_AIDL_USE_UNFROZEN
เป็น false
หมายความว่า Cuttlefish มี target-level
และ PRODUCT_SHIPPING_API_LEVEL
ก่อนหน้าเพื่อแสดงอุปกรณ์รุ่น
ใน Android 14 และต่ำกว่า การแยกความแตกต่างนี้จะทำได้โดยใช้สาขา Git ที่แตกต่างกันซึ่งไม่รับการเปลี่ยนแปลง FCMtarget-level
, ระดับ API ที่ใช้งานจริง หรือโค้ดอื่นๆ ที่กําหนดเป้าหมายเป็นรุ่นถัดไป
กฎการตั้งชื่อโมดูล
ใน Android 11 ระบบจะสร้างโมดูลไลบรารี Stub ขึ้นโดยอัตโนมัติสําหรับชุดค่าผสมของเวอร์ชันและแบ็กเอนด์ที่เปิดใช้แต่ละเวอร์ชัน หากต้องการอ้างอิงโมดูลไลบรารี 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)
- อิงตามเวอร์ชัน ToT
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
- อิงตามเวอร์ชัน ToT:
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
ฯลฯ) จะแชร์ระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์ (เช่น คลาสอาจอยู่ในบูตแพตช์) เมื่อแชร์ชั้นเรียน เซิร์ฟเวอร์จะลิงก์กับชั้นเรียนเวอร์ชันล่าสุดด้วย แม้ว่าชั้นเรียนนั้นจะสร้างขึ้นด้วยอินเทอร์เฟซเวอร์ชันเก่าก็ตาม หากใช้อินเทอร์เฟซเมตานี้ในชั้นเรียนที่แชร์ อินเทอร์เฟซเมตาก็จะเป็นเวอร์ชันล่าสุดเสมอ อย่างไรก็ตาม เมื่อใช้เมธอดดังกล่าวข้างต้น ระบบจะฝังหมายเลขเวอร์ชันของอินเทอร์เฟซไว้ในโค้ดของเซิร์ฟเวอร์ (เนื่องจาก 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 และข้อมูลอื่นๆ ที่คุณต้องการ เนื้อหาต้องได้รับการจัดทําเวอร์ชันด้วยเพื่อให้มีเสถียรภาพ (ไม่ใช่แค่มีโครงสร้าง) ดูข้อมูลเพิ่มเติมได้ที่การกำหนดเวอร์ชันอินเทอร์เฟซ