Android 10, kararlı Android Arayüz Tanımlama Dili (AIDL) desteği ekler. Bu, AIDL arayüzleri tarafından sağlanan uygulama programlama arayüzünü (API) ve uygulama ikili arayüzünü (ABI) takip etmenin yeni bir yoludur. Kararlı AIDL, AIDL ile aynı şekilde çalışır ancak derleme sistemi arayüz uyumluluğunu izler ve yapabileceklerinizle ilgili kısıtlamalar vardır:
- Arayüzler, derleme sisteminde
aidl_interfaces
ile tanımlanır. - Arayüzler yalnızca yapılandırılmış veri içerebilir. Tercih edilen türleri temsil eden Parcelable'lar, AIDL tanımlarına göre otomatik olarak oluşturulur ve otomatik olarak sıralanır ve sıralaması kaldırılır.
- Arayüzler kararlı (geriye dönük uyumlu) olarak bildirilebilir. Bu durumda, API'leri AIDL arayüzünün yanındaki bir dosyada izlenir ve sürüm oluşturulur.
Yapılandırılmış ve kararlı AIDL
Yapılandırılmış AIDL, tamamen AIDL'de tanımlanan türleri ifade eder. Örneğin, paketlenebilir bir bildirim (özel bir paketlenebilir) yapılandırılmış AIDL değildir. Alanları AIDL'de tanımlanan Parcelable'lar yapılandırılmış Parcelable'lar olarak adlandırılır.
Kararlı AIDL, yapı sisteminin ve derleyicinin, paketlenebilir öğelerde yapılan değişikliklerin geriye dönük uyumlu olup olmadığını anlayabilmesi için yapılandırılmış AIDL gerektirir.
Ancak tüm yapılandırılmış arayüzler kararlı değildir. Bir arayüzün kararlı olması için yalnızca yapılandırılmış türler kullanması ve aşağıdaki sürüm oluşturma özelliklerini kullanması gerekir. Aksine, arayüzü oluşturmak için temel derleme sistemi kullanılıyorsa veya unstable:true
ayarlanmışsa arayüz kararlı değildir.
AIDL arayüzü tanımlama
aidl_interface
tanımı şu şekildedir:
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
: Bir AIDL arayüzünü benzersiz şekilde tanımlayan AIDL arayüz modülünün adı.srcs
: Arayüzü oluşturan AIDL kaynak dosyalarının listesi. Bir pakettecom.acme
tanımlanan bir AIDL türüFoo
için yol,<base_path>/com/acme/Foo.aidl
olmalıdır. Burada<base_path>
,Android.bp
'nin bulunduğu dizinle ilgili herhangi bir dizin olabilir. Önceki örnekte<base_path>
,srcs/aidl
'tır.local_include_dir
: Paket adının başladığı yol. Yukarıda açıklanan<base_path>
ile aynıdır.imports
: Bu modülün kullandığıaidl_interface
modüllerin listesi. AIDL arayüzlerinizden biri başka biraidl_interface
arayüzü veya paketlenebilir öğesi kullanıyorsa adını buraya girin. En son sürümü belirtmek için yalnızca adı kullanabilir veya belirli bir sürümü belirtmek için sürüm sonekiyle birlikte (ör.-V1
) adı kullanabilirsiniz. Sürüm belirtme, Android 12'den beri desteklenmektedir.versions
: Arayüzünapi_dir
altında dondurulmuş önceki sürümleri. Android 11'den itibarenversions
,aidl_api/name
altında dondurulur. Bir arayüzün dondurulmuş sürümü yoksa bu belirtilmemeli ve uyumluluk kontrolleri yapılmamalıdır. Bu alanın yerini Android 13 ve sonraki sürümlerdeversions_with_info
almıştır.versions_with_info
: Her biri dondurulmuş bir sürümün adını ve bu aidl_interface sürümünün içe aktardığı diğer aidl_interface modüllerinin sürüm içe aktarmalarını içeren bir liste olan demetlerin listesi. IFACE adlı bir AIDL arayüzünün V sürümünün tanımıaidl_api/IFACE/V
konumunda bulunur. Bu alan Android 13'te kullanıma sunuldu ve doğrudanAndroid.bp
içinde değiştirilmemesi gerekiyor. Alan,*-update-api
veya*-freeze-api
çağrılarak eklenir ya da güncellenir. Ayrıca, bir kullanıcı*-update-api
veya*-freeze-api
işlevini çağırdığındaversions
alanları otomatik olarakversions_with_info
alanına taşınır.stability
: Bu arayüzün kararlılık sözü için isteğe bağlı işaret. Bu özellik yalnızca"vintf"
destekler.stability
ayarlanmamışsa derleme sistemi,unstable
belirtilmediği sürece arayüzün geriye dönük uyumlu olduğunu kontrol eder. Ayarlanmamış olması, bu derleme bağlamında kararlılık içeren bir arayüze karşılık gelir (ör.system.img
ve ilgili bölümlerdeki öğeler gibi tüm sistem öğeleri veyavendor.img
ve ilgili bölümlerdeki öğeler gibi tüm satıcı öğeleri).stability
,"vintf"
olarak ayarlanırsa bu, kararlılık sözü anlamına gelir: Arayüz, kullanıldığı sürece kararlı tutulmalıdır.gen_trace
: İzlemeyi açmak veya kapatmak için isteğe bağlı işaret. Android 14'ten itibarencpp
vejava
arka uçları için varsayılan değertrue
'dir.host_supported
:true
olarak ayarlandığında oluşturulan kitaplıkları ana makine ortamında kullanılabilir hale getiren isteğe bağlı işaret.unstable
: Bu arayüzün kararlı olması gerekmediğini işaretlemek için kullanılan isteğe bağlı işaret. Butrue
olarak ayarlandığında derleme sistemi, arayüz için API dökümü oluşturmaz ve güncellenmesini gerektirmez.frozen
:true
olarak ayarlandığında arayüzün önceki sürümünden bu yana herhangi bir değişiklik yapılmadığını belirten isteğe bağlı işaret. Bu, daha fazla derleme zamanı kontrolü sağlar.false
olarak ayarlandığında arayüzün geliştirme aşamasında olduğu ve yeni değişiklikler içerdiği anlamına gelir. Bu nedenle,foo-freeze-api
komutunun çalıştırılması yeni bir sürüm oluşturur ve değeri otomatik olaraktrue
olarak değiştirir. Android 14'te kullanıma sunuldu.backend.<type>.enabled
: Bu işaretler, AIDL derleyicisinin kod oluşturduğu her bir arka uç için açma/kapatma işlevi görür. Dört arka uç desteklenir: Java, C++, NDK ve Rust. Java, C++ ve NDK arka uçları varsayılan olarak etkindir. Bu üç arka uçtan herhangi birine ihtiyaç duyulmuyorsa açıkça devre dışı bırakılması gerekir. Rust, Android 15'e kadar varsayılan olarak devre dışıdır.backend.<type>.apex_available
: Oluşturulan saplama kitaplığının kullanılabildiği APEX adlarının listesi.backend.[cpp|java].gen_log
: İşlem hakkında bilgi toplamak için ek kod oluşturulup oluşturulmayacağını kontrol eden isteğe bağlı işaret.backend.[cpp|java].vndk.enabled
: Bu arayüzü VNDK'nın bir parçası yapmak için isteğe bağlı işaret. Varsayılan değerfalse
'dır.backend.[cpp|ndk].additional_shared_libraries
: Android 14'te kullanıma sunulan bu işaret, yerel kitaplıklara bağımlılıklar ekler. Bu işaret,ndk_header
vecpp_header
ile birlikte kullanıldığında işe yarar.backend.java.sdk_version
: Java saplama kitaplığının oluşturulduğu SDK sürümünü belirtmek için kullanılan isteğe bağlı işaret. Varsayılan değer:"system_current"
.backend.java.platform_apis
true
olduğunda bu ayarlanmamalıdır.backend.java.platform_apis
: Oluşturulan kitaplıkların SDK yerine platform API'sine göre oluşturulması gerektiğindetrue
olarak ayarlanması gereken isteğe bağlı işaret.
Sürümlerin ve etkinleştirilmiş arka uçların her kombinasyonu için bir saplama kitaplığı oluşturulur. Belirli bir arka uç için sahte kitaplığın belirli bir sürümüne nasıl başvurulacağı hakkında bilgi edinmek için Modül adlandırma kuralları bölümüne bakın.
AIDL dosyaları yazma
Kararlı AIDL'deki arayüzler, yapılandırılmamış parcelable'lar kullanmalarına izin verilmemesi dışında geleneksel arayüzlere benzer (çünkü bunlar kararlı değildir. Yapılandırılmış ve kararlı AIDL bölümüne bakın). Kararlı AIDL'deki temel fark, paketlenebilirlerin nasıl tanımlandığıdır. Daha önce, parcelable'lar önceden bildirilmişti. Kararlı (ve dolayısıyla yapılandırılmış) AIDL'de ise parcelable alanları ve değişkenleri açıkça tanımlanır.
// 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
ve String
için varsayılan değer desteklenir (ancak zorunlu değildir). Android 12'de, kullanıcı tanımlı numaralandırmalar için varsayılan değerler de desteklenir. Varsayılan değer belirtilmediğinde 0'a benzer veya boş bir değer kullanılır.
Varsayılan değeri olmayan numaralandırmalar, sıfır numaralandırıcı olmasa bile 0 olarak başlatılır.
Stub kitaplıkları kullanma
Sahte kitaplıkları modülünüze bağımlılık olarak ekledikten sonra bunları dosyalarınıza dahil edebilirsiniz. Aşağıda, derleme sistemindeki (Android.mk
, eski modül tanımları için de kullanılabilir) stub kitaplıklarına ilişkin örnekler verilmiştir.
Bu örneklerde sürüm bulunmadığı için kararsız bir arayüzün kullanıldığı gösterilmektedir. Sürümlü arayüzlerin adları ek bilgiler içerir. Arayüzleri sürümleme bölümüne bakın.
cc_... {
name: ...,
// use `shared_libs:` to load your library and its transitive dependencies
// dynamically
shared_libs: ["my-module-name-cpp"],
// use `static_libs:` to include the library in this binary and drop
// transitive dependencies
static_libs: ["my-module-name-cpp"],
...
}
# or
java_... {
name: ...,
// use `static_libs:` to add all jars and classes to this jar
static_libs: ["my-module-name-java"],
// use `libs:` to make these classes available during build time, but
// not add them to the jar, in case the classes are already present on the
// boot classpath (such as if it's in framework.jar) or another jar.
libs: ["my-module-name-java"],
// use `srcs:` with `-java-sources` if you want to add classes in this
// library jar directly, but you get transitive dependencies from
// somewhere else, such as the boot classpath or another jar.
srcs: ["my-module-name-java-source", ...],
...
}
# or
rust_... {
name: ...,
rustlibs: ["my-module-name-rust"],
...
}
C++'taki örnek:
#include "some/package/IFoo.h"
#include "some/package/Thing.h"
...
// use just like traditional AIDL
Java'da örnek:
import some.package.IFoo;
import some.package.Thing;
...
// use just like traditional AIDL
Rust'taki örnek:
use aidl_interface_name::aidl::some::package::{IFoo, Thing};
...
// use just like traditional AIDL
Sürüm oluşturma arayüzleri
foo adlı bir modülün bildirilmesi, derleme sisteminde modülün API'sini yönetmek için kullanabileceğiniz bir hedef de oluşturur. Oluşturulduğunda foo-freeze-api, Android sürümüne bağlı olarak api_dir
veya aidl_api/name
altında yeni bir API tanımı ekler ve arayüzün yeni dondurulmuş sürümünü temsil eden bir .hash
dosyası ekler. foo-freeze-api, eklenen sürümü yansıtmak için versions_with_info
özelliğini ve sürüm için imports
özelliğini de günceller. Temel olarak, versions_with_info
içindeki imports
, imports
alanından kopyalanır. Ancak içe aktarma için imports
içinde versions_with_info
'de en son kararlı sürüm belirtiliyor. Bu sürümün açık bir sürümü yok.
versions_with_info
özelliği belirtildikten sonra derleme sistemi, dondurulmuş sürümler arasında ve ayrıca Top of Tree (ToT) ile en son dondurulmuş sürüm arasında uyumluluk kontrolleri gerçekleştirir.
Ayrıca ToT sürümünün API tanımını da yönetmeniz gerekir. Bir API her güncellendiğinde, foo-update-api komutunu çalıştırarak aidl_api/name/current
dosyasını güncelleyin. Bu dosya, ToT sürümünün API tanımını içerir.
Sahipler, arayüzün kararlılığını korumak için yeni öğeler ekleyebilir:
- Bir arayüzün sonuna yönelik yöntemler (veya açıkça tanımlanmış yeni serileri olan yöntemler)
- Bir paketlenebilir öğenin sonuna öğeler (her öğe için varsayılan değer eklenmelidir)
- Sabit değerler
- Android 11'de numaralandırıcılar
- Android 12'de, bir birliğin sonundaki alanlar
Başka hiçbir işleme izin verilmez ve başka hiç kimse arayüzü değiştiremez (aksi takdirde, sahibin yaptığı değişikliklerle çakışma riski oluşur).
Tüm arayüzlerin yayın için dondurulduğunu test etmek amacıyla aşağıdaki ortam değişkenleri ayarlanmış şekilde derleme yapabilirsiniz:
AIDL_FROZEN_REL=true m ...
- Derleme,owner:
alanı belirtilmemiş tüm kararlı AIDL arayüzlerinin dondurulmasını gerektirir.AIDL_FROZEN_OWNERS="aosp test"
- Derleme,owner:
alanı "aosp" veya "test" olarak belirtilmiş tüm kararlı AIDL arayüzlerinin dondurulmasını gerektirir.
İçe aktarma işlemlerinin kararlılığı
Bir arayüzün dondurulmuş sürümleri için içe aktarma sürümlerini güncelleme, Stable AIDL katmanında geriye dönük uyumludur. Ancak bunların güncellenmesi için arayüzün önceki bir sürümünü kullanan tüm sunucuların ve istemcilerin güncellenmesi gerekir. Ayrıca, farklı türlerin farklı sürümleri karıştırıldığında bazı uygulamalar karışabilir. Genellikle, yalnızca türleri içeren veya ortak paketler için bu güvenlidir. Bunun nedeni, IPC işlemlerinden gelen bilinmeyen türleri işlemek için kodun zaten yazılmış olması gerekmesidir.
Android platform kodunda android.hardware.graphics.common
, bu tür sürüm yükseltme işleminin en büyük örneğidir.
Sürümlendirilmiş arayüzleri kullanma
Arayüz yöntemleri
Çalışma zamanında, eski bir sunucuda yeni yöntemler çağrılmaya çalışıldığında, arka uca bağlı olarak yeni istemciler hata veya istisna alır.
cpp
arka ucu::android::UNKNOWN_TRANSACTION
.ndk
arka ucuSTATUS_UNKNOWN_TRANSACTION
.java
arka ucu, API'nin uygulanmadığını belirten bir mesajlaandroid.os.RemoteException
alır.
Bunu ele alma stratejileri için sorgu sürümleri ve varsayılanları kullanma başlıklı makalelere bakın.
Ayrıştırılabilir öğeler
Parcelable'lara yeni alanlar eklendiğinde eski istemciler ve sunucular bunları bırakır. Yeni istemciler ve sunucular eski parcelable'ları aldığında yeni alanların varsayılan değerleri otomatik olarak doldurulur. Bu nedenle, bir paketlenebilir öğedeki tüm yeni alanlar için varsayılan değerler belirtilmesi gerekir.
İstemciler, sunucunun alanı tanımlanmış sürümü uyguladığını bilmedikleri sürece sunucuların yeni alanları kullanmasını beklememelidir (bkz. sürüm sorgulama).
Numaralandırmalar ve sabitler
Benzer şekilde, gelecekte daha fazla değer eklenebileceğinden, istemciler ve sunucular tanınmayan sabit değerleri ve numaralandırıcıları uygun şekilde reddetmeli veya yoksaymalıdır. Örneğin, bir sunucu bilmediği bir numaralandırıcı aldığında işlemi durdurmamalıdır. Sunucu, numaralandırıcıyı yoksaymalı veya istemcinin bu uygulamada desteklenmediğini bilmesi için bir şey döndürmelidir.
Sendikalar
Alıcı eski bir sürümü kullanıyorsa ve alanı bilmiyorsa yeni bir alan içeren bir birliği gönderme işlemi başarısız olur. Uygulama, yeni alanla birleşmeyi hiçbir zaman görmez. Tek yönlü bir işlemse hata yoksayılır. Aksi takdirde hata BAD_VALUE
(C++ veya NDK arka ucu için) ya da IllegalArgumentException
(Java arka ucu için) olur. Hata, istemci eski bir sunucuya yeni alana bir birleşim kümesi gönderdiğinde veya yeni bir sunucudan birleşim alan eski bir istemci olduğunda alınır.
Birden fazla sürümü yönetme
Android'deki bir bağlayıcı ad alanı, oluşturulan aidl
türlerinin birden fazla tanıma sahip olduğu durumları önlemek için belirli bir aidl
arayüzünün yalnızca 1 sürümüne sahip olabilir. C++, her sembolün yalnızca bir tanımını gerektiren Tek Tanım Kuralı'na sahiptir.
Android derlemesi, bir modül aynı aidl_interface
kitaplığının farklı sürümlerine bağlı olduğunda hata verir. Modül, bu kitaplıklara doğrudan veya bağımlılıklarının bağımlılıkları aracılığıyla dolaylı olarak bağlı olabilir. Bu hatalar, başarısız olan modülden aidl_interface
kitaplığının çakışan sürümlerine kadar olan bağımlılık grafiğini gösterir. Tüm bağımlılıkların, bu kitaplıkların aynı (genellikle en son) sürümünü içerecek şekilde güncellenmesi gerekir.
Arayüz kitaplığı birçok farklı modül tarafından kullanılıyorsa aynı sürümü kullanması gereken kitaplık ve işlem grupları için cc_defaults
, java_defaults
ve rust_defaults
oluşturmak faydalı olabilir. Arayüzün yeni bir sürümü kullanıma sunulduğunda bu varsayılanlar güncellenebilir ve bunları kullanan tüm modüller birlikte güncellenerek arayüzün farklı sürümlerinin kullanılmaması sağlanır.
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
modülleri diğer aidl_interface
modüllerini içe aktardığında, belirli sürümlerin birlikte kullanılmasını gerektiren ek bağımlılıklar oluşur. Bu durum, aynı işlemlerde birlikte kullanılan birden fazla aidl_interface
modülüne ortak aidl_interface
modüller içe aktarıldığında yönetilmesi zor bir hâl alabilir.
aidl_interfaces_defaults
, tek bir yerde güncellenebilen ve bu ortak arayüzü içe aktarmak isteyen tüm aidl_interface
modülleri tarafından kullanılabilen bir aidl_interface
için bağımlılıkların en son sürümlerinin tek bir tanımını tutmak üzere kullanılabilir.
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"],
...
}
İşaret tabanlı geliştirme
Geriye dönük uyumlulukları garanti edilmediği için geliştirme aşamasındaki (dondurulmamış) arayüzler, yayın cihazlarında kullanılamaz.
AIDL, kodun en son dondurulmamış sürüme göre yazılması ve yayınlanan cihazlarda kullanılmaya devam etmesi için bu dondurulmamış arayüz kitaplıklarında çalışma zamanı geri dönüşünü destekler. İstemcilerin geriye dönük uyumlu davranışı, mevcut davranışa benzer ve geri dönüşle birlikte uygulamaların da bu davranışları izlemesi gerekir. Sürümlendirilmiş arayüzleri kullanma başlıklı makaleyi inceleyin.
AIDL derleme işareti
Bu davranışı kontrol eden işaret, RELEASE_AIDL_USE_UNFROZEN
build/release/build_flags.bzl
içinde tanımlanır. true
, arayüzün dondurulmamış sürümünün çalışma zamanında kullanıldığı, false
ise dondurulmamış sürümlerin kitaplıklarının son dondurulmuş sürümleri gibi davrandığı anlamına gelir.
Yerel geliştirme için işareti true
olarak değiştirebilirsiniz ancak yayınlamadan önce false
olarak geri döndürmeniz gerekir. Genellikle geliştirme, işaretin true
olarak ayarlandığı bir yapılandırmayla yapılır.
Uyumluluk matrisi ve manifestler
Tedarikçi arayüzü nesneleri (VINTF nesneleri), hangi sürümlerin beklendiğini ve tedarikçi arayüzünün her iki tarafında hangi sürümlerin sağlandığını tanımlar.
Cuttlefish olmayan çoğu cihaz, yalnızca arayüzler dondurulduktan sonra en son uyumluluk matrisini hedefler. Bu nedenle, RELEASE_AIDL_USE_UNFROZEN
'ye göre AIDL kitaplıklarında herhangi bir fark yoktur.
Matrisler
İş ortağına ait arayüzler, geliştirme sırasında cihazın hedeflediği cihaza özel veya ürüne özel uyumluluk matrislerine eklenir. Bu nedenle, bir uyumluluk matrisine yeni ve dondurulmamış bir arayüz sürümü eklendiğinde, önceki dondurulmuş sürümlerin RELEASE_AIDL_USE_UNFROZEN=false
boyunca kalması gerekir. Bunu, farklı RELEASE_AIDL_USE_UNFROZEN
yapılandırmaları için farklı uyumluluk matrisi dosyaları kullanarak veya tüm yapılandırmalarda kullanılan tek bir uyumluluk matrisi dosyasında her iki sürüme de izin vererek çözebilirsiniz.
Örneğin, dondurulmamış bir 4. sürüm eklerken <version>3-4</version>
kullanın.
4. sürüm dondurulduğunda, RELEASE_AIDL_USE_UNFROZEN
false
olduğunda dondurulmuş 4. sürüm kullanıldığından 3. sürümü uyumluluk matrisinden kaldırabilirsiniz.
Manifestler
Android 15'te, libvintf
değerine göre derleme sırasında manifest dosyalarını değiştirmek için RELEASE_AIDL_USE_UNFROZEN
ile ilgili bir değişiklik yapıldı.
Manifestler ve manifest parçaları, bir hizmetin hangi arayüz sürümünü uyguladığını bildirir. Bir arayüzün dondurulmamış en son sürümü kullanılırken manifest, bu yeni sürümü yansıtacak şekilde güncellenmelidir. Manifest girişleri, oluşturulan AIDL kitaplığındaki değişikliği yansıtacak şekilde RELEASE_AIDL_USE_UNFROZEN=false
tarafından ayarlanır.libvintf
Sürüm, artık güncellenmeyen sürüm N
'dan son dondurulmuş sürüm N - 1
'e değiştirildi. Bu nedenle, kullanıcıların her hizmetleri için birden fazla manifest veya manifest parçası yönetmesi gerekmez.
HAL istemci değişiklikleri
HAL istemci kodu, desteklenen her önceki dondurulmuş sürümle geriye dönük olarak uyumlu olmalıdır. RELEASE_AIDL_USE_UNFROZEN
false
olduğunda hizmetler her zaman son dondurulmuş sürüm veya daha önceki bir sürüm gibi görünür (ör. yeni dondurulmamış yöntemleri çağırmak UNKNOWN_TRANSACTION
değerini döndürür ya da yeni parcelable
alanları varsayılan değerlerine sahiptir). Android çerçevesi istemcilerinin önceki sürümlerle geriye dönük uyumlu olması gerekir. Ancak bu, satıcı istemcileri ve iş ortağına ait arayüzlerin istemcileri için yeni bir ayrıntıdır.
HAL uygulamasında yapılan değişiklikler
İşaret tabanlı geliştirme ile HAL geliştirme arasındaki en büyük fark, RELEASE_AIDL_USE_UNFROZEN
false
olduğunda çalışmak için HAL uygulamalarının son dondurulmuş sürümle geriye dönük uyumlu olması gerekliliğidir.
Uygulamalarda ve cihaz kodunda geriye dönük uyumluluğu göz önünde bulundurmak yeni bir uygulamadır. Sürümlendirilmiş arayüzleri kullanma başlıklı makaleyi inceleyin.
Geriye dönük uyumlulukla ilgili hususlar genellikle istemciler ve sunucular, çerçeve kodu ve satıcı kodu için aynıdır. Ancak artık aynı kaynak kodu (mevcut, dondurulmamış sürüm) kullanan iki sürümü etkili bir şekilde uyguladığınız için bilmeniz gereken küçük farklılıklar vardır.
Örnek: Bir arayüzün üç dondurulmuş sürümü var. Arayüz yeni bir yöntemle güncellenir. Hem istemci hem de hizmet, yeni 4. sürüm kitaplığını kullanacak şekilde güncellenir. V4 kitaplığı, arayüzün dondurulmamış bir sürümüne dayandığından RELEASE_AIDL_USE_UNFROZEN
false
olduğunda son dondurulmuş sürüm olan 3. sürüm gibi davranır ve yeni yöntemin kullanılmasını engeller.
Arayüz dondurulduğunda RELEASE_AIDL_USE_UNFROZEN
değerlerinin tümü bu dondurulmuş sürümü kullanır ve geriye dönük uyumluluğu işleyen kod kaldırılabilir.
Geri aramalarda yöntemleri çağırırken UNKNOWN_TRANSACTION
döndürüldüğünde durumu düzgün bir şekilde ele almanız gerekir. Müşteriler, yayın yapılandırmasına bağlı olarak geri çağırmanın iki farklı sürümünü uyguluyor olabilir. Bu nedenle, müşterinin en yeni sürümü gönderdiğini varsayamazsınız ve yeni yöntemler bunu döndürebilir. Bu, kararlı AIDL istemcilerinin Sürüm oluşturulmuş arayüzleri kullanma bölümünde açıklanan sunucularla geriye dönük uyumluluğu korumasına benzer.
// 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();
}
}
Mevcut türlerdeki (parcelable
, enum
, union
) yeni alanlar, RELEASE_AIDL_USE_UNFROZEN
false
olduğunda mevcut olmayabilir veya varsayılan değerlerini içerebilir. Ayrıca, bir hizmetin göndermeye çalıştığı yeni alanların değerleri, süreçten çıkarken bırakılır.
Bu sürümde eklenen yeni türler, arayüz üzerinden gönderilemez veya alınamaz.
RELEASE_AIDL_USE_UNFROZEN
değeri false
olduğunda uygulama, hiçbir istemciden yeni yöntemler için çağrı almaz.
Yeni numaralandırıcıları yalnızca kullanıma sunuldukları sürümde kullanmaya dikkat edin. Önceki sürümde kullanmayın.
Normalde, uzaktan arayüzün hangi sürümü kullandığını görmek için foo->getInterfaceVersion()
kullanılır. Ancak işaret tabanlı sürüm oluşturma desteğiyle iki farklı sürüm uyguladığınız için mevcut arayüzün sürümünü almak isteyebilirsiniz. Bunu, mevcut nesnenin arayüz sürümünü (ör. this->getInterfaceVersion()
) veya my_ver
için diğer yöntemleri kullanarak yapabilirsiniz. Daha fazla bilgi için Uzak nesnenin arayüz sürümünü sorgulama başlıklı makaleyi inceleyin.
Yeni VINTF kararlı arayüzleri
Yeni bir AIDL arayüz paketi eklendiğinde son dondurulmuş sürüm olmadığından RELEASE_AIDL_USE_UNFROZEN
false
olduğunda geri dönülecek bir davranış yoktur. Bu arayüzleri kullanmayın. RELEASE_AIDL_USE_UNFROZEN
değeri false
olduğunda, Hizmet Yöneticisi hizmetin arayüzü kaydetmesine izin vermez ve istemciler arayüzü bulamaz.
Hizmetleri, cihazın makefile'ındaki RELEASE_AIDL_USE_UNFROZEN
işaretinin değerine göre koşullu olarak ekleyebilirsiniz:
ifeq ($(RELEASE_AIDL_USE_UNFROZEN),true)
PRODUCT_PACKAGES += \
android.hardware.health.storage-service
endif
Hizmet daha büyük bir sürecin parçasıysa ve cihaza koşullu olarak eklenemiyorsa hizmetin IServiceManager::isDeclared()
ile bildirilip bildirilmediğini kontrol edebilirsiniz. Bildirilmişse ve kaydı başarısız olduysa işlemi durdurun. Bildirilmezse kaydın başarısız olması beklenir.
Yeni VINTF kararlı uzantı arayüzleri
Yeni uzantı arayüzlerinin
önceki bir sürümü yoktur ve ServiceManager
ile kaydedilmedikleri veya VINTF manifestlerinde bildirilmedikleri için
IServiceManager::isDeclared()
, uzantı arayüzünün başka bir arayüze ne zaman ekleneceğini belirlemek için kullanılamaz.
RELEASE_AIDL_USE_UNFROZEN
değişkeni, yeni dondurulmamış uzantı arayüzünün yayınlanan cihazlarda kullanılmasını önlemek için mevcut arayüze eklenip eklenmeyeceğini belirlemek üzere kullanılabilir. Arayüzün yayınlanan cihazlarda kullanılabilmesi için dondurulması gerekir.
vts_treble_vintf_vendor_test
ve vts_treble_vintf_framework_test
VTS testleri, yayınlanmış bir cihazda dondurulmamış bir uzantı arayüzü kullanıldığında bunu algılar ve hata verir.
Uzantı arayüzü yeni değilse ve daha önce dondurulmuş bir sürümü varsa bu dondurulmuş sürüme geri döner ve ek adım gerekmez.
Geliştirme aracı olarak Cuttlefish
VINTF dondurulduktan sonraki her yıl, çerçeve uyumluluk matrisini (FCM) target-level
ve Cuttlefish'in PRODUCT_SHIPPING_API_LEVEL
değerini, gelecek yılın sürümüyle kullanıma sunulan cihazları yansıtacak şekilde ayarlıyoruz. Gelecek yılki sürümün yeni şartlarını karşılayan ve test edilmiş bir başlatma cihazı olduğundan emin olmak için target-level
ve PRODUCT_SHIPPING_API_LEVEL
değerlerini ayarlıyoruz.
RELEASE_AIDL_USE_UNFROZEN
, true
olduğunda Cuttlefish, gelecekteki Android sürümlerinin geliştirilmesi için kullanılır. Bu, gelecek yılki Android sürümünün FCM düzeyini ve PRODUCT_SHIPPING_API_LEVEL
'yı hedefler. Bu nedenle, gelecek sürümün Tedarikçi Yazılımı Şartları'nı (VSR) karşılaması gerekir.
RELEASE_AIDL_USE_UNFROZEN
false
olduğunda Cuttlefish, yayınlanan cihazı yansıtmak için önceki target-level
ve PRODUCT_SHIPPING_API_LEVEL
'ye sahiptir.
Android 14 ve önceki sürümlerde bu farklılaştırma, FCM target-level
, gönderim API seviyesi veya sonraki sürümü hedefleyen başka bir kodda yapılan değişikliği almayan farklı Git dallarıyla gerçekleştirilir.
Modül adlandırma kuralları
Android 11'de, etkinleştirilen sürümlerin ve arka uçların her kombinasyonu için otomatik olarak bir saplama kitaplığı modülü oluşturulur. Bağlama için belirli bir sahte kitaplık modülüne başvurmak üzere aidl_interface
modülünün adını değil, sahte kitaplık modülünün adını kullanın. Bu ad, ifacename-version-backend biçimindedir.
ifacename
:aidl_interface
modülünün adıversion
şunlardan biridir:- Artık güncellenmeyen sürümler için
Vversion-number
Vlatest-frozen-version-number + 1
, tip-of-tree (henüz dondurulmamış) sürümü için
- Artık güncellenmeyen sürümler için
backend
şunlardan biridir:- Java arka ucu için
java
, - C++ arka ucu için
cpp
, - NDK arka ucu için
ndk
veyandk_platform
. Birincisi uygulamalar, ikincisi ise Android 13'e kadar platform kullanımı içindir. Android 13 ve sonraki sürümlerde yalnızcandk
simgesini kullanın. - Rust arka ucu için
rust
.
- Java arka ucu için
foo adlı bir modülün olduğunu ve bu modülün en son sürümünün 2 olduğunu varsayalım. Bu modül hem NDK'yı hem de C++'ı destekliyor. Bu durumda AIDL şu modülleri oluşturur:
- 1. sürüme göre
foo-V1-(java|cpp|ndk|ndk_platform|rust)
- Sürüm 2'ye (en son kararlı sürüm) göre
foo-V2-(java|cpp|ndk|ndk_platform|rust)
- ToT sürümüne göre
foo-V3-(java|cpp|ndk|ndk_platform|rust)
Android 11 ile karşılaştırıldığında:
foo-backend
, en son kararlı sürümü ifade edenfoo-V2-backend
olur.foo-unstable-backend
, ToT sürümünü ifade edenfoo-V3-backend
olur.
Çıkış dosyası adları her zaman modül adlarıyla aynıdır.
- 1. sürüme göre:
foo-V1-(cpp|ndk|ndk_platform|rust).so
- 2. sürüme göre:
foo-V2-(cpp|ndk|ndk_platform|rust).so
- ToT sürümüne göre:
foo-V3-(cpp|ndk|ndk_platform|rust).so
AIDL derleyicisinin, kararlı bir AIDL arayüzü için unstable
sürüm modülü veya sürüm içermeyen bir modül oluşturmadığını unutmayın.
Android 12'den itibaren, kararlı bir AIDL arayüzünden oluşturulan modül adı her zaman sürümünü içerir.
Yeni meta arayüz yöntemleri
Android 10, kararlı AIDL için çeşitli meta arayüz yöntemleri ekler.
Uzak nesnenin arayüz sürümünü sorgulama
İstemciler, uzak nesnenin uyguladığı arayüzün sürümünü ve karma değerini sorgulayabilir ve döndürülen değerleri, istemcinin kullandığı arayüzün değerleriyle karşılaştırabilir.
cpp
arka ucuyla ilgili örnek:
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
(ve ndk_platform
) arka ucuyla ilgili örnek:
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
arka ucuyla ilgili örnek:
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 dilinde, uzak taraf getInterfaceVersion()
ve getInterfaceHash()
işlevlerini aşağıdaki gibi uygulamalıdır (kopyalama ve yapıştırma hatalarını önlemek için IFoo
yerine super
kullanılır). @SuppressWarnings("static")
yapılandırmasına bağlı olarak uyarıları devre dışı bırakmak için javac
ek açıklaması gerekebilir:
class MyFoo extends IFoo.Stub {
@Override
public final int getInterfaceVersion() { return super.VERSION; }
@Override
public final String getInterfaceHash() { return super.HASH; }
}
Bunun nedeni, oluşturulan sınıfların (IFoo
, IFoo.Stub
vb.) istemci ve sunucu arasında paylaşılmasıdır (örneğin, sınıflar önyükleme sınıf yolunda olabilir). Sınıflar paylaşıldığında, arayüzün eski bir sürümüyle oluşturulmuş olsa bile sunucu, sınıfların en yeni sürümüne göre de bağlanır. Bu meta arayüz, paylaşılan sınıfta uygulanırsa her zaman en yeni sürümü döndürür. Ancak yukarıdaki yöntemi uygulayarak arayüzün sürüm numarası sunucunun koduna yerleştirilir (çünkü IFoo.VERSION
, referans verildiğinde satır içi yapılan bir static final int
'dir). Bu nedenle, yöntem sunucunun oluşturulduğu tam sürümü döndürebilir.
Eski arayüzlerle çalışma
Bir istemci, AIDL arayüzünün daha yeni bir sürümüyle güncellenmiş olabilir ancak sunucu eski AIDL arayüzünü kullanıyor olabilir. Bu gibi durumlarda, eski bir arayüzde bir yöntemin çağrılması UNKNOWN_TRANSACTION
değerini döndürür.
Kararlı AIDL ile istemciler daha fazla kontrol sahibi olur. İstemci tarafında, bir AIDL arayüzü için varsayılan uygulama ayarlayabilirsiniz. Varsayılan uygulamadaki bir yöntem yalnızca yöntem uzak tarafta uygulanmadığında (arayüzün eski bir sürümüyle oluşturulduğu için) çağrılır. Varsayılanlar genel olarak ayarlandığından, potansiyel olarak paylaşılan bağlamlardan kullanılmamalıdır.
Android 13 ve sonraki sürümlerde C++ örneği:
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'da örnek:
IFoo.Stub.setDefaultImpl(new IFoo.Default() {
@Override
public xxx anAddedMethod(...) throws RemoteException {
// do something default
}
}); // once per an interface in a process
foo.anAddedMethod(...);
Bir AIDL arayüzündeki tüm yöntemlerin varsayılan uygulamasını sağlamanız gerekmez. Uzak tarafta uygulanacağı kesin olan yöntemlerin (uzak tarafın, yöntemler AIDL arayüzü açıklamasındayken oluşturulduğundan eminseniz) varsayılan impl
sınıfında geçersiz kılınması gerekmez.
Mevcut AIDL'yi yapılandırılmış veya kararlı AIDL'ye dönüştürme
Mevcut bir AIDL arayüzünüz ve bunu kullanan bir kodunuz varsa arayüzü kararlı bir AIDL arayüzüne dönüştürmek için aşağıdaki adımları uygulayın.
Arayüzünüzün tüm bağımlılıklarını belirleyin. Arayüzün bağlı olduğu her paket için paketin kararlı AIDL'de tanımlanıp tanımlanmadığını belirleyin. Tanımlanmamışsa paket dönüştürülmelidir.
Arayüzünüzdeki tüm parcelable'ları kararlı parcelable'lara dönüştürün (arayüz dosyaları değişmeden kalabilir). Bunu, yapılarını doğrudan AIDL dosyalarında ifade ederek yapın. Yönetim sınıfları, bu yeni türleri kullanmak için yeniden yazılmalıdır. Bu işlem,
aidl_interface
paketi oluşturmadan önce (aşağıda) yapılabilir.Modülünüzün adını, bağımlılıklarını ve ihtiyacınız olan diğer bilgileri içeren bir
aidl_interface
paketi oluşturun (yukarıda açıklandığı gibi). Dengeli (yalnızca yapılandırılmış değil) olması için sürüm oluşturulması da gerekir. Daha fazla bilgi için Arayüzlere sürüm oluşturma başlıklı makaleyi inceleyin.