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