ملاحظات برمجة OpenSL ES

تُكمِّل الملاحظات الواردة في هذا القسم مواصفات OpenSL ES 1.0.1.

الكائنات وتهيئة الواجهة

هناك جانبان في نموذج برمجة OpenSL ES قد لا يكونان مألوفين للمطورين الجدد، وهما التمييز بين الكائنات والواجهات وتسلسل الإعداد.

باختصار، يتشابه كائن OpenSL ES مع مفهوم الكائن في لغات البرمجة، مثل Java وC++ ، باستثناء كائن OpenSL ES الذي لا يظهر إلا من خلال الواجهات المرتبطة به. ويشمل ذلك الواجهة الأولية لجميع الكائنات المسماة SLObjectItf. وما من مؤشر للكائن نفسه، بل هو مؤشر فقط لواجهة SLObjectItf الخاصة بالكائن.

يتم أولاً إنشاء كائن OpenSL ES، ما يؤدي إلى عرض SLObjectItf، ثم تحقيقه. وهذا يشبه نمط البرمجة الشائع لإنشاء كائن أولًا (الذي يجب ألا يفشل أبدًا، باستثناء نقص الذاكرة أو المعلَمات غير الصالحة)، ثم إكمال الإعداد (الذي قد يتعذّر بسبب نقص الموارد). تمنح خطوة الإنجاز التنفيذ مكانًا منطقيًا لتخصيص موارد إضافية إذا لزم الأمر.

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

بعد إنشاء الكائن وتحقيقه، يجب أن يكتسب التطبيق واجهات لكل ميزة يحتاجها، باستخدام GetInterface في SLObjectItf الأولية.

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

بعد الانتهاء من تطبيق الكائن على الكائن، يجب إتلافه صراحةً، ويمكنك مراجعة القسم تدمير أدناه.

الجلب المُسبَق في مشغِّل الصوت

بالنسبة إلى مشغّل الصوت الذي يتضمّن مصدر بيانات معرّف الموارد المنتظم (URI)، يخصّص Object::Realize الموارد ولكنه لا يربط بمصدر البيانات (إعداد) أو يبدأ في الجلب المسبق للبيانات. وتحدث هذه المشاكل بعد ضبط حالة المشغّل على SL_PLAYSTATE_PAUSED أو SL_PLAYSTATE_PLAYING.

وقد تظل بعض المعلومات غير معروفة حتى وقت متأخر نسبيًا من هذا التسلسل. على وجه الخصوص، تعرض Player::GetDuration مبدئيًا SL_TIME_UNKNOWN وتعرض MuteSolo::GetChannelCount إما بنجاح مع عدد القنوات صفر أو نتيجة الخطأ SL_RESULT_PRECONDITIONS_VIOLATED. تعرض واجهات برمجة التطبيقات هذه القيم المناسبة بمجرد أن تكون معروفة.

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

وتفيد واجهة الجلب المُسبَق للحالة في رصد وقت توفُّر جميع المعلومات، أو يمكن لتطبيقك إجراء استطلاع رأي بشكل دوري. يُرجى العِلم أنّ بعض المعلومات قد لا تكون معروفة، مثل مدة بث المحتوى بتنسيق MP3.

تُعد واجهة الجلب المُسبَق للحالة مفيدة أيضًا لرصد الأخطاء. سجِّل استدعاءً وفعِّل حدثَي SL_PREFETCHEVENT_FILLLEVELCHANGE وSL_PREFETCHEVENT_STATUSCHANGE على الأقل. إذا تم إرسال كلا الحدثَين في الوقت نفسه، وظهرت علامة PrefetchStatus::GetFillLevel بقيمة صفرية، و يعرض PrefetchStatus::GetPrefetchStatus تقارير SL_PREFETCHSTATUS_UNDERFLOW، يشير ذلك إلى حدوث خطأ لا يمكن استرداده في مصدر البيانات. ويشمل ذلك عدم القدرة على الاتصال بمصدر البيانات بسبب عدم توفّر اسم الملف المحلي أو عدم صلاحية معرّف الموارد المنتظم (URI) للشبكة.

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

