تصحيح أخطاء الصوت

توضّح هذه المقالة بعض النصائح لتصحيح أخطاء الصوت في Android.

حوض استحمام

"حوض الشاي" CANNOT TRANSLATE ميزة تصحيح أخطاء AudioFlinger المتوفّرة في الإصدارات المخصّصة فقط للاحتفاظ بجزء قصير من المحتوى الصوتي الحديث لتحليله لاحقًا. ويسمح ذلك بمقارنة ما تم تشغيله أو تسجيله بالفعل مقارنةً بما كان متوقعًا

للحفاظ على الخصوصية، يتم إيقاف حوض التشغيل بشكل افتراضي، في كل من وقت التجميع وقت التشغيل. لاستخدام حوض قمزة الغولف، ستحتاج إلى تمكينه عن طريق إعادة التجميع وأيضًا من خلال تعيين خاصية. تأكد من إيقاف هذه الميزة بعد تم تصحيح الأخطاء؛ يجب عدم ترك حوض المشاريع مفعّلة في بُنى الإنتاج.

التعليمات الواردة في هذا القسم مخصّصة لنظام التشغيل Android 7.x والإصدارات الأحدث. بالنسبة إلى نظام التشغيل Android: 5.x و6.x، استبدِل /data/misc/audioserver بـ /data/misc/media بالإضافة إلى ذلك، يجب عليك استخدام userdebug أو بنية المشاركة. في حال استخدام إصدار 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 ملف يهمّك لاحظ أن أسماء ملفات التفريغ الخاصة بالمقطع الصوتي لا تظهر في dumpsys إخراج، ولكن تظل محفوظة في /data/misc/audioserver عند إغلاق المسار.
  5. يُرجى مراجعة ملف الذاكرة للتحقّق من وجود أي مخاوف تتعلق بالخصوصية قبل مشاركتها مع الآخرين.

الاقتراحات

جرِّب هذه الأفكار للحصول على نتائج أكثر فائدة:

  • يمكنك إيقاف أصوات اللمس والنقرات على المفاتيح لتقليل الانقطاعات في إخراج الاختبار.
  • رفع مستوى الصوت إلى أقصى حد
  • إيقاف التطبيقات التي تصدر صوتًا أو تسجِّل من خلال الميكروفون إذا لم تكن مهتمًا باختبارك.
  • يتم حفظ عمليات التفريغ الخاصة بالمقطع الصوتي فقط عند إغلاق المسار. قد تضطر إلى فرض إغلاق التطبيق من أجل تفريغ بياناته الخاصة بالمقطع الصوتي.
  • عليك تنفيذ dumpsys بعد الاختبار مباشرةً. تتوفّر مساحة محدودة للتسجيل.
  • للتأكد من عدم فقدان ملفات التفريغ، قم بتحميلها إلى المضيف بشكل دوري. يتم الاحتفاظ بعدد محدود فقط من ملفات التفريغ؛ تتم إزالة بيانات التفريغ القديمة بعد الوصول إلى هذا الحد.

استعادة

كما هو موضح أعلاه، يجب عدم ترك ميزة حوض الماء مفعّلة. يمكنك استعادة الإصدار والجهاز على النحو التالي:

  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

واجهة برمجة تطبيقات تسجيل لغة Java القياسية في حزمة تطوير البرامج (SDK) لنظام التشغيل 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،
  • إذا تم إيقاف سجل معين للحد من السجل غير المرغوب فيه، فسيتم فقدان أي معلومات قد تم الحصول عليها بواسطة هذا السجل. لا يمكن تمكين سجل معين بأثر رجعي، بعد يتضح أنّ السجلّ كان مهمًا.

Nblogger وmedia.log وMediaLogService

