অডিও ডিবাগিং

এই নিবন্ধে Android অডিও ডিবাগ করার জন্য কিছু পরামর্শ ও কৌশল বর্ণনা করা হয়েছে।

টি সিঙ্ক

"টি সিঙ্ক" হল একটি AudioFlinger ডিবাগিং ফিচার, যা শুধুমাত্র কাস্টম বিল্ডে উপলভ্য, পরবর্তীকালে বিশ্লেষণের জন্য সাম্প্রতিক অডিওর একটি ছোট অংশ ধরে রাখার জন্য। এর ফলে, যা আসলে চালানো বা রেকর্ড করা হয়েছে তার সাথে যা প্রত্যাশিত ছিল তার তুলনা করা যায়।

গোপনীয়তা রক্ষার জন্য, কম্পাইল-টাইম ও রান-টাইম, উভয় ক্ষেত্রেই ডিফল্ট হিসেবে টি সিঙ্ক বন্ধ করা থাকে। টি সিঙ্ক ব্যবহার করতে, আপনাকে আবার কম্পাইল করে এটি চালু করতে হবে, এবং একটি প্রপার্টি সেট করতে হবে। ডিবাগিং করা হয়ে গেলে এই ফিচার বন্ধ করতে ভুলবেন না; প্রোডাকশন বিল্ডে টি সিঙ্ক চালু রাখবেন না।

এই বিভাগে দেওয়া নির্দেশাবলী Android 7.x ও তার পরবর্তী যেকোনও ভার্সনের জন্য। Android 5.x ও 6.x ভার্সনের জন্য, /data/misc/audioserver-এর জায়গায় /data/misc/media ব্যবহার করুন। এছাড়াও, আপনাকে অবশ্যই userdebug বা eng বিল্ড ব্যবহার করতে হবে। আপনি যদি userdebug বিল্ড ব্যবহার করেন, তাহলে এটি দিয়ে verity বন্ধ করুন:

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. ডিভাইসের /system/lib-এ নতুন libaudioflinger.so পুশ বা সিঙ্ক করুন।

রান-টাইম সেট-আপ

  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-এর ভ্যালু হল ০ থেকে ৭-এর মধ্যে একটি সংখ্যা, যা বিভিন্ন বিটের যোগফলকে প্রকাশ করে, ফিচার পিছু একটি করে বিট। AudioFlinger.cpp-এ AudioFlinger::AudioFlinger()-এ কোডটি দেখুন প্রতিটি বিটের ব্যাখ্যা দেওয়া আছে, তবে সংক্ষেপে:

  • ১ = ইনপুট
  • ২ = FastMixer আউটপুট
  • ৪ = পার-ট্র্যাক 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 ম্যাক্রো

Android SDK-তে স্ট্যান্ডার্ড Java ল্যাঙ্গুয়েজ লগিং API হল android.util.Log.

Android NDK-তে সংশ্লিষ্ট C ল্যাঙ্গুয়েজ API হল __android_log_print যা <android/log.h>-এ ঘোষণা করা হয়েছে।

Android ফ্রেমওয়ার্কের নেটিভ অংশের মধ্যে, আমরা ALOGE, ALOGW, ALOGI, ALOGV ইত্যাদি নামের ম্যাক্রো পছন্দ করি। সেগুলি <utils/Log.h>-এ ঘোষণা করা হয় এবং এই নিবন্ধের উদ্দেশ্যে আমরা সেগুলিকে সম্মিলিতভাবে ALOGx হিসেবে উল্লেখ করব।

এইসব API সহজে ব্যবহার করা যায় এবং ভালভাবে বোঝা যায়, তাই Android প্ল্যাটফর্ম জুড়ে এগুলি ব্যাপকভাবে ব্যবহার করা হয়। বিশেষ করে, mediaserver প্রসেস, যার মধ্যে AudioFlinger সাউন্ড সার্ভার অন্তর্ভুক্ত, সেটি ALOGx ব্যাপকভাবে ব্যবহার করে।