باختصار، تسلسل الرمز الموصى به هو:

  1. Engine::CreateAudioPlayer
  2. Object:Realize
  3. Object::GetInterface لـ SL_IID_PREFETCHSTATUS
  4. PrefetchStatus::SetCallbackEventsMask
  5. PrefetchStatus::SetFillUpdatePeriod
  6. PrefetchStatus::RegisterCallback
  7. Object::GetInterface لـ SL_IID_PLAY
  8. من Play::SetPlayState إلى SL_PLAYSTATE_PAUSED، أو SL_PLAYSTATE_PLAYING

ملاحظة: يتم التحضير والجلب المسبق هنا، وخلال هذه الفترة يتم استدعاء معاودة الاتصال مع تحديثات الحالة الدورية.

التدمير

احرص على تدمير جميع الكائنات عند الخروج من التطبيق. يجب تدمير الكائنات بترتيب عكسي عند إنشائها، إذ ليس من الآمن تدمير كائن يحتوي على أي كائنات تابعة. على سبيل المثال، يجب تدمير مشغِّلات الصوت ومسجلات الصوت وتشكيلة الإخراج ثم المحرك في النهاية.

لا يتيح OpenSL ES جمع البيانات غير المرغوب فيها تلقائيًا أو احتساب عدد المراجع للواجهات. بعد طلب البيانات Object::Destroy، تصبح جميع الواجهات المتوفّرة المستمدة من الكائن المرتبط غير معرَّفة.

لا يرصد تنفيذ Android OpenSL ES الاستخدام غير الصحيح لهذه الواجهات. قد يؤدي الاستمرار في استخدام مثل هذه الواجهات بعد إتلاف الكائن إلى تعطُّل تطبيقك أو تصرّفه بطرق غير متوقعة.

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

تصوير استيريو شامل

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

عمليات معاودة الاتصال وسلاسل المحادثات

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

يتم استدعاء معالِجات معاودة الاتصال من سلاسل المحادثات الداخلية غير التابعة للتطبيقات والتي لا تكون مرتبطة بوقت تشغيل Android، لذا فهي غير مؤهَّلة لاستخدام JNI. ولأنّ سلاسل المحادثات الداخلية هذه مهمة لسلامة تنفيذ OpenSL ES، يجب أيضًا ألا يحظر معالج معاودة الاتصال أو يؤدي عملاً زائدًا عن الحد.

إذا احتاج معالج استدعاء الدالة إلى استخدام مؤشر JNI أو تنفيذ عمل لا يتناسب مع استدعاء الاتصال، يجب أن ينشر المعالج بدلاً من ذلك حدثًا لتتم معالجة سلسلة محادثات أخرى. ومن الأمثلة على أعباء العمل المقبولة لرد الاتصال، عرض المخزن المؤقت التالي للمخرجات وإدراجه في قائمة انتظار (لمشغل الصوت)، ومعالجة المخزن المؤقت للإدخال الذي تم ملؤه للتو، وإدراج المخزن المؤقت الفارغ التالي في قائمة الانتظار (لمسجّل الصوت) أو واجهات برمجة تطبيقات بسيطة مثل معظم مجموعة Get. راجِع قسم الأداء أدناه المتعلّق بأعباء العمل.

يُرجى العِلم أنّ المحادثة آمنة: يتم السماح لسلسلة محادثات تطبيق Android التي تم إدخالها في معيار JNI باستدعاء واجهات برمجة تطبيقات OpenSL ES مباشرةً، بما في ذلك تلك التي تحظرها. ومع ذلك، لا يُنصح بحظر الطلبات من سلسلة التعليمات الرئيسية، لأنّ ذلك قد يؤدي إلى عدم استجابة التطبيق (ANR).

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

