1page.title=Audio Debugging 2@jd:body 3 4<!-- 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--> 19<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 5.0, 50and may require changes for other versions. 51</p> 52 53<h3 id="compile">Compile-time setup</h3> 54 55<ol> 56<li><code>cd frameworks/av/services/audioflinger</code></li> 57<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> 60<li><code>adb root</code></li> 61<li><code>adb remount</code></li> 62<li>Push or sync the new <code>libaudioflinger.so</code> to the device's <code>/system/lib</code>.</li> 63</ol> 64 65<h3 id="runtime">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<pre> 85mkdir /data/misc/media 86chown media:media /data/misc/media 87</pre> 88</li> 89<li><code>echo af.tee=# > /data/local.prop</code> 90<br />Where the <code>af.tee</code> value is a number described below. 91</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 id="test">Test and acquire data</h3> 116 117<ol> 118<li>Run your audio test.</li> 119<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> 122<br />This is a PCM .wav file. 123</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, 126but are still saved to <code>/data/misc/media</code> upon track closure. 127</li> 128<li>Review the dump files for privacy concerns before sharing with others.</li> 129</ol> 130 131<h4>Suggestions</h4> 132 133<p>Try these ideas for more useful results:</p> 134 135<ul> 136<li>Disable touch sounds and key clicks.</li> 137<li>Maximize all volumes.</li> 138<li>Disable apps that make sound or record from microphone, 139if they are not of interest to your test. 140</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> 144<li>Do the <code>dumpsys</code> immediately after test; 145there is a limited amount of recording space available.</li> 146<li>To make sure you don't lose your dump files, 147upload them to your host periodically. 148Only a limited number of dump files are preserved; 149older dumps are removed after that limit is reached.</li> 150</ul> 151 152<h3 id="restore">Restore</h3> 153 154<p> 155As noted above, the tee sink feature should not be left enabled. 156Restore your build and device as follows: 157</p> 158<ol> 159<li>Revert the source code changes to <code>Configuration.h</code>.</li> 160<li>Re-build <code>libaudioflinger.so</code>.</li> 161<li>Push or sync the restored <code>libaudioflinger.so</code> 162to the device's <code>/system/lib</code>. 163</li> 164<li><code>adb shell</code></li> 165<li><code>rm /data/local.prop</code></li> 166<li><code>rm /data/misc/media/*.wav</code></li> 167<li><code>reboot</code></li> 168</ol> 169 170<h2 id="mediaLog">media.log</h2> 171 172<h3 id="alogx">ALOGx macros</h3> 173 174<p> 175The standard Java language logging API in Android SDK is 176<a href="http://developer.android.com/reference/android/util/Log.html">android.util.Log</a>. 177</p> 178 179<p> 180The corresponding C language API in Android NDK is 181<code>__android_log_print</code> 182declared in <code><android/log.h></code>. 183</p> 184 185<p> 186Within the native portion of Android framework, we 187prefer macros named <code>ALOGE</code>, <code>ALOGW</code>, 188<code>ALOGI</code>, <code>ALOGV</code>, etc. They are declared in 189<code><utils/Log.h></code>, and for the purposes of this article 190we'll collectively refer to them as <code>ALOGx</code>. 191</p> 192 193<p> 194All of these APIs are easy-to-use and well-understood, so they are pervasive 195throughout the Android platform. In particular the <code>mediaserver</code> 196process, which includes the AudioFlinger sound server, uses 197<code>ALOGx</code> extensively. 198</p> 199 200<p> 201Nevertheless, there are some limitations to <code>ALOGx</code> and friends: 202</p> 203 204<ul> 205<li> 206They are susceptible to "log spam": the log buffer is a shared resource 207so it can easily overflow due to unrelated log entries, resulting in 208missed information. The <code>ALOGV</code> variant is disabled at 209compile-time by default. But of course even it can result in log spam 210if it is enabled. 211</li> 212<li> 213The underlying kernel system calls could block, possibly resulting in 214priority inversion and consequently measurement disturbances and 215inaccuracies. This is of 216special concern to time-critical threads such as <code>FastMixer</code> and <code>FastCapture</code>. 217</li> 218<li> 219If a particular log is disabled to reduce log spam, 220then any information that would have been captured by that log is lost. 221It is not possible to enable a specific log retroactively, 222<i>after</i> it becomes clear that the log would have been interesting. 223</li> 224</ul> 225 226<h3 id="nblog">NBLOG, media.log, and MediaLogService</h3> 227 228<p> 229The <code>NBLOG</code> APIs and associated <code>media.log</code> 230process and <code>MediaLogService</code> 231service together form a newer logging system for media, and are specifically 232designed to address the issues above. We will loosely use the term 233"media.log" to refer to all three, but strictly speaking <code>NBLOG</code> is the 234C++ logging API, <code>media.log</code> is a Linux process name, and <code>MediaLogService</code> 235is an Android binder service for examining the logs. 236</p> 237 238<p> 239A <code>media.log</code> "timeline" is a series 240of log entries whose relative ordering is preserved. 241By convention, each thread should use it's own timeline. 242</p> 243 244<h3 id="benefits">Benefits</h3> 245 246<p> 247The benefits of the <code>media.log</code> system are that it: 248</p> 249<ul> 250<li>Doesn't spam the main log unless and until it is needed.</li> 251<li>Can be examined even when <code>mediaserver</code> crashes or hangs.</li> 252<li>Is non-blocking per timeline.</li> 253<li>Offers less disturbance to performance. 254(Of course no form of logging is completely non-intrusive.) 255</li> 256</ul> 257 258<h3 id="architecture">Architecture</h3> 259 260<p> 261The diagram below shows the relationship of the <code>mediaserver</code> process 262and the <code>init</code> process, before <code>media.log</code> is introduced: 263</p> 264<img src="images/medialog_before.png" alt="Architecture before media.log" id="figure1" /> 265<p class="img-caption"> 266 <strong>Figure 1.</strong> Architecture before media.log 267</p> 268 269<p> 270Notable points: 271</p> 272<ul> 273<li><code>init</code> forks and execs <code>mediaserver</code>.</li> 274<li><code>init</code> detects the death of <code>mediaserver</code>, and re-forks as necessary.</li> 275<li><code>ALOGx</code> logging is not shown.</li> 276</ul> 277 278<p> 279The diagram below shows the new relationship of the components, 280after <code>media.log</code> is added to the architecture: 281</p> 282<img src="images/medialog_after.png" alt="Architecture after media.log" id="figure2" /> 283<p class="img-caption"> 284 <strong>Figure 2.</strong> Architecture after media.log 285</p> 286 287<p> 288Important changes: 289</p> 290 291<ul> 292 293<li> 294Clients use <code>NBLOG</code> API to construct log entries and append them to 295a circular buffer in shared memory. 296</li> 297 298<li> 299<code>MediaLogService</code> can dump the contents of the circular buffer at any time. 300</li> 301 302<li> 303The circular buffer is designed in such a way that any corruption of the 304shared memory will not crash <code>MediaLogService</code>, and it will still be able 305to dump as much of the buffer that is not affected by the corruption. 306</li> 307 308<li> 309The circular buffer is non-blocking and lock-free for both writing 310new entries and reading existing entries. 311</li> 312 313<li> 314No kernel system calls are required to write to or read from the circular buffer 315(other than optional timestamps). 316</li> 317 318</ul> 319 320<h4>Where to use</h4> 321 322<p> 323As of Android 4.4, there are only a few log points in AudioFlinger 324that use the <code>media.log</code> system. Though the new APIs are not as 325easy to use as <code>ALOGx</code>, they are not extremely difficult either. 326We encourage you to learn the new logging system for those 327occasions when it is indispensable. 328In particular, it is recommended for AudioFlinger threads that must 329run frequently, periodically, and without blocking such as the 330<code>FastMixer</code> and <code>FastCapture</code> threads. 331</p> 332 333<h3 id="how">How to use</h3> 334 335<h4>Add logs</h4> 336 337<p> 338First, you need to add logs to your code. 339</p> 340 341<p> 342In <code>FastMixer</code> and <code>FastCapture</code> threads, use code such as this: 343</p> 344<pre> 345logWriter->log("string"); 346logWriter->logf("format", parameters); 347logWriter->logTimestamp(); 348</pre> 349<p> 350As this <code>NBLog</code> timeline is used only by the <code>FastMixer</code> and 351<code>FastCapture</code> threads, 352there is no need for mutual exclusion. 353</p> 354 355<p> 356In other AudioFlinger threads, use <code>mNBLogWriter</code>: 357</p> 358<pre> 359mNBLogWriter->log("string"); 360mNBLogWriter->logf("format", parameters); 361mNBLogWriter->logTimestamp(); 362</pre> 363<p> 364For threads other than <code>FastMixer</code> and <code>FastCapture</code>, 365the thread's <code>NBLog</code> timeline can be used by both the thread itself, and 366by binder operations. <code>NBLog::Writer</code> does not provide any 367implicit mutual exclusion per timeline, so be sure that all logs occur 368within a context where the thread's mutex <code>mLock</code> is held. 369</p> 370 371<p> 372After you have added the logs, re-build AudioFlinger. 373</p> 374 375<p class="caution"><strong>Caution:</strong> 376A separate <code>NBLog::Writer</code> timeline is required per thread, 377to ensure thread safety, since timelines omit mutexes by design. If you 378want more than one thread to use the same timeline, you can protect with an 379existing mutex (as described above for <code>mLock</code>). Or you can 380use the <code>NBLog::LockedWriter</code> wrapper instead of <code>NBLog::Writer</code>. 381However, this negates a prime benefit of this API: its non-blocking 382behavior. 383</p> 384 385<p> 386The full <code>NBLog</code> API is at <code>frameworks/av/include/media/nbaio/NBLog.h</code>. 387</p> 388 389<h4>Enable media.log</h4> 390 391<p> 392<code>media.log</code> is disabled by default. It is active only when property 393<code>ro.test_harness</code> is <code>1</code>. You can enable it by: 394</p> 395 396<pre> 397adb root 398adb shell 399echo ro.test_harness=1 > /data/local.prop 400chmod 644 /data/local.prop 401reboot 402</pre> 403 404<p> 405The connection is lost during reboot, so: 406</p> 407<pre> 408adb shell 409</pre> 410 411The command <code>ps media</code> will now show two processes: 412<ul> 413<li>media.log</li> 414<li>mediaserver</li> 415</ul> 416<p> 417Note the process ID of <code>mediaserver</code> for later. 418</p> 419 420<h4>Displaying the timelines</h4> 421 422<p> 423You can manually request a log dump at any time. 424This command shows logs from all the active and recent timelines, and then clears them: 425</p> 426<pre> 427dumpsys media.log 428</pre> 429 430<p> 431Note that by design timelines are independent, 432and there is no facility for merging timelines. 433</p> 434 435<h4>Recovering logs after mediaserver death</h4> 436 437<p> 438Now try killing <code>mediaserver</code> process: <code>kill -9 #</code>, where # is 439the process ID you noted earlier. You should see a dump from <code>media.log</code> 440in the main <code>logcat</code>, showing all the logs leading up to the crash. 441</p> 442<pre> 443dumpsys media.log 444</pre> 445