Leggere le segnalazioni di bug

I bug sono una realtà in qualsiasi tipo di sviluppo e le segnalazioni di bug sono fondamentali per identificare e risolvere i problemi. Tutte le versioni di Android supportano l'acquisizione di segnalazioni di bug con Android Debug Bridge (adb); le versioni di Android 4.2 e successive supportano un'opzione sviluppatore per acquisire segnalazioni di bug e condividerle via email, Drive e così via.

I report sui bug di Android contengono dati dumpsys, dumpstate e logcat in formato di testo (.txt), il che ti consente di cercare facilmente contenuti specifici. Le sezioni seguenti descrivono in dettaglio i componenti dei report sui bug, descrivono i problemi comuni e forniscono suggerimenti utili e comandi grep per trovare i log associati a questi bug. La maggior parte delle sezioni include anche esempi per il comando e l'output grep e/o l'output dumpsys.

logcat

Il log logcat è un dump basato su stringhe di tutte le informazioni logcat. La parte system è riservata al framework e ha una cronologia più lunga rispetto a main, che contiene tutto il resto. Ogni riga in genere inizia con timestamp UID PID TID log-level, anche se UID potrebbe non essere presente nelle versioni precedenti di Android.

Visualizzare il log eventi

Questo log contiene rappresentazioni di stringhe di messaggi di log in formato binario. È meno rumoroso del log logcat, ma anche un po' più difficile da leggere. Quando visualizzi i log eventi, puoi cercare in questa sezione un ID processo (PID) specifico per vedere cosa ha fatto un processo. Il formato di base è: timestamp PID TID log-level log-tag tag-values.

I livelli di log includono:

  • V: verbose
  • D: debug
  • I: informazioni
  • W: warning
  • E: error

 

Per altri tag utili dei log eventi, consulta /services/core/java/com/android/server/EventLogTags.logtags.

ANR e deadlock

I bug report possono aiutarti a identificare la causa degli errori L'applicazione non risponde (ANR) e degli eventi di deadlock.

Identificare le app che non rispondono

Quando un'applicazione non risponde entro un determinato periodo di tempo, di solito a causa di un thread principale bloccato o occupato, il sistema termina il processo e scarica lo stack in /data/anr. Per scoprire il colpevole di un errore ANR, cerca am_anr nel log eventi binario.

Puoi anche cercare ANR in nel log logcat, che contiene ulteriori informazioni su ciò che utilizzava la CPU al momento dell'errore ANR.

Trovare le analisi dello stack

Spesso puoi trovare analisi dello stack che corrispondono a un errore ANR. Assicurati che il timestamp e il PID nelle tracce della VM corrispondano all'ANR che stai esaminando, quindi controlla il thread principale del processo. Ricorda:

  • Il thread principale indica solo cosa stava facendo il thread al momento dell'errore ANR, che potrebbe o meno corrispondere alla vera causa dell'errore ANR. Lo stack nella segnalazione di bug potrebbe essere innocente; qualcos'altro potrebbe essere rimasto bloccato per molto tempo, ma non abbastanza a lungo da causare un errore ANR, prima di sbloccarsi.
  • Potrebbero esistere più set di stack trace (VM TRACES JUST NOW e VM TRACES AT LAST ANR). Assicurati di visualizzare la sezione corretta.

Trovare i deadlock

I deadlock spesso vengono visualizzati per la prima volta come ANR perché i thread si bloccano. Se il deadlock colpisce il server di sistema, il watchdog lo interromperà, generando una voce nel log simile a: WATCHDOG KILLING SYSTEM PROCESS. Dal punto di vista dell'utente, il dispositivo si riavvia, anche se tecnicamente si tratta di un riavvio del runtime anziché di un vero e proprio riavvio.

  • In un riavvio del runtime, il server di sistema si arresta e viene riavviato; l'utente vede il dispositivo tornare all'animazione all'avvio.
  • In un riavvio, il kernel si è arrestato in modo anomalo e l'utente vede il dispositivo tornare al logo di avvio di Google.

Per trovare i deadlock, controlla le sezioni delle tracce della VM per individuare un pattern in cui il thread A è in attesa di qualcosa detenuto dal thread B, che a sua volta è in attesa di qualcosa detenuto dal thread A.

Attività

Un'attività è un componente dell'applicazione che fornisce una schermata con cui gli utenti interagiscono per fare qualcosa, ad esempio comporre un numero, scattare una foto, inviare un'email e così via. Dal punto di vista di una segnalazione di bug, un'attività è una singola azione mirata che un utente può eseguire, il che rende molto importante individuare l'attività che era in primo piano durante un arresto anomalo. Le attività (tramite ActivityManager) eseguono processi, quindi individuare tutti gli arresti e gli avvii dei processi per una determinata attività può anche aiutare a risolvere i problemi.

Visualizzare le attività con stato attivo

Per visualizzare una cronologia delle attività mirate, cerca am_focused_activity.

Visualizzazioni avviate

Per visualizzare una cronologia degli avvii dei processi, cerca Start proc.

Determinare se il dispositivo è in thrashing