তবে, ALOGx ও বন্ধুদের ক্ষেত্রে কিছু সীমাবদ্ধতা আছে:

  • এগুলি "লগ স্প্যাম" দ্বারা প্রভাবিত হতে পারে: লগ বাফার হল একটি শেয়ার করা রিসোর্স তাই এটি সহজেই অপ্রাসঙ্গিক লগ এন্ট্রির কারণে ওভারফ্লো হতে পারে, যার ফলে তথ্য মিস হয়ে যেতে পারে। ALOGV ভেরিয়েন্ট ডিফল্ট হিসেবে কম্পাইল-টাইমে বন্ধ করা থাকে। তবে এটি চালু করা থাকলে, এর ফলে লগ স্প্যাম হতে পারে।
  • আন্ডারলায়িং কার্নেল সিস্টেম কল ব্লক করতে পারে, এর ফলে সম্ভবত অগ্রাধিকারের ইনভার্সন এবং ফলস্বরূপ পরিমাপ সংক্রান্ত সমস্যা ও অনিশ্চয়তা হতে পারে। এটি FastMixer এবং FastCapture-এর মতো সময়-সংবেদনশীল থ্রেডের ক্ষেত্রে বিশেষভাবে গুরুত্বপূর্ণ।
  • লগ স্প্যাম কমানোর জন্য কোনও নির্দিষ্ট লগ বন্ধ করা হলে, সেই লগ যে তথ্য ক্যাপচার করত তা আর পাওয়া যায় না। কোনও নির্দিষ্ট লগ, সেটি যে ইন্টারেস্টিং হতে পারত তা স্পষ্ট হয়ে যাওয়ার পরে রেট্রোঅ্যাক্টিভভাবে চালু করা সম্ভব নয়।

NBLOG, media.log ও MediaLogService

NBLOG API এবং সংশ্লিষ্ট media.log প্রসেস ও MediaLogService পরিষেবা একসাথে মিডিয়ার জন্য একটি নতুন লগিং সিস্টেম তৈরি করে এবং উপরে উল্লেখ করা সমস্যাগুলি সমাধান করার জন্য বিশেষভাবে ডিজাইন করা হয়েছে। আমরা এই তিনটিকেই বোঝাতে "media.log" শব্দটি আলগাভাবে ব্যবহার করব, তবে কঠোরভাবে বলতে গেলে NBLOG হল C++ লগিং API, media.log হল একটি Linux প্রসেস নাম এবং MediaLogService লগ পরীক্ষা করার জন্য একটি Android বাইন্ডার পরিষেবা।

media.log "টাইমলাইন" হল লগ এন্ট্রির একটি সিরিজ যেখানে আপেক্ষিক ক্রম বজায় রাখা হয়। কনভেনশন অনুযায়ী, প্রতিটি থ্রেডের নিজস্ব টাইমলাইন ব্যবহার করা উচিত।

সুবিধা

media.log সিস্টেমের সুবিধা হল যে এটি:

  • প্রয়োজন না হলে মূল লগ স্প্যাম করে না।
  • mediaserver ক্র্যাশ বা হ্যাং করলেও পরীক্ষা করা যায়।
  • প্রতিটি টাইমলাইনের জন্য নন-ব্লকিং।
  • পারফর্ম্যান্সের ক্ষেত্রে কম সমস্যা হয়। (অবশ্যই, কোনও ধরনের লগিংই সম্পূর্ণভাবে নন-ইনট্রুসিভ নয়।)

স্থাপত্যশিল্প

media.log চালু করার আগে, নিচের ডায়াগ্রামে mediaserver প্রসেস ও init প্রসেসের মধ্যে সম্পর্ক দেখানো হয়েছে:

media.log-এর আগের আর্কিটেকচার

ছবি ১. media.log-এর আগের আর্কিটেকচার

উল্লেখযোগ্য পয়েন্ট:

  • init forks and execs mediaserver.
  • init mediaserver-এর মৃত্যু শনাক্ত করে এবং প্রয়োজন অনুযায়ী আবার ফর্ক করে।
  • ALOGx লগিং দেখানো হয় না।