لا يمكن ضمان أن يكون لسلسلة المحادثات التي يتم تشغيل معالج معاودة الاتصال بها الهوية نفسها عبر استدعاءات مختلفة. لذلك، لا تعتمد على pthread_t التي يعرضها pthread_self() أو pid_t التي يعرضها gettid() لتكون متسقًا في مختلف الطلبات. للسبب نفسه، لا تستخدم واجهات برمجة تطبيقات التخزين المحلي لسلسلة المحادثات (بروتوكول أمان طبقة النقل) مثل pthread_setspecific() وpthread_getspecific() من معاودة الاتصال.

يضمن التنفيذ عدم حدوث عمليات استدعاء متزامنة من النوع نفسه للكائن نفسه. ومع ذلك، يمكن أن تكون استدعاءات الاستدعاء المتزامنة من أنواع مختلفة للكائن نفسه ممكنة في سلاسل التعليمات المختلفة.

عروض أداء

بما أنّ OpenSL ES هو واجهة برمجة تطبيقات أصلية بلغة C، فإنّ سلاسل التطبيقات غير المستندة إلى وقت التشغيل التي تستدعي OpenSL ES ليس لها أعباء زائدة ذات صلة بوقت التشغيل، مثل الإيقاف المؤقت لجمع البيانات المهملة. باستثناء واحد المذكور أدناه، لا توجد فائدة إضافية من الأداء لاستخدام OpenSL ES غير ذلك. وعلى وجه الخصوص، لا يضمن استخدام OpenSL ES تحسينات مثل انخفاض وقت استجابة الصوت وأولوية جدولة أعلى مقارنةً بما يوفّره النظام الأساسي بشكل عام. من ناحية أخرى، ومع استمرار تطوّر نظام Android الأساسي وعمليات تنفيذ أجهزة محدَّدة، يمكن لتطبيق OpenSL ES الاستفادة من أي تحسينات مستقبلية في أداء النظام.

