kararlı AIDL

Android 10, AIDL arayüzleri tarafından sağlanan uygulama programı arayüzünü (API)/uygulama ikili arayüzünü (ABI) takip etmenin yeni bir yolu olan kararlı Android Arayüz Tanımlama Dili (AIDL) desteğini ekler. Kararlı AIDL'nin AIDL'den aşağıdaki temel farklılıkları vardır:

  • Arayüzler yapı sisteminde aidl_interfaces ile tanımlanır.
  • Arayüzler yalnızca yapılandırılmış veriler içerebilir. İstenilen türleri temsil eden ayrıştırılabilirler, AIDL tanımlarına göre otomatik olarak oluşturulur ve otomatik olarak sıralanır ve sıralanmamış hale getirilir.
  • Arayüzler kararlı (geriye dönük uyumlu) olarak bildirilebilir. Bu gerçekleştiğinde, 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'ye karşı

Yapılandırılmış AIDL, yalnızca AIDL'de tanımlanan türleri ifade eder. Örneğin, parsellenebilir bir bildirim (özel bir parsellenebilir), AIDL olarak yapılandırılmış değildir. AIDL'de alanları tanımlanan parsellenebilirlere yapılandırılmış parsellenebilirler denir.

Kararlı AIDL, yapı sistemi ve derleyicinin parsellenebilir öğelerde yapılan değişikliklerin geriye dönük olarak 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ürleri kullanması ve ayrıca aşağıdaki sürüm oluşturma özelliklerini kullanması gerekir. Bunun tersine, bir arayüz, onu oluşturmak için çekirdek yapı sistemi kullanılıyorsa veya unstable:true ayarlanmışsa kararlı değildir.

AIDL arayüzünü tanımlama

