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

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

المغسلة المحملة

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

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

التعليمات الواردة في هذا القسم خاصة بنظام التشغيل Android 7.x والإصدارات الأحدث. لنظام التشغيل Android 5.x و 6.x ، استبدل /data/misc/audioserver بـ /data/misc/media . بالإضافة إلى ذلك ، يجب عليك استخدام userdebug أو eng build. إذا كنت تستخدم بنية userdebug ، فقم بتعطيل verity باستخدام:

adb root && adb disable-verity && adb reboot

إعداد وقت الترجمة

  1. cd frameworks/av/services/audioflinger
  2. تحرير Configuration.h .
  3. Uncomment #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 = تسجيل صوتي لكل مسار و 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 في وقت الترجمة افتراضيًا. ولكن بالطبع يمكن أن يؤدي إلى تسجيل البريد العشوائي إذا تم تمكينه.
  • قد يتم حظر استدعاءات نظام النواة الأساسية ، مما قد يؤدي إلى انعكاس الأولوية وبالتالي اضطرابات القياس وعدم الدقة. هذا مصدر قلق خاص للخيوط ذات الأهمية الزمنية مثل FastMixer و FastCapture .
  • إذا تم تعطيل سجل معين لتقليل البريد العشوائي في السجل ، فسيتم فقد أي معلومات تم التقاطها بواسطة هذا السجل. لا يمكن تمكين سجل معين بأثر رجعي ، بعد أن يتضح أن السجل كان سيكون مثيرًا للاهتمام.

NBLOG و media.log و MediaLogService

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

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

فوائد

تتمثل مزايا نظام media.log في أنه:

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

هندسة عامة

يوضح الرسم البياني أدناه العلاقة بين عملية خادم الوسائط وعملية init ، قبل media.log mediaserver

العمارة قبل media.log

الشكل 1. العمارة قبل media.log

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

  • init forks and 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 أي استثناء متبادل ضمني لكل مخطط زمني ، لذا تأكد من أن جميع السجلات تحدث في سياق يتم فيه الاحتفاظ بمفتاح كائن المزامنة (mutex) الخاص mLock الترابط.

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

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