ومن هذه التطورات إتاحة انخفاض وقت استجابة إخراج الصوت. تم تضمين أسس لوقت استجابة أقل للمخرجات في البداية في Android 4.1 (مستوى واجهة برمجة التطبيقات 16)، ثم واصلت التقدم في Android 4.2 (مستوى واجهة برمجة التطبيقات 17). تتوفر هذه التحسينات عبر OpenSL ES لعمليات تنفيذ الأجهزة التي تطالب بالميزة android.hardware.audio.low_latency. إذا لم يطالب الجهاز بهذه الميزة، ولكنه متوافق مع Android 2.3 (المستوى 9 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، سيظل بإمكانك استخدام واجهات برمجة تطبيقات OpenSL ES، إلا أنّ وقت استجابة الإخراج قد يكون أطول. ولا يتم استخدام مسار وقت الاستجابة المنخفض للناتج إلا إذا كان التطبيق يطلب حجم ذاكرة مؤقتة ومعدَّل عيّنة متوافقَين مع إعدادات الإخراج الأصلية للجهاز. هذه المعلمات خاصة بالأجهزة ويجب الحصول عليها كما هو موضّح أدناه.

بدءًا من Android 4.2 (المستوى 17 من واجهة برمجة التطبيقات)، يمكن للتطبيق طلب البحث عن معدّل الإخراج الأصلي أو المثالي للنظام الأساسي وحجم المخزن المؤقت لمصدر الإخراج الأساسي على الجهاز. عند دمج التطبيق مع اختبار الميزة المذكور أعلاه، يمكن الآن للتطبيق ضبط نفسه بشكل مناسب لتوفير نتائج وقت الاستجابة الأقل على الأجهزة التي تطلب التوافق مع هذه الميزة.

بالنسبة إلى نظام التشغيل Android 4.2 (المستوى 17 من واجهة برمجة التطبيقات) والإصدارات الأقدم، يجب توفير عدد مخزن مؤقّت بمقدار اثنين أو أكثر لوقت الاستجابة الأقل. بدايةً من نظام التشغيل Android 4.3 (المستوى 18 لواجهة برمجة التطبيقات)، يكفي عدد مخازن مؤقتة بمقدار واحد لوقت الاستجابة الأقل.

وتستبعد جميع واجهات OpenSL ES لتأثيرات الإخراج مسار الاستجابة السريعة.

التسلسل المُوصى به هو على النحو التالي:

  1. تحقَّق من المستوى 9 من واجهة برمجة التطبيقات أو مستوى أعلى لتأكيد استخدام OpenSL ES.
  2. ابحث عن ميزة android.hardware.audio.low_latency باستخدام رمز مثل التالي:

    Kotlin

    import android.content.pm.PackageManager
    ...
    val pm: PackageManager = context.packageManager
    val claimsFeature: Boolean = pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY)
    

    Java

    import android.content.pm.PackageManager;
    ...
    PackageManager pm = getContext().getPackageManager();
    boolean claimsFeature = pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
    
  3. تحقَّق من المستوى 17 من واجهة برمجة التطبيقات أو مستوى أعلى لتأكيد استخدام android.media.AudioManager.getProperty().
  4. يمكنك الحصول على معدّل الإخراج الأصلي أو الأمثل وحجم المخزن المؤقت لمصدر البيانات الناتج عن هذا الجهاز باستخدام رمز على النحو التالي:

    Kotlin

    import android.media.AudioManager
    ...
    val am = getSystemService(Context.AUDIO_SERVICE) as AudioManager
    val sampleRate: String = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)
    val framesPerBuffer: String = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)
    

    Java

    import android.media.AudioManager;
    ...
    AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    String sampleRate = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
    String framesPerBuffer = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
    
    يُرجى العِلم أنّ sampleRate وframesPerBuffer هما سلاسل. تحقَّق أولاً من وجود قيمة فارغة، ثم حوِّلها إلى عدد صحيح باستخدام Integer.parseInt().
  5. استخدِم الآن OpenSL ES لإنشاء مشغّل صوت باستخدام محدِّد مواقع بيانات قائمة انتظار المخزن المؤقت PCM.

ملاحظة: يمكنك استخدام تطبيق اختبار حجم المخزن المؤقت للصوت لتحديد حجم المخزن المؤقت الأصلي ومعدّل العينة في تطبيقات الصوت OpenSL ES الصوتية على جهازك الصوتي. يمكنك أيضًا الانتقال إلى GitHub لعرض نماذج حجم المخزن المؤقت للصوت.

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

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

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

يمكن تشغيل الصوت بوقت استجابة أقل للمخرجات التالية فقط:

ويكون وقت استجابة مكبِّر الصوت أعلى من المسارات الأخرى في بعض الأجهزة بسبب معالجة الإشارات الرقمية لتصحيح مكبرات الصوت وحمايتها.

بدءًا من الإصدار 5.0 من نظام التشغيل Android (المستوى 21 من واجهة برمجة التطبيقات)، يتوفّر إدخال الصوت بوقت استجابة أقصر على أجهزة محدّدة. للاستفادة من هذه الميزة، تأكد أولاً من توفر ناتج وقت استجابة أقل كما هو موضح أعلاه. إن إمكانية إخراج زمن الانتقال أقصر شرط أساسي لميزة الإدخال ذات وقت الاستجابة المنخفض. بعد ذلك، عليك إنشاء مسجِّل صوتي بنفس معدل العينة وحجم المخزن المؤقت اللذين سيتم استخدامهما للمخرجات. تمنع واجهات OpenSL ES لتأثيرات الإدخال مسار وقت الاستجابة المنخفض. الإعداد المسبَق للتسجيل يجب استخدام SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION مع وقت الاستجابة الأقل. يؤدي هذا الإعداد مسبقًا إلى إيقاف معالجة الإشارات الرقمية الخاصة بالجهاز والتي قد تضيف وقت استجابة إلى مسار الإدخال. لمزيد من المعلومات حول الإعدادات المسبقة للتسجيل، اطّلع على القسم واجهة إعداد Android أعلاه.

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

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

