Lire les rapports de bogues

Les bogues sont une réalité dans tout type de développement et les rapports de bogues sont essentiels pour identifier et résoudre les problèmes. Toutes les versions d'Android prennent en charge la capture des rapports de bogues avec Android Debug Bridge (adb) ; Les versions Android 4.2 et supérieures prennent en charge une option de développement permettant de rédiger des rapports de bogues et de les partager par e-mail, Drive, etc.

Les rapports de bogues Android contiennent des données dumpsys , dumpstate et logcat au format texte (.txt), vous permettant de rechercher facilement un contenu spécifique. Les sections suivantes détaillent les composants du rapport de bogues, décrivent les problèmes courants et donnent des conseils utiles et des commandes grep pour rechercher les journaux associés à ces bogues. La plupart des sections incluent également des exemples de commande et de sortie grep et/ou de sortie dumpsys .

Logcat

Le journal logcat est un vidage basé sur une chaîne de toutes les informations logcat . La partie système est réservée au framework et a un historique plus long que main qui contient tout le reste. Chaque ligne commence généralement par timestamp UID PID TID log-level , bien que l' UID puisse ne pas être répertorié dans les anciennes versions d'Android.

Afficher le journal des événements

Ce journal contient des représentations sous forme de chaîne de messages de journal au format binaire. Il est moins bruyant que le log logcat mais aussi un peu plus difficile à lire. Lorsque vous consultez les journaux d'événements, vous pouvez rechercher dans cette section un ID de processus (PID) spécifique pour voir ce qu'un processus a fait. Le format de base est le suivant : timestamp PID TID log-level log-tag tag-values ​​.

Les niveaux de journalisation incluent les éléments suivants :

  • V : verbeux
  • D : débogage
  • Moi : informations
  • W : avertissement
  • E : erreur

Pour d'autres balises de journal d'événements utiles, reportez-vous à /services/core/java/com/android/server/EventLogTags.logtags .

ANR et blocages

Les rapports de bogues peuvent vous aider à identifier la cause des erreurs ANR (Application Not Responding) et des événements de blocage.

Identifiez les applications qui ne répondent pas

Lorsqu'une application ne répond pas dans un certain délai, généralement en raison d'un thread principal bloqué ou occupé, le système tue le processus et vide la pile dans /data/anr . Pour découvrir le coupable derrière un ANR, recherchez am_anr dans le journal des événements binaires.

Vous pouvez également rechercher ANR in le journal logcat , qui contient plus d'informations sur ce qui utilisait le processeur au moment de l'ANR.

Rechercher des traces de pile

Vous pouvez souvent trouver des traces de pile qui correspondent à un ANR. Assurez-vous que l'horodatage et le PID sur les traces de la VM correspondent à l'ANR que vous étudiez, puis vérifiez le thread principal du processus. Gardez à l'esprit:

  • Le thread principal vous indique uniquement ce que le thread faisait au moment de l'ANR, ce qui peut ou non correspondre à la véritable cause de l'ANR. (La pile dans le rapport de bogue est peut-être innocente ; quelque chose d'autre peut être resté bloqué pendant longtemps – mais pas assez longtemps pour l'ANR – avant de se décoller.)
  • Il peut exister plusieurs ensembles de traces de pile ( VM TRACES JUST NOW et VM TRACES AT LAST ANR ). Assurez-vous que vous consultez la bonne section.

Trouver les blocages

Les blocages apparaissent souvent d'abord sous forme d'ANR car les threads restent bloqués. Si le blocage atteint le serveur système, le chien de garde finira par le tuer, ce qui entraînera une entrée dans le journal similaire à : WATCHDOG KILLING SYSTEM PROCESS . Du point de vue de l'utilisateur, l'appareil redémarre, bien que techniquement il s'agisse d'un redémarrage d'exécution plutôt que d'un véritable redémarrage.

  • Lors d'un redémarrage d'exécution , le serveur système s'arrête et est redémarré ; l'utilisateur voit l'appareil revenir à l'animation de démarrage.
  • Lors d'un redémarrage , le noyau s'est écrasé ; l'utilisateur voit l'appareil revenir au logo de démarrage de Google.