aidl_interface tanımı şuna benzer:

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. com.acme paketinde tanımlanan AIDL türü Foo yolu <base_path>/com/acme/Foo.aidl konumunda olmalıdır; burada <base_path> , Android.bp bulunduğu dizinle ilişkili herhangi bir dizin olabilir. Yukarıdaki örnekte <base_path> srcs/aidl .
  • local_include_dir : Paket adının başladığı yol. Yukarıda açıklanan <base_path> e karşılık gelir.
  • imports : Bunun kullandığı aidl_interface modüllerinin listesi. AIDL arayüzlerinizden biri başka bir aidl_interface bir arayüz veya ayrıştırılabilir bir arayüz kullanıyorsa, adını buraya yazın. Bu, en son sürüme atıfta bulunmak için tek başına ad veya belirli bir sürüme atıfta bulunmak için sürüm son ekine sahip ad ( -V1 gibi) olabilir. Sürüm belirtme Android 12'den bu yana destekleniyor
  • versions : Arayüzün api_dir altında dondurulan önceki sürümleri, Android 11'den itibaren versions aidl_api/ name altında dondurulur. Bir arayüzün dondurulmuş versiyonları yoksa bu belirtilmemelidir ve uyumluluk kontrolleri yapılmayacaktır. Bu alan, 13 ve üzeri sürümler için versions_with_info ile değiştirildi.
  • versions_with_info : Her biri dondurulmuş bir sürümün adını ve aidl_interface'in bu sürümünün içe aktardığı diğer aidl_interface modüllerinin sürüm içe aktarımlarını içeren bir listeyi içeren tanımlama listeleri listesi. AIDL arayüzü IFACE'in V versiyonunun tanımı aidl_api/ IFACE / V adresinde bulunur. Bu alan Android 13'te tanıtıldı ve doğrudan Android.bp'de değiştirilmesi beklenmiyor. Alan *-update-api veya *-freeze-api çağrılarak eklenir veya güncellenir. Ayrıca, bir kullanıcı *-update-api veya *-freeze-api çağırdığında versions alanları otomatik olarak versions_with_info taşınır.
  • stability : Bu arayüzün kararlılık vaadi için isteğe bağlı işaret. Şu anda yalnızca "vintf" desteklemektedir. Bu ayarlanmadıysa, bu, bu derleme bağlamında kararlı bir arayüze karşılık gelir (bu nedenle buraya yüklenen bir arayüz yalnızca birlikte derlenen şeylerle kullanılabilir, örneğin system.img'de). Eğer bu "vintf" olarak ayarlanırsa, bu bir kararlılık vaadine karşılık gelir: Arayüz kullanıldığı sürece kararlı tutulmalıdır.
  • gen_trace : İzlemeyi açmak veya kapatmak için kullanılan isteğe bağlı bayrak. Android 14'ten başlayarak cpp ve java arka uçları için varsayılan değer true .
  • host_supported : true olarak ayarlandığında oluşturulan kitaplıkların ana bilgisayar ortamında kullanılabilir olmasını sağlayan isteğe bağlı bayrak.
  • unstable : Bu arayüzün kararlı olması gerekmediğini işaretlemek için kullanılan isteğe bağlı bayrak. Bu true olarak ayarlandığında, derleme sistemi arayüz için API dökümü oluşturmaz ve bunun güncellenmesini gerektirmez.
  • frozen : true olarak ayarlandığında arayüzün önceki arayüzü sürümünden bu yana hiçbir değişiklik olmadığı anlamına gelen isteğe bağlı bayrak. Bu, daha fazla derleme zamanı denetimi sağlar. false olarak ayarlandığında bu, arayüzün geliştirme aşamasında olduğu ve yeni değişikliklere sahip olduğu anlamına gelir; dolayısıyla foo-freeze-api çalıştırıldığında yeni bir sürüm oluşturulacak ve değer otomatik olarak true olarak değiştirilecektir. Android 14'te tanıtıldı.
  • backend.<type>.enabled : Bu bayraklar, AIDL derleyicisinin kod oluşturduğu arka uçların her birini değiştirir. Şu anda dört arka uç desteklenmektedir: 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 varsayılan olarak devre dışıdır.
  • backend.<type>.apex_available : Oluşturulan saplama kitaplığının mevcut olduğu APEX adlarının listesi.
  • backend.[cpp|java].gen_log : İşlem hakkında bilgi toplamak için ek kod oluşturulup oluşturulmayacağını denetleyen isteğe bağlı bayrak.
  • backend.[cpp|java].vndk.enabled : Bu arayüzü VNDK'nin bir parçası yapmak için isteğe bağlı işaret. Varsayılan false .
  • backend.[cpp|ndk].additional_shared_libraries : Android 14'te sunulan bu işaret, yerel kitaplıklara bağımlılıklar ekler. Bu bayrak ndk_header ve cpp_header ile kullanışlıdır.
  • backend.java.sdk_version : Java saplama kitaplığının oluşturulduğu SDK sürümünü belirten isteğe bağlı bayrak. Varsayılan "system_current" dır. backend.java.platform_apis doğru olduğunda bu ayarlanmamalıdır.
  • backend.java.platform_apis : Oluşturulan kitaplıkların SDK yerine platform API'sine göre derlenmesi gerektiğinde true olarak ayarlanması gereken isteğe bağlı bayrak.

Sürümlerin ve etkinleştirilen arka uçların her birleşimi için bir saplama kitaplığı oluşturulur. Belirli bir arka uç için saplama kitaplığının belirli bir sürümüne nasıl başvurulacağını öğrenmek için bkz . Modül adlandırma kuralları .

AIDL dosyalarını yazma

Kararlı AIDL'deki arayüzler, yapılandırılmamış parsellenebilirleri kullanmalarına izin verilmemesi dışında geleneksel arayüzlere benzer (çünkü bunlar kararlı değildir! bkz. Yapılandırılmış ve kararlı AIDL'ye karşı ). Kararlı AIDL'deki temel fark, parsellenebilirlerin nasıl tanımlandığıdır. Daha önce parsellenebilirler ileriye dönük beyan ediliyordu; Kararlı (ve dolayısıyla yapılandırılmış) AIDL'de parsellenebilir alanlar ve değişkenler 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 bir değer şu anda desteklenmektedir (ancak gerekli değildir). Android 12'de kullanıcı tanımlı numaralandırmalara yönelik varsayılanlar da desteklenir. Varsayılan belirtilmediğinde 0 benzeri 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.

Saplama kitaplıklarını kullanma