أوضاع الأداء

بدءًا من نظام التشغيل Android 7.1 (مستوى واجهة برمجة التطبيقات 25)، قدّم OpenSL ES طريقة لتحديد وضع الأداء للمسار الصوتي. الخيارات هي:

  • SL_ANDROID_PERFORMANCE_NONE: ما مِن متطلبات أداء محدَّدة. يسمح هذا الإعداد بتأثيرات الأجهزة والبرامج.
  • SL_ANDROID_PERFORMANCE_LATENCY: يتم منح الأولوية لوقت الاستجابة. ليس هناك تأثيرات للأجهزة أو البرامج. وهذا هو الوضع التلقائي.
  • SL_ANDROID_PERFORMANCE_LATENCY_EFFECTS: يتم إعطاء الأولوية لوقت الاستجابة مع السماح بتأثيرات الأجهزة والبرامج.
  • SL_ANDROID_PERFORMANCE_POWER_SAVING: الأولوية المعطاة للحفاظ على الطاقة. يسمح هذا الإعداد بتأثيرات الأجهزة والبرامج.

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

لضبط وضع الأداء، يجب طلب SetConfiguration باستخدام واجهة ضبط Android، على النحو الموضّح أدناه:

  // Obtain the Android configuration interface using a previously configured SLObjectItf.
  SLAndroidConfigurationItf configItf = nullptr;
  (*objItf)->GetInterface(objItf, SL_IID_ANDROIDCONFIGURATION, &configItf);

  // Set the performance mode.
  SLuint32 performanceMode = SL_ANDROID_PERFORMANCE_NONE;
    result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE,
                                                     &performanceMode, sizeof(performanceMode));

الأمان والأذونات

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

يجب أن تطلب التطبيقات التي تستخدم OpenSL ES الأذونات التي قد تحتاج إليها لواجهات برمجة التطبيقات المشابهة غير الأصلية. على سبيل المثال، إذا كان تطبيقك يسجّل الصوت، سيحتاج إلى إذن android.permission.RECORD_AUDIO. يجب أن تحتوي التطبيقات التي تستخدم التأثيرات الصوتية على android.permission.MODIFY_AUDIO_SETTINGS. تحتاج التطبيقات التي تشغّل موارد معرّف الموارد المنتظم (URI) للشبكة إلى android.permission.NETWORK. لمزيد من المعلومات، راجع العمل باستخدام أذونات النظام.

اعتمادًا على إصدار النظام الأساسي وتنفيذه، قد تعمل برامج تحليل محتوى الوسائط وبرامج ترميز البرامج في سياق تطبيق Android الذي يستدعي OpenSL ES (برامج ترميز الأجهزة هي برامج تجريدية ولكنها تعتمد على الأجهزة). ويعدّ المحتوى السيئ المصمّم لاستغلال الثغرات الأمنية في برامج الترميز وبرامج الترميز أحد متجهات هجوم معروف. ننصحك بعدم تشغيل الوسائط إلا من مصادر موثوقة أو تقسيم تطبيقك بحيث يتم تشغيل الرمز الذي يعالج الوسائط الواردة من مصادر غير موثوقة في بيئة تحميها وضع الحماية نسبيًا. على سبيل المثال، يمكنك معالجة الوسائط من مصادر غير موثوقة في عملية منفصلة. على الرغم من أن كلتا العمليتين ستظلان تعملان باستخدام نفس المعرّف الفريد، فإن هذا الفصل يجعل الهجوم أكثر صعوبة.