Pour trouver des blocages, recherchez dans les sections de traces de la VM un modèle de thread A attendant quelque chose détenu par le thread B, qui à son tour attend quelque chose détenu par le thread A.

Activités

Une activité est un composant d'application qui fournit un écran avec lequel les utilisateurs interagissent pour faire quelque chose comme composer un numéro, prendre une photo, envoyer un e-mail, etc. Du point de vue d'un rapport de bug, une activité est une chose unique et ciblée qu'un utilisateur peut faire. , ce qui rend très important la localisation de l'activité ciblée lors d'un accident. Les activités (via ActivityManager) exécutent des processus, donc la localisation de tous les arrêts et démarrages de processus pour une activité donnée peut également faciliter le dépannage.

Afficher les activités ciblées

Pour afficher un historique des activités ciblées, recherchez am_focused_activity .

Le processus d'affichage démarre

Pour afficher un historique des démarrages de processus, recherchez Start proc .

Déterminer si l'appareil se débat

Pour déterminer si l'appareil est en panne , recherchez une augmentation anormale de l'activité autour am_proc_died et am_proc_start dans un court laps de temps.

Mémoire

Étant donné que les appareils Android disposent souvent d'une mémoire physique limitée, la gestion de la mémoire vive (RAM) est essentielle. Les rapports de bogues contiennent plusieurs indicateurs de mémoire faible ainsi qu'un dumpstate qui fournit un instantané de la mémoire.

Identifier une mémoire faible

Une mémoire faible peut provoquer un ralentissement du système car il tue certains processus pour libérer de la mémoire mais continue de démarrer d'autres processus. Pour afficher des preuves corroborantes d'une mémoire faible, recherchez les concentrations d'entrées am_proc_died et am_proc_start dans le journal des événements binaires.

Une mémoire faible peut également ralentir le changement de tâche et contrecarrer les tentatives de retour (car la tâche à laquelle l'utilisateur tentait de revenir a été interrompue). Si le lanceur a été tué, il redémarre lorsque l'utilisateur appuie sur le bouton d'accueil et les journaux montrent que le lanceur recharge son contenu.

Afficher les indicateurs historiques

L'entrée am_low_memory dans le journal des événements binaires indique que le dernier processus mis en cache est mort. Après cela, le système commence à supprimer les services.

Afficher les indicateurs de battage

D'autres indicateurs de perturbation du système (pagination, récupération directe, etc.) incluent les cycles de consommation kswapd , kworker et mmcqd . (Gardez à l'esprit que le rapport de bug collecté peut influencer les indicateurs de raclée.)

Les journaux ANR peuvent fournir un instantané de mémoire similaire.

Obtenez un instantané de la mémoire

L'instantané de mémoire est un état de vidage qui répertorie les processus Java et natifs en cours d'exécution (pour plus de détails, reportez-vous à Affichage des allocations globales de mémoire ). Gardez à l’esprit que l’instantané ne donne que l’état à un moment précis ; le système aurait pu être en meilleur (ou pire) état avant l’instantané.

Diffusions

Les applications génèrent des diffusions pour envoyer des événements au sein de l'application actuelle ou vers une autre application. Les récepteurs de diffusion s'abonnent à des messages spécifiques (via des filtres), leur permettant à la fois d'écouter et de répondre à une diffusion. Les rapports de bogues contiennent des informations sur les diffusions envoyées et non envoyées, ainsi qu'un dumpsys de tous les récepteurs écoutant une diffusion spécifique.

Voir les émissions historiques

Les émissions historiques sont celles qui ont déjà été envoyées, classées par ordre chronologique inverse.

La section récapitulative est un aperçu des 300 dernières diffusions en premier plan et des 300 dernières diffusions en arrière-plan.

La section détaillée contient des informations complètes sur les 50 dernières diffusions en premier plan et les 50 dernières diffusions en arrière-plan, ainsi que les récepteurs pour chaque diffusion. Récepteurs dotés d'un :

  • Les entrées BroadcastFilter sont enregistrées au moment de l’exécution et sont envoyées uniquement aux processus déjà en cours d’exécution.
  • Les entrées ResolveInfo sont enregistrées via des entrées de manifeste. L'ActivityManager démarre le processus pour chaque ResolveInfo s'il n'est pas déjà en cours d'exécution.

