バグレポートを読む

バグはあらゆるタイプの開発において現実のものであり、バグレポートは問題を特定して解決するために重要です。 Androidのすべてのバージョンは、 Android Debug Bridge(adb)を使用したバグレポートのキャプチャをサポートしています。 Androidバージョン4.2以降では、バグレポートを取得し、メールやドライブなどで共有するためのデベロッパーオプションがサポートされています。

Androidのバグレポートには、 dumpsysdumpstatelogcatのデータがテキスト(.txt)形式で含まれているため、特定のコンテンツを簡単に検索できます。次のセクションでは、バグレポートのコンポーネントについて詳しく説明し、一般的な問題について説明し、それらのバグに関連するログを見つけるための役立つヒントとgrepコマンドを示します。ほとんどのセクションには、 grepコマンドと出力および/またはdumpsys出力の例も含まれています。

Logcat

logcatログは、すべてのlogcat情報の文字列ベースのダンプです。システム部分はフレームワーク用に予約されており、他のすべてを含むメインよりも長い履歴があります。各行は通常、 timestamp UID PID TID log-levelで始まりますが、古いバージョンのAndroidではUIDがリストされていない場合があります。

イベントログの表示

このログには、バイナリ形式のログメッセージの文字列表現が含まれています。 logcatログよりもノイズは少ないですが、読みにくいです。イベントログを表示する場合、このセクションで特定のプロセスID(PID)を検索して、プロセスが実行していることを確認できます。基本的な形式は次のとおりです。 timestamp PID TID log-level log-tag tag-values

ログレベルには次のものが含まれます。

  • V:冗長
  • D:デバッグ
  • I:情報
  • W:警告
  • E:エラー

その他の便利なイベントログタグについては、/ services / core / java / com / android / server /EventLogTags.logtagsを参照してください。

ANRとデッドロック

バグレポートは、 Application Not Responding(ANR)エラーとデッドロックイベントの原因を特定するのに役立ちます。

応答しないアプリの特定

アプリケーションが特定の時間内に応答しない場合、通常はメインスレッドがブロックされているかビジーであるために、システムはプロセスを強制終了し、スタックを/data/anrにダンプします。 ANRの背後にある原因を発見するには、バイナリイベントログでam_anrのgrepを実行します。

logcatログでANR in grepすることもできます。このログには、ANRの時点でCPUを使用していたものに関する詳細情報が含まれています。

スタックトレースの検索

多くの場合、ANRに対応するスタックトレースを見つけることができます。 VMトレースのタイムスタンプとPIDが調査しているANRと一致していることを確認してから、プロセスのメインスレッドを確認してください。覚えておいてください:

  • メインスレッドは、ANRの時点でスレッドが何をしていたかのみを示します。これは、ANRの真の原因に対応する場合と対応しない場合があります。 (バグレポートのスタックは無実である可能性があります。他の何かが長い間スタックしている可能性がありますが、ANRには十分な長さではありませんが、スタックが解除される前に。)
  • 複数のスタックトレースのセット( VM TRACES JUST NOWおよびVM TRACES AT LAST ANR )が存在する可能性があります。正しいセクションを表示していることを確認してください。

デッドロックの検出

スレッドがスタックしているため、デッドロックは最初にANRとして表示されることがよくあります。デッドロックがシステムサーバーに到達すると、ウォッチドッグは最終的にそれを強制終了し、ログに次のようなエントリが表示されます: WATCHDOG KILLING SYSTEM PROCESS 。ユーザーの観点からは、デバイスは再起動しますが、技術的には、これは実際の再起動ではなく、ランタイムの再起動です。

  • 実行時の再起動では、システムサーバーが停止し、再起動されます。ユーザーには、デバイスが起動アニメーションに戻るのが表示されます。
  • 再起動時に、カーネルがクラッシュしました。ユーザーには、デバイスがGoogleブートロゴに戻るのが表示されます。

デッドロックを見つけるには、VMトレースセクションで、スレッドBが保持しているものを待機しているスレッドAのパターンを確認します。スレッドBは、スレッドAが保持しているものを待機しています。

活動

アクティビティは、ユーザーが番号のダイヤル、写真の撮影、電子メールの送信などを行うために対話する画面を提供するアプリケーションコンポーネントです。バグレポートの観点からは、アクティビティはユーザーが実行できる単一の焦点を絞ったものです。 、これにより、クラッシュ時にフォーカスされていたアクティビティを特定することが非常に重要になります。アクティビティ(ActivityManagerを介して)はプロセスを実行するため、特定のアクティビティのすべてのプロセスの停止と開始を特定することも、トラブルシューティングに役立ちます。

焦点を絞った活動を見る

フォーカスされたアクティビティの履歴を表示するには、 am_focused_activityを検索します。

表示プロセスが開始されます

プロセス開始の履歴を表示するには、 Start procを検索します。

デバイスがスラッシングしていますか?

デバイスがスラッシングしているかどうかを判断するには、 am_proc_diedおよびam_proc_start周辺のアクティビティが短時間で異常に増加していないかどうかを確認します。

