این مقاله چند نکته و ترفند برای اشکالزدایی صدای Android را شرح میدهد.
روشویی تی
«سینک تی» یک ویژگی اشکالزدایی AudioFlinger است که فقط در ساختهای سفارشی دردسترس است و برای حفظ یک قطعه کوتاه از صدای اخیر برای تجزیهوتحلیل بعدی استفاده میشود. این کار امکان مقایسه بین آنچه واقعاً پخش یا ضبط شده است با آنچه انتظار میرفت را فراهم میکند.
برای حفظ حریم خصوصی، سینک تی بهطور پیشفرض در زمان کامپایل و زمان اجرا غیرفعال است. برای استفاده از tee sink، باید آن را با کامپایل مجدد و همچنین با تنظیم یک ویژگی فعال کنید. پساز اتمام اشکالزدایی، حتماً این ویژگی را غیرفعال کنید؛ سینک tee نباید در ساختهای تولید فعال باقی بماند.
دستورالعملهای این بخش برای Android نسخه ۷.x و بالاتر است. برای Android
5.x و 6.x، /data/misc/audioserver را با
/data/misc/media جایگزین کنید. علاوهبراین، باید از ساخت کاربر اشکالزدایی یا
مهندسی استفاده کنید. اگر از ساخت userdebug استفاده میکنید، با این دستور verity را غیرفعال کنید:
adb root && adb disable-verity && adb reboot
راهاندازی زمان ترجمه
cd frameworks/av/services/audioflinger- ویرایش
Configuration.h. - لغو نظر
#define TEE_SINK. libaudioflinger.soرا بازسازی کنید.adb rootadb remountlibaudioflinger.soجدید را به/system/libدستگاه ارسال یا همگامسازی کنید.
راهاندازی زمان اجرا
adb shell getprop | grep ro.debuggable
تأیید کنید که برونداد این است:[ro.debuggable]: [1]adb shellls -ld /data/misc/audioserver
تأیید کنید که برونداد این است:
drwx------ media media ... media
اگر دایرکتوری وجود ندارد، آن را بهصورت زیر ایجاد کنید:
mkdir /data/misc/audioserverchown media:media /data/misc/audioserverecho af.tee=# > /data/local.prop
که در آن مقدارaf.teeعددی است که در زیر توضیح داده شده است.chmod 644 /data/local.propreboot
مقادیر برای دارایی af.tee
مقدار af.tee عددی بین ۰ و ۷ است که
مجموع چند بیت را نشان میدهد، یک بیت برای هر ویژگی.
برای توضیح هر بخش، کد را در AudioFlinger::AudioFlinger() در AudioFlinger.cpp ببینید
اما بهطور خلاصه:
- ۱ = ورودی
- ۲ = برونداد FastMixer
- ۴ = AudioRecord و AudioTrack برای هر قطعه
هنوز بیتی برای بافر عمیق یا میکسر معمولی وجود ندارد، اما میتوانید بااستفاده از «۴.» نتایج مشابهی دریافت کنید.
آزمایش و کسب دادهها
- آزمایش صدا را اجرا کنید.
adb shell dumpsys media.audio_flinger- در برونداد
dumpsysبهدنبال خطی مانند این بگردید:
tee copied to /data/misc/audioserver/20131010101147_2.wav
این فایل PCM با پسوند wav است. - سپس
adb pullهر/data/misc/audioserver/*.wavفایل موردعلاقه را اضافه کنید؛ توجه داشته باشید که نام فایلهای تخلیه مخصوص قطعه در بروندادdumpsysنشان داده نمیشود، اما همچنان پساز بسته شدن قطعه در/data/misc/audioserverذخیره میشوند. - قبلاز همرسانی کردن فایلهای تخلیه با دیگران، آنها را ازنظر نگرانیهای حریم خصوصی بررسی کنید.
پیشنهادها
برای نتایج مفیدتر، این ایدهها را امتحان کنید:
- برای کاهش وقفهها در برونداد آزمایش، صداهای لمس و کلیکهای کلید را غیرفعال کنید.
- همه صداها را به حداکثر برسانید.
- برنامههایی را که صدا تولید میکنند یا از میکروفون ضبط میکنند غیرفعال کنید، اگر برای آزمایش شما جالب نیستند.
- دادههای انبوهشی خاص قطعه فقط زمانی ذخیره میشود که قطعه بسته باشد؛ ممکن است لازم باشد برنامهای را اجباراً ببندید تا دادههای انبوهشی خاص قطعه آن را دریافت کنید
dumpsysرا بلافاصله پساز آزمایش انجام دهید؛ فضای ضبط محدود است.- برای اینکه فایلهای تخلیه را ازدست ندهید، آنها را بهطور دورهای در میزبان خود بارگذاری کنید. فقط تعداد محدودی از فایلهای تخلیه حفظ میشوند؛ تخلیههای قدیمیتر پساز رسیدن به این محدودیت برداشته میشوند.
بازگرداندن
همانطور که در بالا ذکر شد، ویژگی سینک تی نباید فعال باقی بماند. ساختمان و دستگاهتان را بهصورت زیر بازیابی کنید:
- تغییرات کد منبع را به
Configuration.hبرگردانید. libaudioflinger.soرا بازسازی کنید.libaudioflinger.soبازیابیشده را به/system/libدستگاه ارسال یا همگامسازی کنید.adb shellrm /data/local.proprm /data/misc/audioserver/*.wavreboot
media.log
ماکروهای ALOGx
میانای برنامهسازی کاربردی استاندارد ثبت گزارش زبان Java در «کیت توسعه نرمافزار Android» android.util.Log است.
میانای برنامهسازی کاربردی زبان C مربوطه در Android NDK
__android_log_print
در <android/log.h> تعریف شده است.
در بخش بومی چارچوب Android، ما
ترجیح میدهیم از کلاندستورهایی با نامهای ALOGE، ALOGW،
ALOGI، ALOGV، و غیره استفاده کنیم. این کلاندستورها در
<utils/Log.h> تعریف شدهاند، و برای اهداف این مقاله
بهطور کلی از آنها بهعنوان ALOGx یاد میکنیم.
همه این میاناهای برنامهسازی کاربردی آسان و قابلفهم هستند، بنابراین در سراسر پلاتفرم Android فراگیر هستند. بهطور خاص، mediaserver
فرایند، که شامل سرور صدای AudioFlinger میشود، بهطور گسترده از
ALOGx استفاده میکند.
بااینحال، محدودیتهایی برای ALOGx و دوستان وجود دارد:
-
این گزارشها مستعد «هرزنامه گزارش» هستند: بافر گزارش یک منبع مشترک است
بنابراین بهراحتی میتواند بهدلیل ورودیهای گزارش نامربوط سرریز شود و درنتیجه
اطلاعات ازدست برود. متغیر
ALOGVبهطور پیشفرض در زمان کامپایل غیرفعال است. اما البته حتی این هم میتواند منجر به هرزنامه گزارش شود اگر فعال باشد. -
فراخوانیهای سیستم هسته اصلی ممکن است مسدود شود، که احتمالاً منجر به
وارونگی اولویت و درنتیجه اختلالات و
عدم دقت در اندازهگیری میشود. این موضوع بهویژه برای رشتههای حساس به زمان مثل
FastMixerوFastCaptureاهمیت دارد. - اگر گزارش خاصی برای کاهش هرزنامه گزارش غیرفعال شده باشد، هرگونه اطلاعاتی که توسط آن گزارش ثبت میشد ازدست میرود. فعال کردن گزارش خاصی بهصورت پسرونده، پساز مشخص شدن اینکه گزارش جالب بوده است، امکانپذیر نیست.
NBLOG، media.log، و MediaLogService
NBLOG APIs و media.log
فرایند و MediaLogService
سرویس مرتبط با آنها با هم سیستم گزارشگیری جدیدتری برای رسانهها تشکیل میدهند و بهطور خاص برای رفع مشکلات فوق طراحی شدهاند. ما بهطور کلی از اصطلاح
«media.log» برای اشاره به هر سه استفاده میکنیم، اما بهطور دقیق NBLOG
میانای برنامهسازی کاربردی ثبت گزارش C++ است، media.log نام فرایند Linux است، و MediaLogService
سرویس binder در Android برای بررسی گزارشها است.
media.log «خط زمان» مجموعهای از ورودیهای گزارش است که ترتیب نسبی آنها حفظ میشود.
طبق قرارداد، هر رشته باید از خط زمان خودش استفاده کند.
مزايا
مزایای سیستم media.log این است که:
- تا زمانی که لازم نباشد، گزارش اصلی را با هرزنامه پر نمیکند.
- حتی وقتی
mediaserverازکار میافتد یا هنگ میکند، میتوان آن را بررسی کرد. - برای هر خط زمان غیرمسدودکننده است.
- اختلال کمتری در عملکرد ایجاد میکند. (البته هیچ نوعی از گزارشگیری کاملاً غیرمزاحم نیست.)
معماری
نمودار زیر رابطه فرایند mediaserver و فرایند init را قبلاز معرفی media.log نشان میدهد:
شکل ۱. معماری قبلاز media.log
نکات قابلتوجه:
-
initانشعاب وmediaserverاجرا. -
initمرگmediaserverرا تشخیص میدهد و درصورت نیاز دوباره انشعاب ایجاد میکند. - گزارشگیری
ALOGxنشان داده نمیشود.
نمودار زیر رابطه جدید عناصر را پساز اضافه شدن media.log به معماری نشان میدهد:
شکل ۲. معماری بعداز media.log
تغییرات مهم:
-
کارخواهها از
NBLOGAPI برای ساختن ورودیهای گزارش و پیوست کردن آنها به بافر حلقوی در حافظه مشترک استفاده میکنند. -
MediaLogServiceمیتواند محتوای میانگیر دایرهای را در هر زمانی تخلیه کند. -
میانگیر دایرهای بهگونهای طراحی شده است که هرگونه خرابی در حافظه مشترک باعث ازکارافتادن
MediaLogServiceنمیشود و همچنان میتواند بخشهایی از میانگیر را که تحت تأثیر خرابی قرار نگرفتهاند تخلیه کند. - بافر دایرهای برای نوشتن ورودیهای جدید و خواندن ورودیهای موجود غیرمسدودکننده و بدون قفل است.
- برای نوشتن در بافر حلقوی یا خواندن از آن، به هیچ فراخوان سیستم هسته نیاز نیست (بهجز مُهرهای زمان اختیاری).
کجا میتواند استفاده شود
از Android 4.4، فقط چند نقطه گزارش در AudioFlinger وجود دارد که از سیستم media.log استفاده میکند. اگرچه استفاده از میاناهای برنامهسازی کاربردی جدید به آسانی 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 رشته میتواند هم توسط خود رشته و هم
توسط عملیات binder استفاده شود. NBLog::Writer هیچگونه انحصار متقابل ضمنی برای هر خط زمان ارائه نمیدهد، بنابراین مطمئن شوید که همه گزارشها در زمینهای رخ میدهند که انحصار متقابل رشته mLock حفظ میشود.
پساز افزودن گزارشها، AudioFlinger را دوباره بسازید.
احتیاط:
برای هر رشته، NBLog::Writer خط زمان جداگانهای لازم است
تا ایمنی رشته تضمین شود، زیرا خطوط زمان بهطور طراحیشده از متقابلها صرفنظر میکنند. اگر میخواهید بیشاز یک رشته از یک خط زمان استفاده کند، میتوانید با یک
متقابل انحصاری موجود (همانطور که در بالا برای mLock توضیح داده شد) محافظت کنید. یا میتوانید
بهجای NBLog::Writer از بستهبندی NBLog::LockedWriter استفاده کنید.
بااینحال، این کار یکی از مزایای اصلی این API را ازبین میبرد: عملکرد غیرمسدودکننده آن.
میانای برنامهسازی کاربردی کامل NBLog در frameworks/av/include/media/nbaio/NBLog.h است.
فعال کردن media.log
media.log بهطور پیشفرض غیرفعال است. فقط وقتی دارایی
ro.test_harness 1 باشد فعال است. میتوانید آن را ازطریق زیر فعال کنید:
adb rootadb shellecho ro.test_harness=1 > /data/local.propchmod 644 /data/local.propreboot
اتصال درطول بازراهاندازی قطع میشود، بنابراین:
adb shell
ps media اکنون دو فرایند را نشان میدهد:
- media.log
- کارساز رسانه
شناسه پردازش mediaserver را برای بعد یادداشت کنید.
نمایش خط زمانها
هرزمان بخواهید میتوانید بهصورت دستی درخواست تخلیه گزارش کنید. این فرمان گزارشهای همه خطوط زمان فعال و اخیر را نشان میدهد و سپس آنها را پاک میکند:
dumpsys media.log
توجه داشته باشید که خطوط زمان بهطور مستقل طراحی شدهاند، و هیچ امکانی برای ادغام خطوط زمان وجود ندارد.
بازیابی گزارشها پساز خرابی mediaserver
اکنون سعی کنید فرایند mediaserver را متوقف کنید: kill -9 #، که در آن # شناسه فرایندی است که قبلاً یادداشت کردهاید. باید یک تخلیه از media.log
در logcat اصلی ببینید که همه گزارشهای منتهی به خرابی را نشان میدهد.
dumpsys media.log