Afficher les diffusions actives

Les diffusions actives sont celles qui n'ont pas encore été envoyées. Un nombre important dans la file d'attente signifie que le système ne peut pas distribuer les diffusions assez rapidement pour suivre le rythme.

Afficher les auditeurs de diffusion

Pour afficher une liste des récepteurs écoutant une diffusion, consultez la table de résolution du récepteur dans les dumpsys activity broadcasts . L'exemple suivant affiche tous les récepteurs écoutant USER_PRESENT .

Surveiller les conflits

La journalisation des conflits de moniteur peut parfois indiquer un conflit de moniteur réel, mais indique le plus souvent que le système est tellement chargé que tout a ralenti. Vous pouvez voir de longs événements de surveillance enregistrés par ART dans le journal système ou dans le journal des événements.

Dans le journal système :

10-01 18:12:44.343 29761 29914 W art     : Long monitor contention event with owner method=void android.database.sqlite.SQLiteClosable.acquireReference() from SQLiteClosable.java:52 waiters=0 for 3.914s

Dans le journal des événements :

10-01 18:12:44.364 29761 29914 I dvm_lock_sample: [com.google.android.youtube,0,pool-3-thread-9,3914,ScheduledTaskMaster.java,138,SQLiteClosable.java,52,100]

Compilation de fond

La compilation peut être coûteuse et charger l'appareil.

La compilation peut se produire en arrière-plan lors du téléchargement des mises à jour du Google Play Store. Dans ce cas, les messages de l'application Google Play Store ( finsky ) et installd apparaissent avant les messages dex2oat .

La compilation peut également se produire en arrière-plan lorsqu'une application charge un fichier dex qui n'a pas encore été compilé. Dans ce cas, vous ne verrez pas la journalisation finsky ou installd .

Narratif

Établir le récit d’un problème (comment il a commencé, ce qui s’est passé, comment le système a réagi) nécessite une chronologie solide des événements. Vous pouvez utiliser les informations contenues dans le rapport de bogue pour synchroniser les chronologies de plusieurs journaux et déterminer l'horodatage exact du rapport de bogue.

Synchroniser les chronologies

Un rapport de bogue reflète plusieurs chronologies parallèles : journal système, journal des événements, journal du noyau et plusieurs chronologies spécialisées pour les diffusions, les statistiques de la batterie, etc. Malheureusement, les chronologies sont souvent rapportées en utilisant des bases de temps différentes.

Les horodatages du système et du journal des événements sont dans le même fuseau horaire que celui de l'utilisateur (comme le sont la plupart des autres horodatages). Par exemple, lorsque l'utilisateur appuie sur le bouton d'accueil, le journal système signale :

10-03 17:19:52.939  1963  2071 I ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10200000 cmp=com.google.android.googlequicksearchbox/com.google.android.launcher.GEL (has extras)} from uid 1000 on display 0

Pour la même action, le journal des événements rapporte :

10-03 17:19:54.279  1963  2071 I am_focused_activity: [0,com.google.android.googlequicksearchbox/com.google.android.launcher.GEL]

Les journaux du noyau ( dmesg ) utilisent une base de temps différente, marquant les éléments du journal avec les secondes écoulées depuis la fin du chargeur de démarrage. Pour enregistrer cette échelle de temps sur d’autres échelles de temps, recherchez les messages de suspension de sortie et de suspension d’entrée :

<6>[201640.779997] PM: suspend exit 2015-10-03 19:11:06.646094058 UTC
…
<6>[201644.854315] PM: suspend entry 2015-10-03 19:11:10.720416452 UTC

Étant donné que les journaux du noyau peuvent ne pas inclure la durée de la suspension, vous devez enregistrer le journal par morceaux entre les messages d'entrée et de sortie de suspension. De plus, les journaux du noyau utilisent le fuseau horaire UTC et doivent être ajustés au fuseau horaire de l'utilisateur.

Identifier l'heure du rapport de bug

Pour déterminer quand un rapport de bogue a été effectué, vérifiez d'abord le journal système (Logcat) pour le dumpstate: begin :