メモリー

Androidデバイスでは物理メモリが制限されていることが多いため、ランダムアクセスメモリ(RAM)の管理が重要です。バグレポートには、メモリ不足のいくつかのインジケータと、メモリスナップショットを提供するダンプ状態が含まれています。

低メモリの特定

メモリが少ないと、一部のプロセスが強制終了されてメモリが解放されますが、他のプロセスは引き続き開始されるため、システムがクラッシュする可能性があります。メモリ不足の裏付けとなる証拠を表示するには、バイナリイベントログでam_proc_diedおよびam_proc_startエントリの濃度を確認します。

メモリが少ないと、タスクの切り替えが遅くなり、戻りの試行が妨げられる可能性があります(ユーザーが戻ろうとしていたタスクが強制終了されたため)。ランチャーが強制終了された場合、ユーザーがホームボタンに触れると再起動し、ログにはランチャーがコンテンツをリロードしたことが示されます。

履歴インジケーターの表示

バイナリイベントログのam_low_memoryエントリは、最後にキャッシュされたプロセスが停止したことを示します。この後、システムはサービスの強制終了を開始します。

スラッシングインジケーターの表示

システムスラッシングのその他の指標(ページング、直接再生など)には、 kswapdkworker 、およびmmcqd消費サイクルが含まれます。 (収集されるバグレポートがスラッシングインジケーターに影響を与える可能性があることに注意してください。)

ANRログは、同様のメモリスナップショットを提供できます。

メモリスナップショットの取得

メモリスナップショットは、実行中のJavaプロセスとネイティブプロセスを一覧表示するダンプ状態です(詳細については、全体的なメモリ割り当ての表示を参照してください)。スナップショットは特定の時点の状態のみを提供することに注意してください。スナップショットの前は、システムの状態が良好(または不良)であった可能性があります。

放送

アプリケーションはブロードキャストを生成して、現在のアプリケーション内または別のアプリケーションにイベントを送信します。ブロードキャストレシーバーは、(フィルターを介して)特定のメッセージをサブスクライブし、ブロードキャストのリッスンと応答の両方を可能にします。バグレポートには、送信済みブロードキャストと未送信ブロードキャストに関する情報、および特定のブロードキャストをリッスンしているすべての受信者のdumpsysが含まれます。

過去の放送を見る

過去の放送は、すでに送信されたものであり、時系列の逆順にリストされています。

要約セクションは、過去300回のフォアグラウンドブロードキャストと過去300回のバックグラウンドブロードキャストの概要です。

詳細セクションには、過去50回のフォアグラウンドブロードキャストと過去50回のバックグラウンドブロードキャストの完全な情報、および各ブロードキャストの受信機が含まれています。次のような受信機:

  • BroadcastFilterエントリは実行時に登録され、すでに実行中のプロセスにのみ送信されます。
  • ResolveInfoエントリは、マニフェストエントリを介して登録されます。 ActivityManagerは、ResolveInfoがまだ実行されていない場合、各ResolveInfoのプロセスを開始します。

アクティブなブロードキャストの表示

アクティブなブロードキャストとは、まだ送信されていないブロードキャストです。キュー内の数が多いということは、システムが追いつくのに十分な速さでブロードキャストをディスパッチできないことを意味します。

放送リスナーの視聴

ブロードキャストをリッスンしているレシーバーのリストを表示するには、 dumpsys activity broadcastsのレシーバーリゾルバーテーブルを確認してください。次の例は、 USER_PRESENTをリッスンしているすべてのレシーバーを表示します。

競合を監視する

モニターの競合ログは、実際のモニターの競合を示す場合がありますが、ほとんどの場合、システムの負荷が非常に高く、すべての速度が低下していることを示します。 ARTによってシステムまたはイベントログに記録された長いモニターイベントが表示される場合があります。

システムログ:

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

イベントログ:

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]

バックグラウンドコンパイル

コンパイルにはコストがかかり、デバイスをロードする可能性があります。

Google Playストアのアップデートがダウンロードされているときに、バックグラウンドでコンパイルが行われる場合があります。この場合、Google Playストアアプリ( finsky )およびinstalldされたメッセージは、 dex2oatメッセージの前に表示されます。

アプリケーションがまだコンパイルされていないdexファイルをロードしているときに、コンパイルがバックグラウンドで発生することもあります。この場合、 finskyまたはinstalldのログは表示されません。

物語

問題の説明(問題がどのように始まったか、何が起こったか、システムがどのように反応したか)を確立するには、イベントの確実なタイムラインが必要です。バグレポートの情報を使用して、複数のログ間でタイムラインを同期し、バグレポートの正確なタイムスタンプを決定できます。

タイムラインの同期

バグレポートには、システムログ、イベントログ、カーネルログ、ブロードキャスト、バッテリー統計などの複数の特殊なタイムラインなど、複数の並列タイムラインが反映されます。残念ながら、タイムラインは異なるタイムベースを使用して報告されることがよくあります。