Per determinare se il dispositivo è in thrashing, controlla se si verifica un aumento anomalo dell'attività intorno a am_proc_died e am_proc_start in un breve periodo di tempo.

Memoria

Poiché i dispositivi Android spesso hanno una memoria fisica limitata, la gestione della memoria ad accesso casuale (RAM) è fondamentale. I report sui bug contengono diversi indicatori di memoria insufficiente, nonché un dumpstate che fornisce un'istantanea della memoria.

Identificare la memoria in esaurimento

La memoria insufficiente può causare un'attività frenetica del sistema, che termina alcuni processi per liberare memoria, ma continua ad avviare altri processi. Per visualizzare prove a sostegno della memoria insufficiente, cerca concentrazioni di voci am_proc_died e am_proc_start nel log eventi binario.

La memoria insufficiente può anche rallentare il cambio di attività e impedire i tentativi di ritorno (perché l'attività a cui l'utente stava cercando di tornare è stata interrotta). Se il launcher è stato terminato, viene riavviato quando l'utente tocca il pulsante Home e i log mostrano il ricaricamento dei contenuti del launcher.

Visualizzare gli indicatori storici

La voce am_low_memory nel log eventi binario indica che l'ultimo processo memorizzato nella cache è terminato. Dopodiché, il sistema inizia a interrompere i servizi.

Visualizzare gli indicatori di thrashing

Altri indicatori di thrashing del sistema (paging, direct reclaim e così via) includono kswapd, kworker e mmcqd che consumano cicli. Tieni presente che il report bug raccolto può influire sugli indicatori di thrashing.

I log ANR possono fornire un'istantanea della memoria simile.

Acquisire uno snapshot della memoria

Lo snapshot della memoria è un dumpstate che elenca i processi Java e nativi in esecuzione (per i dettagli, consulta Visualizzazione delle allocazioni di memoria complessive). Tieni presente che lo snapshot fornisce solo lo stato in un momento specifico; il sistema potrebbe essere stato in condizioni migliori (o peggiori) prima dello snapshot.

Trasmissione

Le applicazioni generano trasmissioni per inviare eventi all'interno dell'applicazione corrente o a un'altra applicazione. I ricevitori di annunci si iscrivono a messaggi specifici (tramite filtri), il che consente loro di ascoltare e rispondere a un annuncio. I report sui bug contengono informazioni sulle trasmissioni inviate e non inviate, nonché un dumpsys di tutti i ricevitori che ascoltano una trasmissione specifica.

Visualizzare le trasmissioni storiche

Le trasmissioni storiche sono quelle già inviate, elencate in ordine cronologico inverso.

La sezione Riepilogo offre una panoramica delle ultime 300 trasmissioni in primo piano e delle ultime 300 trasmissioni in background.

La sezione Dettagli contiene informazioni complete per le ultime 50 trasmissioni in primo piano e le ultime 50 trasmissioni in background, nonché i ricevitori per ogni trasmissione. Ricevitori con:

  • Le voci BroadcastFilter vengono registrate in fase di runtime e inviate solo ai processi già in esecuzione.
  • La voce ResolveInfo viene registrata tramite le voci del file manifest. ActivityManager avvia il processo per ogni ResolveInfo se non è già in esecuzione.

Visualizzare le trasmissioni attive

I broadcast attivi sono quelli che devono ancora essere inviati. Un numero elevato nella coda indica che il sistema non riesce a inviare le trasmissioni abbastanza velocemente.

Visualizzare gli ascoltatori della trasmissione

Per visualizzare un elenco dei ricevitori in ascolto di una trasmissione, controlla la tabella di risoluzione dei ricevitori in dumpsys activity broadcasts. L'esempio seguente mostra tutti i ricevitori in ascolto di USER_PRESENT.

Monitorare la contesa

La registrazione della contesa del monitor a volte può indicare una contesa effettiva del monitor, ma il più delle volte indica che il sistema è così carico che tutto è rallentato. Potresti visualizzare eventi di monitoraggio lunghi registrati da ART nel log di sistema o degli eventi.

Nel log di sistema:

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

Nel log eventi:

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]

Compilazione in background

La compilazione può essere costosa e caricare il dispositivo.

La compilazione potrebbe avvenire in background durante il download degli aggiornamenti del Google Play Store. In questo caso, i messaggi dell'app Google Play Store (finsky) e installd vengono visualizzati prima dei messaggi dex2oat.

La compilazione può avvenire anche in background quando un'applicazione carica un file dex che non è ancora stato compilato. In questo caso, non vedrai la registrazione di finsky o installd.

Presentazione narrativa

Per stabilire la cronologia di un problema (come è iniziato, cosa è successo, come ha reagito il sistema) è necessaria una solida sequenza temporale degli eventi. Puoi utilizzare le informazioni nel report sui bug per sincronizzare le sequenze temporali in più log e determinare il timestamp esatto del report sui bug.

Sincronizzare le cronologie

Un bugreport riflette più cronologie parallele: log di sistema, log eventi, log del kernel e più cronologie specializzate per trasmissioni, statistiche della batteria, ecc. Purtroppo, le cronologie vengono spesso segnalate utilizzando basi temporali diverse.