10-03 17:19:54.322 19398 19398 I dumpstate: begin

Ensuite, vérifiez les horodatages du journal du noyau ( dmesg ) pour le message Starting service 'bugreport' :

<5>[207064.285315] init: Starting service 'bugreport'...

Travaillez à rebours pour corréler les deux événements, en gardant à l'esprit les mises en garde mentionnées dans Chronologies de synchronisation . Bien qu'il se passe beaucoup de choses après le lancement du rapport de bogue, la plupart des activités ne sont pas très utiles car le fait de prendre le rapport de bogue charge considérablement le système.

Pouvoir

Le journal des événements contient l'état d'alimentation de l'écran, où 0 correspond à l'écran éteint, 1 à l'écran allumé et 2 au verrouillage du clavier terminé.

Les rapports de bogues contiennent également des statistiques sur les wakelocks, un mécanisme utilisé par les développeurs d'applications pour indiquer que leur application doit garder l'appareil allumé. (Pour plus de détails sur les wakelocks, reportez-vous à PowerManager.WakeLock et Keep the CPU on .)

Les statistiques agrégées sur la durée du wakelock suivent uniquement la durée pendant laquelle un wakelock est réellement responsable du maintien de l'appareil éveillé et n'incluent pas le temps pendant lequel l'écran est allumé. De plus, si plusieurs wakelocks sont maintenus simultanément, la durée du wakelock est répartie entre ces wakelocks.

Pour plus d'aide sur la visualisation de l'état de l'alimentation, utilisez Battery Historian , un outil open source de Google pour analyser les consommateurs de batterie à l'aide de fichiers de rapport de bogues Android.

Paquets

La section DUMP OF SERVICE package contient les versions de l'application (et d'autres informations utiles).

Processus

Les rapports de bogues contiennent une énorme quantité de données sur les processus, notamment l'heure de début et d'arrêt, la durée d'exécution, les services associés, le score oom_adj , etc. Pour plus de détails sur la façon dont Android gère les processus, reportez-vous à Processus et threads .

Déterminer la durée d'exécution du processus

La section procstats contient des statistiques complètes sur la durée d'exécution des processus et des services associés. Pour un résumé rapide et lisible par l'homme, recherchez AGGREGATED OVER pour afficher les données des trois ou 24 dernières heures, puis recherchez Summary: pour afficher la liste des processus, la durée d'exécution de ces processus avec différentes priorités et leur RAM. utilisation au format min-moyenne-max PSS/min-moyenne-max USS.

Raisons pour lesquelles un processus est en cours d'exécution

La section dumpsys activity processes répertorie tous les processus en cours d'exécution classés par score oom_adj (Android indique l'importance du processus en attribuant au processus une valeur oom_adj , qui peut être mise à jour dynamiquement par ActivityManager). Le résultat est similaire à celui d’un instantané de mémoire mais inclut des informations supplémentaires sur la cause de l’exécution du processus. Dans l'exemple ci-dessous, les entrées en gras indiquent que le processus gms.persistent s'exécute avec une priorité vis (visible) car le processus système est lié à son NetworkLocationService .

Analyses

Suivez les étapes suivantes pour identifier les applications effectuant des analyses Bluetooth Low Energy (BLE) excessives :

  • Rechercher les messages du journal pour BluetoothLeScanner :
    $ grep 'BluetoothLeScanner' ~/downloads/bugreport.txt
    07-28 15:55:19.090 24840 24851 D BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5
    
  • Localisez le PID dans les messages du journal. Dans cet exemple, « 24840 » et « 24851 » sont PID (ID de processus) et TID (ID de thread).
  • Localisez l'application associée au PID :
    PID #24840: ProcessRecord{4fe996a 24840:com.badapp/u0a105}
    

    Dans cet exemple, le nom du package est com.badapp .

  • Recherchez le nom du package sur Google Play pour identifier l'application responsable : https://play.google.com/store/apps/details?id=com.badapp .

Remarque : Pour les appareils exécutant Android 7.0, le système collecte des données pour les analyses BLE et associe ces activités à l'application initiatrice. Pour plus de détails, voir Analyses Low Energy (LE) et Bluetooth .