ART TI

Sous Android 8.0 et versions ultérieures, l'interface ART Tooling (ART TI) expose certains éléments internes d'exécution et permet aux profileurs et aux débogueurs d'influencer le comportement d'exécution des applications. Vous pouvez l'utiliser pour implémenter des outils de performances de pointe fournis pour implémenter des agents natifs sur d'autres plates-formes.

Les éléments internes d'exécution sont exposés aux agents qui ont été chargés dans le processus d'exécution. Ils communiquent avec l'ART via des appels directs et des rappels. L'environnement d'exécution prend en charge plusieurs agents afin que les différents problèmes de profilage orthogonal puissent être séparés. Les agents peuvent être fournis au début de l'exécution (lorsque dalvikvm ou app_process sont appelés) ou associés à un processus déjà en cours d'exécution.

Étant donné que la possibilité d'instrumenter et de modifier le comportement de l'application et de l'environnement d'exécution est très puissante, deux mesures de sécurité ont été intégrées à l'instrumentation ART:

  • Tout d'abord, le code qui expose l'interface de l'agent, JVMTI, est implémenté en tant que plug-in d'exécution, et non en tant que composant principal de l'environnement d'exécution. Le chargement des plug-ins peut être limité afin d'empêcher les agents de trouver l'un des points d'interface.
  • Deuxièmement, la classe ActivityManager et le processus d'exécution ne permettent aux agents de s'attacher qu'aux applications débogables. Les applications débogables ont été approuvées par leurs développeurs pour être analysées et instrumentées, et ne sont pas distribuées aux utilisateurs finaux. Le Google Play Store n'autorise pas la distribution d'applications débogables. Cela garantit que les applications normales (y compris les composants principaux) ne peuvent pas être instrumentées ni manipulées.

Conception

Le flux général et l'interconnexion dans une application instrumentée sont illustrés dans la figure 1.

Flux et interconnexion dans une application instrumentée
Figure 1 : Flux et interconnexion d'une application instrumentée

Le plug-in ART libopenjdkjvmti expose l'intent TI ART, qui est conçu pour répondre aux besoins et aux contraintes de la plate-forme:

  • La redéfinition de classe est basée sur des fichiers Dex, qui ne contiennent qu'une seule définition de classe, au lieu de fichiers de classe.
  • Les API Java pour l'instrumentation et la redéfinition ne sont pas exposées.

L'outil d'instrumentation ART est également compatible avec les profileurs Android Studio.

Charger ou joindre un agent

Pour associer un agent au démarrage de l'environnement d'exécution, utilisez cette commande pour charger à la fois le plug-in JVMTI et l'agent donné:

dalvikvm -Xplugin:libopenjdkjvmti.so -agentpath:/path/to/agent/libagent.so …

Aucune mesure de sécurité n'est mise en place lorsqu'un agent est chargé au démarrage de l'environnement d'exécution. N'oubliez donc pas qu'un environnement d'exécution démarré manuellement permet une modification complète sans mesures de sécurité. (Cela permet de tester ART.)

Remarque: Cela ne s'applique pas aux applications normales (y compris le serveur système) sur un appareil. Les applications sont dérivées d'un zygote déjà en cours d'exécution, et un processus zygote n'est pas autorisé à charger d'agents.

Pour associer un agent à une application déjà en cours d'exécution, utilisez la commande suivante:

adb shell cmd activity attach-agent [process]
/path/to/agent/libagent.so[=agent-options]

Si le plug-in JVMTI n'a pas encore été chargé, l'association d'un agent charge à la fois le plug-in et la bibliothèque de l'agent.

Un agent ne peut être associé qu'à une application en cours d'exécution marquée comme débogable (dans le fichier manifeste de l'application, avec l'attribut android:debuggable défini sur true au niveau du nœud de l'application). La classe ActivityManager et l'ART effectuent des vérifications avant d'autoriser l'association d'un agent. La classe ActivityManager vérifie l'état de débogage des informations actuelles de l'application (dérivées des données de la classe PackageManager), et l'environnement d'exécution vérifie son état actuel, qui a été défini au démarrage de l'application.

Emplacements des agents

L'environnement d'exécution doit charger des agents dans le processus en cours, afin que l'agent puisse s'y associer directement et communiquer avec lui. L'ART lui-même est indépendant de l'emplacement spécifique d'où provient l'agent. La chaîne est utilisée pour un appel dlopen. Les autorisations du système de fichiers et les règles SELinux limitent le chargement réel.

Pour fournir des agents pouvant être exécutés par une application débogable, procédez comme suit:

  • Intégrez l'agent dans le répertoire de la bibliothèque de l'APK de l'application.
  • Utilisez run-as pour copier l'agent dans le répertoire de données de l'application.

API

La méthode suivante a été ajoutée à android.os.Debug.

/**
     * Attach a library as a jvmti agent to the current runtime, with the given classloader
     * determining the library search path.
     * Note: agents may only be attached to debuggable apps. Otherwise, this function will
     * throw a SecurityException.
     *
     * @param library the library containing the agent.
     * @param options the options passed to the agent.
     * @param classLoader the classloader determining the library search path.
     *
     * @throws IOException if the agent could not be attached.
     * @throws a SecurityException if the app is not debuggable.
     */
    public static void attachJvmtiAgent(@NonNull String library, @Nullable String options,
            @Nullable ClassLoader classLoader) throws IOException {

Autres API Android

La commande attach-agent est visible publiquement. Cette commande associe un agent JVMTI à un processus en cours d'exécution:

adb shell 'am attach-agent com.example.android.displayingbitmaps
\'/data/data/com.example.android.displayingbitmaps/code_cache/libfieldnulls.so=Ljava/lang/Class;.name:Ljava/lang/String;\''

Les commandes am start -P et am start-profiler/stop-profiler sont semblables à la commande attach-agent.

JVMTI

Cette fonctionnalité expose l'API JVMTI aux agents (code natif). Voici les principales fonctionnalités:

  • Redéfinir une classe
  • Suivre l'allocation d'objets et la récupération de mémoire
  • Itération sur tous les objets d'un tas, en suivant l'arborescence de référence des objets.
  • Inspecter les piles d'appels Java
  • Suspendre (et reprendre) tous les threads.

Différentes fonctionnalités peuvent être disponibles selon les versions d'Android.

Compatibilité

Cette fonctionnalité nécessite une prise en charge de l'environnement d'exécution de base qui n'est disponible que sur Android 8.0 ou version ultérieure. Les fabricants d'appareils n'ont pas besoin d'apporter de modifications pour implémenter cette fonctionnalité. Il fait partie d'AOSP.

Validation

Le CTS teste les éléments suivants sur Android 8 et versions ultérieures:

  • Tests que les agents se connectent aux applications débogables et ne parviennent pas à se connecter aux applications non débogables.
  • Teste toutes les API JVMTI implémentées
  • Vérifie que l'interface binaire des agents est stable

Des tests supplémentaires ont été ajoutés à Android 9 et versions ultérieures, et sont inclus dans les tests CTS pour ces versions.