Stub kütüphanelerini modülünüze bağımlılık olarak ekledikten sonra bunları dosyalarınıza dahil edebilirsiniz. Aşağıda derleme sistemindeki saplama kitaplıklarının örnekleri verilmiştir ( Android.mk , eski modül tanımları için de kullanılabilir):

cc_... {
    name: ...,
    shared_libs: ["my-module-name-cpp"],
    ...
}
# or
java_... {
    name: ...,
    // can also be shared_libs if desire 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++'daki ö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 adında bir modül bildirmek aynı zamanda derleme sisteminde modülün API'sini yönetmek için kullanabileceğiniz bir hedef oluşturur. Oluşturulduğunda foo-freeze-api, Android sürümüne bağlı olarak api_dir veya aidl_api/ name altına yeni bir API tanımı ekler ve her ikisi de arayüzün yeni dondurulmuş sürümünü temsil eden bir .hash dosyası ekler. foo-freeze-api ayrıca ek sürümü ve sürüme yönelik imports yansıtacak şekilde versions_with_info özelliğini de günceller. Temel olarak, versions_with_info dosyasındaki imports imports alanından kopyalanır. Ancak en son kararlı sürüm, açık bir sürümü olmayan içe aktarma için versions_with_info dosyasındaki imports belirtilir. versions_with_info özelliği belirtildikten sonra derleme sistemi, dondurulmuş sürümler arasında ve ayrıca Ağacın Tepesi (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 güncellendiğinde, ToT sürümünün API tanımını içeren aidl_api/ name /current güncellemek için foo-update-api komutunu çalıştırın.

Bir arayüzün kararlılığını korumak için sahipler yenilerini ekleyebilir:

  • Bir arayüzün sonuna kadar olan yöntemler (veya açıkça tanımlanmış yeni serilere sahip yöntemler)
  • Bir parsellenebilirin sonuna kadar olan öğeler (her öğe için bir varsayılanın eklenmesini gerektirir)
  • Sabit değerler
  • Android 11'de numaralandırıcılar
  • Android 12'de birleşimin sonuna kadar olan alanlar

Başka hiçbir eyleme izin verilmez ve başka hiç kimse bir arayüzü değiştiremez (aksi takdirde, sahibinin yaptığı değişikliklerle çakışma riski vardır).

Tüm arayüzlerin yayınlanmak üzere dondurulduğunu test etmek için aşağıdaki çevresel değişkenleri kullanarak derleme yapabilirsiniz:

  • AIDL_FROZEN_REL=true m ... - yapı owner: alanı belirtilmemiş tüm kararlı AIDL arayüzlerinin dondurulmasını gerektirir.
  • AIDL_FROZEN_OWNERS="aosp test" - derleme, tüm kararlı AIDL arayüzlerinin owner: "aosp" veya "test" olarak belirtilen alan.

İthalatın istikrarı

Bir arayüzün dondurulmuş sürümleri için içe aktarma sürümlerinin güncellenmesi, Kararlı AIDL katmanında geriye dönük olarak uyumludur. Ancak bunların güncellenmesi, arayüzün eski sürümünü kullanan tüm sunucuların ve istemcilerin güncellenmesini gerektirir ve bazı uygulamalar, farklı tür sürümlerini karıştırırken karışabilir. Genel olarak, yalnızca türler veya ortak paketler için bu güvenlidir çünkü IPC işlemlerinden bilinmeyen türleri işlemek için kodun zaten yazılması gerekir.

Android platformunda android.hardware.graphics.common kodu bu tür sürüm yükseltmenin 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öntemleri çağırmaya çalışırken, yeni istemciler arka uca bağlı olarak bir hata veya bir istisna ile karşılaşırlar.

  • cpp arka ucu ::android::UNKNOWN_TRANSACTION alır.
  • ndk arka ucu STATUS_UNKNOWN_TRANSACTION alır.
  • java arka ucu, API'nin uygulanmadığını belirten bir mesajla android.os.RemoteException alır.

Bunu ele almaya yönelik stratejiler için sürümleri sorgulama ve varsayılanları kullanma konusuna bakın.

Parçalanabilirler

Parçalanabilirlere yeni alanlar eklendiğinde eski istemciler ve sunucular bunları bırakır. Yeni istemciler ve sunucular eski parsellenebilirleri aldığında, yeni alanlar için varsayılan değerler otomatik olarak doldurulur. Bu, bir parsellenebilirdeki tüm yeni alanlar için varsayılan değerlerin belirtilmesi gerektiği anlamına gelir.

İstemciler, sunucunun tanımlanmış alana sahip sürümü uyguladığını bilmedikçe sunucuların yeni alanları kullanmasını beklememelidir (bkz . sürüm sorgulama).

Numaralandırmalar ve sabitler

Benzer şekilde, gelecekte daha fazlası eklenebileceğinden, istemciler ve sunucular tanınmayan sabit değerleri ve numaralandırıcıları uygun şekilde reddetmeli veya yok saymalıdır. Örneğin, bir sunucu bilmediği bir numaralandırıcı aldığında iptal etmemelidir. Ya bunu görmezden gelmeli ya da müşterinin bu uygulamada desteklenmediğini bilmesi için bir şey döndürmelidir.

Sendikalar

Alıcının eski olması ve alandan haberi olmaması durumunda, yeni bir alanla birleşim göndermeye çalışmak başarısız olur. Uygulama hiçbir zaman yeni alanla birlik görmeyecektir. Tek yönlü bir işlemse başarısızlık göz ardı edilir; aksi halde hata BAD_VALUE (C++ veya NDK arka ucu için) veya IllegalArgumentException (Java arka ucu için). Hata, istemcinin eski bir sunucuya yeni alana bir birleşim seti göndermesi veya birleşimi yeni bir sunucudan alan eski bir istemci olması durumunda alınır.

Bayrak tabanlı geliştirme

Geliştirme aşamasındaki (dondurulmamış) arayüzler, sürüm cihazlarında kullanılamaz çünkü bunların geriye dönük uyumluluğu garanti edilmez.

AIDL, kodun en son dondurulmamış sürüme karşı yazılması ve yayın cihazlarında kullanılmaya devam edilmesi amacıyla bu dondurulmamış arayüz kitaplıkları için çalışma zamanı geri dönüşünü destekler. İstemcilerin geriye dönük uyumlu davranışları mevcut davranışlara benzer ve geri dönüşle birlikte uygulamaların da bu davranışları takip etmesi gerekir. Bkz . Sürümlendirilmiş arayüzleri kullanma .

AIDL oluşturma bayrağı

Bu davranışı kontrol eden bayrak build/release/build_flags.bzl dosyasında tanımlanan RELEASE_AIDL_USE_UNFROZEN . true , arayüzün dondurulmamış sürümünün çalışma zamanında kullanıldığı anlamına gelir ve false , dondurulmamış sürümlerin kitaplıklarının hepsinin son dondurulmuş sürümleri gibi davrandığı anlamına gelir. Yerel geliştirme için bayrağı true olarak geçersiz kılabilirsiniz ancak yayınlanmadan önce onu false değerine döndürmeniz gerekir. Genellikle geliştirme, bayrağı true olarak ayarlanmış bir yapılandırmayla yapılır.

Uyumluluk matrisi ve bildirimleri

Satıcı arayüzü nesneleri (VINTF nesneleri) , hangi sürümlerin beklendiğini ve satıcı arayüzünün her iki tarafında hangi sürümlerin sağlandığını tanımlar.

Mürekkepbalığı olmayan cihazların çoğu, yalnızca arayüzler dondurulduktan sonra en son uyumluluk matrisini hedefler, bu nedenle RELEASE_AIDL_USE_UNFROZEN dayalı AIDL kitaplıklarında hiçbir fark yoktur.

İş ortağına ait arayüzler, cihazın geliştirme sırasında hedeflediği cihaza özel veya ürüne özel uyumluluk matrislerine eklenir. Dolayısıyla, uyumluluk matrisine bir arayüzün dondurulmamış yeni bir sürümü eklendiğinde, RELEASE_AIDL_USE_UNFROZEN=false için önceki dondurulmuş sürümlerin 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 halledebilirsiniz.

Örneğin, dondurulmamış bir sürüm 4 eklerken <version>3-4</version> kullanın.

Sürüm 4 dondurulduğunda, sürüm 3'ü uyumluluk matrisinden kaldırabilirsiniz çünkü RELEASE_AIDL_USE_UNFROZEN false olduğunda dondurulmuş sürüm 4 kullanılır.

HAL istemci değişiklikleri

HAL istemci kodunun önceki desteklenen donmuş sürümlerle geriye dönük olarak uyumlu olması gerekir. RELEASE_AIDL_USE_UNFROZEN false olduğunda, hizmetler her zaman en son dondurulmuş sürüme veya daha önceki sürüme benzer (örneğin, yeni dondurulmamış yöntemlerin çağrılması UNKNOWN_TRANSACTION değerini döndürür veya yeni parcelable alanlar varsayılan değerlerine sahiptir). Android çerçeve istemcilerinin önceki ek sürümlerle geriye dönük olarak uyumlu olması gerekir, ancak bu, satıcı istemciler ve iş ortaklarına ait arayüzlerin istemcileri için yeni bir ayrıntıdır.

HAL uygulama değişiklikleri

Bayrak tabanlı geliştirmeyle 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 olarak uyumlu olması gerekliliğidir. Uygulamalarda ve cihaz kodunda geriye dönük uyumluluğun dikkate alınması yeni bir uygulamadır. Bkz . Sürümlendirilmiş arayüzleri kullanma .

Geriye dönük uyumlulukla ilgili hususlar genellikle istemciler ve sunucular ile çerçeve kodu ve satıcı kodu için aynıdır, ancak artık aynı kaynak kodunu kullanan iki sürümü etkili bir şekilde uyguladığınızdan, bilmeniz gereken ince farklar vardır. (mevcut, dondurulmamış sürüm).

Örnek: Bir arayüzün üç dondurulmuş versiyonu vardır. Arayüz yeni bir yöntemle güncellendi. İstemci ve hizmetin her ikisi de yeni sürüm 4 kitaplığını kullanacak şekilde güncellendi. V4 kitaplığı arayüzün dondurulmamış bir sürümünü temel aldığından, RELEASE_AIDL_USE_UNFROZEN false olduğunda son dondurulmuş sürüm olan sürüm 3 gibi davranır ve yeni yöntemin kullanılmasını engeller.

Arayüz dondurulduğunda RELEASE_AIDL_USE_UNFROZEN tüm değerleri bu dondurulmuş sürümü kullanır ve geriye dönük uyumluluğu işleyen kod kaldırılabilir.

Geri çağırmalarda yöntemleri çağırırken, UNKNOWN_TRANSACTION döndürüldüğünde durumu incelikle ele almalısınız. İstemciler, sürüm yapılandırmasına bağlı olarak bir geri çağırmanın iki farklı sürümünü uyguluyor olabilir; dolayısıyla istemcinin en yeni sürümü göndereceğini varsayamazsınız ve yeni yöntemler bunu döndürebilir. Bu, AIDL istemcilerinin , Sürümlü arayüzleri kullanma bölümünde açıklanan sunucularla geriye dönük uyumluluğu ne kadar istikrarlı koruduğuna 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();
  }
}