واجهات برمجة تطبيقات NBLOG وmedia.log المرتبطة وMediaLogService تشكل معًا نظام تسجيل أحدث للوسائط، مصممة لمعالجة المشكلات أعلاه. سنستخدم مصطلح "media.log" (سجل "media.log" للإشارة إلى هذه السمات الثلاث، ولكن NBLOG هو واجهة برمجة تطبيقات تسجيل C++، وmedia.log هو اسم عملية Linux، وMediaLogService يعدّ خدمة ربط Android لفحص السجلات.

"المخطط الزمني" لـ media.log عبارة عن سلسلة من إدخالات السجل التي يتم الاحتفاظ بترتيبها النسبي. حسب الاصطلاح، يجب أن تستخدم كل سلسلة محادثات المخطط الزمني الخاص بها.

المزايا

في ما يلي مزايا نظام media.log:

  • لا يتم إرسال رسائل غير مرغوب فيها إلى السجلّ الرئيسي ما لم تكن هناك حاجة إليه.
  • يمكن فحصه حتى في حال تعطُّل "mediaserver" أو توقُّفه.
  • لا يؤدي إلى حظر المحتوى وفقًا للمخطط الزمني.
  • يؤدي إلى إزعاج أقل بالأداء. (بالطبع لا يعد أي شكل من أشكال التسجيل غير تطفلي على الإطلاق.)

هندسة معمارية

يوضّح الرسم البياني التالي العلاقة بين عملية mediaserver وعملية init، قبل طرح media.log:

البنية قبل media.log

الشكل 1. البنية قبل media.log

النقاط البارزة:

  • تتم مشاركة بيانات init وexecs mediaserver.
  • يرصد init وفاة mediaserver، ويعيد شوكه عند الضرورة.
  • تسجيل ALOGx غير معروض.

يوضح الرسم التخطيطي أدناه العلاقة الجديدة بين المكونات، بعد إضافة media.log إلى البنية:

البنية بعد media.log

الشكل 2. البنية بعد media.log

تغييرات مهمة:

  • يستخدم العملاء واجهة برمجة التطبيقات NBLOG لإنشاء إدخالات سجلّ وإلحاقها بـ مخزن مؤقت دائري في الذاكرة المشتركة.
  • يستطيع MediaLogService تفريغ محتوى المخزن المؤقت الدائري في أي وقت.
  • تم تصميم المورد الاحتياطي الدائري بطريقة تجعل أي تلف في لن تتعطّل الذكريات المشترَكة في MediaLogService، وسيبقى بالإمكان الوصول إليها. بتفريغ أكبر قدر ممكن من المورد الاحتياطي الذي لا يتأثر بالتلف.
  • المخزن المؤقت الدائري لا يحجب الصوت ولا يمكن قفله لكل من الكتابة الإدخالات الجديدة وقراءة الإدخالات الحالية.
  • لا يلزم وجود استدعاءات نظام نواة للكتابة في المخزن المؤقت الدائري أو القراءة منه (باستثناء الطوابع الزمنية الاختيارية).

أماكن الاستخدام

بدايةً من الإصدار 4.4 من نظام التشغيل Android، لا تتوفّر سوى نقاط تسجيل قليلة في 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 لسلسلة المحادثات من خلال كل من سلسلة المحادثات نفسها من خلال عمليات المربط. لا تقدّم NBLog::Writer أي استبعاد متبادل ضمني لكل مخطط زمني، لذا تأكد من حدوث جميع السجلات ضمن سياق يتم فيه الاحتفاظ بتجاهل سلسلة المحادثات mLock.

بعد إضافة السجلّات، أعِد إنشاء AudioFlinger.

تنبيه: يجب توفّر مخطَّط زمني NBLog::Writer منفصل لكل سلسلة محادثات. لضمان أمان سلاسل المحادثات، لأنّ المخططات الزمنية تحذف عناصر الاستبعاد المتكرّرة حسب تصميمها إذا كنت إذا كنت تريد أكثر من سلسلة محادثات واحدة تستخدم المخطط الزمني نفسه، يمكنك حماية حسابك من خلال كائن المزامنة الحالي (كما هو موضَّح أعلاه في mLock). أو يمكنك استخدام برنامج تضمين NBLog::LockedWriter بدلاً من NBLog::Writer ومع ذلك، ينفي ذلك إحدى المزايا الرئيسية لواجهة برمجة التطبيقات هذه، ألا وهي: السلوك.

واجهة برمجة التطبيقات NBLog الكاملة على frameworks/av/include/media/nbaio/NBLog.h.

تفعيل ملف media.log

يكون media.log غير مفعَّل تلقائيًا. تكون نشطة فقط عندما تكون الخاصية تم 1 ميزة ro.test_harness. يمكنك تفعيل هذه الميزة من خلال اتّباع الخطوات التالية:

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 #، حيث تكون # بمعرّف العملية الذي لاحظته سابقًا. من المفترض أن يظهر لك ملف تفريغ من media.log. في logcat الرئيسي، مع عرض جميع السجلات التي أدت إلى التعطُّل.

dumpsys media.log