blob: ebab35b663b3c8e7fb0fc38c745097878640529c [file] [log] [blame]
Glenn Kasten37784a52014-02-03 11:57:33 -08001page.title=Audio Debugging
2@jd:body
3
4<div id="qv-wrapper">
5 <div id="qv">
6 <h2>In this document</h2>
7 <ol id="auto-toc">
8 </ol>
9 </div>
10</div>
11
12<p>
13This article describes some tips and tricks for debugging Android audio.
14</p>
15
16<h2 id="teeSink">Tee Sink</h2>
17
18<p>
19The "tee sink" is
20an AudioFlinger debugging feature, available in custom builds only,
21for retaining a short fragment of recent audio for later analysis.
22This permits comparison between what was actually played or recorded
23vs. what was expected.
24</p>
25
26<p>
27For privacy the tee sink is disabled by default, at both compile-time and
28run-time. To use the tee sink, you will need to enable it by re-compiling,
29and also by setting a property. Be sure to disable this feature after you are
30done debugging; the tee sink should not be left enabled in production builds.
31</p>
32
33<p>
34The instructions in the remainder of this section are for Android 4.4,
35and may require changes for other versions.
36</p>
37
38<h3>Compile-time setup</h3>
39
40<ol>
41<li><code>cd frameworks/av/services/audioflinger</code></li>
Clay Murphy3a7af3a2014-09-09 17:29:09 -070042<li>Edit <code>Configuration.h</code>.</li>
43<li>Uncomment <code>#define TEE_SINK</code>.</li>
44<li>Re-build <code>libaudioflinger.so</code>.</li>
Glenn Kasten37784a52014-02-03 11:57:33 -080045<li><code>adb root</code></li>
46<li><code>adb remount</code></li>
Clay Murphy3a7af3a2014-09-09 17:29:09 -070047<li>Push or sync the new <code>libaudioflinger.so</code> to the device's <code>/system/lib</code>.</li>
Glenn Kasten37784a52014-02-03 11:57:33 -080048</ol>
49
50<h3>Run-time setup</h3>
51
52<ol>
53<li><code>adb shell getprop | grep ro.debuggable</code>
54<br />Confirm that the output is: <code>[ro.debuggable]: [1]</code>
55</li>
56<li><code>adb shell</code></li>
57<li><code>ls -ld /data/misc/media</code>
58<br />
59<p>
60Confirm that the output is:
61</p>
62<pre>
63drwx------ media media ... media
64</pre>
65<br />
66<p>
67If the directory does not exist, create it as follows:
68</p>
69<code>
70mkdir /data/misc/media
71chown media:media /data/misc/media
72</code>
73</li>
74<li><code>echo af.tee=# &gt; /data/local.prop</code>
Clay Murphy3a7af3a2014-09-09 17:29:09 -070075<br />Where the <code>af.tee</code> value is a number described below.
Glenn Kasten37784a52014-02-03 11:57:33 -080076</li>
77<li><code>chmod 644 /data/local.prop</code></li>
78<li><code>reboot</code></li>
79</ol>
80
81<h4>Values for <code>af.tee</code> property</h4>
82
83<p>
84The value of <code>af.tee</code> is a number between 0 and 7, expressing
85the sum of several bits, one per feature.
86See the code at <code>AudioFlinger::AudioFlinger()</code> in <code>AudioFlinger.cpp</code>
87for an explanation of each bit, but briefly:
88</p>
89<ul>
90<li>1 = input</li>
91<li>2 = FastMixer output</li>
92<li>4 = per-track AudioRecord and AudioTrack</li>
93</ul>
94
95<p>
96There is no bit for deep buffer or normal mixer yet,
97but you can get similar results using "4."
98</p>
99
100<h3>Test and acquire data</h3>
101
102<ol>
Clay Murphy3a7af3a2014-09-09 17:29:09 -0700103<li>Run your audio test.</li>
Glenn Kasten37784a52014-02-03 11:57:33 -0800104<li><code>adb shell dumpsys media.audio_flinger</code></li>
105<li>Look for a line in dumpsys output such as this:<br />
106<code>tee copied to /data/misc/media/20131010101147_2.wav</code>
Clay Murphy3a7af3a2014-09-09 17:29:09 -0700107<br />This is a PCM .wav file.</br>
Glenn Kasten37784a52014-02-03 11:57:33 -0800108</li>
109<li><code>adb pull</code> any <code>/data/misc/media/*.wav</code> files of interest;
110note that track-specific dump filenames do not appear in the dumpsys output,
Clay Murphy3a7af3a2014-09-09 17:29:09 -0700111but are still saved to <code>/data/misc/media</code> upon track closure.
Glenn Kasten37784a52014-02-03 11:57:33 -0800112</li>
Clay Murphy3a7af3a2014-09-09 17:29:09 -0700113<li>Review the dump files for privacy concerns before sharing with others.</li>
Glenn Kasten37784a52014-02-03 11:57:33 -0800114</ol>
115
116<h4>Suggestions</h4>
117
118<p>Try these ideas for more useful results:</p>
119
120<ul>
Clay Murphy3a7af3a2014-09-09 17:29:09 -0700121<li>Disable touch sounds and key clicks.</li>
122<li>Maximize all volumes.</li>
Glenn Kasten37784a52014-02-03 11:57:33 -0800123<li>Disable apps that make sound or record from microphone,
Clay Murphy3a7af3a2014-09-09 17:29:09 -0700124if they are not of interest to your test.
Glenn Kasten37784a52014-02-03 11:57:33 -0800125</li>
126<li>Track-specific dumps are only saved when the track is closed;
127you may need to force close an app in order to dump its track-specific data
128<li>Do the <code>dumpsys</code> immediately after test;
Clay Murphy3a7af3a2014-09-09 17:29:09 -0700129there is a limited amount of recording space available.</li>
Glenn Kasten37784a52014-02-03 11:57:33 -0800130<li>To make sure you don't lose your dump files,
131upload them to your host periodically.
132Only a limited number of dump files are preserved;
133older dumps are removed after that limit is reached.</li>
134</ul>
135
136<h3>Restore</h3>
137
138<p>
139As noted above, the tee sink feature should not be left enabled.
140Restore your build and device as follows:
141</p>
142<ol>
Clay Murphy3a7af3a2014-09-09 17:29:09 -0700143<li>Revert the source code changes to <code>Configuration.h</code>.</li>
144<li>Re-build <code>libaudioflinger.so</code>.</li>
Glenn Kasten37784a52014-02-03 11:57:33 -0800145<li>Push or sync the restored <code>libaudioflinger.so</code>
Clay Murphy3a7af3a2014-09-09 17:29:09 -0700146to the device's <code>/system/lib</code>.
Glenn Kasten37784a52014-02-03 11:57:33 -0800147</li>
148<li><code>adb shell</code></li>
149<li><code>rm /data/local.prop</code></li>
150<li><code>rm /data/misc/media/*.wav</code></li>
151<li><code>reboot</code></li>
152</ol>
153
Glenn Kasten3dbc8042014-02-04 09:58:32 -0800154<h2 id="mediaLog">media.log</h2>
155
156<h3>ALOGx macros</h3>
157
158<p>
159The standard Java language logging API in Android SDK is
160<a class="external-link" href="http://developer.android.com/reference/android/util/Log.html" target="_android">android.util.Log</a>.
161</p>
162
163<p>
164The corresponding C language API in Android NDK is
165<code>__android_log_print</code>
166declared in <code>&lt;android/log.h&gt;</code>.
167</p>
168
169<p>
170Within the native portion of Android framework, we
171prefer macros named <code>ALOGE</code>, <code>ALOGW</code>,
172<code>ALOGI</code>, <code>ALOGV</code>, etc. They are declared in
173<code>&lt;utils/Log.h&gt;</code>, and for the purposes of this article
174we'll collectively refer to them as <code>ALOGx</code>.
175</p>
176
177<p>
178All of these APIs are easy-to-use and well-understood, so they are pervasive
179throughout the Android platform. In particular the <code>mediaserver</code>
180process, which includes the AudioFlinger sound server, uses
181<code>ALOGx</code> extensively.
182</p>
183
184<p>
185Nevertheless, there are some limitations to <code>ALOGx</code> and friends:
186</p>
187
188<ul>
189<li>
190They are suspectible to "log spam": the log buffer is a shared resource
191so it can easily overflow due to unrelated log entries, resulting in
192missed information. The <code>ALOGV</code> variant is disabled at
193compile-time by default. But of course even it can result in log spam
194if it is enabled.
195</li>
196<li>
197The underlying kernel system calls could block, possibly resulting in
198priority inversion and consequently measurement disturbances and
199inaccuracies. This is of
200special concern to time-critical threads such as <code>FastMixer</code>.
201</li>
202<li>
203If a particular log is disabled to reduce log spam,
204then any information that would have been captured by that log is lost.
205It is not possible to enable a specific log retroactively,
206<i>after</i> it becomes clear that the log would have been interesting.
207</li>
208</ul>
209
210<h3>NBLOG, media.log, and MediaLogService</h3>
211
212<p>
213The <code>NBLOG</code> APIs and associated <code>media.log</code>
214process and <code>MediaLogService</code>
215service together form a newer logging system for media, and are specifically
216designed to address the issues above. We will loosely use the term
217"media.log" to refer to all three, but strictly speaking <code>NBLOG</code> is the
218C++ logging API, <code>media.log</code> is a Linux process name, and <code>MediaLogService</code>
219is an Android binder service for examining the logs.
220</p>
221
222<p>
223A <code>media.log</code> "timeline" is a series
224of log entries whose relative ordering is preserved.
225By convention, each thread should use it's own timeline.
226</p>
227
228<h3>Benefits</h3>
229
230<p>
Clay Murphy3a7af3a2014-09-09 17:29:09 -0700231The benefits of the <code>media.log</code> system are that it:
Glenn Kasten3dbc8042014-02-04 09:58:32 -0800232</p>
233<ul>
Clay Murphy3a7af3a2014-09-09 17:29:09 -0700234<li>Doesn't spam the main log unless and until it is needed.</li>
235<li>Can be examined even when <code>mediaserver</code> crashes or hangs.</li>
236<li>Is non-blocking per timeline.</li>
237<li>Offers less disturbance to performance.
238(Of course no form of logging is completely non-intrusive.)
Glenn Kasten3dbc8042014-02-04 09:58:32 -0800239</li>
240</ul>
241
242<h3>Architecture</h3>
243
244<p>
245The diagram below shows the relationship of the <code>mediaserver</code> process
246and the <code>init</code> process, before <code>media.log</code> is introduced:
247</p>
248<img src="audio/images/medialog_before.png" alt="Architecture before media.log" />
249<p>
250Notable points:
251</p>
252<ul>
Clay Murphy3a7af3a2014-09-09 17:29:09 -0700253<li><code>init</code> forks and execs <code>mediaserver</code>.</li>
254<li><code>init</code> detects the death of <code>mediaserver</code>, and re-forks as necessary.</li>
255<li><code>ALOGx</code> logging is not shown.
Glenn Kasten3dbc8042014-02-04 09:58:32 -0800256</ul>
257
258<p>
259The diagram below shows the new relationship of the components,
260after <code>media.log</code> is added to the architecture:
261</p>
262<img src="audio/images/medialog_after.png" alt="Architecture after media.log" />
263<p>
264Important changes:
265</p>
266
267<ul>
268
269<li>
270Clients use <code>NBLOG</code> API to construct log entries and append them to
271a circular buffer in shared memory.
272</li>
273
274<li>
275<code>MediaLogService</code> can dump the contents of the circular buffer at any time.
276</li>
277
278<li>
279The circular buffer is designed in such a way that any corruption of the
280shared memory will not crash <code>MediaLogService</code>, and it will still be able
281to dump as much of the buffer that is not affected by the corruption.
282</li>
283
284<li>
285The circular buffer is non-blocking and lock-free for both writing
286new entries and reading existing entries.
287</li>
288
289<li>
290No kernel system calls are required to write to or read from the circular buffer
291(other than optional timestamps).
292</li>
293
294</ul>
295
296<h4>Where to use</h4>
297
298<p>
299As of Android 4.4, there are only a few log points in AudioFlinger
300that use the <code>media.log</code> system. Though the new APIs are not as
301easy to use as <code>ALOGx</code>, they are not extremely difficult either.
302We encourage you to learn the new logging system for those
303occasions when it is indispensable.
304In particular, it is recommended for AudioFlinger threads that must
305run frequently, periodically, and without blocking such as the
306<code>FastMixer</code> thread.
307</p>
308
309<h3>How to use</h3>
310
311<h4>Add logs</h4>
312
313<p>
314First, you need to add logs to your code.
315</p>
316
317<p>
318In <code>FastMixer</code> thread, use code such as this:
319</p>
320<pre>
321logWriter->log("string");
322logWriter->logf("format", parameters);
323logWriter->logTimestamp();
324</pre>
325<p>
326As this <code>NBLog</code> timeline is used only by the <code>FastMixer</code> thread,
327there is no need for mutual exclusion.
328</p>
329
330<p>
331In other AudioFlinger threads, use <code>mNBLogWriter</code>:
332</p>
333<pre>
334mNBLogWriter->log("string");
335mNBLogWriter->logf("format", parameters);
336mNBLogWriter->logTimestamp();
337</pre>
338<p>
339For threads other than <code>FastMixer</code>,
340the thread's <code>NBLog</code> timeline can be used by both the thread itself, and
341by binder operations. <code>NBLog::Writer</code> does not provide any
342implicit mutual exclusion per timeline, so be sure that all logs occur
343within a context where the thread's mutex <code>mLock</code> is held.
344</p>
345
346<p>
347After you have added the logs, re-build AudioFlinger.
348</p>
349
Clay Murphy3a7af3a2014-09-09 17:29:09 -0700350<p class="caution"><strong>Caution:</strong>
Glenn Kasten3dbc8042014-02-04 09:58:32 -0800351A separate <code>NBLog::Writer</code> timeline is required per thread,
352to ensure thread safety, since timelines omit mutexes by design. If you
353want more than one thread to use the same timeline, you can protect with an
354existing mutex (as described above for <code>mLock</code>). Or you can
355use the <code>NBLog::LockedWriter</code> wrapper instead of <code>NBLog::Writer</code>.
356However, this negates a prime benefit of this API: its non-blocking
357behavior.
358</p>
359
360<p>
361The full <code>NBLog</code> API is at <code>frameworks/av/include/media/nbaio/NBLog.h</code>.
362</p>
363
364<h4>Enable media.log</h4>
365
366<p>
367<code>media.log</code> is disabled by default. It is active only when property
368<code>ro.test_harness</code> is <code>1</code>. You can enable it by:
369</p>
370
371<pre>
372adb root
373adb shell
374echo ro.test_harness=1 > /data/local.prop
375chmod 644 /data/local.prop
376reboot
377</pre>
378
379<p>
380The connection is lost during reboot, so:
381</p>
382<pre>
383adb shell
384</pre>
385
386The command <code>ps media</code> will now show two processes:
387<ul>
388<li>media.log</li>
389<li>mediaserver</li>
390</ul>
391<p>
392Note the process ID of <code>mediaserver</code> for later.
393</p>
394
395<h4>Displaying the timelines</h4>
396
397<p>
398You can manually request a log dump at any time.
399This command shows logs from all the active and recent timelines, and then clears them:
400</p>
401<pre>
402dumpsys media.log
403</pre>
404
405<p>
406Note that by design timelines are independent,
407and there is no facility for merging timelines.
408</p>
409
410<h4>Recovering logs after mediaserver death</h4>
411
412<p>
413Now try killing <code>mediaserver</code> process: <code>kill -9 #</code>, where # is
414the process ID you noted earlier. You should see a dump from <code>media.log</code>
415in the main <code>logcat</code>, showing all the logs leading up to the crash.
416</p>
417<pre>
418dumpsys media.log
419</pre>