Android 10 unterstützt die stabile Android-Oberfläche Definition Language (AIDL), eine neue Möglichkeit, den Überblick über das Anwendungsprogramm zu behalten Interface (API) und Binärschnittstelle (Application binary Interface, ABI) von AIDL Schnittstellen. Stabile AIDL funktioniert genauso wie AIDL, aber das Build-System verfolgt die Kompatibilität der Benutzeroberfläche. Außerdem gelten bestimmte Einschränkungen im Hinblick auf Folgendes:
- Schnittstellen werden im Build-System mit
aidl_interfaces
definiert. - Schnittstellen können nur strukturierte Daten enthalten. Parcelables, die für die bevorzugte Typen automatisch anhand ihrer AIDL-Definition und automatisch marschiert und unmarshalliert.
- Schnittstellen können als stabil (abwärtskompatibel) deklariert werden. Wenn diese wird ihre API in einer Datei neben der AIDL nachverfolgt und versioniert. .
Strukturierte vs. stabile AIDL
Strukturierte AIDL bezieht sich auf Typen, die ausschließlich in AIDL definiert sind. Beispiel: Die Deklaration „parcelable“ (ein benutzerdefiniertes Paket) ist keine strukturierte AIDL. Parcelables Die in AIDL definierten Felder werden als strukturierte Parcelables bezeichnet.
Stabiler AIDL erfordert eine strukturierte AIDL, damit das Build-System und der Compiler erstellt werden können
können Sie nachvollziehen, ob Änderungen
an Paketen abwärtskompatibel sind.
Allerdings sind nicht alle strukturierten Oberflächen stabil. Um stabil zu bleiben,
Eine Schnittstelle darf nur strukturierte Typen sowie Folgendes enthalten:
Funktionen zur Versionsverwaltung. Umgekehrt ist eine Schnittstelle nicht stabil, wenn der Core
System verwendet wird, oder wenn unstable:true
festgelegt ist.
AIDL-Schnittstelle definieren
Eine Definition von aidl_interface
sieht so aus:
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
: Der Name des AIDL-Schnittstellenmoduls, das ein AIDL-Schnittstelle.srcs
: Die Liste der AIDL-Quelldateien, aus denen die Schnittstelle besteht. Der Pfad Für einen in einem Paket definierten AIDL-TypFoo
muss sichcom.acme
hier befinden:<base_path>/com/acme/Foo.aidl
, wobei<base_path>
ein beliebiges Verzeichnis sein kann zu dem Verzeichnis, in dem sichAndroid.bp
befindet. Im vorherigen Beispiel<base_path>
istsrcs/aidl
.local_include_dir
: Pfad, von dem aus der Paketname beginnt. Es entspricht dem oben erläuterten<base_path>
.imports
: Eine Liste vonaidl_interface
-Modulen, die verwendet werden. Wenn eines Ihrer AIDL-Schnittstellen verwenden eine Schnittstelle oder ein Paket von einer anderenaidl_interface
, gib hier den Namen ein. Das kann der Name selbst, auf die neuesten Version oder der Name mit dem Versionssuffix (z. B.-V1
) für den Verweis einer bestimmten Version. Die Angabe einer Version wird seit Android 12 unterstütztversions
: Die vorherigen Versionen der Benutzeroberfläche, die unterapi_dir
eingefroren, ab Android 11 Dieversions
sind unteraidl_api/name
fixiert. Wenn es keine fixierten Versionen einer Schnittstelle gibt, Das sollte nicht angegeben werden und es gibt keine Kompatibilitätsprüfungen. Dieses Feld wurde durchversions_with_info
für Android ersetzt 13 und höher.versions_with_info
: Liste der Tupel, von denen jedes den Namen eines eingefrorene Version und eine Liste mit Versionsimporten anderer aidl_interface Module, die von dieser Version von aidl_interface importiert wurden. Die Definition der Version V einer AIDL-Schnittstelle, die sich unter IFACE befindetaidl_api/IFACE/V
Dieses Feld wurde mit Android 13 eingeführt. und nicht direkt inAndroid.bp
geändert werden soll. Das Feld ist durch Aufrufen von*-update-api
oder*-freeze-api
hinzugefügt oder aktualisiert wurde. Außerdem werdenversions
-Felder automatisch zuversions_with_info
migriert. Ein Nutzer ruft*-update-api
oder*-freeze-api
auf.stability
: Das optionale Flag für das Stabilitätversprechen dieser Schnittstelle. Dies unterstützt nur"vintf"
. Wennstability
nicht festgelegt ist, wird der Build System prüft, ob die Schnittstelle abwärtskompatibel ist, es sei denn,unstable
ist angegeben. Wenn die Festlegung nicht festgelegt ist, entspricht dies einer Schnittstelle mit Stabilität innerhalb dieses Kompilierungskontexts (also entweder alle Systemelemente, z. B. Dinge insystem.img
und die zugehörigen Partitionen oder alle Anbieter Dinge, z. B. Dinge invendor.img
und zugehörige Partitionen). Wennstability
ist auf"vintf"
gesetzt, was einem Stabilitätsversprechen entspricht: muss die Schnittstelle während ihrer Verwendung stabil gehalten werden.gen_trace
: Das optionale Flag zum Aktivieren oder Deaktivieren des Tracings. Beginnt in Android 14 ist die Standardeinstellungtrue
fürcpp
undjava
Back-Ends.host_supported
: Das optionale Flag, das bei Einstellung auftrue
den Bibliotheken generiert, die für die Hostumgebung zur Verfügung stehen.unstable
: Das optionale Flag, das verwendet wird, um zu kennzeichnen, dass diese Schnittstelle nicht müssen stabil sein. Wenn dieser Wert auftrue
gesetzt ist, hat das Build-System weder erstellt den API-Dump für die Schnittstelle und muss nicht aktualisiert werden.frozen
: Das optionale Flag, das bei Einstellung auftrue
bedeutet, dass die Schnittstelle keine Änderungen seit der vorherigen Version der Benutzeroberfläche. Dies ermöglicht mehr Überprüfungen während der Build-Erstellung. Wennfalse
festgelegt ist, befindet sich die Schnittstelle in und neue Änderungen enthält, sodass das Ausführen vonfoo-freeze-api
ein neue Version hinzu und ändern Sie den Wert automatisch intrue
. Vorgestellt in Android 14backend.<type>.enabled
: Diese Flags aktivieren/deaktivieren die einzelnen Back-Ends, für den der AIDL-Compiler Code generiert. Vier Back-Ends werden unterstützt: Java, C++, NDK und Rust. Java-, C++- und NDK-Back-Ends sind aktiviert ist standardmäßig aktiviert. Wenn eines dieser drei Back-Ends nicht benötigt wird, explizit deaktiviert werden. Rust ist bis Android standardmäßig deaktiviert 15 (AOSP experimentell)backend.<type>.apex_available
: Die Liste der APEX-Namen, die generiert wurden -Stub-Bibliothek verfügbar ist.backend.[cpp|java].gen_log
: Das optionale Flag, das steuert, ob Zusätzlichen Code zum Sammeln von Informationen zur Transaktion generieren.backend.[cpp|java].vndk.enabled
: Das optionale Flag zum Erstellen dieser Schnittstelle. Teil des VNDK. Der Standardwert istfalse
.backend.[cpp|ndk].additional_shared_libraries
: Vorgestellt in Unter Android 14 fügt dieses Flag Abhängigkeiten zum native Bibliotheken. Dieses Flag ist fürndk_header
undcpp_header
nützlich.backend.java.sdk_version
: Das optionale Flag zum Angeben der Version des SDK, für das die Java-Stub-Bibliothek erstellt wurde. Die Standardeinstellung ist"system_current"
Sollte nicht festgelegt werden, wennbackend.java.platform_apis
isttrue
.backend.java.platform_apis
: Das optionale Flag, das auftrue
, wenn die generierten Bibliotheken für die Plattform-API erstellt werden müssen anstatt auf das SDK.
Für jede Kombination der Versionen und aktivierten Back-Ends wird ein Stub Bibliothek erstellt wird. So verweisen Sie auf die spezifische Version der Stub-Bibliothek für ein bestimmtes Back-End finden Sie unter Benennungsregeln für Module.
AIDL-Dateien schreiben
Schnittstellen in der stabilen AIDL ähneln herkömmlichen Schnittstellen, wobei die Sie dürfen keine unstrukturierten Parcelables verwenden, diese sind nicht stabil! Siehe Strukturiert im Vergleich zu stabil AIDL. Der Hauptunterschied bei der stabilen AIDL besteht darin, Parcelables definiert sind. Zuvor wurden Parcelables Forward deklariert; in stabile (und daher strukturierte) AIDL, Parcelables-Felder und Variablen explizit definiert ist.
// in a file like 'some/package/Thing.aidl'
package some.package;
parcelable SubThing {
String a = "foo";
int b;
}
Ein Standardwert wird unterstützt (aber nicht erforderlich) für boolean
, char
,
float
, double
, byte
, int
, long
und String
. In Android
12 sind Standardeinstellungen für benutzerdefinierte Aufzählungen
unterstützt. Wenn kein Standardwert angegeben ist, wird ein 0-ähnlicher oder leerer Wert verwendet.
Aufzählungen ohne Standardwert werden mit 0 initialisiert, selbst wenn
Kein Zähler mit Null.
Stub-Bibliotheken verwenden
Nachdem Sie Stub-Bibliotheken als Abhängigkeit zu Ihrem Modul hinzugefügt haben,
die Sie in Ihre Dateien einfügen können. Hier sind Beispiele für Stub-Bibliotheken in der
Build-System erstellen (Android.mk
kann auch für Legacy-Moduldefinitionen verwendet werden):
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"],
...
}
Beispiel in C++:
#include "some/package/IFoo.h"
#include "some/package/Thing.h"
...
// use just like traditional AIDL
Beispiel in Java:
import some.package.IFoo;
import some.package.Thing;
...
// use just like traditional AIDL
Beispiel in Rust:
use aidl_interface_name::aidl::some::package::{IFoo, Thing};
...
// use just like traditional AIDL
Versionsverwaltung von Schnittstellen
Wird ein Modul mit dem Namen foo deklariert, wird auch ein Ziel im Build-System erstellt.
mit dem Sie die API des Moduls verwalten können. Nach der Erstellung wird foo-Free-api
fügt unter api_dir
eine neue API-Definition hinzu oder
aidl_api/name
, je nach Android-Version und
fügt eine .hash
-Datei hinzu, die beide die neu fixierte Version des
. Mit foo-Free-api wird auch die Eigenschaft versions_with_info
aktualisiert.
um die zusätzliche Version und imports
für die Version widerzuspiegeln. Grundsätzlich
„imports
“ im Feld „versions_with_info
“ wird aus dem Feld „imports
“ kopiert. Die
die neueste stabile Version ist in imports
in versions_with_info
für die
für die es keine explizite Version gibt.
Nachdem das Attribut versions_with_info
angegeben wurde, wird das Build-System ausgeführt.
Kompatibilitätsprüfungen zwischen eingefrorenen Versionen und zwischen Top of Tree (ToT)
und die neueste eingefrorene Version.
Außerdem musst du die API-Definition der ToT-Version verwalten. Wenn eine API
aktualisiert: Führen Sie zum Aktualisieren foo-update-api aus.
aidl_api/name/current
die die API-Definition der ToT-Version enthält.
Um die Stabilität einer Oberfläche zu wahren, können Inhaber neue Elemente hinzufügen:
- Methoden am Ende einer Schnittstelle (oder Methoden mit explizit definierten neuen Seriennummern)
- Elemente am Ende eines Pakets (erfordert das Hinzufügen eines Standardwerts für jedes Attribut) -Element)
- Konstantenwerte
- In Android 11 können Zähler
- In Android 12 sind Felder am Ende einer Union (Union)
Andere Aktionen sind nicht zulässig und niemand sonst kann eine Schnittstelle ändern. (Andernfalls riskieren sie einen Konflikt mit Änderungen, die der Inhaber vornimmt.)
Um zu testen, ob alle Schnittstellen für die Veröffentlichung eingefroren sind, können Sie einen Build mit dem folgende Umgebungsvariablen festgelegt:
AIDL_FROZEN_REL=true m ...
– für den Build sind alle stabilen AIDL-Schnittstellen erforderlich, um für die keinowner:
-Feld angegeben ist.AIDL_FROZEN_OWNERS="aosp test"
– für den Build sind alle stabilen AIDL-Schnittstellen erforderlich wird mit demowner:
-Feld als "aosp" fixiert oder „Test“.
Stabilität von Importen
Das Aktualisieren der Importversionen für eingefrorene Versionen einer Schnittstelle auf der stabilen AIDL-Ebene. Die Aktualisierung erfordert jedoch, Aktualisierung aller Server und Clients, die eine frühere Version der Benutzeroberfläche verwenden und einige Apps können verwirrt sein, wenn sie verschiedene Versionen von Typen mischen. Im Allgemeinen ist dies bei nur Typen oder gängigen Paketen sicher, da der Code bereits geschrieben wurden, um unbekannte Typen aus IPC-Transaktionen zu verarbeiten.
Im Android-Plattformcode ist android.hardware.graphics.common
der größte
Beispiel für diese Art von Versionsupgrade.
Versionierte Schnittstellen verwenden
Schnittstellenmethoden
Zur Laufzeit erhalten neue Clients, wenn Sie versuchen, neue Methoden auf einem alten Server aufzurufen, je nach Back-End entweder einen Fehler oder eine Ausnahme.
cpp
-Back-End erhält::android::UNKNOWN_TRANSACTION
.ndk
-Back-End erhältSTATUS_UNKNOWN_TRANSACTION
.- Das
java
-Backend erhältandroid.os.RemoteException
mit einer Meldung, die besagt, dass Die API ist nicht implementiert.
Strategien zur Bewältigung dieses Problems finden Sie unter Abfragen von Versionen und Standardeinstellungen verwenden.
Parcelables
Wenn zu Paketen neue Felder hinzugefügt werden, werden sie von alten Clients und Servern verworfen. Wenn neue Clients und Server alte Pakete erhalten, werden die Standardwerte für neue werden automatisch ausgefüllt. Das bedeutet, dass Standardeinstellungen für alle neuen Felder in einem Paket angegeben.
Clients sollten nicht erwarten, dass Server die neuen Felder verwenden, es sei denn, sie kennen der Server die Version implementiert, für die das Feld definiert ist (siehe Abfragen von Versionen) ausführen.
Enums und Konstanten
Ebenso sollten Clients und Server nicht erkannte Elemente entweder ablehnen oder ignorieren. je nach Bedarf konstante Werte und Zähler, da weitere addiert werden können. in die Zukunft zu führen. Ein Server sollte z. B. nicht abgeschaltet werden, wenn er eine den es nicht kennt. Der Server sollte das Feld oder etwas zurückgeben, damit der Client weiß, dass dies nicht diese Implementierung.
Gewerkschaften
Der Versuch, eine Union mit einem neuen Feld zu senden, schlägt fehl, wenn der Empfänger alt und
auf diesem Gebiet nicht weiß. Bei der Implementierung wird die Vereinigung mit
in das neue Feld ein. Der Fehler wird ignoriert, wenn es sich um
One-Way-Transaktion Andernfalls ist der Fehler BAD_VALUE
(für die C++- oder NDK-
Back-End) oder IllegalArgumentException
(für das Java-Back-End). Der Fehler lautet
empfangen, wenn der Client einen Union-Set-Wert für das neue Feld an ein altes
oder wenn es sich um einen alten Client handelt, der die Union von einem neuen Server erhält.
Flag-basierte Entwicklung
In der Entwicklung befindliche (nicht eingefrorene) Schnittstellen können auf Release-Geräten nicht verwendet werden, weil dass sie nicht abwärtskompatibel sind.
AIDL unterstützt das Laufzeit-Fallback für diese nicht eingefrorenen Schnittstellenbibliotheken der Reihe nach damit Code für die neueste nicht eingefrorene Version geschrieben und weiterhin verwendet wird. auf Release-Geräten. Das abwärtskompatible Verhalten von Clients ähnelt und mit dem Fallback müssen die Implementierungen für diese Verhaltensweisen. Weitere Informationen finden Sie unter Versionierte Schnittstellen verwenden
AIDL-Build-Flag
Das Flag, das dieses Verhalten steuert, ist RELEASE_AIDL_USE_UNFROZEN
definiert in build/release/build_flags.bzl
. true
steht für die nicht eingefrorene Version von
die Schnittstelle zur Laufzeit verwendet wird, und false
steht für die Bibliotheken des
Nicht eingefrorene Versionen verhalten sich wie ihre letzte eingefrorene Version.
Sie können das Flag mit true
überschreiben für
lokale Entwicklung, muss aber vor der Veröffentlichung auf false
zurückgesetzt werden. Normalerweise
Die Entwicklung erfolgt mit einer Konfiguration, für die das Flag auf true
gesetzt ist.
Kompatibilitätsmatrix und Manifeste
Anbieterschnittstellenobjekte (VINTF-Objekte) definieren welche Versionen erwartet werden und welche Versionen auf beiden Seiten über die Benutzeroberfläche des Anbieters.
Die meisten Geräte, die nicht Sepia sind, richten sich nach der neuesten Kompatibilitätsmatrix
nachdem Schnittstellen eingefroren sind, gibt es also keinen Unterschied in der AIDL
Bibliotheken basierend auf RELEASE_AIDL_USE_UNFROZEN
.
Matrizen
Geräte- oder produktspezifische Benutzeroberflächen des Partners werden hinzugefügt.
Kompatibilitätsmatrixs, auf die das Gerät bei der Entwicklung ausgerichtet ist. Wenn also ein
einer Kompatibilitätsmatrix eine neue, nicht eingefrorene Version
müssen die vorherigen eingefrorenen Versionen
RELEASE_AIDL_USE_UNFROZEN=false
Sie können dies erreichen, indem Sie verschiedene
Kompatibilitätsmatrix-Dateien für verschiedene RELEASE_AIDL_USE_UNFROZEN
Konfigurationen oder beide Versionen in einer einzigen Kompatibilitätsmatrix-Datei zulassen
der in allen Konfigurationen verwendet wird.
Wenn Sie beispielsweise eine nicht fixierte Version 4 hinzufügen, verwenden Sie <version>3-4</version>
.
Wenn Version 4 eingefroren ist, kannst du Version 3 aus der Kompatibilitätsmatrix entfernen
da die eingefrorene Version 4 verwendet wird, wenn RELEASE_AIDL_USE_UNFROZEN
false
.
Manifeste
In Android 15 (AOSP experimentell) wird eine Änderung in libvintf
für
Manifestdateien zum Zeitpunkt der Erstellung basierend auf dem Wert
RELEASE_AIDL_USE_UNFROZEN
.
Die Manifeste und Manifestfragmente geben an, welche Version einer Schnittstelle
implementiert wird. Wenn Sie die neueste nicht eingefrorene Version einer Schnittstelle verwenden,
muss das Manifest entsprechend aktualisiert werden. Wann?
RELEASE_AIDL_USE_UNFROZEN=false
werden die Manifesteinträge angepasst durch
libvintf
, um die Änderung an der generierten AIDL-Bibliothek widerzuspiegeln. Die Version
wird von der nicht eingefrorenen Version N
in
der letzten eingefrorenen Version N - 1
. So müssen Nutzer nicht mehrere
Manifeste oder Manifest-Fragmente für jeden ihrer Dienste.
Änderungen am HAL-Client
HAL-Client-Code muss mit jedem zuvor unterstützten eingefrorenen Gerät abwärtskompatibel sein.
Version. Wenn RELEASE_AIDL_USE_UNFROZEN
den Wert false
hat, suchen Dienste immer
z. B. die letzte eingefrorene Version oder eine frühere Version (z. B. Aufruf einer neuen, nicht fixierten Version).
gibt UNKNOWN_TRANSACTION
zurück oder neue parcelable
-Felder erhalten
Standardwerten). Android-Framework-Clients müssen rückwärts
mit früheren Versionen kompatibel, aber das ist ein neues Detail
von Anbietern und von partnereigenen Benutzeroberflächen.
Änderungen an der HAL-Implementierung
Der größte Unterschied in der HAL-Entwicklung mit Flag-basierter Entwicklung ist die
HAL-Implementierungen müssen abwärtskompatibel mit der
die eingefrorene Version funktioniert, wenn RELEASE_AIDL_USE_UNFROZEN
den Status false
hat.
Die Berücksichtigung der Abwärtskompatibilität bei Implementierungen und Gerätecode ist eine neue
Übung. Weitere Informationen finden Sie unter Versionierte Version verwenden
Benutzeroberflächen.
Die Überlegungen zur Abwärtskompatibilität sind für die sowie für Framework-Code und Anbietercode. kleine Unterschiede, die Sie kennen müssen, da Sie jetzt Implementierung von zwei Versionen, die den gleichen Quellcode verwenden (die aktuelle, nicht eingefrorene Version).
Beispiel: Eine Schnittstelle hat drei eingefrorene Versionen. Die Benutzeroberfläche wird mit einem
neue Methode. Der Client und der Dienst wurden auf die neue Version 4 aktualisiert.
Bibliothek. Da die V4-Bibliothek auf einer nicht eingefrorenen Version des
verhält es sich wie die letzte eingefrorene Version, Version 3,
RELEASE_AIDL_USE_UNFROZEN
ist false
und verhindert die Verwendung der neuen Methode.
Wenn die Schnittstelle fixiert ist, verwenden alle Werte von RELEASE_AIDL_USE_UNFROZEN
diese Abfrage
die eingefrorene Version
und der Code für die Abwärtskompatibilität entfernt werden.
Wenn Sie Methoden für Rückrufe aufrufen, müssen Sie den Fall
UNKNOWN_TRANSACTION
wird zurückgegeben. Die Kundschaft könnte zwei verschiedene
Versionen eines Callbacks, die auf der Releasekonfiguration basieren,
dass der Client die neueste Version sendet, und neue Methoden
dies. Das ähnelt der Wartung von stabilen AIDL-Clients
wird im Artikel Versionierte Version verwenden
Benutzeroberflächen.
// 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();
}
}
Neue Felder in vorhandenen Typen (parcelable
, enum
, union
)
nicht vorhanden sind oder ihre Standardwerte enthalten, wenn RELEASE_AIDL_USE_UNFROZEN
gleich
false
und die Werte neuer Felder, die ein Dienst zu senden versucht, werden entfernt
den Weg aus dem Prozess zu beseitigen.
Neue Typen, die in dieser nicht eingefrorenen Version hinzugefügt wurden, können nicht gesendet werden oder über die Benutzeroberfläche empfangen werden.
Die Implementierung erhält niemals einen Aufruf für neue Methoden von Clients, wenn
RELEASE_AIDL_USE_UNFROZEN
ist false
.
Achten Sie darauf, neue Zähler nur mit der Version zu verwenden, in der sie eingeführt wurden. und nicht die vorherige Version.
Normalerweise verwendest du foo->getInterfaceVersion()
, um zu sehen, welche Version der Fernbedienung
verwendet wird. Mit der Flag-basierten Versionsverwaltung
Implementierung von zwei verschiedenen Versionen. Sie sollten also die Version
der aktuellen Benutzeroberfläche. Rufen Sie dazu die Schnittstellenversion der
aktuelles Objekt, z. B. this->getInterfaceVersion()
oder das andere
Methoden für my_ver
. Siehe Oberflächenversion der Fernbedienung abfragen
Objekt
.
Neue stabile VINTF-Oberflächen
Wenn ein neues AIDL-Schnittstellenpaket
hinzugefügt wird, gibt es keine letzte eingefrorene Version.
Es gibt kein Verhalten für einen Fallback, wenn RELEASE_AIDL_USE_UNFROZEN
false
. Verwenden Sie diese Oberflächen nicht. Wenn RELEASE_AIDL_USE_UNFROZEN
gleich
false
, lässt Service Manager zu, dass der Dienst die Schnittstelle nicht registriert.
und die Kundschaft wird es nicht finden.
Sie können die Dienste basierend auf dem Wert des Felds
Das Flag RELEASE_AIDL_USE_UNFROZEN
im Geräte-Makefile:
ifeq ($(RELEASE_AIDL_USE_UNFROZEN),true)
PRODUCT_PACKAGES += \
android.hardware.health.storage-service
endif
Wenn der Dienst Teil eines größeren Prozesses ist, sodass er dem Gerät nicht hinzugefügt werden kann
können Sie prüfen, ob der Dienst mit
IServiceManager::isDeclared()
Wenn es deklariert ist und nicht registriert werden konnte,
brechen Sie den Vorgang ab. Wenn es nicht deklariert ist, schlägt die Registrierung wahrscheinlich fehl.
Sepien als Entwicklungstool
Jedes Jahr, nachdem die VINTF eingefroren ist, passen wir die Framework-Kompatibilität an
Matrix (FCM) target-level
und PRODUCT_SHIPPING_API_LEVEL
von Sepien
also für Geräte, die nächstes Jahr auf den Markt kommen. Wir passen die
target-level
und PRODUCT_SHIPPING_API_LEVEL
, um sicherzugehen, dass
Markteinführung eines Geräts, das getestet wurde und die neuen Anforderungen für
Veröffentlichung.
Wenn RELEASE_AIDL_USE_UNFROZEN
den Wert true
hat, ist der Sepia-Tintenfisch:
die für die Entwicklung zukünftiger Android-Versionen
verwendet werden. Es ist auf Android-Smartphones
des FCM-Levels und PRODUCT_SHIPPING_API_LEVEL
des Release, sodass es
die Vendor Software requirements (VSR) des nächsten Release.
Wenn RELEASE_AIDL_USE_UNFROZEN
den Wert false
hat, hat Tintenfisch den vorherigen Wert
target-level
und PRODUCT_SHIPPING_API_LEVEL
, um ein Releasegerät anzugeben.
In Android 14 und niedriger wäre diese Unterscheidung
mit verschiedenen Git-Zweigen erreicht, die die Änderung zu FCM nicht übernehmen
target-level
, Versand-API-Level oder einen anderen Code für die nächste
Veröffentlichung.
Regeln für die Benennung von Modulen
In Android 11 wird für jede Kombination aus Version und
aktiviert sind, wird automatisch ein Stub-Bibliotheksmodul erstellt. Empfehlen
mit einem bestimmten Stub-Bibliotheksmodul verknüpfen, verwenden Sie nicht den Namen der
aidl_interface
-Modul, aber der Name des Stub-Bibliotheksmoduls,
ifacename, version, backend, wobei
ifacename
: Name des Modulsaidl_interface
version
ist entweder <ph type="x-smartling-placeholder">- </ph>
Vversion-number
für die eingefrorenen VersionenVlatest-frozen-version-number + 1
für den Tipp-of-Tree-Version (noch nicht gefroren)
backend
ist entweder <ph type="x-smartling-placeholder">- </ph>
java
für das Java-Back-Endcpp
für das C++-Back-Endndk
oderndk_platform
für das NDK-Back-End. Ersteres gilt für Apps und der Letzteres für die Plattformnutzung bis Android 13. In Android 13 und höher (nurndk
).rust
für Rust-Back-End.
Angenommen, es gibt ein Modul namens foo mit der neuesten Version 2. und unterstützt sowohl NDK als auch C++. In diesem Fall generiert AIDL diese Module:
- Basierend auf Version 1
<ph type="x-smartling-placeholder">
- </ph>
foo-V1-(java|cpp|ndk|ndk_platform|rust)
- Basierend auf Version 2 (der neuesten stabilen Version)
<ph type="x-smartling-placeholder">
- </ph>
foo-V2-(java|cpp|ndk|ndk_platform|rust)
- Basierend auf der Version der Nutzungsbedingungen
<ph type="x-smartling-placeholder">
- </ph>
foo-V3-(java|cpp|ndk|ndk_platform|rust)
Im Vergleich zu Android 11:
foo-backend
(siehe neueste stabile Version) Version zufoo-V2-backend
foo-unstable-backend
(bezeichnet die Nutzungsbedingungen) Version zufoo-V3-backend
Die Namen der Ausgabedateien sind immer mit den Modulnamen identisch.
- Basierend auf Version 1:
foo-V1-(cpp|ndk|ndk_platform|rust).so
- Basierend auf Version 2:
foo-V2-(cpp|ndk|ndk_platform|rust).so
- Basierend auf Version der Nutzungsbedingungen:
foo-V3-(cpp|ndk|ndk_platform|rust).so
Der AIDL-Compiler erstellt weder ein unstable
-Versionsmodul
oder ein nicht versioniertes Modul für eine stabile AIDL-Schnittstelle.
Ab Android 12 wird der aus einem
Die stabile AIDL-Schnittstelle enthält immer ihre Version.
Neue Metaschnittstellenmethoden
Android 10 fügt mehrere Meta-Schnittstellenmethoden für die und stabile AIDL.
Schnittstellenversion des Remote-Objekts abfragen
Clients können die Version und den Hash der Schnittstelle abfragen, die das Remoteobjekt implementiert die zurückgegebenen Werte und vergleicht sie mit den Werten der -Schnittstelle. die der Client nutzt.
Beispiel mit dem Back-End 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();
Beispiel mit dem Back-End ndk
(und dem 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);
Beispiel mit dem Back-End 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();
Für die Sprache Java MÜSSEN auf der Remoteseite getInterfaceVersion()
und
getInterfaceHash()
wie folgt (super
wird anstelle von IFoo
verwendet, um
beim Kopieren und Einfügen. Die Anmerkung @SuppressWarnings("static")
kann
werden zum Deaktivieren von Warnungen benötigt (je nach javac
-Konfiguration):
class MyFoo extends IFoo.Stub {
@Override
public final int getInterfaceVersion() { return super.VERSION; }
@Override
public final String getInterfaceHash() { return super.HASH; }
}
Das liegt daran, dass die generierten Klassen (IFoo
, IFoo.Stub
usw.) freigegeben sind.
zwischen Client und Server (z. B. können sich die Klassen im Bootmodus
classpath). Wenn Klassen freigegeben werden, ist der Server auch mit dem
die neuesten Versionen der Klassen, auch wenn sie mit einer älteren Version erstellt wurden.
Version der Benutzeroberfläche. Wenn dieses Meta-Interface im gemeinsam verwendeten
gibt es immer die neueste Version zurück. Durch die Implementierung der Methode
Wie oben ist die Versionsnummer der Schnittstelle in den Code des Servers eingebettet.
(weil IFoo.VERSION
eine static final int
ist, die beim Verweis eingefügt wird)
Dadurch kann die Methode genau die Version zurückgeben, mit der der Server erstellt wurde.
Umgang mit älteren Benutzeroberflächen
Möglicherweise wird ein Client mit der neueren Version einer AIDL aktualisiert
aber der Server verwendet die alte AIDL-Schnittstelle. In solchen Fällen
Das Aufrufen einer Methode auf einer alten Schnittstelle gibt UNKNOWN_TRANSACTION
zurück.
Mit der stabilen AIDL haben Clients mehr Kontrolle. Auf der Clientseite können Sie Eine Standardimplementierung für eine AIDL-Schnittstelle. Eine Methode in der Standardmethode -Implementierung wird nur aufgerufen, wenn die Methode nicht im Remote- da sie mit einer älteren Version der Benutzeroberfläche erstellt wurde. Seit sind die Standardeinstellungen global und sollten nicht für potenziell freigegebene Kontexte.
Beispiel in C++ unter Android 13 und höher:
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
Beispiel in 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(...);
Sie müssen nicht die Standardimplementierung aller Methoden in einer AIDL bereitstellen
. Methoden, die garantiert auf der Remoteseite implementiert werden
da Sie sicher sind, dass die Remote-Version erstellt wurde, als die Methoden in der
AIDL-Schnittstellenbeschreibung) müssen im Standard-impl
nicht überschrieben werden.
.
Vorhandene AIDL in strukturierte oder stabile AIDL konvertieren
Wenn Sie bereits eine AIDL-Schnittstelle und einen Code haben, der diese verwendet, verwenden Sie Folgendes: zum Konvertieren der Schnittstelle in eine stabile AIDL-Schnittstelle.
Identifizieren Sie alle Abhängigkeiten Ihrer Schnittstelle. Für jedes Paket: ob das Paket in der stabilen AIDL definiert ist. Wenn nicht definiert ist, muss das Paket konvertiert werden.
Konvertieren Sie alle Parcelables in Ihrer Schnittstelle in stabile Parcelables (das Benutzeroberflächendateien selbst nicht verändert werden können). Vorgehensweise und drückt ihre Struktur direkt in AIDL-Dateien aus. Verwaltungsklassen müssen um diese neuen Typen zu verwenden. Das können Sie tun, bevor Sie ein
aidl_interface
-Paket (siehe unten).Erstellen Sie wie oben beschrieben ein
aidl_interface
-Paket, das die Name des Moduls, seine Abhängigkeiten und alle anderen Informationen, die Sie benötigen. Damit sie stabil und nicht nur strukturiert ist, muss sie auch versioniert werden. Weitere Informationen finden Sie unter Schnittstellen versionieren.