システムログとイベントログのタイムスタンプは、(他のほとんどのタイムスタンプと同様に)ユーザーと同じタイムゾーンにあります。たとえば、ユーザーがホームボタンをタップすると、システムログは次のように報告します。

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

同じアクションについて、イベントログは次のことを報告します。

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

カーネル( dmesg )ログは異なるタイムベースを使用し、ブートローダーが完了してから秒数でログ項目にタグを付けます。このタイムスケールを他のタイムスケールに登録するには、サスペンド出口およびサスペンドエントリメッセージを検索します。

<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

カーネルログにはサスペンド中の時間が含まれない場合があるため、サスペンドエントリメッセージとエグジットメッセージの間にログを区分的に登録する必要があります。さらに、カーネルログはUTCタイムゾーンを使用するため、ユーザーのタイムゾーンに合わせて調整する必要があります。

バグレポート時間の特定

バグレポートがいつ取得されたかを判断するには、最初にシステムログ(Logcat)でdumpstateを確認しますdumpstate: begin

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

次に、カーネルログ( dmesg )のタイムスタンプでStarting service 'bugreport'メッセージを確認します。

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

タイムラインの同期で説明されている警告を念頭に置いて、2つのイベントを相互に関連付けるために逆方向に作業します。バグレポートが開始された後は多くのことが起こりますが、バグレポートを取得するという行為はシステムにかなりの負荷をかけるため、ほとんどのアクティビティはあまり役に立ちません。

イベントログには、画面の電源ステータスが含まれます。0は画面オフ、1は画面オン、2はキーガード完了用です。

バグレポートには、アプリケーション開発者がデバイスをオンのままにする必要があることを示すためにアプリケーション開発者が使用するメカニズムであるウェイクロックに関する統計も含まれています。 (ウェイクロックの詳細については、 PowerManager.WakeLockおよびCPUをオンに保つを参照してください。)

集約されたウェイクロック期間の統計は、ウェイクロックが実際にデバイスのアウェイクを維持する役割を果たしている時間のみを追跡し、画面がオンになっている時間は含まれません。さらに、複数のウェイクロックが同時に保持されている場合、ウェイクロックの継続時間はそれらのウェイクロックに分散されます。

電力ステータスの視覚化の詳細については、GoogleのオープンソースツールであるBattery Historianを使用して、Androidのバグレポートファイルを使用してバッテリーの消費者を分析してください。

パッケージ

DUMP OF SERVICE packageのセクションには、アプリケーションのバージョン(およびその他の役立つ情報)が含まれています。

プロセス

バグレポートには、開始時間と停止時間、実行時間、関連サービス、 oom_adjスコアなど、プロセスに関する大量のデータが含まれています。Androidがプロセスを管理する方法の詳細については、 「プロセスとスレッド」を参照してください。

プロセスランタイムの決定

procstatsセクションには、プロセスと関連サービスが実行されている期間に関する完全な統計が含まれています。人間が読める形式の概要をすばやく表示するには、 AGGREGATED OVERを検索して、過去3時間または24時間のデータを表示してから、 Summary:を検索して、プロセスのリスト、プロセスがさまざまな優先度で実行された時間、およびRAMを表示します。 min-average-max PSS / min-average-maxUSSとしてフォーマットされた使用法。

プロセスが実行されているのはなぜですか?

dumpsys activity processesセクションには、現在実行中のすべてのプロセスがoom_adjスコア順に一覧表示されます(Androidは、プロセスにoom_adj値を割り当てることでプロセスの重要性を示します。この値は、ActivityManagerによって動的に更新できます)。出力はメモリスナップショットの出力と似ていますが、プロセスの実行の原因に関する追加情報が含まれています。以下の例では、太字のエントリは、システムプロセスがNetworkLocationServiceにバインドされているため、 gms.persistentプロセスがvis (表示)優先度で実行されていることを示しています。

スキャン

次の手順を使用して、過剰なBluetooth Low Energy(BLE)スキャンを実行しているアプリケーションを特定します。

  • BluetoothLeScannerのログメッセージを検索する:
    $ grep 'BluetoothLeScanner' ~/downloads/bugreport.txt
    07-28 15:55:19.090 24840 24851 D BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5
    
  • ログメッセージでPIDを見つけます。この例では、「24840」と「24851」はPID(プロセスID)とTID(スレッドID)です。
  • PIDに関連付けられているアプリケーションを見つけます:
    PID #24840: ProcessRecord{4fe996a 24840:com.badapp/u0a105}
    

    この例では、パッケージ名はcom.badappです。

  • Google Playでパッケージ名を検索して、責任のあるアプリケーションを特定します: https ://play.google.com/store/apps/details?id = com.badapp。

:Android 7.0を実行しているデバイスの場合、システムはBLEスキャンのデータを収集し、これらのアクティビティを開始アプリケーションに関連付けます。詳細については、低エネルギー(LE)およびBluetoothスキャンを参照してください。