RELEASE_AIDL_USE_UNFROZEN false olduğunda ve bir hizmetin göndermeye çalıştığı yeni alanların değerleri işlemden çıkarken bırakıldığında, mevcut türlerdeki ( parcelable , enum , union ) yeni alanlar mevcut olmayabilir veya varsayılan değerlerini içermeyebilir.

Dondurulmamış bu sürümde eklenen yeni türler, arayüz üzerinden gönderilemez veya alınamaz.

RELEASE_AIDL_USE_UNFROZEN false olduğunda uygulama hiçbir zaman istemcilerden yeni yöntemler için çağrı almaz.

Yeni numaralandırıcıları önceki sürümle değil, yalnızca tanıtıldıkları sürümle kullanmaya dikkat edin.

Normalde uzak arayüzün hangi sürümü kullandığını görmek için foo->getInterfaceVersion() kullanırsınız. Ancak bayrak tabanlı sürüm oluşturma desteğiyle iki farklı sürüm uyguluyorsunuz, dolayısıyla mevcut arayüzün sürümünü almak isteyebilirsiniz. Bunu, geçerli nesnenin arayüz sürümünü (örneğin this->getInterfaceVersion() veya my_ver için diğer yöntemleri alarak yapabilirsiniz. Daha fazla bilgi için bkz . Uzak nesnenin arayüz sürümünü sorgulama .

Yeni VINTF kararlı arayüzler

Yeni bir AIDL arayüz paketi eklendiğinde, dondurulmuş son sürüm yoktur, dolayısıyla RELEASE_AIDL_USE_UNFROZEN false olduğunda geri dönülecek bir davranış yoktur. Bu arayüzleri kullanmayın. RELEASE_AIDL_USE_UNFROZEN false olduğunda, Hizmet Yöneticisi hizmetin arayüzü kaydetmesine izin vermez ve istemciler onu bulamaz.

Hizmetleri, aygıt makefile'ındaki RELEASE_AIDL_USE_UNFROZEN bayrağının 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 onu koşullu olarak cihaza ekleyemiyorsanız, hizmetin IServiceManager::isDeclared() ile bildirilip bildirilmediğini kontrol edebilirsiniz. Bildirildiyse ve kayıt yapılamadıysa işlemi iptal edin. Bildirilmediği takdirde kayıt işleminin başarısız olması beklenir.

Bir geliştirme aracı olarak mürekkepbalığı

Her yıl VINTF dondurulduktan sonra, Mürekkepbalığı'nın çerçeve uyumluluk matrisi (FCM) target-level ve PRODUCT_SHIPPING_API_LEVEL , gelecek yılın sürümüyle piyasaya sürülecek cihazları yansıtacak şekilde ayarlıyoruz. Test edilen ve gelecek yılın sürümü için yeni gereksinimleri karşılayan bir başlatma cihazı olduğundan emin olmak için target-level ve PRODUCT_SHIPPING_API_LEVEL ayarlıyoruz.

RELEASE_AIDL_USE_UNFROZEN true olduğunda Mürekkepbalığı gelecekteki Android sürümlerinin geliştirilmesi için kullanılır. Gelecek yılın Android sürümünün FCM düzeyini ve PRODUCT_SHIPPING_API_LEVEL değerini hedefleyerek bir sonraki sürümün Satıcı Yazılım Gereksinimlerini (VSR) karşılamasını gerektirir.

RELEASE_AIDL_USE_UNFROZEN false olduğunda Mürekkepbalığı bir önceki target-level ve bir sürüm cihazını yansıtacak şekilde PRODUCT_SHIPPING_API_LEVEL sahiptir. Android 14 ve önceki sürümlerde bu farklılaştırma, FCM target-level , gönderim API düzeyindeki veya sonraki sürümü hedefleyen herhangi bir koddaki değişikliği algılamayan farklı Git dallarıyla gerçekleştirilir.

Modül adlandırma kuralları

Android 11'de, sürümlerin ve etkinleştirilen arka uçların her birleşimi için otomatik olarak bir saplama kitaplığı modülü oluşturulur. Bağlanmak üzere belirli bir saplama kitaplığı modülüne başvurmak için aidl_interface modülünün adını değil, saplama kitaplığı modülünün ifacename - version - backend adını kullanın; burada

  • ifacename : aidl_interface modülünün adı
  • version ikisinden biri
    • Dondurulmuş versiyonlar için V version-number
    • V latest-frozen-version-number + 1
  • backend ikisinden biri
    • Java arka ucu için java ,
    • C++ arka ucu için cpp ,
    • NDK arka ucu için ndk veya ndk_platform . İlki uygulamalar içindir, ikincisi ise platform kullanımı içindir.
    • Rust'ın arka ucu için rust .

Foo adında bir modül olduğunu ve en son sürümünün 2 olduğunu ve hem NDK'yı hem de C++'ı desteklediğini varsayalım. Bu durumda AIDL şu modülleri oluşturur:

  • Sürüm 1'e göre
    • foo-V1-(java|cpp|ndk|ndk_platform|rust)
  • Sürüm 2'ye dayanmaktadır (en son kararlı sürüm)
    • 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,

  • En son kararlı sürüme atıfta bulunan foo- backend , foo- V2 - backend olur
  • ToT sürümüne atıfta bulunan foo-unstable- backend , foo- V3 - backend olur

Çıktı dosyası adları her zaman modül adlarıyla aynıdır.

  • Sürüm 1'e dayanmaktadır: foo-V1-(cpp|ndk|ndk_platform|rust).so
  • Sürüm 2'ye dayanmaktadır: foo-V2-(cpp|ndk|ndk_platform|rust).so
  • ToT sürümüne dayanmaktadır: foo-V3-(cpp|ndk|ndk_platform|rust).so

AIDL derleyicisinin, kararlı bir AIDL arayüzü için unstable bir sürüm modülü veya sürümü olmayan 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 onun 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 karmasını sorgulayabilir ve döndürülen değerleri, istemcinin kullandığı arayüzün değerleriyle karşılaştırabilir.

cpp arka ucuyla ö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 ö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 dili için, uzak tarafın getInterfaceVersion() ve getInterfaceHash() ı aşağıdaki gibi uygulaması ZORUNLUDUR (kopyalama/yapıştırma hatalarını önlemek için IFoo yerine super kullanılır. Uyarıları devre dışı bırakmak için @SuppressWarnings("static") açıklamasına ihtiyaç duyulabilir. javac yapılandırması):

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, sunucu, arayüzün eski bir sürümüyle oluşturulmuş olsa bile, sınıfların en yeni sürümüne 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. Bununla birlikte, yukarıdaki yöntemin uygulanmasıyla, arayüzün sürüm numarası sunucunun koduna gömülür (çünkü IFoo.VERSION başvurulduğunda satır içi olan static final int ) ve böylece yöntem, sunucunun oluşturulduğu tam sürümü döndürebilir. ile.

Eski arayüzlerle uğraşmak

Bir istemcinin AIDL arayüzünün daha yeni bir sürümüyle güncellenmesi mümkündür ancak sunucu eski AIDL arayüzünü kullanıyordur. 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 kontrole sahip olur. İstemci tarafında, AIDL arayüzüne varsayılan bir uygulama ayarlayabilirsiniz. Varsayılan uygulamadaki bir yöntem yalnızca yöntem uzak tarafta uygulanmadığında çağrılır (çünkü arabirimin daha eski bir sürümüyle oluşturulmuştur). Varsayılanlar genel olarak ayarlandığından potansiyel olarak paylaşılan bağlamlarda 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(...);

AIDL arayüzündeki tüm yöntemlerin varsayılan uygulamasını sağlamanıza gerek yoktur. Uzak tarafta uygulanması garanti edilen yöntemlerin (çünkü uzaktan kumandanın, yöntemler AIDL arabirim açıklamasındayken oluşturulduğundan emin olduğunuzdan) varsayılan impl sınıfında geçersiz kılınmasına gerek yoktur.

Mevcut AIDL'yi yapılandırılmış/kararlı AIDL'ye dönüştürme

Mevcut bir AIDL arayüzünüz ve onu kullanan kodunuz varsa, arayüzü kararlı bir AIDL arayüzüne dönüştürmek için aşağıdaki adımları kullanın.

  1. Arayüzünüzün tüm bağımlılıklarını tanımlayın. 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 paketin dönüştürülmesi gerekir.

  2. Arayüzünüzdeki tüm parsellenebilirleri kararlı parsellenebilirlere dönüştürün (arayüz dosyalarının kendisi değişmeden kalabilir). Bunu, yapılarını doğrudan AIDL dosyalarında ifade ederek yapın. Bu yeni türleri kullanmak için yönetim sınıflarının yeniden yazılması gerekir. Bu, aidl_interface paketini oluşturmadan önce yapılabilir (aşağıda).

  3. 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 (yukarıda açıklandığı gibi) oluşturun. Stabil hale getirmek için (yalnızca yapılandırılmış değil), aynı zamanda sürümlendirilmesi de gerekir. Daha fazla bilgi için bkz . Sürüm oluşturma arayüzleri .