Android 10 में, Android 10 के साथ अच्छे से काम करने वाले Android इंटरफ़ेस की डेफ़िनिशन लैंग्वेज (एआईडीएल) काम करती है. यह एआईडीएल इंटरफ़ेस से मिले ऐप्लिकेशन प्रोग्राम इंटरफ़ेस (एपीआई) और ऐप्लिकेशन बाइनरी इंटरफ़ेस (एबीआई) को ट्रैक करने का एक नया तरीका है. स्थिर एआईडीएल और एआईडीएल में ये मुख्य अंतर हैं:
- इंटरफ़ेस को बिल्ड सिस्टम में
aidl_interfaces
के साथ तय किया जाता है. - इंटरफ़ेस में सिर्फ़ स्ट्रक्चर्ड डेटा हो सकता है. पसंदीदा टाइप को दिखाने वाले पार्सल, एआईडीएल की परिभाषा के आधार पर अपने-आप बन जाते हैं. साथ ही, वे अपने-आप मार्शल और अनमार्शल हो जाते हैं.
- इंटरफ़ेस को स्टेबल (पुराने वर्शन के साथ काम करने वाले) के तौर पर बताया जा सकता है. ऐसा होने पर, उनके एपीआई को ट्रैक किया जाता है और एआईडीएल इंटरफ़ेस के बगल में मौजूद फ़ाइल में उसका वर्शन बनाया जाता है.
स्ट्रक्चर्ड बनाम स्टेबल एआईडीएल
स्ट्रक्चर्ड एआईडीएल का मतलब ऐसे टाइप से है जिन्हें पूरी तरह से एआईडीएल में बताया गया है. उदाहरण के लिए, पार्स किए जा सकने वाले एलान (पसंद के मुताबिक पार्स किया जा सकने वाला) का एआईडीएल स्ट्रक्चर्ड डेटा इस्तेमाल नहीं किया जा सकता. एआईडीएल में तय किए गए फ़ील्ड वाले पार्स किए जा सकने वाले पार्सल को स्ट्रक्चर्ड पार्सल कहा जाता है.
स्टेबल एआईडीएल को स्ट्रक्चर्ड एआईडीएल की ज़रूरत होती है, ताकि बिल्ड सिस्टम और कंपाइलर यह समझ सकें कि पार्स किए जा सकने वाले कोड में किए गए बदलाव पुराने सिस्टम के साथ काम करते हैं या नहीं.
हालांकि, सभी स्ट्रक्चर्ड इंटरफ़ेस स्टेबल नहीं होते. स्थिर रहने के लिए, इंटरफ़ेस में सिर्फ़ स्ट्रक्चर्ड टाइप का इस्तेमाल होना चाहिए. साथ ही, इसमें नीचे दी गई वर्शन की सुविधाओं का भी इस्तेमाल होना चाहिए. इसके उलट, अगर किसी इंटरफ़ेस को बनाने के लिए मुख्य बिल्ड सिस्टम का इस्तेमाल किया गया है या unstable:true
सेट है, तो वह स्थिर नहीं होता.
एआईडीएल इंटरफ़ेस तय करना
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
: एआईडीएल इंटरफ़ेस मॉड्यूल का नाम, जो किसी एआईडीएल इंटरफ़ेस की खास तौर पर पहचान करता है.srcs
: इंटरफ़ेस बनाने वाली AIDL सोर्स फ़ाइलों की सूची.com.acme
पैकेज में बताए गए AIDL टाइपFoo
का पाथ,<base_path>/com/acme/Foo.aidl
पर होना चाहिए. यहां<base_path>
,Android.bp
वाली डायरेक्ट्री से जुड़ी कोई भी डायरेक्ट्री हो सकती है. पिछले उदाहरण में,<base_path>
,srcs/aidl
है.local_include_dir
: वह पाथ जहां से पैकेज का नाम शुरू होता है. यह ऊपर बताए गए<base_path>
के मुताबिक है.imports
:aidl_interface
मॉड्यूल की सूची जिनका यह इस्तेमाल किया जाता है. अगर आपके किसी एआईडीएल इंटरफ़ेस में ऐसे इंटरफ़ेस का इस्तेमाल किया जाता है जिसे दूसरेaidl_interface
से पार्स किया जा सकता है, तो उसका नाम यहां डालें. नए वर्शन के बारे में बताने के लिए, यह नाम हो सकता है. इसके अलावा, किसी खास वर्शन के बारे में बताने के लिए, वर्शन के सफ़िक्स (जैसे कि-V1
) का नाम भी हो सकता है. यह तय करना कि Android 12 और इसके बाद के वर्शन का इस्तेमाल किया जा रहा है या नहींversions
: इंटरफ़ेस के पिछले वर्शन जोapi_dir
में फ़्रीज़ किए गए हैं और Android 11 की शुरुआत से,versions
कोaidl_api/name
में फ़्रीज़ किया गया है. अगर किसी इंटरफ़ेस का कोई फ़्रोज़न वर्शन नहीं है, तो इसे बताना नहीं चाहिए. साथ ही, इसके काम करने के तरीके की जांच भी नहीं की जाएगी. इस फ़ील्ड को Android 13 और उसके बाद के वर्शन के लिए,versions_with_info
से बदल दिया गया है.versions_with_info
: टुपल की सूची, जिसमें हर एक में फ़्रीज़ किए गए वर्शन का नाम होता है. साथ ही, एक सूची भी होती है, जिसमें aidl_interface के इस वर्शन से इंपोर्ट किए गए अन्य aidl_interface मॉड्यूल के वर्शन की जानकारी होती है. AIDL इंटरफ़ेस IFACE के वर्शन V की परिभाषाaidl_api/IFACE/V
पर दी गई है. यह फ़ील्ड Android 13 में लॉन्च किया गया था. इसमें सीधे तौर परAndroid.bp
में बदलाव नहीं किया जाना चाहिए था.*-update-api
या*-freeze-api
को चालू करके, इस फ़ील्ड को जोड़ा या अपडेट किया जाता है. साथ ही, जब कोई उपयोगकर्ता*-update-api
या*-freeze-api
शुरू करता है, तोversions
फ़ील्ड अपने-आपversions_with_info
पर माइग्रेट हो जाते हैं.stability
: इस इंटरफ़ेस की स्थिरता का वादा करने के लिए वैकल्पिक फ़्लैग. यह सिर्फ़"vintf"
के साथ काम करता है. अगरstability
सेट नहीं है, तो बिल्ड सिस्टम यह जांच करता है कि इंटरफ़ेस पुराने सिस्टम के साथ काम करता है या नहीं. ऐसा तब तक होगा, जब तकunstable
सेट नहीं किया गया हो. अगर नीति को सेट नहीं किया जाता है, तो यह इस कंपाइलेशन कॉन्टेक्स्ट में स्थिरता वाले इंटरफ़ेस से मेल खाता है. (इसलिए, सिस्टम की सभी चीज़ें, जैसे किsystem.img
की चीज़ें और इससे जुड़े पार्टिशन या सभी वेंडर चीज़ें, जैसे किvendor.img
और मिलते-जुलते सेगमेंट में मौजूद चीज़ें). अगरstability
को"vintf"
पर सेट किया गया है, तो इसका मतलब है कि स्थिरता प्रॉमिस: जब तक इंटरफ़ेस का इस्तेमाल किया जाता है, तब तक उसे स्थिर रखना चाहिए.gen_trace
: ट्रेस करने की सुविधा को चालू या बंद करने के लिए, वैकल्पिक फ़्लैग. Android 14 से,cpp
औरjava
बैकएंड के लिए डिफ़ॉल्ट तौर परtrue
है.host_supported
: यह वैकल्पिक फ़्लैगtrue
पर सेट करने से, जनरेट की गई लाइब्रेरी को होस्ट एनवायरमेंट के लिए उपलब्ध कराता है.unstable
: वह वैकल्पिक फ़्लैग जिसका इस्तेमाल यह बताने के लिए किया जाता है कि इस इंटरफ़ेस का स्थिर होना ज़रूरी नहीं है. इसेtrue
पर सेट करने पर बिल्ड सिस्टम, इंटरफ़ेस के लिए न तो एपीआई डंप बनाता है और न ही उसे अपडेट करने की ज़रूरत होती है.frozen
: जब यह वैकल्पिक फ़्लैगtrue
पर सेट किया जाता है, तो इसका मतलब है कि इंटरफ़ेस के पिछले वर्शन के बाद से इंटरफ़ेस में कोई बदलाव नहीं हुआ है. इससे, ज़्यादा बिल्ड-टाइम चेक की सुविधा मिलती है. अगर इसेfalse
पर सेट किया जाता है, तो इसका मतलब है कि इंटरफ़ेस पर अभी काम चल रहा है और इसमें नए बदलाव किए गए हैं. इसलिए,foo-freeze-api
को चलाने पर एक नया वर्शन जनरेट होता है और इसकी वैल्यू अपने-आपtrue
में बदल जाती है. Android 14 में पेश किया गया.backend.<type>.enabled
: ये फ़्लैग, हर उस बैकएंड को टॉगल करते हैं जिसके लिए एआईडीएल कंपाइलर कोड जनरेट करता है. चार बैकएंड काम करते हैं: Java, C++, NDK, और Rust. डिफ़ॉल्ट रूप से, Java, C++, और NDK बैकएंड चालू होते हैं. अगर इन तीनों में से किसी भी बैकएंड की ज़रूरत नहीं है, तो उसे साफ़ तौर पर बंद करना होगा. Android 15 (एओएसपी एक्सपेरिमेंट के तौर पर उपलब्ध) तक, Rust की सुविधा डिफ़ॉल्ट रूप से बंद रहती है.backend.<type>.apex_available
: उन APEX नामों की सूची जिनके लिए जनरेट की गई स्टब लाइब्रेरी उपलब्ध है.backend.[cpp|java].gen_log
: वह वैकल्पिक फ़्लैग जो यह कंट्रोल करता है कि लेन-देन की जानकारी इकट्ठा करने के लिए, अतिरिक्त कोड जनरेट करना है या नहीं.backend.[cpp|java].vndk.enabled
: इस इंटरफ़ेस को VNDK का हिस्सा बनाने के लिए, वैकल्पिक फ़्लैग. डिफ़ॉल्ट वैल्यूfalse
है.backend.[cpp|ndk].additional_shared_libraries
: Android 14 में पेश किया गया यह फ़्लैग, नेटिव लाइब्रेरी में डिपेंडेंसी जोड़ता है. यह फ़्लैगndk_header
औरcpp_header
के लिए काम का है.backend.java.sdk_version
: SDK टूल के उस वर्शन के बारे में बताने के लिए वैकल्पिक फ़्लैग जिसके लिए Java स्टब लाइब्रेरी बनाई गई है. डिफ़ॉल्ट वैल्यू"system_current"
है.backend.java.platform_apis
केtrue
होने पर, इस वैल्यू को सेट नहीं करना चाहिए.backend.java.platform_apis
: यह वैकल्पिक फ़्लैग है. इसे तबtrue
पर सेट किया जाना चाहिए, जब जनरेट की गई लाइब्रेरी को SDK टूल के बजाय प्लैटफ़ॉर्म एपीआई के ज़रिए बनाना हो.
वर्शन के हर कॉम्बिनेशन और चालू बैकएंड के लिए, एक स्टब लाइब्रेरी बनाई जाती है. किसी खास बैकएंड के लिए, स्टब लाइब्रेरी के खास वर्शन का हवाला देने का तरीका जानने के लिए, मॉड्यूल का नाम रखने के नियम देखें.
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 से शुरू किया जाता है. भले ही, शून्य एन्यूमरेटर न हो.
स्टब लाइब्रेरी का इस्तेमाल करना
अपने मॉड्यूल के लिए डिपेंडेंसी के तौर पर स्टब लाइब्रेरी जोड़ने के बाद, उन्हें अपनी फ़ाइलों में शामिल किया जा सकता है. यहां बिल्ड सिस्टम में स्टब लाइब्रेरी के उदाहरण दिए गए हैं (लेगसी मॉड्यूल की परिभाषाओं के लिए भी 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 नाम के साथ किसी मॉड्यूल का एलान करने से बिल्ड सिस्टम में भी एक टारगेट बन जाता है. इसका इस्तेमाल मॉड्यूल के एपीआई को मैनेज करने के लिए किया जा सकता है. foo-freeze-api के बनाए जाने पर, Android वर्शन के आधार पर api_dir
या aidl_api/name
में नई एपीआई परिभाषा जोड़ी जाती है और एक .hash
फ़ाइल जुड़ जाती है. यह दोनों फ़ाइलें, इंटरफ़ेस के नए फ़्रीज़ किए गए वर्शन को दिखाती हैं. foo-freeze-api को वर्शन के लिए, versions_with_info
प्रॉपर्टी और imports
को दिखाने के लिए भी अपडेट किया जाता है. दरअसल, versions_with_info
में मौजूद imports
को imports
फ़ील्ड से कॉपी किया जाता है. हालांकि, इंपोर्ट करने के लिए नए स्टेबल वर्शन की जानकारी versions_with_info
में imports
में दी गई है,
जिसका कोई खास वर्शन उपलब्ध नहीं है.
versions_with_info
प्रॉपर्टी तय होने के बाद बिल्ड सिस्टम, फ़्रीज़ किए गए वर्शन के साथ-साथ टॉप ऑफ़ ट्री (ToT) और सबसे नए फ़्रीज़ किए गए वर्शन के बीच भी कंपैटबिलिटी की जांच करता है.
इसके अलावा, आपको ToT वर्शन की एपीआई डेफ़िनिशन को भी मैनेज करना होगा. जब भी कोई एपीआई अपडेट किया जाए, तो अपडेट करने के लिए foo-update-api को चलाएं.aidl_api/name/current
इसमें ToT वर्शन की एपीआई डेफ़िनिशन शामिल है.
इंटरफ़ेस को एक जैसा बनाए रखने के लिए, मालिक इसमें ये नई चीज़ें जोड़ सकते हैं:
- इंटरफ़ेस के अंत तक के तरीके या साफ़ तौर पर तय किए गए नए क्रमों वाले मेथड
- पार्स किए जा सकने वाले एलिमेंट के आखिर में मौजूद एलिमेंट (हर एलिमेंट के लिए डिफ़ॉल्ट तौर पर जोड़ा जाना ज़रूरी है)
- कॉन्स्टेंट वैल्यू
- Android 11 में एन्यूमरेटर
- Android 12 में, यूनियन के आखिर तक के फ़ील्ड
कोई अन्य कार्रवाई करने की अनुमति नहीं है और कोई भी अन्य व्यक्ति इंटरफ़ेस में बदलाव नहीं कर सकता (ऐसा न करने पर, मालिक के किए गए बदलावों से टकराव का खतरा हो सकता है).
सभी इंटरफ़ेस रिलीज़ करने के लिए फ़्रीज़ किए गए हैं या नहीं, इसकी जांच करने के लिए, यहां दिए गए एनवायरमेंट वैरिएबल सेट का इस्तेमाल करके बनाएं:
AIDL_FROZEN_REL=true m ...
- बिल्ड के लिए ऐसे सभी एआईडीएल इंटरफ़ेस को फ़्रीज़ करना ज़रूरी है जिनमें कोईowner:
फ़ील्ड न हो.AIDL_FROZEN_OWNERS="aosp test"
- बिल्ड के लिए सभी स्थायी AIDL इंटरफ़ेस को "aosp" या "test" के तौर पर दिए गएowner:
फ़ील्ड के साथ फ़्रीज़ करना ज़रूरी है.
इंपोर्ट होने की स्थिरता
किसी इंटरफ़ेस के फ़्रोज़न वर्शन के लिए इंपोर्ट के वर्शन को अपडेट करने की सुविधा, स्टेबल एआईडीएल लेयर के साथ पुराने सिस्टम के साथ काम करती है. हालांकि, इन्हें अपडेट करने के लिए उन सभी सर्वर और क्लाइंट को अपडेट करना पड़ता है जो इंटरफ़ेस के पिछले वर्शन का इस्तेमाल करते हैं. साथ ही, अलग-अलग तरह के वर्शन को मिलाकर इस्तेमाल करने पर कुछ ऐप्लिकेशन को भ्रम हो सकता है. आम तौर पर, सिर्फ़ टाइप वाले या सामान्य पैकेज के लिए, यह सुरक्षित होता है. ऐसा इसलिए, क्योंकि आईपीसी ट्रांज़ैक्शन से मिलने वाले अनजान तरह के ट्रांज़ैक्शन को मैनेज करने के लिए, कोड को पहले से लिखा जाना ज़रूरी है.
Android प्लैटफ़ॉर्म कोड में android.hardware.graphics.common
, इस तरह के वर्शन अपग्रेड का सबसे बड़ा उदाहरण है.
वर्शन वाले इंटरफ़ेस का इस्तेमाल करना
इंटरफ़ेस के तरीके
रनटाइम के दौरान, किसी पुराने सर्वर पर नए तरीकों को कॉल करने की कोशिश करते समय, नए क्लाइंट को बैकएंड के आधार पर कोई गड़बड़ी या अपवाद मिलता है.
cpp
बैकएंड को::android::UNKNOWN_TRANSACTION
मिलता है.ndk
बैकएंड कोSTATUS_UNKNOWN_TRANSACTION
मिलता है.java
बैकएंड को यह मैसेजandroid.os.RemoteException
मिलता है कि एपीआई लागू नहीं है.
इसे मैनेज करने की रणनीतियों के लिए, क्वेरी वर्शन और डिफ़ॉल्ट इस्तेमाल देखें.
पार्स किए जा सकने वाले
जब पार्स किए जा सकने वाले किसी फ़ील्ड में नए फ़ील्ड जोड़े जाते हैं, तो पुराने क्लाइंट और सर्वर उन्हें छोड़ देते हैं. जब नए क्लाइंट और सर्वर को पुराने पार्सल किए जा सकते हैं, तो नए फ़ील्ड की डिफ़ॉल्ट वैल्यू अपने-आप भर जाती हैं. इसका मतलब है कि पार्स किए जा सकने वाले किसी फ़ील्ड में, सभी नए फ़ील्ड के लिए डिफ़ॉल्ट जानकारी देनी होगी.
क्लाइंट से तब तक नए फ़ील्ड का इस्तेमाल करने की उम्मीद नहीं की जानी चाहिए, जब तक उन्हें पता न हो कि सर्वर उस वर्शन को लागू कर रहा है जिसमें फ़ील्ड तय किया गया है (क्वेरी वर्शन देखें).
Enum और कॉन्सटेंट
इसी तरह, क्लाइंट और सर्वर को ऐसे वैल्यू और एन्यूमरेटर को अस्वीकार या अनदेखा करना चाहिए जिनकी पहचान नहीं की जा सकी. ऐसा इसलिए, क्योंकि आने वाले समय में और भी वैल्यू जोड़ी जा सकती हैं. उदाहरण के लिए, किसी ऐसे एन्यूमरेटर को मिलने पर सर्वर को रद्द नहीं किया जाना चाहिए जिसके बारे में उसे पता नहीं है. सर्वर को या तो एनुमरेटर को अनदेखा करना चाहिए या कुछ रिटर्न करना चाहिए, ताकि क्लाइंट को पता चल सके कि इस इंप्लिमेंटेशन में यह काम नहीं करता है.
यूनियन
अगर पाने वाला पुराना है और उसे फ़ील्ड के बारे में नहीं पता है,
तो नए फ़ील्ड के साथ यूनियन भेजने की कोशिश नहीं की जा सकती. लागू करने पर, कभी भी नए फ़ील्ड के साथ यूनियन नहीं दिखेगा. अगर यह एकतरफ़ा ट्रांज़ैक्शन है, तो इसे अनदेखा कर दिया जाता है. ऐसा न होने पर, गड़बड़ी BAD_VALUE
(C++ या NDK बैकएंड के लिए) या IllegalArgumentException
(Java बैकएंड के लिए) होती है. गड़बड़ी तब मिलती है, जब क्लाइंट किसी पुराने सर्वर को नए फ़ील्ड में यूनियन सेट भेज रहा होता है या जब कोई पुराना क्लाइंट, नए सर्वर से नए फ़ील्ड में यूनियन सेट कर रहा होता है.
फ़्लैग-आधारित डेवलपमेंट
रिलीज़ डिवाइसों पर इन-डेवलपमेंट (अनफ़्रीज़ किए गए) इंटरफ़ेस इस्तेमाल नहीं किए जा सकते, क्योंकि वे पुराने सिस्टम के साथ काम करने की गारंटी नहीं देते.
एआईडीएल, इन अनफ़्रीज़ की गई इंटरफ़ेस लाइब्रेरी के लिए रन टाइम फ़ॉलबैक के साथ काम करता है, ताकि फ़्रोज़न किए गए नए वर्शन के हिसाब से कोड को लिखा जा सके और रिलीज़ डिवाइसों पर भी उसका इस्तेमाल किया जा सके. क्लाइंट का पुराने सिस्टम के साथ काम करने का तरीका, मौजूदा व्यवहार जैसा ही होता है. साथ ही, फ़ॉलबैक को लागू करने के लिए इन व्यवहार के हिसाब से ही काम करना होता है. वर्शन वाले इंटरफ़ेस इस्तेमाल करना देखें.
एआईडीएल बिल्ड फ़्लैग
इस व्यवहार को कंट्रोल करने वाले फ़्लैग को build/release/build_flags.bzl
में RELEASE_AIDL_USE_UNFROZEN
बताया गया है. true
का मतलब है कि रन टाइम के दौरान, इंटरफ़ेस के बिना फ़्रीज़ किए गए वर्शन का इस्तेमाल किया जाता है. false
का मतलब है कि जिन वर्शन को फ़्रीज़ नहीं किया गया है उनकी लाइब्रेरी, पिछले फ़्रीज किए गए वर्शन की तरह काम करती हैं.
लोकल डेवलपमेंट के लिए, फ़्लैग को true
में बदला जा सकता है. हालांकि, रिलीज़ से पहले इसे वापस false
में सेट करना होगा. आम तौर पर, ऐसे कॉन्फ़िगरेशन की मदद से डेवलपमेंट किया जाता है जिसमें फ़्लैग, true
पर सेट होता है.
कंपैटबिलिटी मैट्रिक्स और मेनिफ़ेस्ट
वेंडर इंटरफ़ेस ऑब्जेक्ट (VINTF ऑब्जेक्ट) से पता चलता है कि कौनसे वर्शन ज़रूरी हैं और वेंडर इंटरफ़ेस के दोनों ओर कौनसे वर्शन उपलब्ध कराए जाते हैं.
ज़्यादातर नॉन-कटलफ़िश डिवाइस, काम करने वाले नए मैट्रिक्स को टारगेट करते हैं. ऐसा इंटरफ़ेस के फ़्रीज़ होने के बाद ही होता है. इसलिए, RELEASE_AIDL_USE_UNFROZEN
पर आधारित एआईडीएल लाइब्रेरी में कोई अंतर नहीं होता.
मैट्रिक्स
पार्टनर के मालिकाना हक वाले इंटरफ़ेस, डिवाइस या किसी प्रॉडक्ट के साथ काम करने के लिए बने ऐसे मैट्रिक्स में जोड़े जाते हैं जिन्हें डिवाइस डेवलपमेंट के दौरान टारगेट करता है. इसलिए, जब
किसी इंटरफ़ेस के नए और बिना फ़्रीज़ किए गए वर्शन को, काम करने वाले मैट्रिक्स में जोड़ा जाता है,
तो पिछले फ़्रीज़ किए गए वर्शन RELEASE_AIDL_USE_UNFROZEN=false
के लिए बने रहने चाहिए. इसे मैनेज करने के लिए, अलग-अलग RELEASE_AIDL_USE_UNFROZEN
कॉन्फ़िगरेशन के लिए, अलग-अलग कंपैटबिलिटी मैट्रिक्स फ़ाइलों का इस्तेमाल करें. इसके अलावा, सभी कॉन्फ़िगरेशन में इस्तेमाल की जाने वाली, कंपैटबिलिटी मैट्रिक्स फ़ाइल में दोनों वर्शन की अनुमति देकर भी इसे मैनेज किया जा सकता है.
उदाहरण के लिए, फ़्रीज़ न किए गए वर्शन 4 को जोड़ते समय, <version>3-4</version>
का इस्तेमाल करें.
वर्शन 4 को फ़्रीज़ किए जाने पर, काम करने वाले मैट्रिक्स से वर्शन 3 को हटाया जा सकता है. ऐसा इसलिए किया जा सकता है, क्योंकि RELEASE_AIDL_USE_UNFROZEN
false
होने पर, फ़्रीज़ किए गए वर्शन 4 का इस्तेमाल किया जाता है.
मेनिफ़ेस्ट
Android 15 (एओएसपी को एक्सपेरिमेंट के तौर पर शुरू किया गया) 15 में, RELEASE_AIDL_USE_UNFROZEN
की वैल्यू के आधार पर बिल्ड के समय मेनिफ़ेस्ट फ़ाइलों में बदलाव करने के लिए, libvintf
में बदलाव किया गया है.
मेनिफ़ेस्ट और मेनिफ़ेस्ट फ़्रैगमेंट से यह पता चलता है कि सेवा, इंटरफ़ेस का कौनसा वर्शन लागू करेगी. किसी इंटरफ़ेस के फ़्रीज़ न किए गए नए वर्शन का इस्तेमाल करते समय,
इस नए वर्शन को दिखाने के लिए मेनिफ़ेस्ट को अपडेट करना ज़रूरी है. जब जनरेट की गई एआईडीएल लाइब्रेरी में हुए बदलाव को दिखाने के लिए, RELEASE_AIDL_USE_UNFROZEN=false
मेनिफ़ेस्ट एंट्री में libvintf
के हिसाब से बदलाव किया जाता है. इस वर्शन में, फ़्रीज़ नहीं किए गए वर्शन N
से, पिछले फ़्रीज़ किए गए वर्शन N - 1
में बदलाव किया गया है. इसलिए, उपयोगकर्ताओं को अपनी हर सेवा के लिए, एक से ज़्यादा मेनिफ़ेस्ट या मेनिफ़ेस्ट फ़्रैगमेंट मैनेज करने की ज़रूरत नहीं होती.
एचएएल क्लाइंट में किए गए बदलाव
एचएएल क्लाइंट कोड को, पिछले हर फ़्रीज़ किए गए वर्शन के साथ पुराने सिस्टम के साथ काम करना चाहिए. जब RELEASE_AIDL_USE_UNFROZEN
, false
पर सेट होता है, तो सेवाएं हमेशा फ़्रीज़ किए गए पिछले वर्शन या उससे पहले की तरह दिखती हैं. उदाहरण के लिए, फ़्रीज़ किए गए नए तरीकों को कॉल करने पर UNKNOWN_TRANSACTION
या parcelable
के नए फ़ील्ड की डिफ़ॉल्ट वैल्यू दिखती है. यह ज़रूरी है कि Android फ़्रेमवर्क क्लाइंट, पुराने वर्शन के साथ काम करें. हालांकि, वेंडर क्लाइंट और पार्टनर के मालिकाना हक वाले इंटरफ़ेस के क्लाइंट के लिए, यह नई जानकारी है.
एचएएल को लागू करने के तरीके में बदलाव
फ़्लैग-आधारित डेवलपमेंट के साथ एचएएल डेवलपमेंट में सबसे बड़ा अंतर यह है कि एचएएल को लागू करना ज़रूरी है और यह ज़रूरी है कि जब RELEASE_AIDL_USE_UNFROZEN
false
हो, तो एचएएल को पिछले फ़्रोज़न वर्शन के साथ काम करने लायक बनाया जाए.
डिवाइस कोड और लागू करने के तरीके में पुराने सिस्टम के साथ काम करने की सुविधा
को ध्यान में रखना नई प्रक्रिया है. वर्शन वाले इंटरफ़ेस का इस्तेमाल करना देखें.
पुराने सिस्टम के साथ काम करने से जुड़ी ज़रूरी बातें आम तौर पर क्लाइंट और सर्वर, फ़्रेमवर्क कोड और वेंडर कोड,
उदाहरण: किसी इंटरफ़ेस में तीन फ़्रीज़ किए गए वर्शन होते हैं. इंटरफ़ेस को एक नए तरीके से अपडेट किया गया है. क्लाइंट और सेवा, दोनों को नए वर्शन 4 लाइब्रेरी का इस्तेमाल करने के लिए अपडेट किया जाता है. V4 लाइब्रेरी, इंटरफ़ेस के बिना फ़्रीज़ किए गए वर्शन पर आधारित होती है. इसलिए, यह पिछले फ़्रीज किए गए वर्शन यानी वर्शन 3 की तरह काम करती है, जबकि RELEASE_AIDL_USE_UNFROZEN
false
है. इसकी वजह से इसमें नए तरीके का इस्तेमाल नहीं किया जा सकता.
जब इंटरफ़ेस फ़्रीज़ होता है, तो RELEASE_AIDL_USE_UNFROZEN
की सभी वैल्यू उस फ़्रीज़ किए गए वर्शन का इस्तेमाल करती हैं. साथ ही, पुराने सिस्टम के साथ काम करने की सुविधा को मैनेज करने वाले कोड को हटाया जा सकता है.
कॉलबैक पर तरीकों को कॉल करते समय, आपको UNKNOWN_TRANSACTION
को वापस करने पर, केस को सही तरीके से हैंडल करना होगा. ऐसा हो सकता है कि रिलीज़ के कॉन्फ़िगरेशन के आधार पर, क्लाइंट कॉलबैक के दो अलग-अलग वर्शन लागू कर रहे हों. इसलिए, हो सकता है कि आप यह मानकर न चलें कि क्लाइंट सबसे नया वर्शन भेजता है. ऐसा हो सकता है कि नए तरीके से यह वर्शन दिखे. यह ठीक वैसे ही है जैसे स्थिर एआईडीएल क्लाइंट, सर्वर के साथ पुराने सिस्टम के साथ काम करते हैं. वर्शन वाले इंटरफ़ेस का इस्तेमाल करना सेक्शन में बताया गया है.
// 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();
}
}
अगर RELEASE_AIDL_USE_UNFROZEN
false
है, तो हो सकता है कि मौजूदा टाइप (parcelable
, enum
, union
) के नए फ़ील्ड मौजूद न हों या उनकी डिफ़ॉल्ट वैल्यू शामिल न हों. साथ ही, प्रोसेस के दौरान ऐसे नए फ़ील्ड की वैल्यू हटा दी जाती हैं जिन्हें कोई सेवा भेजने की कोशिश करती है.
फ़्रीज़ न किए गए इस वर्शन में जोड़े गए नए टाइप, इंटरफ़ेस से न तो भेजे जा सकते हैं और न ही पाए जा सकते हैं.
RELEASE_AIDL_USE_UNFROZEN
के false
होने पर, लागू करने की प्रोसेस को कभी भी किसी क्लाइंट से नए तरीकों के लिए कॉल नहीं किया जाता.
नए एन्यूमरेटर का इस्तेमाल सिर्फ़ उसी वर्शन के साथ करें जिसमें उन्हें पेश किया गया है, न कि पिछले वर्शन के साथ.
आम तौर पर, foo->getInterfaceVersion()
का इस्तेमाल करके यह देखा जाता है कि रिमोट इंटरफ़ेस किस वर्शन का इस्तेमाल कर रहा है. हालांकि, फ़्लैग-आधारित वर्शन के साथ, दो अलग-अलग वर्शन लागू किए जा रहे हैं, इसलिए हो सकता है कि आप मौजूदा इंटरफ़ेस का वर्शन पाना चाहें. ऐसा करने के लिए, मौजूदा ऑब्जेक्ट का इंटरफ़ेस वर्शन पाएं. उदाहरण के लिए, this->getInterfaceVersion()
या my_ver
के लिए दूसरे तरीके. ज़्यादा जानकारी के लिए, रिमोट ऑब्जेक्ट के इंटरफ़ेस वर्शन की क्वेरी करना देखें.
नए VINTF और स्टेबल इंटरफ़ेस
नया एआईडीएल इंटरफ़ेस पैकेज जोड़ने पर, उसका कोई आखिरी वर्शन नहीं होता. इसलिए, RELEASE_AIDL_USE_UNFROZEN
के false
होने के बाद, वापस आकर कोई कार्रवाई नहीं की जा सकती. इन इंटरफ़ेस का इस्तेमाल न करें. RELEASE_AIDL_USE_UNFROZEN
के false
होने पर, सेवा मैनेजर, सेवा को इंटरफ़ेस रजिस्टर करने की अनुमति नहीं देगा और क्लाइंट इसे नहीं खोज पाएंगे.
डिवाइस मेकफ़ाइल में RELEASE_AIDL_USE_UNFROZEN
फ़्लैग की वैल्यू के आधार पर, सेवाओं को कुछ शर्तों के साथ जोड़ा जा सकता है:
ifeq ($(RELEASE_AIDL_USE_UNFROZEN),true)
PRODUCT_PACKAGES += \
android.hardware.health.storage-service
endif
अगर सेवा किसी बड़ी प्रोसेस का हिस्सा है, तो इसे डिवाइस पर कुछ शर्तों के साथ नहीं जोड़ा जा सकता. ऐसे में, यह देखें कि IServiceManager::isDeclared()
के साथ सेवा का एलान किया गया है या नहीं. अगर यह एलान हो चुका है और रजिस्टर नहीं हो पाया है, तो
प्रोसेस को रद्द करें. अगर इसका एलान नहीं किया गया है, तो हो सकता है कि यह रजिस्टर न हो पाए.
डेवलपमेंट टूल के तौर पर कटलफ़िश
वीआईएनटीएफ़ के फ़्रीज़ होने के बाद, हर साल हम फ़्रेमवर्क के साथ काम करने वाले मैट्रिक्स (FCM) target-level
और कटलफ़िश के PRODUCT_SHIPPING_API_LEVEL
में बदलाव करते हैं. इससे, वे अगले साल रिलीज़ होने वाले डिवाइसों के बारे में जानकारी दिखाते हैं. हम target-level
और PRODUCT_SHIPPING_API_LEVEL
में बदलाव करते हैं, ताकि यह पक्का किया जा सके कि लॉन्च होने वाले कुछ ऐसे डिवाइस मौजूद हैं जिनकी जांच की जा चुकी है और जो अगले साल की रिलीज़ से जुड़ी नई ज़रूरी शर्तों को पूरा करते हैं.
जब RELEASE_AIDL_USE_UNFROZEN
की उम्र true
है, तो आने वाले समय में Android के रिलीज़ होने वाले अपडेट बनाने के लिए, Cuttleफ़िश का इस्तेमाल किया जाएगा. यह अगले साल के Android
रिलीज़ के FCM लेवल और PRODUCT_SHIPPING_API_LEVEL
को टारगेट करता है. इसके लिए, इसे अगली रिलीज़ की वेंडर सॉफ़्टवेयर
ज़रूरी शर्तों (वीएसआर) को पूरा करना होगा.
जब RELEASE_AIDL_USE_UNFROZEN
की वैल्यू false
है, तब रिलीज़ डिवाइस को दिखाने के लिए, कटलफ़िश के पिछले target-level
और PRODUCT_SHIPPING_API_LEVEL
पॉइंट होते हैं.
Android 14 और उससे पहले के वर्शन में, यह फ़र्क़
Git के उन अलग-अलग ब्रांच के साथ किया जाएगा जो FCM
target-level
, शिपिंग एपीआई लेवल या अगली रिलीज़ को टारगेट करने वाले किसी भी अन्य कोड में किए गए बदलाव को
नहीं चुनते.
मॉड्यूल का नाम रखने के नियम
Android 11 में, चालू किए गए बैकएंड और वर्शन के हर कॉम्बिनेशन के लिए, एक स्टब लाइब्रेरी मॉड्यूल अपने-आप बन जाता है. किसी खास स्टब लाइब्रेरी मॉड्यूल को लिंक करने के लिए, aidl_interface
मॉड्यूल के नाम का इस्तेमाल न करें. इसके बजाय, स्टब लाइब्रेरी मॉड्यूल के नाम का इस्तेमाल करें, जो कि ifacename-version-backend है, जहां
ifacename
:aidl_interface
मॉड्यूल का नामversion
इनमें से कोई एक है- फ़्रीज़ किए गए वर्शन के लिए
Vversion-number
- ट्री-ऑफ़-ट्री (अभी-अभी
फ़्रोज़न) वर्शन के लिए
Vlatest-frozen-version-number + 1
- फ़्रीज़ किए गए वर्शन के लिए
backend
इनमें से कोई एक है- Java बैकएंड के लिए
java
, - C++ बैकएंड के लिए
cpp
, - NDK बैकएंड के लिए,
ndk
याndk_platform
. पहला वाला वर्शन ऐप्लिकेशन के लिए है और बाद वाला विकल्प, Android 13 तक के लिए प्लैटफ़ॉर्म का इस्तेमाल करने के लिए है. Android 13 और उसके बाद के वर्शन में, सिर्फ़ndk
का इस्तेमाल करें. - Rust बैकएंड के लिए
rust
.
- Java बैकएंड के लिए
मान लें कि 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
ध्यान दें कि एआईडीएल कंपाइलर, न तो unstable
वर्शन वाला मॉड्यूल बनाता है और न ही स्थिर एआईडीएल इंटरफ़ेस के लिए, बिना वर्शन वाला मॉड्यूल.
Android 12 के बाद से, स्टेबल एआईडीएल इंटरफ़ेस से जनरेट किए गए मॉड्यूल के नाम में हमेशा इसका वर्शन शामिल होता है.
मेटा इंटरफ़ेस की नई विधियां
Android 10 में, स्टेबल एआईडीएल के लिए कई मेटा इंटरफ़ेस मेथड जोड़े गए हैं.
रिमोट ऑब्जेक्ट के इंटरफ़ेस वर्शन की क्वेरी करें
क्लाइंट, रिमोट ऑब्जेक्ट को लागू करने वाले इंटरफ़ेस के वर्शन और हैश की क्वेरी कर सकते हैं. साथ ही, दिखाई गई वैल्यू की तुलना, क्लाइंट के इस्तेमाल किए गए इंटरफ़ेस की वैल्यू से कर सकते हैं.
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()
को इस तरह से लागू करना होगा (कॉपी करने और चिपकाने से जुड़ी गलतियों से बचने के लिए, IFoo
के बजाय super
का इस्तेमाल किया जाता है. javac
कॉन्फ़िगरेशन के आधार पर, चेतावनियां बंद करने के लिए, @SuppressWarnings("static")
एनोटेशन की ज़रूरत पड़ सकती है:
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
होता है, जिसे रेफ़रंस के दौरान इनलाइन किया जाता है) और इस तरह यह तरीका वही वर्शन दिखा सकता है जिससे सर्वर बनाया गया था.
पुराने इंटरफ़ेस से निपटें
ऐसा हो सकता है कि किसी क्लाइंट को एआईडीएल इंटरफ़ेस के नए वर्शन से अपडेट किया गया हो, लेकिन सर्वर पुराने एआईडीएल इंटरफ़ेस का इस्तेमाल कर रहा हो. ऐसे मामलों में,
किसी पुराने इंटरफ़ेस पर किसी तरीके को कॉल करने पर, UNKNOWN_TRANSACTION
नतीजा मिलता है.
एआईडीएल के साथ बेहतर तरीके से काम करने पर, क्लाइंट को ज़्यादा कंट्रोल मिलता है. क्लाइंट-साइड में, एआईडीएल इंटरफ़ेस पर डिफ़ॉल्ट लागू होने की सुविधा सेट की जा सकती है. डिफ़ॉल्ट लागू करने का कोई तरीका सिर्फ़ तब इस्तेमाल किया जाता है, जब वह रिमोट साइड में लागू न किया गया हो. ऐसा इसलिए, क्योंकि इसे इंटरफ़ेस के पुराने वर्शन का इस्तेमाल करके बनाया गया है. डिफ़ॉल्ट सेटिंग दुनिया भर में सेट होती हैं. इसलिए, उनका इस्तेमाल ऐसे कॉन्टेक्स्ट से नहीं किया जाना चाहिए जो शेयर किए गए हों.
Android 13 और उसके बाद के वर्शन में C++ पर इसका उदाहरण:
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(...);
आपको किसी एआईडीएल इंटरफ़ेस में सभी तरीकों को डिफ़ॉल्ट रूप से लागू करने की सुविधा देने की ज़रूरत नहीं है. जिन तरीकों के लिए रिमोट साइड में लागू होने की गारंटी होती है उन्हें डिफ़ॉल्ट impl
क्लास में ओवरराइड करने की ज़रूरत नहीं होती. ऐसा इसलिए होता है, क्योंकि आपको यकीन है कि रिमोट को एआईडीएल इंटरफ़ेस की जानकारी में बताए जाने के दौरान ही बनाया गया था.
मौजूदा एआईडीएल को स्ट्रक्चर्ड या स्टेबल एआईडीएल में बदलें
अगर आपके पास कोई मौजूदा AIDL और ऐसा कोड है जो उसका इस्तेमाल करता है, तो इंटरफ़ेस को स्थिर एआईडीएल इंटरफ़ेस में बदलने के लिए, यहां दिया गया तरीका अपनाएं.
अपने इंटरफ़ेस की सभी निर्भरताओं का पता लगाएं. इंटरफ़ेस पर निर्भर हर पैकेज के लिए, देखें कि पैकेज स्टेबल एआईडीएल में है या नहीं. अगर तय नहीं है, तो पैकेज को बदलना होगा.
अपने इंटरफ़ेस में मौजूद सभी पार्सल को स्थिर पार्सल किए जा सकने वाले फ़ॉर्मैट में बदलें. इंटरफ़ेस फ़ाइलों में कोई बदलाव नहीं किया जा सकता. ऐसा करने के लिए, उनके स्ट्रक्चर को सीधे तौर पर एआईडीएल फ़ाइलों में दिखाएं. इन नए टाइप का इस्तेमाल करने के लिए, मैनेजमेंट क्लास को फिर से लिखना होगा. यह कार्रवाई,
aidl_interface
पैकेज बनाने से पहले की जा सकती है. इसकी जानकारी नीचे दी गई है.ऐसा
aidl_interface
पैकेज बनाएं (जैसा कि ऊपर बताया गया है) जिसमें आपके मॉड्यूल का नाम, उसकी डिपेंडेंसी, और ज़रूरत के मुताबिक अन्य जानकारी शामिल हो. इसे स्टेबलाइज़ करने के लिए (सिर्फ़ स्ट्रक्चर ही नहीं) करने के लिए, इसका वर्शन भी होना चाहिए. ज़्यादा जानकारी के लिए, वर्शन इंटरफ़ेस देखें.