ART-Dienstkonfiguration

Sehen Sie sich zuerst einen allgemeinen Überblick über den ART-Dienst an.

Ab Android 14 wird On-Device-AOT-Kompilierung für Apps (auch „Dexopt“ genannt) werden von ART Service verarbeitet. Der ART Service ist Teil der ART. und können über Systemeigenschaften und APIs angepasst werden.

Systemeigenschaften

ART Service unterstützt alle relevanten dex2oat-Optionen.

Außerdem unterstützt der ART-Dienst die folgenden Systemeigenschaften:

pm.dexopt.<Grund>

Hierbei handelt es sich um eine Reihe von Systemeigenschaften, die die Standard-Compiler-Filter bestimmen für alle vordefinierten Kompilierungsgründe, die in Dexopt-Szenarien beschrieben sind.

Weitere Informationen finden Sie unter Compiler-Filter.

Die Standardwerte lauten:

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-Compiler-Filter 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 geladen) dynamisch mit Context#createPackageContext mit CONTEXT_INCLUDE_CODE) Solche Apps dürfen keine lokalen aus Datenschutzgründen nicht mehr zu sehen ist.

Wenn bei einer solchen App eine profilgestützte Kompilierung angefordert wird, muss zuerst der ART-Dienst verwendet werden. versucht, 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 über ein Profil erstellt wird, hat diese Property keine Auswirkungen.

pm.dexopt.<reason>.concurrency (Standard: 1)

Dies ist die Anzahl der dex2oat-Aufrufe für eine bestimmte vordefinierte Kompilierung (first-boot, boot-after-ota, boot-after-mainline-update und bg-dexopt.

Beachten Sie, dass der Effekt dieser Option mit dex2oat-Optionen zur Ressourcennutzung (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ährend pm.dexopt.<reason>.concurrency die Anzahl der dex2oat-Aufrufe. 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.

Bei zu vielen dex2oat-Aufrufen kann das Gerät jedoch Arbeitsspeicher, obwohl dies durch Festlegen von dalvik.vm.dex2oat-swap auf true, um die Verwendung einer Auslagerungsdatei zuzulassen. Zu viele Aufrufe können außerdem unnötigen Kontextwechsel. 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 konfiguriert ist, entfernt ART Service nur Apps, die in den letzten Anzahl der Tage

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, die Pakete in der angegebenen Liste von BatchDexoptStartCallback für bg-dexopt werden nie herabgestuft.

pm.dexopt.disable_bg_dexopt (Standardeinstellung: false)

Dies dient nur zu Testzwecken. ART Service kann den Hintergrund nicht planen. Dexopt des Jobs entfernen.

Wenn der Hintergrund-Dexopt-Job bereits geplant ist, aber noch nicht ausgeführt wurde: hat keine Auswirkung. Das heißt, der Job wird 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

Die erste Zeile verhindert, dass der Hintergrunddexopt-Job geplant wird, falls dies noch nicht geplant. Mit der zweiten Zeile wird die Planung des Jobs zum Entfernen des Hintergrunds aufgehoben, wenn und bricht den Hintergrund-Dexopt-Job sofort ab, wenn ausgeführt wird.

ART-Service-APIs

ART Service stellt Java APIs zur 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. Ein Helfer Funktion com.android.server.pm.DexOptHelper#getArtManagerLocal können Sie erhalten.

import static com.android.server.pm.DexOptHelper.getArtManagerLocal;

Für die meisten APIs ist eine Instanz von PackageManagerLocal.FilteredSnapshot erforderlich. das die Informationen zu allen 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 für die APIs aufgeführt.

Dexopt für eine App auslösen

Sie können jederzeit Dexopt für jede App auslösen, indem Sie folgenden Befehl aufrufen: ArtManagerLocal#dexoptPackage

try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
  getArtManagerLocal().dexoptPackage(
      snapshot,
      "com.google.android.calculator",
      new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build());
}

Du kannst auch einen eigenen Deaktivierungsgrund 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());
}

Deaktivierung 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. Dies kann 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 Hintergrunddexopt-Funktion abbrechen, die vom ART Service initiiert wird.

getArtManagerLocal().cancelBackgroundDexoptJob();

Dexopt-Ergebnisse erhalten

Wenn ein Vorgang durch einen dexoptPackage-Aufruf initiiert wird, können Sie das Ergebnis abrufen vom Rückgabewert ab.