I timestamp dei log di sistema e degli eventi si trovano nello stesso fuso orario dell'utente (come la maggior parte degli altri timestamp). Ad esempio, quando l'utente tocca il pulsante Home, il log di sistema segnala:

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

Per la stessa azione, il log eventi riporta:

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

I log del kernel (dmesg) utilizzano una base temporale diversa, contrassegnando le voci di log con i secondi trascorsi dal completamento del bootloader. Per registrare questa scala temporale in altre scale temporali, cerca i messaggi sospendi uscita e sospendi ingresso:

<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

Poiché i log del kernel potrebbero non includere l'ora durante la sospensione, devi registrare il log a tratti tra i messaggi di entrata e uscita dalla sospensione. Inoltre, i log del kernel utilizzano il fuso orario UTC e devono essere adattati al fuso orario dell'utente.

Identificare l'ora della segnalazione di bug

Per determinare quando è stata generata una segnalazione di bug, controlla innanzitutto il log di sistema (Logcat) per dumpstate: begin:

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

Successivamente, controlla i timestamp del log del kernel (dmesg) per il messaggio Starting service 'bugreport':

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

Procedi a ritroso per correlare i due eventi, tenendo presente le avvertenze menzionate in Sincronizzazione delle sequenze temporali. Sebbene si verifichino molte attività dopo l'avvio della segnalazione di bug, la maggior parte non è molto utile, in quanto l'operazione di acquisizione della segnalazione di bug carica notevolmente il sistema.

Potenza

Il log eventi contiene lo stato di accensione dello schermo, dove 0 indica che lo schermo è spento, 1 indica che lo schermo è acceso e 2 indica che la protezione tasti è stata completata.

I report sui bug contengono anche statistiche sui wake lock, un meccanismo utilizzato dagli sviluppatori di applicazioni per indicare che la loro applicazione deve mantenere il dispositivo acceso. Per maggiori dettagli sui wakelock, consulta PowerManager.WakeLock e Mantenere la CPU attiva.

Le statistiche aggregate sulla durata del wakelock monitorano solo il tempo in cui un wakelock è effettivamente responsabile del mantenimento attivo del dispositivo e non includono il tempo con lo schermo acceso. Inoltre, se vengono mantenuti più wakelock contemporaneamente, la durata del wakelock viene distribuita tra questi wakelock.

Per visualizzare più facilmente lo stato di alimentazione, utilizza Battery Historian, uno strumento open source di Google per analizzare i consumatori di batteria utilizzando i file bugreport di Android.

Pacchetti

La sezione DUMP OF SERVICE package contiene le versioni dell'applicazione (e altre informazioni utili).

Processi

I report sui bug contengono una grande quantità di dati per i processi, inclusi ora di inizio e di interruzione, durata di esecuzione, servizi associati, punteggio oom_adj e così via. Per informazioni dettagliate su come Android gestisce i processi, consulta Processi e thread.

Determinare la durata del processo

La sezione procstats contiene statistiche complete sulla durata di esecuzione dei processi e dei servizi associati. Per un riepilogo rapido e leggibile da persone, cerca AGGREGATED OVER per visualizzare i dati delle ultime tre o 24 ore, poi cerca Summary: per visualizzare l'elenco dei processi, la durata di esecuzione di questi processi a varie priorità e il loro utilizzo di RAM formattato come PSS/USS min-media-max.

Motivi per cui un processo è in esecuzione

La sezione dumpsys activity processes elenca tutti i processi attualmente in esecuzione ordinati in base al punteggio oom_adj (Android indica l'importanza del processo assegnandogli un valore oom_adj, che può essere aggiornato dinamicamente da ActivityManager). L'output è simile a quello di un'istantanea della memoria, ma include informazioni aggiuntive su ciò che causa l'esecuzione del processo. Nell'esempio riportato di seguito, le voci in grassetto indicano che il processo gms.persistent è in esecuzione con priorità vis (visibile) perché il processo di sistema è associato al relativo NetworkLocationService.

Scansioni

Per identificare le applicazioni che eseguono un numero eccessivo di scansioni Bluetooth Low Energy (BLE):

  • Trova i messaggi di log per BluetoothLeScanner:
    $ grep 'BluetoothLeScanner' ~/downloads/bugreport.txt
    07-28 15:55:19.090 24840 24851 D BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5
    
  • Individua il PID nei messaggi di log. In questo esempio, "24840" e "24851" sono PID (ID processo) e TID (ID thread).
  • Individua l'applicazione associata al PID:
    PID #24840: ProcessRecord{4fe996a 24840:com.badapp/u0a105}
    

    In questo esempio, il nome del pacchetto è com.badapp.

  • Cerca il nome del pacchetto su Google Play per identificare l'applicazione responsabile: https://play.google.com/store/apps/details?id=com.badapp.

Nota: per i dispositivi con Android 7.0, il sistema raccoglie dati per le scansioni BLE e associa queste attività all'applicazione che le ha avviate. Per maggiori dettagli, vedi Scansioni Bluetooth e Low Energy (LE).