اشکال زدایی صدا

در این مقاله نکات و ترفندهایی برای اشکال زدایی صدای اندروید توضیح داده شده است.

سینک سه راهی

"تی سینک" یک ویژگی اشکال زدایی 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

تنظیم زمان کامپایل

  1. cd frameworks/av/services/audioflinger
  2. ویرایش Configuration.h .
  3. لغو نظر #define TEE_SINK .
  4. بازسازی libaudioflinger.so .
  5. adb root
  6. adb remount
  7. libaudioflinger.so جدید را با /system/lib دستگاه فشار دهید یا همگام کنید.

تنظیم زمان اجرا

  1. adb shell getprop | grep ro.debuggable
    تأیید کنید که خروجی این است: [ro.debuggable]: [1]
  2. adb shell
  3. ls -ld /data/misc/audioserver

    تأیید کنید که خروجی این است:

    drwx------ media media ... media
    

    اگر دایرکتوری وجود ندارد، آن را به صورت زیر ایجاد کنید:

    mkdir /data/misc/audioserver
    chown media:media /data/misc/audioserver
    
  4. echo af.tee=# > /data/local.prop
    جایی که مقدار af.tee عددی است که در زیر توضیح داده شده است.
  5. chmod 644 /data/local.prop
  6. reboot

ارزش برای اموال af.tee

مقدار af.tee عددی بین 0 تا 7 است که مجموع چند بیت را بیان می کند، یک بیت در هر ویژگی. برای توضیح هر بیت، کد را در AudioFlinger::AudioFlinger() در AudioFlinger.cpp ببینید، اما به طور خلاصه:

  • 1 = ورودی
  • 2 = خروجی FastMixer
  • 4 = ضبط صوتی و آهنگ صوتی در هر آهنگ

هنوز بیتی برای بافر عمیق یا میکسر معمولی وجود ندارد، اما می توانید نتایج مشابهی را با استفاده از "4" دریافت کنید.

تست و کسب داده ها

  1. تست صوتی خود را اجرا کنید.
  2. adb shell dumpsys media.audio_flinger
  3. به دنبال خطی در خروجی dumpsys مانند زیر باشید:
    tee copied to /data/misc/audioserver/20131010101147_2.wav
    این یک فایل PCM .wav است.
  4. سپس adb pull هر فایل /data/misc/audioserver/*.wav مورد علاقه را بکشد. توجه داشته باشید که نام فایل‌های dump مخصوص آهنگ در خروجی dumpsys ظاهر نمی‌شوند، اما پس از بسته شدن مسیر همچنان در /data/misc/audioserver ذخیره می‌شوند.
  5. قبل از به اشتراک گذاشتن با دیگران، فایل های dump را برای نگرانی های مربوط به حریم خصوصی بررسی کنید.

پیشنهادات

این ایده ها را برای نتایج مفیدتر امتحان کنید:

  • برای کاهش وقفه در خروجی تست، صداهای لمسی و کلیک کلید را غیرفعال کنید.
  • تمام حجم ها را به حداکثر برسانید.
  • برنامه‌هایی را که از میکروفون صدا می‌سازند یا ضبط می‌کنند، در صورتی که برای آزمایش شما جالب نیستند، غیرفعال کنید.
  • تخلیه های مخصوص مسیر فقط زمانی ذخیره می شوند که مسیر بسته باشد. ممکن است لازم باشد یک برنامه را به اجبار ببندید تا داده های مربوط به آهنگ آن را حذف کنید
  • بلافاصله پس از آزمایش dumpsys انجام دهید. فضای ضبط محدودی در دسترس است.
  • برای اطمینان از اینکه فایل های dump خود را از دست نمی دهید، آنها را به صورت دوره ای در هاست خود آپلود کنید. فقط تعداد محدودی از فایل های dump حفظ شده است. پس از رسیدن به این حد، زباله های قدیمی حذف می شوند.

بازگرداندن

همانطور که در بالا ذکر شد، ویژگی تی سینک نباید فعال بماند. بیلد و دستگاه خود را به صورت زیر بازیابی کنید:

  1. تغییرات کد منبع را به Configuration.h برگردانید.
  2. بازسازی libaudioflinger.so .
  3. libaudioflinger.so بازیابی شده را با /system/lib دستگاه فشار دهید یا همگام کنید.
  4. adb shell
  5. rm /data/local.prop
  6. rm /data/misc/audioserver/*.wav
  7. reboot

media.log

ماکروهای ALOGx

API استاندارد گزارش‌گیری زبان جاوا در Android SDK android.util.Log است.

API زبان C مربوطه در Android NDK __android_log_print است که در <android/log.h> اعلام شده است.

در بخش اصلی چارچوب Android، ماکروهایی به نام‌های ALOGE ، ALOGW ، ALOGI <utils/Log.h> ALOGV ، و غیره را ترجیح می‌دهیم 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

شکل 1. معماری قبل از media.log

نکات قابل توجه:

  • init forks و execs mediaserver .
  • init مرگ mediaserver را تشخیص می دهد و در صورت لزوم دوباره فورک می کند.
  • گزارش ALOGx نشان داده نمی شود.

نمودار زیر رابطه جدید مؤلفه ها را پس از افزودن media.log به معماری نشان می دهد:

معماری بعد از media.log

شکل 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