DexoptResult result;
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
  result = getArtManagerLocal().dexoptPackage(...);
}

// Process the result here.
...

Der ART-Dienst startet auch in vielen Szenarien selbst Dexopt-Vorgänge, z. B. Hintergrunddexopt. Zum Abhören aller Dexopt-Ergebnisse, unabhängig davon, ob der Vorgang durch einen dexoptPackage-Aufruf oder den ART Service initiiert wurde, 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 Executor des Callbacks. Um den Callback auszuführen, im selben Thread, der dexopt ausführt, 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, die von ART Service ausgeführt werden sequenziell. Alle Rückrufe bleiben für alle zukünftigen Anrufe aktiv, es sei denn, wenn Sie sie entfernen.

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 initiiert selbst Dexopt-Vorgänge während des Starts und im Hintergrund. Dexopt. Um die Paketliste oder dexopt-Parameter für diese Vorgänge anzupassen, ArtManagerLocal#setBatchDexoptStartCallback verwenden.

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 Artikel zur Paketliste hinzufügen, Artikel daraus entfernen, sie sortieren 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.

Du kannst maximal ein BatchDexoptStartCallback festlegen. 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#clearBatchDexoptStartCallback

getArtManagerLocal().clearBatchDexoptStartCallback();

Parameter des Hintergrund-Dexopt-Jobs anpassen

Standardmäßig wird der Job zur Hintergrunddexopt-Funktion einmal täglich ausgeführt, wenn das Gerät inaktiv ist und Aufladen. Dies kann geändert werden mit ArtManagerLocal#setScheduleBackgroundDexoptJobCallback

getArtManagerLocal().setScheduleBackgroundDexoptJobCallback(
    Runnable::run,
    builder -> {
      builder.setPeriodic(TimeUnit.DAYS.toMillis(2));
    });

Du kannst maximal ein ScheduleBackgroundDexoptJobCallback festlegen. Der Callback wird bleiben für alle zukünftigen Anrufe aktiv, es sei denn, Sie löschen sie.

Wenn du den Callback löschen möchtest, verwende 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);

Du kannst nur ein 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();

Die bei der App-Installation durchgeführte Dexoptimierung wird nicht von ART initiiert. Dienst. Stattdessen wird er vom Paketmanager über ein dexoptPackage Anruf. Daher wird sie nicht ausgelöst, BatchDexoptStartCallback Um die Deaktivierung bei der App-Installation zu deaktivieren, Paketmanager kann dexoptPackage nicht aufrufen.

Compiler-Filter für bestimmte Pakete überschreiben (Android 15 und höher)

Sie können den Compiler-Filter für bestimmte Pakete überschreiben, indem Sie ein über setAdjustCompilerFilterCallback zurückrufen. Der Callback wird als wenn ein Paket entfernt wird, unabhängig davon, ob diese durch ART-Dienst während des Boot- und Hintergrunddexopts oder durch einen dexoptPackage-API-Aufruf.

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 Temperaturregelung des Hintergrund-Dexopt-Jobs wird vom Jobplaner durchgeführt. Der Job wird sofort abgebrochen, wenn die Temperatur erreicht THERMAL_STATUS_MODERATE Der Schwellenwert von THERMAL_STATUS_MODERATE ist einstellbar.

Bestimmen, ob Hintergrund-Dexopt ausgeführt wird

Der Hintergrund-Dexopt-Job wird vom Jobplaner verwaltet und seine Job-ID ist 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

Um die Dexopt-Funktion mithilfe eines Profils zu steuern, platzieren Sie eine .prof- oder eine .dm-Datei neben dem APK

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 Datei .dm muss der Name der APK-Datei mit dem Präfix Erweiterung durch .dm ersetzt. Beispiel:

base.dm

Um zu überprüfen, ob das Profil zum Entfernen verwendet wird, führen Sie „dexopt“ mit speed-profile 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 ausgeführt. mit speed-profile und übergibt -v, um das ausführliche Ergebnis auszugeben.

Wenn das Profil bereits verwendet wird, sehen Sie actualCompilerFilter=speed-profile in für das Ergebnis. 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}

Häufige Gründe, warum ART Service das Profil nicht verwendet, sind:

  • Das Profil hat einen falschen Dateinamen oder es 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.)