در این مقاله نکات و ترفندهایی برای اشکال زدایی صدای اندروید توضیح داده شده است.
سینک سه راهی
"تی سینک" یک ویژگی اشکال زدایی AudioFlinger است که فقط در بیلدهای سفارشی موجود است، برای حفظ یک قطعه کوتاه از صدای اخیر برای تجزیه و تحلیل بعدی. این امکان مقایسه بین آنچه در واقع پخش یا ضبط شده در مقابل آنچه مورد انتظار بود را فراهم می کند.
برای حفظ حریم خصوصی، سینک سه راهی به طور پیش فرض، هم در زمان کامپایل و هم در زمان اجرا، غیرفعال است. برای استفاده از تی سینک، باید با کامپایل مجدد و همچنین با تنظیم یک ویژگی، آن را فعال کنید. پس از اتمام اشکال زدایی، حتما این ویژگی را غیرفعال کنید. سینک سه راهی نباید در ساخت های تولیدی فعال بماند.
دستورالعمل های این بخش برای اندروید 7.x و بالاتر است. برای Android 5.x و 6.x، /data/misc/audioserver
را با /data/misc/media
جایگزین کنید. علاوه بر این، باید از userdebug یا eng build استفاده کنید. اگر از ساخت userdebug استفاده میکنید، اعتبار را با استفاده از:
adb root && adb disable-verity && adb reboot
تنظیم زمان کامپایل
-
cd frameworks/av/services/audioflinger
- ویرایش
Configuration.h
. - لغو نظر
#define TEE_SINK
. - بازسازی
libaudioflinger.so
. -
adb root
-
adb remount
-
libaudioflinger.so
جدید را با/system/lib
دستگاه فشار دهید یا همگام کنید.
تنظیم زمان اجرا
-
adb shell getprop | grep ro.debuggable
تأیید کنید که خروجی این است:[ro.debuggable]: [1]
-
adb shell
-
ls -ld /data/misc/audioserver
تأیید کنید که خروجی این است:
drwx------ media media ... media
اگر دایرکتوری وجود ندارد، آن را به صورت زیر ایجاد کنید:
mkdir /data/misc/audioserver
chown media:media /data/misc/audioserver
echo af.tee=# > /data/local.prop
جایی که مقدارaf.tee
عددی است که در زیر توضیح داده شده است.-
chmod 644 /data/local.prop
-
reboot
ارزش برای اموال af.tee
مقدار af.tee
عددی بین 0 تا 7 است که مجموع چند بیت را بیان می کند، یک بیت در هر ویژگی. برای توضیح هر بیت، کد را در AudioFlinger::AudioFlinger()
در AudioFlinger.cpp
ببینید، اما به طور خلاصه:
- 1 = ورودی
- 2 = خروجی FastMixer
- 4 = ضبط صوتی و آهنگ صوتی در هر آهنگ
هنوز بیتی برای بافر عمیق یا میکسر معمولی وجود ندارد، اما می توانید نتایج مشابهی را با استفاده از "4" دریافت کنید.
تست و کسب داده ها
- تست صوتی خود را اجرا کنید.
-
adb shell dumpsys media.audio_flinger
- به دنبال خطی در خروجی
dumpsys
مانند زیر باشید:
tee copied to /data/misc/audioserver/20131010101147_2.wav
این یک فایل PCM .wav است. - سپس adb هر فایل
/data/misc/audioserver/*.wav
مورد علاقه راadb pull
. توجه داشته باشید که نام فایلهای dump مخصوص آهنگ در خروجیdumpsys
ظاهر نمیشوند، اما پس از بسته شدن مسیر همچنان در/data/misc/audioserver
ذخیره میشوند. - قبل از به اشتراک گذاشتن با دیگران، فایل های dump را برای نگرانی های مربوط به حریم خصوصی بررسی کنید.
پیشنهادات
این ایده ها را برای نتایج مفیدتر امتحان کنید:
- برای کاهش وقفه در خروجی تست، صداهای لمسی و کلیک کلید را غیرفعال کنید.
- تمام حجم ها را به حداکثر برسانید.
- برنامههایی را که از میکروفون صدا میسازند یا ضبط میکنند، در صورتی که برای آزمایش شما جالب نیستند، غیرفعال کنید.
- تخلیه های مخصوص مسیر فقط زمانی ذخیره می شوند که مسیر بسته باشد. ممکن است لازم باشد یک برنامه را به اجبار ببندید تا داده های مربوط به آهنگ آن را حذف کنید
- بلافاصله پس از آزمایش
dumpsys
انجام دهید. فضای ضبط محدودی در دسترس است. - برای اطمینان از اینکه فایل های dump خود را از دست نمی دهید، آنها را به صورت دوره ای در هاست خود آپلود کنید. فقط تعداد محدودی از فایل های dump حفظ شده است. پس از رسیدن به این حد، زباله های قدیمی حذف می شوند.
بازیابی کنید
همانطور که در بالا ذکر شد، ویژگی تی سینک نباید فعال بماند. بیلد و دستگاه خود را به صورت زیر بازیابی کنید:
- تغییرات کد منبع را به
Configuration.h
برگردانید. - بازسازی
libaudioflinger.so
. -
libaudioflinger.so
بازیابی شده را با/system/lib
دستگاه فشار دهید یا همگام کنید. -
adb shell
-
rm /data/local.prop
-
rm /data/misc/audioserver/*.wav
-
reboot
media.log
ماکروهای ALOGx
API استاندارد گزارشگیری زبان جاوا در Android SDK android.util.Log است.
API زبان C مربوطه در Android NDK __android_log_print
است که در <android/log.h>
اعلام شده است.
در بخش اصلی چارچوب اندروید، ماکروهایی به نامهای ALOGE
، ALOGW
، ALOGI
، ALOGV
و غیره <utils/Log.h>
ترجیح میدهیم ALOGx
.
همه این APIها برای استفاده آسان و به خوبی قابل درک هستند، بنابراین در سراسر پلتفرم اندروید فراگیر هستند. به ویژه فرآیند mediaserver
، که شامل سرور صوتی AudioFlinger است، از ALOGx
به طور گسترده استفاده می کند.
با این وجود، محدودیت هایی برای ALOGx
و دوستان وجود دارد:
- آنها مستعد "ورود هرزنامه" هستند: بافر گزارش یک منبع مشترک است بنابراین می تواند به راحتی به دلیل ورودی های گزارش نامرتبط سرریز شود و در نتیجه اطلاعات از دست رفته باشد. نوع
ALOGV
به طور پیش فرض در زمان کامپایل غیرفعال است. اما البته اگر فعال باشد حتی میتواند منجر به ورود اسپم شود. - فراخوانی های سیستم هسته اصلی می تواند مسدود شود و احتمالاً منجر به وارونگی اولویت و در نتیجه اختلالات و عدم دقت در اندازه گیری شود. این موضوع برای رشتههای حساس زمانی مانند
FastMixer
وFastCapture
اهمیت ویژهای دارد. - اگر یک گزارش خاص برای کاهش هرزنامههای گزارش غیرفعال شود، هر گونه اطلاعاتی که توسط آن گزارش گرفته میشد از بین میرود. پس از اینکه مشخص شد که گزارش جالب بوده است، امکان فعال کردن یک گزارش خاص به صورت ماسبق وجود ندارد.
NBLOG، media.log و MediaLogService
API های NBLOG
و فرآیند media.log
مرتبط و سرویس MediaLogService
با هم یک سیستم گزارش جدیدتر برای رسانه ها را تشکیل می دهند و به طور خاص برای رسیدگی به مشکلات بالا طراحی شده اند. ما از اصطلاح "media.log" برای اشاره به هر سه استفاده می کنیم، اما NBLOG
به طور دقیق API گزارش C++ است، media.log
نام فرآیند لینوکس است و MediaLogService
یک سرویس بایندر اندروید برای بررسی گزارش ها است.
«خط زمانی» media.log
مجموعهای از ورودیهای گزارش است که ترتیب نسبی آنها حفظ میشود. طبق قرارداد، هر رشته باید از جدول زمانی خاص خود استفاده کند.
مزایا
مزایای سیستم media.log
این است که:
- گزارش اصلی را اسپم نمی کند مگر اینکه و تا زمانی که لازم باشد.
- حتی زمانی که
mediaserver
از کار می افتد یا هنگ می کند، قابل بررسی است. - در جدول زمانی غیر مسدود است.
- اختلال کمتری در عملکرد ایجاد می کند. (البته هیچ شکلی از ورود به سیستم کاملاً غیرقابل نفوذ نیست.)
معماری
نمودار زیر رابطه بین فرآیند mediaserver
و فرآیند init
را قبل از معرفی media.log
نشان میدهد:
![معماری قبل از media.log](https://source.android.google.cn/static/docs/core/audio/images/medialog_before.png?authuser=2&hl=fa)
شکل 1. معماری قبل از media.log
نکات قابل توجه:
-
init
forks و execsmediaserver
. -
init
مرگmediaserver
را تشخیص می دهد و در صورت لزوم دوباره فورک می کند. - گزارش
ALOGx
نشان داده نمی شود.
نمودار زیر رابطه جدید مؤلفه ها را پس از افزودن media.log
به معماری نشان می دهد:
![معماری بعد از media.log](https://source.android.google.cn/static/docs/core/audio/images/medialog_after.png?authuser=2&hl=fa)
شکل 2. معماری پس از media.log
تغییرات مهم:
- کلاینت ها از
NBLOG
API برای ساخت ورودی های گزارش و اضافه کردن آنها به یک بافر دایره ای در حافظه مشترک استفاده می کنند. -
MediaLogService
می تواند محتویات بافر دایره ای را در هر زمان تخلیه کند. - بافر دایره ای به گونه ای طراحی شده است که هر گونه خرابی در حافظه مشترک
MediaLogService
را خراب نمی کند و همچنان می تواند تا آنجایی از بافری که تحت تأثیر خرابی قرار نگرفته است تخلیه کند. - بافر دایره ای هم برای نوشتن ورودی های جدید و هم برای خواندن ورودی های موجود غیر مسدود و بدون قفل است.
- هیچ فراخوانی سیستم هسته برای نوشتن یا خواندن از بافر دایره ای (غیر از مهرهای زمانی اختیاری) لازم نیست.
محل استفاده
از اندروید 4.4، تنها چند نقطه ثبت در AudioFlinger وجود دارد که از سیستم media.log
استفاده می کنند. اگرچه استفاده از APIهای جدید به آسانی ALOGx
نیست، اما بسیار دشوار نیز نیستند. ما شما را تشویق میکنیم که سیستم جدید ثبت را برای مواردی که ضروری است بیاموزید. به طور خاص، برای رشتههای AudioFlinger توصیه میشود که باید به طور مکرر، دورهای و بدون مسدود کردن مانند رشتههای FastMixer
و FastCapture
اجرا شوند.
نحوه استفاده
سیاههها را اضافه کنید
ابتدا باید لاگ ها را به کد خود اضافه کنید.
در رشته های FastMixer
و FastCapture
از کدهایی مانند زیر استفاده کنید:
logWriter->log("string"); logWriter->logf("format", parameters); logWriter->logTimestamp();
از آنجایی که این جدول زمانی NBLog
فقط توسط رشته های FastMixer
و FastCapture
استفاده می شود، نیازی به حذف متقابل وجود ندارد.
در سایر رشته های AudioFlinger، از mNBLogWriter
استفاده کنید:
mNBLogWriter->log("string"); mNBLogWriter->logf("format", parameters); mNBLogWriter->logTimestamp();
برای رشتههایی غیر از FastMixer
و FastCapture
، جدول زمانی NBLog
رشته میتواند هم توسط خود رشته و هم توسط عملیات بایندر استفاده شود. NBLog::Writer
هیچ گونه حذف ضمنی متقابل را در هر خط زمانی ارائه نمیکند، بنابراین مطمئن شوید که همه گزارشها در زمینهای اتفاق میافتند که mLock
mutex رشته در آن نگهداری میشود.
پس از اینکه گزارش ها را اضافه کردید، AudioFlinger را دوباره بسازید.
احتیاط: یک NBLog::Writer
جدول زمانی جداگانه برای هر رشته مورد نیاز است تا از ایمنی رشته اطمینان حاصل شود، زیرا خطوط زمانی با طراحی mutexes را حذف می کنند. اگر میخواهید بیش از یک رشته از یک جدول زمانی استفاده کنند، میتوانید با یک mutex موجود محافظت کنید (همانطور که در بالا برای mLock
توضیح داده شد). یا می توانید به جای NBLog:: NBLog::Writer
NBLog::LockedWriter
استفاده کنید. با این حال، این یک مزیت اصلی این API را نفی می کند: رفتار غیر مسدود کننده آن.
API کامل NBLog
در frameworks/av/include/media/nbaio/NBLog.h
است.
media.log را فعال کنید
media.log
به طور پیش فرض غیرفعال است. فقط زمانی فعال است که ویژگی ro.test_harness
1
باشد. شما می توانید آن را فعال کنید:
adb root
adb shell
echo ro.test_harness=1 > /data/local.prop
chmod 644 /data/local.prop
reboot
اتصال در حین راه اندازی مجدد قطع می شود، بنابراین:
adb shell
ps media
اکنون دو فرآیند را نشان می دهد:- media.log
- مدیا سرور
برای بعداً به شناسه فرآیند mediaserver
توجه کنید.
نمایش جدول زمانی
هر زمان که بخواهید می توانید به صورت دستی درخواست تخلیه سیاهه کنید. این دستور گزارشها را از تمام خطوط زمانی فعال و اخیر نشان میدهد و سپس آنها را پاک میکند:
dumpsys media.log
توجه داشته باشید که خطوط زمانی توسط طراحی مستقل هستند و هیچ امکانی برای ادغام خطوط زمانی وجود ندارد.
بازیابی لاگ ها پس از مرگ مدیا سرور
اکنون سعی کنید فرآیند mediaserver
را بکشید: kill -9 #
، که در آن # شناسه فرآیندی است که قبلاً ذکر کردید. شما باید یک Dump از media.log
در logcat
اصلی ببینید، که همه گزارشهای منتهی به خرابی را نشان میدهد.
dumpsys media.log