Bevor Sie beginnen, sehen Sie sich eine allgemeine Übersicht über den ART-Dienst an.
Ab Android 14 wird die On-Device-AOT-Kompilierung für Apps (auch als dexopt bezeichnet) vom ART-Dienst verwaltet. Der ART-Dienst ist Teil des ART-Moduls und kann über Systemeigenschaften und APIs angepasst werden.
Systemeigenschaften
Der ART-Dienst unterstützt alle relevanten dex2oat-Optionen.
Außerdem unterstützt der ART-Dienst die folgenden Systemeigenschaften:
pm.dexopt.<Grund>
Dies ist eine Reihe von Systemeigenschaften, die die Standardcompilerfilter für alle vordefinierten Kompilierungsgründe festlegen, die in Dexopt-Szenarien beschrieben sind.
Weitere Informationen finden Sie unter Compiler-Filter.
Die Standardwerte sind:
pm.dexopt.first-boot=verify
pm.dexopt.boot-after-ota=verify
pm.dexopt.boot-after-mainline-update=verify
pm.dexopt.bg-dexopt=speed-profile
pm.dexopt.inactive=verify
pm.dexopt.cmdline=verify
pm.dexopt.shared (Standard: Geschwindigkeit)
Dies ist der Fallback-Compilerfilter für Apps, die von anderen Apps verwendet werden.
Prinzipiell führt ART Service eine profilgestützte Kompilierung (speed-profile
) für
wenn möglich, in der Regel während der Hintergrund-Deaktivierung. Es gibt jedoch einige Apps, die von anderen Apps verwendet werden (entweder über <uses-library>
oder dynamisch mit Context#createPackageContext
über CONTEXT_INCLUDE_CODE
geladen). Solche Apps können aus Datenschutzgründen keine lokalen Profile verwenden.
Wenn für eine solche App eine profilbasierte Kompilierung angefordert wird, versucht der ART-Dienst zuerst, ein Cloud-Profil zu verwenden. Wenn kein Cloud-Profil vorhanden ist, ART Service
verwendet den von pm.dexopt.shared
angegebenen Compiler-Filter.
Wenn die angeforderte Kompilierung nicht profilbasiert ist, hat diese Property keine Auswirkungen.
pm.dexopt.<reason>.concurrency (Standard: 1)
Dies ist die Anzahl der dex2oat-Aufrufe aus bestimmten vordefinierten Gründen für die Kompilierung (first-boot
, boot-after-ota
, boot-after-mainline-update
und bg-dexopt
).
Beachten Sie, dass der Effekt dieser Option mit
dex2oat-Ressourcennutzungsoptionen (dalvik.vm.*dex2oat-threads
,
dalvik.vm.*dex2oat-cpu-set
und die Aufgabenprofile):
dalvik.vm.*dex2oat-threads
steuert die Anzahl der Threads für jeden dex2oat-Aufruf, währendpm.dexopt.<reason>.concurrency
die Anzahl der dex2oat-Aufrufe steuert. Das heißt, die maximale Anzahl gleichzeitiger Threads ist das Produkt der beiden Systemeigenschaften.dalvik.vm.*dex2oat-cpu-set
und die Aufgabenprofile binden immer den CPU-Kern. Auslastung, unabhängig von der maximalen Anzahl gleichzeitiger Threads (im Folgenden oben).
Ein einzelner dex2oat-Aufruf nutzt möglicherweise nicht alle CPU-Kerne, unabhängig davon,
von dalvik.vm.*dex2oat-threads
. Daher erhöht sich die Anzahl der dex2oat-
Aufrufe (pm.dexopt.<reason>.concurrency
) können CPU-Kerne besser nutzen, um
den Gesamtfortschritt von Dexopt zu beschleunigen. Dies ist besonders nützlich, wenn Sie
starten.
Zu viele dex2oat-Aufrufe können jedoch dazu führen, dass dem Gerät der Arbeitsspeicher ausgeht. Dies kann jedoch abgemildert werden, indem dalvik.vm.dex2oat-swap
auf true
festgelegt wird, um die Verwendung einer Auslagerungsdatei zu ermöglichen. Zu viele Aufrufe können auch zu unnötigen Kontextwechseln führen. Sie sollten diese Zahl daher sorgfältig
für jedes Produkt einzeln bewerten.
pm.dexopt.downgrade_after_inactive_days (Standardeinstellung: nicht festgelegt)
Wenn diese Option aktiviert ist, deaktiviert der ART-Dienst nur Apps, die in den letzten angegebenen Tagen verwendet wurden.
Wenn nur noch wenig Speicherplatz verfügbar ist, wird während der Hintergrunddexoptimierung der ART-Service aktiviert.
stufen den Compilerfilter von Anwendungen herunter, die in den letzten angegebenen
Anzahl der Tage, um Speicherplatz freizugeben. Der Compiler-Grund hierfür ist inactive
,
und der Compiler-Filter wird durch pm.dexopt.inactive
bestimmt. Der Gruppenbereich
Der Grenzwert zum Auslösen dieser Funktion ist der Grenzwert für wenig Speicherplatz des Speichermanagers
(konfigurierbar über die globalen Einstellungen sys_storage_threshold_percentage
und
sys_storage_threshold_max_bytes
, Standard: 500 MB) plus 500 MB.
Wenn Sie die Liste der Pakete über ArtManagerLocal#setBatchDexoptStartCallback
anpassen, werden die Pakete in der Liste, die BatchDexoptStartCallback
für bg-dexopt
zur Verfügung stellt, nie herabgestuft.
pm.dexopt.disable_bg_dexopt (Standardeinstellung: false)
Diese Funktion ist nur für Tests vorgesehen. Dadurch wird verhindert, dass der ART-Dienst den Deopt-Job im Hintergrund plant.
Wenn der Hintergrund-Dexopt-Job bereits geplant ist, aber noch nicht ausgeführt wurde: hat keine Auswirkung. Der Job wird also weiterhin ausgeführt.
Eine empfohlene Abfolge von Befehlen, um zu verhindern, dass der Hintergrund-Entfernungsjob ausgeführt wird:
setprop pm.dexopt.disable_bg_dexopt true
pm bg-dexopt-job --disable
Mit der ersten Zeile wird verhindert, dass der dexopt-Job im Hintergrund geplant wird, falls er noch nicht geplant ist. In der zweiten Zeile wird die Planung des dexopt-Jobs im Hintergrund aufgehoben, falls er bereits geplant ist, und er wird sofort abgebrochen, falls er gerade ausgeführt wird.
ART-Service-APIs
Der ART-Dienst stellt Java APIs für die Anpassung bereit. Die APIs sind definiert in
ArtManagerLocal
Siehe Javadoc in
art/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
für
Nutzungen (Android 14-Quelle, unveröffentlichte Entwicklungsquelle).
ArtManagerLocal
ist ein Singleton, der von LocalManagerRegistry
verwaltet wird. Die Hilfsfunktion com.android.server.pm.DexOptHelper#getArtManagerLocal
hilft Ihnen dabei.
import static com.android.server.pm.DexOptHelper.getArtManagerLocal;
Die meisten APIs erfordern eine Instanz von PackageManagerLocal.FilteredSnapshot
, die die Informationen aller Apps enthält. Rufen Sie dazu einfach
PackageManagerLocal#withFilteredSnapshot
, wobei PackageManagerLocal
ebenfalls
ein Singleton-Paket von LocalManagerRegistry
, das hier erhältlich ist:
com.android.server.pm.PackageManagerServiceUtils#getPackageManagerLocal
.
import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;
Im Folgenden sind einige typische Anwendungsfälle der APIs aufgeführt.
Dexopt für eine App auslösen
Sie können dexopt jederzeit für eine beliebige App auslösen, indem Sie ArtManagerLocal#dexoptPackage
aufrufen.
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
getArtManagerLocal().dexoptPackage(
snapshot,
"com.google.android.calculator",
new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build());
}
Sie können auch einen eigenen Grund für die Deaktivierung von Dexopt angeben. In diesem Fall werden die Prioritätsklasse Der Compilerfilter muss explizit festgelegt werden.
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
getArtManagerLocal().dexoptPackage(
snapshot,
"com.google.android.calculator",
new DexoptParams.Builder("my-reason")
.setCompilerFilter("speed-profile")
.setPriorityClass(ArtFlags.PRIORITY_BACKGROUND)
.build());
}
dexopt abbrechen
Wenn ein Vorgang durch einen dexoptPackage
-Aufruf initiiert wird, können Sie eine
Abbruchsignal, mit dem Sie den Vorgang an einem bestimmten Punkt abbrechen können. Das kann hilfreich sein, wenn Sie dexopt asynchron ausführen.
Executor executor = ...; // Your asynchronous executor here.
var cancellationSignal = new CancellationSignal();
executor.execute(() -> {
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
getArtManagerLocal().dexoptPackage(
snapshot,
"com.google.android.calculator",
new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build(),
cancellationSignal);
}
});
// When you want to cancel the operation.
cancellationSignal.cancel();
Sie können auch die Deaktivierung von dexopt im Hintergrund abbrechen, die vom ART-Dienst initiiert wird.
getArtManagerLocal().cancelBackgroundDexoptJob();
Dexopt-Ergebnisse abrufen
Wenn ein Vorgang durch einen dexoptPackage
-Aufruf initiiert wird, können Sie das Ergebnis abrufen
aus dem Rückgabewert.
DexoptResult result;
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
result = getArtManagerLocal().dexoptPackage(...);
}
// Process the result here.
...
Der ART-Dienst initiiert in vielen Fällen auch selbst DeXOpt-Vorgänge, z. B. im Hintergrund. Wenn Sie alle dexopt-Ergebnisse abhören möchten, unabhängig davon, ob der Vorgang durch einen dexoptPackage
-Aufruf oder durch den ART-Dienst initiiert wird, verwenden Sie ArtManagerLocal#addDexoptDoneCallback
.
getArtManagerLocal().addDexoptDoneCallback(
false /* onlyIncludeUpdates */,
Runnable::run,
(result) -> {
// Process the result here.
...
});
Das erste Argument bestimmt, ob nur Aktualisierungen im Ergebnis berücksichtigt werden sollen. Wenn nur Pakete überwachen möchten, die per Dexopt aktualisiert wurden, setzen Sie den Wert auf "true".
Das zweite Argument ist der Ausführende des Callbacks. Wenn Sie den Rückruf in demselben Thread ausführen möchten, in dem dexopt ausgeführt wird, verwenden Sie Runnable::run
. Wenn Sie das nicht möchten,
-Callback zum Blockieren von Dexopt. Verwenden Sie einen asynchronen Executor.
Sie können mehrere Callbacks hinzufügen. Der ART-Dienst führt sie dann nacheinander aus. Alle Callbacks bleiben für alle zukünftigen Anrufe aktiv, es sei denn, Sie entfernen sie.
Wenn du einen Callback entfernen möchtest, behalte die Referenz des Callbacks bei, wenn du
fügen Sie sie hinzu und verwenden Sie ArtManagerLocal#removeDexoptDoneCallback
.
DexoptDoneCallback callback = (result) -> {
// Process the result here.
...
};
getArtManagerLocal().addDexoptDoneCallback(
false /* onlyIncludeUpdates */, Runnable::run, callback);
// When you want to remove it.
getArtManagerLocal().removeDexoptDoneCallback(callback);
Paketliste und Dexopt-Parameter anpassen
Der ART-Dienst startet die DeXOpt-Vorgänge selbst beim Starten und im Hintergrund. Verwenden Sie ArtManagerLocal#setBatchDexoptStartCallback
, um die Paketliste oder die dexopt-Parameter für diese Vorgänge anzupassen.
getArtManagerLocal().setBatchDexoptStartCallback(
Runnable::run,
(snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
switch (reason) {
case ReasonMapping.REASON_BG_DEXOPT:
var myPackages = new ArrayList<String>(defaultPackages);
myPackages.add(...);
myPackages.remove(...);
myPackages.sort(...);
builder.setPackages(myPackages);
break;
default:
// Ignore unknown reasons.
}
});
Sie können der Paketliste Elemente hinzufügen, Elemente daraus entfernen, sie sortieren oder sogar eine ganz andere Liste verwenden.
Unbekannte Gründe müssen von deinem Rückruf ignoriert werden, da weitere Gründe hinzugefügt werden können in in die Zukunft zu führen.
Sie können maximal einen BatchDexoptStartCallback
festlegen. Der Callback bleibt
Für alle zukünftigen Anrufe aktiv, es sei denn, Sie löschen sie.
Wenn Sie den Rückruf löschen möchten, verwenden Sie ArtManagerLocal#clearBatchDexoptStartCallback
.
getArtManagerLocal().clearBatchDexoptStartCallback();
Parameter des dexopt-Jobs im Hintergrund anpassen
Standardmäßig wird der Job zur Hintergrunddexopt-Funktion einmal täglich ausgeführt, wenn das Gerät inaktiv ist
und Aufladen. Das lässt sich mit ArtManagerLocal#setScheduleBackgroundDexoptJobCallback
ändern.
getArtManagerLocal().setScheduleBackgroundDexoptJobCallback(
Runnable::run,
builder -> {
builder.setPeriodic(TimeUnit.DAYS.toMillis(2));
});
Du kannst maximal ein ScheduleBackgroundDexoptJobCallback
festlegen. Der Rückruf bleibt für alle zukünftigen Anrufe aktiv, es sei denn, Sie löschen ihn.
Wenn Sie den Rückruf löschen möchten, verwenden Sie ArtManagerLocal#clearScheduleBackgroundDexoptJobCallback
.
getArtManagerLocal().clearScheduleBackgroundDexoptJobCallback();
Dexopt vorübergehend deaktivieren
Jeder von ART Service initiierte Dexopt-Vorgang löst ein
BatchDexoptStartCallback
Sie können die Vorgänge weiter abbrechen,
Dexopt effektiv deaktivieren.
Wenn Sie die Hintergrunddexopt-Funktion abbrechen, wird die Standardeinstellung verwendet. Wiederholungsrichtlinie (30 Sekunden, exponentiell, begrenzt auf 5 Stunden).
// Good example.
var shouldDisableDexopt = new AtomicBoolean(false);
getArtManagerLocal().setBatchDexoptStartCallback(
Runnable::run,
(snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
if (shouldDisableDexopt.get()) {
cancellationSignal.cancel();
}
});
// Disable dexopt.
shouldDisableDexopt.set(true);
getArtManagerLocal().cancelBackgroundDexoptJob();
// Re-enable dexopt.
shouldDisableDexopt.set(false);
Sie können maximal eine BatchDexoptStartCallback
haben. Wenn Sie auch
BatchDexoptStartCallback
zum Anpassen der Paketliste oder zum Entfernen der Parameter
müssen Sie den Code in einem Callback kombinieren.
// Bad example.
// Disable dexopt.
getArtManagerLocal().unscheduleBackgroundDexoptJob();
// Re-enable dexopt.
getArtManagerLocal().scheduleBackgroundDexoptJob();
Der DeXOpt-Vorgang, der bei der App-Installation ausgeführt wird, wird nicht vom ART-Dienst initiiert. Stattdessen wird der Vorgang vom Paketmanager über ein
dexoptPackage
Anruf. Daher wird BatchDexoptStartCallback
nicht ausgelöst. Um die Deaktivierung bei der App-Installation zu deaktivieren,
Paketmanager kann dexoptPackage
nicht aufrufen.
Compilerfilter für bestimmte Pakete überschreiben (Android 15 und höher)
Sie können den Compiler-Filter für bestimmte Pakete überschreiben, indem Sie eine
über setAdjustCompilerFilterCallback
zurückrufen. Der Rückruf wird immer dann aufgerufen, wenn ein Paket dexoptiert wird, unabhängig davon, ob die Deaktivierung durch den ART-Dienst während des Bootens und der Deaktivierung im Hintergrund oder durch einen dexoptPackage
API-Aufruf initiiert wird.
Wenn ein Paket keine Anpassung erfordert, muss der Callback
originalCompilerFilter
getArtManagerLocal().setAdjustCompilerFilterCallback(
Runnable::run,
(packageName, originalCompilerFilter, reason) -> {
if (isVeryImportantPackage(packageName)) {
return "speed-profile";
}
return originalCompilerFilter;
});
Du kannst nur eine AdjustCompilerFilterCallback
festlegen. Wenn Sie
AdjustCompilerFilterCallback
zum Überschreiben des Compiler-Filters für mehrere
Paketen, müssen Sie den Code in einem Callback kombinieren. Der Callback bleibt
Für alle zukünftigen Anrufe aktiv, es sei denn, Sie löschen sie.
Wenn du den Callback löschen möchtest, verwende
ArtManagerLocal#clearAdjustCompilerFilterCallback
getArtManagerLocal().clearAdjustCompilerFilterCallback();
Weitere Anpassungen
Der ART-Dienst unterstützt auch einige andere Anpassungen.
Grenzwert zu Temperatur für Hintergrund-Dexopt festlegen
Die thermische Steuerung des dexopt-Jobs im Hintergrund erfolgt über den Job Scheduler.
Der Job wird sofort abgebrochen, wenn die Temperatur erreicht
THERMAL_STATUS_MODERATE
Der Schwellenwert von
THERMAL_STATUS_MODERATE
ist einstellbar.
Prüfen, ob dexopt im Hintergrund ausgeführt wird
Der Hintergrund-dexopt-Job wird vom Job Scheduler verwaltet und seine Job-ID lautet 27873780
. Verwenden Sie Job Scheduler APIs, um festzustellen, ob der Job ausgeführt wird.
// Good example.
var jobScheduler =
Objects.requireNonNull(mContext.getSystemService(JobScheduler.class));
int reason = jobScheduler.getPendingJobReason(27873780);
if (reason == PENDING_JOB_REASON_EXECUTING) {
// Do something when the job is running.
...
}
// Bad example.
var backgroundDexoptRunning = new AtomicBoolean(false);
getArtManagerLocal().setBatchDexoptStartCallback(
Runnable::run,
(snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
if (reason.equals(ReasonMapping.REASON_BG_DEXOPT)) {
backgroundDexoptRunning.set(true);
}
});
getArtManagerLocal().addDexoptDoneCallback(
false /* onlyIncludeUpdates */,
Runnable::run,
(result) -> {
if (result.getReason().equals(ReasonMapping.REASON_BG_DEXOPT)) {
backgroundDexoptRunning.set(false);
}
});
if (backgroundDexoptRunning.get()) {
// Do something when the job is running.
...
}
Profil für Dexopt angeben
Wenn Sie ein Profil für dexopt verwenden möchten, legen Sie eine .prof
- oder .dm
-Datei neben die APK-Datei ab.
Die Datei .prof
muss eine Profildatei im Binärformat sein und der Dateiname muss
Der Dateiname des APK + .prof
. Beispiel:
base.apk.prof
Der Dateiname der .dm
-Datei muss der Dateiname der APK-Datei mit dem
Erweiterung durch .dm
ersetzt. Beispiel:
base.dm
Um zu prüfen, ob das Profil für dexopt verwendet wird, führen Sie dexopt mit speed-profile
aus und prüfen Sie das Ergebnis.
pm art clear-app-profiles <package-name>
pm compile -m speed-profile -f -v <package-name>
Die erste Zeile löscht alle von der Laufzeit erstellten Profile (d.h. die in
/data/misc/profiles
) und prüfen Sie, ob das Profil neben dem APK
das einzige Profil, das ART Service verwenden kann. In der zweiten Zeile wird dexopt mit speed-profile
ausgeführt und -v
übergeben, um das ausführliche Ergebnis zu drucken.
Wenn das Profil verwendet wird, wird in den Ergebnissen actualCompilerFilter=speed-profile
angezeigt. Andernfalls wird actualCompilerFilter=verify
angezeigt. Beispiel:
DexContainerFileDexoptResult{dexContainerFile=/data/app/~~QR0fTV0UbDbIP1Su7XzyPg==/com.google.android.gms-LvusF2uARKOtBbcaPHdUtQ==/base.apk, primaryAbi=true, abi=x86_64, actualCompilerFilter=speed-profile, status=PERFORMED, dex2oatWallTimeMillis=4549, dex2oatCpuTimeMillis=14550, sizeBytes=3715344, sizeBeforeBytes=3715344}
Typische Gründe, warum der ART-Dienst das Profil nicht verwendet:
- Das Profil hat einen falschen Dateinamen oder befindet sich nicht neben dem APK.
- Das Profil hat das falsche Format.
- Das Profil entspricht nicht dem APK. (Die Prüfsummen im Profil
stimmt mit den Prüfsummen der
.dex
-Dateien im APK überein.)