নিচের ডায়াগ্রামে কম্পোনেন্টের নতুন সম্পর্ক দেখানো হয়েছে, media.log আর্কিটেকচারে যোগ করার পরে:

media.log-এর পরে আর্কিটেকচার

ছবি ২. media.log-এর পরে আর্কিটেকচার।

গুরুত্বপূর্ণ পরিবর্তন:

  • ক্লায়েন্টরা লগ এন্ট্রি তৈরি করতে NBLOG API ব্যবহার করে এবং সেগুলিকে শেয়ার করা মেমরিতে একটি সার্কুলার বাফারে যোগ করে।
  • MediaLogService যেকোনও সময় সার্কুলার বাফারের কন্টেন্ট ডাম্প করতে পারে।
  • সার্কুলার বাফার এমনভাবে ডিজাইন করা হয়েছে যে শেয়ার করা মেমরির কোনও দুর্নীতি MediaLogService ক্র্যাশ করবে না এবং এটি এখনও দুর্নীতি দ্বারা প্রভাবিত হয়নি এমন বাফারের যতটা সম্ভব ডাম্প করতে পারবে।
  • নতুন এন্ট্রি লেখার এবং আগে থেকে থাকা এন্ট্রি পড়ার, দু'টি ক্ষেত্রেই সার্কুলার বাফার নন-ব্লকিং এবং লক-ফ্রি।
  • বৃত্তাকার বাফার (ঐচ্ছিক টাইমস্ট্যাম্প ছাড়া) থেকে লেখা বা পড়ার জন্য কোনও কার্নেল সিস্টেম কল প্রয়োজন হয় না।

কোথায় ব্যবহার করা যাবে

Android 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 হোল্ড করা হয়।

লগ যোগ করার পরে, AudioFlinger আবার তৈরি করুন।

সতর্কতা: থ্রেড পিছু আলাদা NBLog::Writer টাইমলাইন প্রয়োজন, থ্রেড সুরক্ষা নিশ্চিত করতে, কারণ টাইমলাইন ডিজাইন অনুযায়ী মিউটেক্স বাদ দেয়। আপনি যদি একটির বেশি থ্রেড একই টাইমলাইন ব্যবহার করতে চান, তাহলে আপনি আগে থেকে থাকা মিউটেক্স (mLock-এর জন্য উপরে যেভাবে বর্ণনা করা হয়েছে) দিয়ে সুরক্ষিত করতে পারেন। অথবা আপনি NBLog::Writer-এর পরিবর্তে NBLog::LockedWriter র‍্যাপার ব্যবহার করতে পারেন। তবে, এটি এই API-এর একটি প্রধান সুবিধা বাতিল করে দেয়: এর নন-ব্লকিং আচরণ।

সম্পূর্ণ NBLog API 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

পরে দেখার জন্য mediaserver-এর প্রসেস আইডি নোট করে রাখুন।

টাইমলাইন দেখান

আপনি যেকোনও সময় ম্যানুয়ালি লগ ডাম্পের অনুরোধ করতে পারবেন। এই কমান্ডটি সব অ্যাক্টিভ ও সাম্প্রতিক টাইমলাইন থেকে লগ দেখায় এবং তারপরে সেগুলি মুছে দেয়:

dumpsys media.log

মনে রাখবেন, ডিজাইন অনুযায়ী টাইমলাইনগুলি স্বাধীন, এবং টাইমলাইন মার্জ করার কোনও সুবিধা নেই।

mediaserver বন্ধ হয়ে যাওয়ার পরে লগ ফিরিয়ে আনা

এখন mediaserver প্রসেস বন্ধ করার চেষ্টা করুন: kill -9 #, যেখানে # হল প্রসেস আইডি যা আপনি আগে লিখে রেখেছিলেন। ক্র্যাশ হওয়ার আগে পর্যন্ত সব লগ সহ media.log থেকে logcat-এ একটি ডাম্প দেখতে পাবেন।

dumpsys media.log