توضح هذه المقالة بعض النصائح والحيل لتصحيح أخطاء صوت 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
إعداد وقت الترجمة
-
cd frameworks/av/services/audioflinger
- تحرير
Configuration.h
. - قم بإلغاء التعليق
#define TEE_SINK
. - إعادة بناء
libaudioflinger.so
. -
adb root
-
adb remount
- ادفع
libaudioflinger.so
الجديد أو قم بمزامنته مع/system/lib
الخاص بالجهاز.
إعداد وقت التشغيل
-
adb shell getprop | grep ro.debuggable
تأكد من أن الإخراج هو:[ro.debuggable]: [1]
-
adb shell
-
ls -ld /data/misc/audioserver
تأكد من أن الإخراج هو:
drwx------ media media ... media
إذا كان الدليل غير موجود، قم بإنشائه كما يلي:
mkdir /data/misc/audioserver
chown media:media /data/misc/audioserver
-
echo af.tee=# > /data/local.prop
حيث تكون قيمةaf.tee
عبارة عن رقم موضح أدناه. -
chmod 644 /data/local.prop
-
reboot
قيم خاصية af.tee
قيمة af.tee
هي رقم يقع بين 0 و7، ويعبر عن مجموع عدة بتات، واحدة لكل ميزة. راجع الكود الموجود في AudioFlinger::AudioFlinger()
في AudioFlinger.cpp
للحصول على شرح لكل بت، ولكن باختصار:
- 1 = الإدخال
- 2 = إخراج FastMixer
- 4 = AudioRecord وAudioTrack لكل مسار
لا يوجد أي جزء من المخزن المؤقت العميق أو الخلاط العادي حتى الآن، ولكن يمكنك الحصول على نتائج مماثلة باستخدام "4".
اختبار والحصول على البيانات
- قم بإجراء اختبار الصوت الخاص بك.
-
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 shell
-
rm /data/local.prop
-
rm /data/misc/audioserver/*.wav
-
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](https://source.android.com/static/docs/core/audio/images/medialog_before.png?authuser=6&hl=ar)
الشكل 1. الهندسة المعمارية قبل media.log
النقاط البارزة:
-
init
forks و execsmediaserver
. - يكتشف
init
وفاةmediaserver
، ويعيد الشوكات عند الضرورة. - لا يتم عرض تسجيل
ALOGx
.
يوضح الرسم البياني أدناه العلاقة الجديدة بين المكونات، بعد إضافة media.log
إلى البنية:
![العمارة بعد media.log](https://source.android.com/static/docs/core/audio/images/medialog_after.png?authuser=6&hl=ar)
الشكل 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