Avant de commencer, consultez une présentation générale du service ART.
À partir d'Android 14, compilation anticipée (ou anticipée) sur l'appareil pour (ou dexopt) est gérée par le service ART. Le service ART est intégré à ART. par l'intermédiaire des propriétés système et des API.
Propriétés système
Le service ART prend en charge toutes les fonctionnalités Options dex2oat.
De plus, le service ART prend en charge les propriétés système suivantes:
pm.dexopt.<reason>
Il s'agit d'un ensemble de propriétés système qui déterminent les filtres de compilation par défaut pour tous les motifs de compilation prédéfinis décrits dans les scénarios de DevOps.
Pour en savoir plus, consultez Filtres du compilateur.
Les valeurs par défaut standards sont les suivantes:
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 (valeur par défaut: vitesse)
Il s'agit du filtre de compilation de remplacement pour les applications utilisées par d'autres applications.
En principe, le service ART effectue une compilation guidée par profil (speed-profile
) pour
toutes les applications lorsque cela est possible, généralement lors du dexopt en arrière-plan. Cependant, il existe
certaines applications utilisées par d'autres applications (via <uses-library>
ou chargées
de manière dynamique à l'aide de Context#createPackageContext
avec
CONTEXT_INCLUDE_CODE
). Ces applications ne peuvent pas utiliser l'accès local
pour des raisons de confidentialité.
Pour ce type d'application, si la compilation guidée par profil est demandée, le service ART doit d'abord être utilisé.
tente d'utiliser un profil cloud. Si aucun profil cloud n'existe, le service ART
revient à utiliser le filtre de compilation spécifié par pm.dexopt.shared
.
Si la compilation demandée n'est pas guidée par le profil, cette propriété n'a aucun effet.
pm.dexopt.<reason>.concurrency (par défaut: 1)
Il s'agit du nombre d'appels dex2oat pour certaines compilations prédéfinies
motifs (first-boot
, boot-after-ota
, boot-after-mainline-update
et
bg-dexopt
).
Notez que l'effet de cette option est combiné
Options d'utilisation des ressources dex2oat (dalvik.vm.*dex2oat-threads
,
dalvik.vm.*dex2oat-cpu-set
et les profils de tâches):
dalvik.vm.*dex2oat-threads
contrôle le nombre de threads pour chaque dex2oat appel, tandis quepm.dexopt.<reason>.concurrency
contrôle le nombre des appels dex2oat. Autrement dit, le nombre maximal de threads simultanés est de produit des deux propriétés système.dalvik.vm.*dex2oat-cpu-set
et les profils de tâche ont toujours lié le cœur de processeur quel que soit le nombre maximal de threads simultanés (abordés ci-dessus).
Un seul appel de dex2oat peut ne pas exploiter pleinement tous les cœurs de processeur,
sur dalvik.vm.*dex2oat-threads
. L'augmentation du nombre de "dex2oat"
les appels (pm.dexopt.<reason>.concurrency
) peuvent mieux utiliser les cœurs de processeur pour
accélérer la progression
globale de dexopt. Ceci est particulièrement
utile pendant
démarrer.
Toutefois, un trop grand nombre d'appels dex2oat peut entraîner l'épuisement
mémoire, même si cela peut être atténué en définissant dalvik.vm.dex2oat-swap
sur
true
pour permettre l'utilisation d'un fichier d'échange. Un trop grand nombre d'appels peut aussi entraîner
un changement de contexte inutile. Ce nombre doit donc être réglé avec soin.
produit par produit.
pm.dexopt.downgrade_after_inactive_days (valeur par défaut: non définie)
Si cette option est définie, le service ART ne dexopte que les applications utilisées au cours de la dernière nombre de jours.
De plus, si l'espace de stockage est presque faible, en arrière-plan, le service ART
rétrograde le filtre de compilation des applications qui ne sont pas utilisées au cours de la
pour libérer de l'espace. Pour le compilateur, cela est inactive
,
et le filtre de compilateur est déterminé par pm.dexopt.inactive
. L'espace
de déclenchement de cette fonctionnalité est le seuil de faible espace du gestionnaire d'espace de stockage
(configurable via les paramètres globaux sys_storage_threshold_percentage
et
sys_storage_threshold_max_bytes
, valeur par défaut: 500 Mo) plus 500 Mo.
Si vous personnalisez la liste des packages via
ArtManagerLocal#setBatchDexoptStartCallback
, les packages de la liste fournie.
par BatchDexoptStartCallback
pour bg-dexopt
ne sont jamais rétrogradés.
pm.dexopt.disable_bg_dexopt (valeur par défaut : "false")
Ces informations ne sont utilisées qu'à des fins de test. Cela empêche le service ART de planifier l'arrière-plan dexopt.
Si le job dexopt en arrière-plan est déjà planifié, mais n'a pas encore été exécuté, n'a aucun effet. Autrement dit, le job continue de s'exécuter.
Séquence de commandes recommandée pour empêcher le job dexopt en arrière-plan en cours d'exécution:
setprop pm.dexopt.disable_bg_dexopt true
pm bg-dexopt-job --disable
La première ligne empêche la planification de la tâche dexopt en arrière-plan, si elle est pas encore planifiée. La deuxième ligne annule la planification du job dexopt en arrière-plan, si il est déjà planifié et annule immédiatement la tâche dexopt en arrière-plan, si s'il est exécuté.
API de service ART
Le service ART expose des API Java pour la personnalisation. Les API sont définies
ArtManagerLocal
Consultez le Javadoc dans
art/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
pour
(source Android 14, source de développement non publiée).
ArtManagerLocal
est un singleton détenu par LocalManagerRegistry
. Une aide
la fonction com.android.server.pm.DexOptHelper#getArtManagerLocal
vous aide
l'obtenir.
import static com.android.server.pm.DexOptHelper.getArtManagerLocal;
La plupart des API nécessitent une instance de PackageManagerLocal.FilteredSnapshot
,
qui contient les informations
de toutes les applications. Pour l'obtenir, appelez
PackageManagerLocal#withFilteredSnapshot
, où PackageManagerLocal
est également
un singleton détenu par LocalManagerRegistry
et pouvant être obtenu via
com.android.server.pm.PackageManagerServiceUtils#getPackageManagerLocal
import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;
Voici quelques cas d'utilisation types des API.
Déclencher dexopt pour une application
Vous pouvez déclencher dexopt pour n'importe quelle appli à tout moment en appelant
ArtManagerLocal#dexoptPackage
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
getArtManagerLocal().dexoptPackage(
snapshot,
"com.google.android.calculator",
new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build());
}
Vous pouvez également transmettre votre propre motif dexopt. Dans ce cas, la classe de priorité et le filtre du compilateur doit être défini explicitement.
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());
}
Annuler dexopt
Si une opération est lancée par un appel dexoptPackage
, vous pouvez transmettre un
signal d'annulation, qui vous permet d'annuler l'opération à un moment donné. Cela peut
être utile lorsque vous exécutez dexopt de manière asynchrone.
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();
Vous pouvez également annuler le dexopt en arrière-plan, initié par le service ART.
getArtManagerLocal().cancelBackgroundDexoptJob();
Obtenir des résultats dexopt
Si une opération est lancée par un appel dexoptPackage
, vous pouvez obtenir le résultat
de la valeur renvoyée.
DexoptResult result;
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
result = getArtManagerLocal().dexoptPackage(...);
}
// Process the result here.
...
Le service ART lance lui-même des opérations dexopt dans de nombreux scénarios :
dexopt. Pour écouter tous les résultats dexopt, que l'opération soit
initié par un appel dexoptPackage
ou par le service ART, utilisez
ArtManagerLocal#addDexoptDoneCallback
getArtManagerLocal().addDexoptDoneCallback(
false /* onlyIncludeUpdates */,
Runnable::run,
(result) -> {
// Process the result here.
...
});
Le premier argument détermine s'il faut inclure uniquement les mises à jour dans le résultat. Si vous ne voulez écouter que les packs mis à jour par dexopt, définissez-le sur true.
Le deuxième argument est l'exécuteur du rappel. Pour exécuter le rappel sur
le même thread qui exécute dexopt, utilisez Runnable::run
. Si vous ne souhaitez pas
pour bloquer dexopt, utilisez un exécuteur asynchrone.
Vous pouvez ajouter plusieurs rappels, et le service ART les exécutera tous de manière séquentielle. Tous les rappels resteront actifs pour tous les appels ultérieurs, sauf si vous les supprimez.
Si vous souhaitez supprimer un rappel, conservez la référence du rappel lorsque vous
l'ajouter et utiliser 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);
Personnaliser la liste des packages et les paramètres dexopt
Le service ART lance lui-même les opérations dexopt au démarrage et en arrière-plan
dexopt. Pour personnaliser la liste de packages ou
les paramètres dexopt pour ces opérations,
utiliser ArtManagerLocal#setBatchDexoptStartCallback
.
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.
}
});
Vous pouvez ajouter des éléments à la liste de packages, en supprimer, la trier ou même utiliser une liste complètement différente.
Votre rappel doit ignorer des motifs inconnus, car d'autres motifs peuvent être ajoutés dans à l'avenir.
Vous ne pouvez définir qu'un seul BatchDexoptStartCallback
. Le rappel sera maintenu
active pour tous les prochains appels, sauf si vous l'effacez.
Si vous souhaitez effacer le rappel, utilisez
ArtManagerLocal#clearBatchDexoptStartCallback
getArtManagerLocal().clearBatchDexoptStartCallback();
Personnaliser les paramètres de la tâche dexopt en arrière-plan
Par défaut, la tâche dexopt en arrière-plan s'exécute une fois par jour lorsque l'appareil est inactif
et en charge. Vous pouvez modifier ce paramètre à l'aide de
ArtManagerLocal#setScheduleBackgroundDexoptJobCallback
getArtManagerLocal().setScheduleBackgroundDexoptJobCallback(
Runnable::run,
builder -> {
builder.setPeriodic(TimeUnit.DAYS.toMillis(2));
});
Vous ne pouvez définir qu'un seul ScheduleBackgroundDexoptJobCallback
. Le rappel
reste actif pour tous les prochains appels, sauf si vous l'effacez.
Si vous souhaitez effacer le rappel, utilisez
ArtManagerLocal#clearScheduleBackgroundDexoptJobCallback
getArtManagerLocal().clearScheduleBackgroundDexoptJobCallback();
Désactiver temporairement dexopt
Toute opération dexopt initiée par le service ART déclenche une
BatchDexoptStartCallback
Vous pouvez continuer
à annuler les opérations pour
désactiver efficacement dexopt.
Si l'opération que vous annulez est dexopt en arrière-plan, elle suit la stratégie de nouvelle tentative (30 secondes, exponentielle, plafonnée à 5 heures).
// 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);
Vous ne pouvez avoir qu'un seul BatchDexoptStartCallback
. Si vous souhaitez également utiliser
BatchDexoptStartCallback
pour personnaliser la liste de packages ou les paramètres dexopt ;
vous devez combiner le code dans un seul rappel.
// Bad example.
// Disable dexopt.
getArtManagerLocal().unscheduleBackgroundDexoptJob();
// Re-enable dexopt.
getArtManagerLocal().scheduleBackgroundDexoptJob();
L'opération dexopt effectuée lors de l'installation de l'application n'est pas lancée par ART.
de service. Il est lancé par le gestionnaire de packages
dexoptPackage
appel. Par conséquent, elle ne déclenche pas
BatchDexoptStartCallback
Pour désactiver dexopt lors de l'installation de l'application, empêchez le
d'appeler dexoptPackage
.
Remplacer le filtre de compilation pour certains packages (Android 15 et versions ultérieures)
Vous pouvez remplacer le filtre de compilateur pour certains packages en enregistrant un
via setAdjustCompilerFilterCallback
. Le rappel est appelé
chaque fois qu'un package va être dexopted, peu importe que dexopt soit initié par
Service ART pendant le démarrage et l'opération dexopt en arrière-plan ou par un appel d'API dexoptPackage
Si un colis n'a pas besoin d'être ajusté, le rappel doit renvoyer
originalCompilerFilter
getArtManagerLocal().setAdjustCompilerFilterCallback(
Runnable::run,
(packageName, originalCompilerFilter, reason) -> {
if (isVeryImportantPackage(packageName)) {
return "speed-profile";
}
return originalCompilerFilter;
});
Vous ne pouvez définir qu'un seul AdjustCompilerFilterCallback
. Si vous souhaitez utiliser
AdjustCompilerFilterCallback
pour remplacer le filtre de compilation pour plusieurs
vous devez combiner le code dans un seul rappel. Le rappel est maintenu
active pour tous les prochains appels, sauf si vous l'effacez.
Si vous souhaitez effacer le rappel, utilisez
ArtManagerLocal#clearAdjustCompilerFilterCallback
getArtManagerLocal().clearAdjustCompilerFilterCallback();
Autres personnalisations
Le service ART prend également en charge d'autres personnalisations.
Définir le seuil thermique pour la dexopt en arrière-plan
Le contrôle thermique du job dexopt en arrière-plan est effectué par le planificateur de jobs.
Le job est immédiatement annulé lorsque la température atteint
THERMAL_STATUS_MODERATE
Le seuil de
THERMAL_STATUS_MODERATE
est réglable.
Déterminer si dexopt est en cours d'exécution en arrière-plan
Le job dexopt en arrière-plan est géré par le planificateur de jobs, et son ID de job est
27873780
Pour déterminer si le job est en cours d'exécution, utilisez les API Job Scheduler.
// 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.
...
}
Fournir un profil pour dexopt
Pour utiliser un profil afin de guider dexopt, placez un fichier .prof
ou .dm
à côté de
APK.
Le fichier .prof
doit être un fichier de profil au format binaire et le nom du fichier doit être
Le nom de fichier de l'APK suivi de .prof
Par exemple :
base.apk.prof
Le nom du fichier .dm
doit être celui de l'APK avec le
extension remplacée par .dm
. Par exemple :
base.dm
Pour vérifier que le profil est utilisé pour dexopt, exécutez dexopt avec
speed-profile
et vérifiez le résultat.
pm art clear-app-profiles <package-name>
pm compile -m speed-profile -f -v <package-name>
La première ligne efface tous les profils produits par l'environnement d'exécution (c'est-à-dire ceux de
/data/misc/profiles
), le cas échéant, pour vous assurer que le profil situé à côté de l'APK est bien
le seul profil que le service ART peut utiliser. La deuxième ligne exécute dexopt
avec speed-profile
et transmet -v
pour imprimer le résultat détaillé.
Si le profil est utilisé, actualCompilerFilter=speed-profile
s'affiche dans
le résultat. Sinon, actualCompilerFilter=verify
s'affiche. Par exemple :
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}
Le service ART n'utilise généralement pas le profil pour les raisons suivantes:
- Le nom du profil est incorrect ou il ne figure pas à côté de l'APK.
- Le format du profil est incorrect.
- Le profil ne correspond pas à l'APK. (Les sommes de contrôle du profil ne
correspondent aux sommes de contrôle des fichiers
.dex
dans l'APK.)