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

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

بالوعة المحملة

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

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

التعليمات الواردة في هذا القسم مخصصة لنظام التشغيل Android 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 = AudioRecord وAudioTrack لكل مسار

لا يوجد أي جزء من المخزن المؤقت العميق أو الخلاط العادي حتى الآن، ولكن يمكنك الحصول على نتائج مماثلة باستخدام "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 القياسية في Android SDK هي 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 في وقت الترجمة بشكل افتراضي. ولكن بالطبع يمكن أن يؤدي ذلك إلى تسجيل بريد عشوائي إذا تم تمكينه.
  • يمكن أن يتم حظر مكالمات نظام kernel الأساسي، مما قد يؤدي إلى انعكاس الأولوية وبالتالي حدوث اضطرابات في القياس وعدم الدقة. يعد هذا مصدر قلق خاص لسلاسل العمليات ذات الوقت الحرج مثل FastMixer و FastCapture .
  • إذا تم تعطيل سجل معين لتقليل البريد العشوائي في السجل، فسيتم فقدان أي معلومات كان من الممكن أن يتم التقاطها بواسطة هذا السجل. ليس من الممكن تمكين سجل معين بأثر رجعي، بعد أن يصبح من الواضح أن السجل كان مثيرًا للاهتمام.

NBLOG وmedia.log وMediaLogService

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

"المخطط الزمني" 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 ، وسيظل قادرًا على تفريغ أكبر قدر ممكن من المخزن المؤقت الذي لم يتأثر بالفساد.
  • المخزن المؤقت الدائري غير محظور وخالي من القفل لكتابة الإدخالات الجديدة وقراءة الإدخالات الموجودة.
  • ليست هناك حاجة لاستدعاءات نظام kernel للكتابة أو القراءة من المخزن المؤقت الدائري (بخلاف الطوابع الزمنية الاختيارية).

أين تستخدم

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

بعد إضافة السجلات، قم بإعادة إنشاء AudioFlinger.

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

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

dumpsys media.log