یادداشت های این بخش تکمیل کننده مشخصات OpenSL ES 1.0.1 هستند.
اشیاء و مقداردهی اولیه رابط
دو جنبه از مدل برنامه نویسی OpenSL ES که ممکن است برای توسعه دهندگان جدید ناآشنا باشد، تمایز بین اشیاء و رابط ها و ترتیب اولیه سازی است.
به طور خلاصه، یک شی OpenSL ES شبیه مفهوم شی در زبان های برنامه نویسی مانند جاوا و C++ است، با این تفاوت که یک شی OpenSL ES تنها از طریق رابط های مرتبط با آن قابل مشاهده است. این شامل رابط اولیه برای همه اشیا، به نام SLObjectItf
است. هیچ دسته ای برای خود یک شی وجود ندارد، فقط یک دسته برای رابط SLObjectItf
شی وجود دارد.
ابتدا یک شی OpenSL ES ایجاد می شود که یک SLObjectItf
برمی گرداند و سپس متوجه می شود . این شبیه به الگوی برنامهنویسی رایج در ابتدا ساخت یک شی (که هرگز نباید به جز کمبود حافظه یا پارامترهای نامعتبر با شکست مواجه شود)، و سپس تکمیل مقداردهی اولیه (که ممکن است به دلیل کمبود منابع با شکست مواجه شود) است. مرحله تحقق به پیاده سازی مکانی منطقی برای تخصیص منابع اضافی در صورت نیاز می دهد.
به عنوان بخشی از API برای ایجاد یک شی، یک برنامه کاربردی آرایه ای از رابط های مورد نظر را مشخص می کند که قصد دارد بعداً آنها را بدست آورد. توجه داشته باشید که این آرایه به طور خودکار اینترفیس ها را نمی گیرد. این صرفاً نشان دهنده قصد آینده برای به دست آوردن آنها است. رابط ها به صورت ضمنی یا صریح متمایز می شوند. یک رابط صریح باید در آرایه فهرست شود اگر بعداً به دست آید. لازم نیست یک رابط ضمنی در آرایه ایجاد شی فهرست شود، اما فهرست کردن آن در آنجا ضرری ندارد. OpenSL ES یک نوع رابط دیگر به نام پویا دارد که نیازی به مشخص کردن آن در آرایه ایجاد شی نیست و میتواند بعداً پس از ایجاد شی اضافه شود. پیادهسازی اندروید یک ویژگی راحت را برای جلوگیری از این پیچیدگی فراهم میکند که در رابطهای پویا هنگام ایجاد شی توضیح داده شده است.
پس از ایجاد و تحقق شیء، برنامه باید با استفاده از GetInterface
در SLObjectItf
اولیه، واسط هایی را برای هر ویژگی مورد نیاز خود بدست آورد.
در نهایت، شی برای استفاده از طریق رابط های آن در دسترس است، هرچند توجه داشته باشید که برخی از اشیاء نیاز به تنظیمات بیشتری دارند. به طور خاص، یک پخش کننده صوتی با منبع داده URI برای تشخیص خطاهای اتصال به آمادگی بیشتری نیاز دارد. برای جزئیات بیشتر به بخش واکشی اولیه پخش کننده صوتی مراجعه کنید.
پس از اینکه درخواست شما با شی انجام شد، باید به صراحت آن را از بین ببرید. بخش Destroy را در زیر ببینید.
واکشی اولیه پخش کننده صوتی
برای پخش کننده صوتی با منبع داده URI، Object::Realize
منابع را تخصیص می دهد اما به منبع داده متصل نمی شود ( آماده می شود ) یا شروع به پیش واکشی داده نمی کند. اینها زمانی رخ میدهند که حالت پخشکننده روی SL_PLAYSTATE_PAUSED
یا SL_PLAYSTATE_PLAYING
تنظیم شود.
برخی از اطلاعات ممکن است تا اواخر این توالی هنوز ناشناخته باشند. به ویژه، در ابتدا Player::GetDuration
SL_TIME_UNKNOWN
را برمیگرداند و MuteSolo::GetChannelCount
یا با موفقیت با تعداد کانال صفر یا نتیجه خطا SL_RESULT_PRECONDITIONS_VIOLATED
برمیگردد. این APIها پس از شناخته شدن مقادیر مناسب را برمی گردانند.
سایر ویژگیهایی که در ابتدا ناشناخته هستند عبارتند از نرخ نمونه و نوع محتوای رسانه واقعی بر اساس بررسی هدر محتوا (بر خلاف نوع MIME و نوع کانتینر مشخص شده توسط برنامه). اینها نیز بعداً در حین آماده سازی/پیش واکشی تعیین می شوند، اما هیچ API برای بازیابی آنها وجود ندارد.
رابط وضعیت پیش واکشی برای تشخیص اینکه چه زمانی همه اطلاعات در دسترس هستند یا برنامه شما می تواند به صورت دوره ای نظرسنجی کند مفید است. توجه داشته باشید که برخی از اطلاعات، مانند مدت زمان پخش MP3، ممکن است هرگز مشخص نباشد.
رابط وضعیت prefetch نیز برای تشخیص خطاها مفید است. پاسخ تماس را ثبت کنید و حداقل رویدادهای SL_PREFETCHEVENT_FILLLEVELCHANGE
و SL_PREFETCHEVENT_STATUSCHANGE
را فعال کنید. اگر هر دوی این رویدادها به طور همزمان تحویل داده شوند و PrefetchStatus::GetFillLevel
یک سطح صفر را گزارش کند و PrefetchStatus::GetPrefetchStatus
SL_PREFETCHSTATUS_UNDERFLOW
را گزارش کند، این نشان دهنده یک خطای غیرقابل بازیابی در منبع داده است. این شامل عدم امکان اتصال به منبع داده است زیرا نام فایل محلی وجود ندارد یا URI شبکه نامعتبر است.
انتظار میرود نسخه بعدی OpenSL ES پشتیبانی واضحتری را برای رسیدگی به خطاها در منبع داده اضافه کند. با این حال، برای سازگاری باینری آینده، ما قصد داریم به پشتیبانی از روش فعلی برای گزارش یک خطای غیرقابل بازیابی ادامه دهیم.
به طور خلاصه، یک دنباله کد توصیه شده عبارت است از:
-
Engine::CreateAudioPlayer
-
Object:Realize
-
Object::GetInterface
برایSL_IID_PREFETCHSTATUS
-
PrefetchStatus::SetCallbackEventsMask
-
PrefetchStatus::SetFillUpdatePeriod
-
PrefetchStatus::RegisterCallback
-
Object::GetInterface
برایSL_IID_PLAY
-
Play::SetPlayState
رویSL_PLAYSTATE_PAUSED
یاSL_PLAYSTATE_PLAYING
توجه: آماده سازی و واکشی اولیه در اینجا اتفاق می افتد. در این مدت تماس با شما با بهروزرسانیهای دورهای وضعیت فراخوانی میشود.
نابود کردن
هنگام خروج از برنامه، مطمئن شوید که تمام اشیاء را از بین ببرید. اشیاء باید به ترتیب معکوس از ایجادشان از بین بروند، زیرا از بین بردن شیئی که دارای اشیاء وابسته است بی خطر نیست. به عنوان مثال، به ترتیب زیر را از بین ببرید: پخش کننده ها و ضبط کننده های صوتی، میکس خروجی، و در نهایت موتور.
OpenSL ES از جمعآوری خودکار زباله یا شمارش مرجع رابطها پشتیبانی نمیکند. پس از فراخوانی Object::Destroy
، تمام اینترفیس های موجود که از شی مرتبط مشتق شده اند، تعریف نشده می شوند.
اجرای Android OpenSL ES استفاده نادرست از چنین رابط هایی را تشخیص نمی دهد. ادامه استفاده از چنین رابطهایی پس از از بین رفتن شی میتواند باعث از کار افتادن برنامه شما یا رفتار غیرقابل پیشبینی شود.
توصیه میکنیم که رابط اصلی شیء و همه رابطهای مرتبط را بهعنوان بخشی از توالی تخریب شیء خود بهصراحت روی NULL
تنظیم کنید، که از سوءاستفاده تصادفی دسته رابط قدیمی جلوگیری میکند.
پاننگ استریو
هنگامی که Volume::EnableStereoPosition
برای فعال کردن پانینگ استریو یک منبع مونو استفاده می شود، در سطح کل قدرت صدا 3 دسی بل کاهش می یابد. این مورد نیاز است تا سطح کل توان صدا ثابت بماند، زیرا منبع از یک کانال به کانال دیگر حرکت می کند. بنابراین، فقط در صورت نیاز، موقعیت استریو را فعال کنید. برای اطلاعات بیشتر به مقاله ویکیپدیا در مورد حرکت صوتی مراجعه کنید.
تماس ها و موضوعات
زمانی که پیادهسازی یک رویداد را شناسایی میکند، کنترلکنندههای پاسخ به تماس معمولاً به صورت همزمان فراخوانی میشوند. این نقطه با توجه به برنامه ناهمزمان است، بنابراین باید از مکانیزم همگامسازی غیرمسدود برای کنترل دسترسی به متغیرهای مشترک بین برنامه و کنترل کننده تماس استفاده کنید. در کد مثال، مانند صفهای بافر، ما یا این همگامسازی را حذف کردهایم یا برای سادگی از همگامسازی مسدودکننده استفاده کردهایم. با این حال، همگام سازی غیر مسدود کننده مناسب برای هر کد تولیدی حیاتی است.
کنترلکنندههای پاسخ به تماس از رشتههای غیربرنامهای داخلی فراخوانی میشوند که به زمان اجرای Android متصل نیستند، بنابراین برای استفاده از JNI واجد شرایط نیستند. از آنجایی که این رشتههای داخلی برای یکپارچگی اجرای OpenSL ES حیاتی هستند، یک کنترل کننده تماس نیز نباید کار بیش از حد را مسدود یا انجام دهد.
اگر کنترل کننده تماس شما باید از JNI استفاده کند یا کاری را اجرا کند که متناسب با پاسخ تماس نیست، کنترل کننده باید در عوض رویدادی را برای یک رشته دیگر ارسال کند تا پردازش شود. نمونههایی از بار کاری پاسخگوی قابل قبول عبارتند از رندر کردن و ردیف کردن بافر خروجی بعدی (برای یک AudioPlayer)، پردازش بافر ورودی تازه پر شده و قرار دادن بافر خالی بعدی (برای یک AudioRecorder) یا APIهای ساده مانند اکثر خانواده Get . در مورد حجم کار به بخش عملکرد زیر مراجعه کنید.
توجه داشته باشید که عکس آن بی خطر است: یک رشته برنامه Android که وارد JNI شده است مجاز است مستقیماً APIهای OpenSL ES، از جمله آنهایی که مسدود می کنند، فراخوانی کند. با این حال، مسدود کردن تماسها از رشته اصلی توصیه نمیشود، زیرا ممکن است منجر به عدم پاسخگویی برنامه (ANR) شود.
تصمیم گیری در مورد رشته ای که یک کنترل کننده برگشت تماس را فراخوانی می کند تا حد زیادی به اجرا بستگی دارد. دلیل این انعطاف پذیری اجازه بهینه سازی های آینده، به ویژه در دستگاه های چند هسته ای است.
رشته ای که کنترل کننده برگشت تماس روی آن اجرا می شود، تضمینی برای داشتن هویت یکسان در تماس های مختلف نیست. بنابراین، به pthread_t
برگردانده شده توسط pthread_self()
یا pid_t
برگردانده شده توسط gettid()
اعتماد نکنید تا در تماس ها یکسان باشد. به همین دلیل، از APIهای ذخیرهسازی محلی رشته (TLS) مانند pthread_setspecific()
و pthread_getspecific()
از یک callback استفاده نکنید.
پیاده سازی تضمین می کند که تماس های همزمان از یک نوع، برای یک شی، رخ نمی دهد. با این حال، تماسهای همزمان از انواع مختلف برای یک شی در رشتههای مختلف امکانپذیر است.
عملکرد
از آنجایی که OpenSL ES یک API بومی C است، رشتههای برنامه بدون زمان اجرا که OpenSL ES را فراخوانی میکنند، سربار مربوط به زمان اجرا مانند توقفهای جمعآوری زباله ندارند. به استثنای یک استثنا که در زیر توضیح داده شده است، استفاده از OpenSL ES هیچ مزیت عملکردی دیگری جز این ندارد. به طور خاص، استفاده از OpenSL ES بهبودهایی مانند تأخیر کمتر صدا و اولویت زمانبندی بالاتر نسبت به آنچه که پلتفرم به طور کلی ارائه میکند را تضمین نمیکند. از سوی دیگر، همانطور که پلتفرم اندروید و پیاده سازی های دستگاه خاص همچنان در حال تکامل هستند، یک برنامه OpenSL ES می تواند انتظار داشته باشد که از هر گونه بهبود عملکرد سیستم در آینده بهره مند شود.
یکی از این تحولات، پشتیبانی از کاهش تاخیر خروجی صدا است. زیربنای کاهش تاخیر خروجی ابتدا در Android 4.1 (سطح API 16) گنجانده شد و سپس پیشرفت مداوم در Android 4.2 (سطح API 17) رخ داد. این پیشرفتها از طریق OpenSL ES برای پیادهسازی دستگاههایی که ادعا میکنند ویژگی android.hardware.audio.low_latency
در دسترس هستند. اگر دستگاه ادعای این ویژگی را ندارد اما از Android 2.3 (سطح API 9) یا جدیدتر پشتیبانی میکند، همچنان میتوانید از OpenSL ES API استفاده کنید اما تاخیر خروجی ممکن است بیشتر باشد. مسیر تاخیر خروجی کمتر تنها در صورتی استفاده میشود که برنامه یک اندازه بافر و نرخ نمونه درخواست کند که با پیکربندی خروجی بومی دستگاه سازگار باشد. این پارامترها برای دستگاه خاص هستند و باید همانطور که در زیر توضیح داده شده است به دست آیند.
با شروع Android 4.2 (سطح API 17)، یک برنامه کاربردی میتواند نرخ نمونه خروجی بومی یا بهینه پلتفرم و اندازه بافر را برای جریان خروجی اصلی دستگاه جستجو کند. هنگامی که یک برنامه با آزمایش ویژگی که قبلاً ذکر شد ترکیب شود، اکنون یک برنامه می تواند خود را به طور مناسب برای خروجی تاخیر کمتر در دستگاه هایی که ادعای پشتیبانی دارند پیکربندی کند.
برای Android 4.2 (سطح API 17) و قبل از آن، تعداد بافر دو یا بیشتر برای تأخیر کمتر مورد نیاز است. با شروع Android 4.3 (سطح API 18)، تعداد بافر یک برای تأخیر کمتر کافی است.
همه رابطهای OpenSL ES برای جلوههای خروجی از مسیر تاخیر کمتر جلوگیری میکنند.
دنباله توصیه شده به شرح زیر است:
- برای تأیید استفاده از OpenSL ES، سطح API 9 یا بالاتر را بررسی کنید.
- با استفاده از کدهایی مانند این، ویژگی
android.hardware.audio.low_latency
را بررسی کنید:کاتلین
import android.content.pm.PackageManager ... val pm: PackageManager = context.packageManager val claimsFeature: Boolean = pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY)
جاوا
import android.content.pm.PackageManager; ... PackageManager pm = getContext().getPackageManager(); boolean claimsFeature = pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
- برای تأیید استفاده از
android.media.AudioManager.getProperty()
سطح API 17 یا بالاتر را بررسی کنید. - با استفاده از کدهایی مانند این، نرخ نمونه خروجی بومی یا بهینه و اندازه بافر را برای جریان خروجی اصلی این دستگاه دریافت کنید: توجه داشته باشید که
کاتلین
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)
جاوا
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
رشته هایی هستند. ابتدا null را بررسی کنید و سپس با استفاده ازInteger.parseInt()
به int تبدیل کنید. - اکنون از OpenSL ES برای ایجاد AudioPlayer با یاب داده صف بافر PCM استفاده کنید.
توجه: میتوانید از برنامه آزمایشی Audio Buffer Size برای تعیین اندازه بافر اصلی و نرخ نمونه برای برنامههای صوتی OpenSL ES در دستگاه صوتی خود استفاده کنید. همچنین میتوانید برای مشاهده نمونههایی در اندازه بافر صوتی به GitHub مراجعه کنید.
تعداد پخشکنندههای صوتی با تأخیر کمتر محدود است. اگر برنامه شما به بیش از چند منبع صوتی نیاز دارد، میکس صدای خود را در سطح برنامه در نظر بگیرید. مطمئن شوید که پخش کننده های صوتی خود را هنگامی که فعالیت شما متوقف می شود از بین ببرید، زیرا آنها یک منبع جهانی هستند که با سایر برنامه ها به اشتراک گذاشته شده است.
برای جلوگیری از اشکالات قابل شنیدن، کنترل کننده پاسخ تماس صف بافر باید در یک پنجره زمانی کوچک و قابل پیش بینی اجرا شود. این معمولاً به معنی عدم انسداد نامحدود در mutexes، شرایط، یا عملیات I/O است. در عوض، قفلهای آزمایشی ، قفلها و انتظارها با وقفههای زمانی و الگوریتمهای غیرمسدود کننده را در نظر بگیرید.
محاسبات مورد نیاز برای رندر بافر بعدی (برای AudioPlayer) یا مصرف بافر قبلی (برای AudioRecord) باید تقریباً به همان مقدار زمان برای هر پاسخ به تماس نیاز داشته باشد. از الگوریتمهایی که در مدت زمان غیر قطعی اجرا میشوند یا محاسبات خود را پشت سر میگذارند اجتناب کنید. در صورتی که زمان CPU صرف شده در هر تماس معین به طور قابل توجهی بزرگتر از میانگین باشد، محاسبات برگشت به تماس پشت سر هم است. به طور خلاصه، ایدهآل این است که زمان اجرای CPU هندلر واریانس نزدیک به صفر داشته باشد و کنترل کننده برای زمانهای نامحدود مسدود نشود.
صدای تاخیر کمتر فقط برای این خروجی ها امکان پذیر است:
- بلندگوهای روی دستگاه
- هدفون سیمی.
- هدست سیمی.
- خط بیرون.
- صدای دیجیتال USB .
در برخی از دستگاه ها، به دلیل پردازش سیگنال دیجیتال برای تصحیح و محافظت بلندگو، تاخیر بلندگو نسبت به مسیرهای دیگر بیشتر است.
از Android 5.0 (API Level 21)، ورودی صوتی با تأخیر کمتر در دستگاههای منتخب پشتیبانی میشود. برای استفاده از این ویژگی، ابتدا تأیید کنید که خروجی با تأخیر کمتر همانطور که در بالا توضیح داده شد در دسترس است. قابلیت خروجی با تاخیر کمتر پیش نیاز ویژگی ورودی با تاخیر کمتر است. سپس یک AudioRecorder با همان نرخ نمونه و اندازه بافری که برای خروجی استفاده می شود ایجاد کنید. رابطهای OpenSL ES برای جلوههای ورودی از مسیر تأخیر کمتر جلوگیری میکنند. رکورد از پیش تنظیم شده SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION
باید برای تأخیر کمتر استفاده شود. این از پیش تنظیم، پردازش سیگنال دیجیتال خاص دستگاه را غیرفعال می کند که ممکن است به مسیر ورودی تاخیر بیافزاید. برای اطلاعات بیشتر در مورد از پیش تنظیم رکورد، بخش رابط پیکربندی Android در بالا را ببینید.
برای ورودی و خروجی همزمان، کنترل کننده های تکمیل صف بافر جداگانه برای هر طرف استفاده می شود. هیچ تضمینی برای ترتیب نسبی این تماسها یا همگامسازی ساعتهای صوتی وجود ندارد، حتی زمانی که هر دو طرف از یک نرخ نمونه استفاده میکنند. برنامه شما باید داده ها را با همگام سازی بافر مناسب بافر کند.
یکی از پیامدهای ساعتهای صوتی بالقوه مستقل، نیاز به تبدیل نرخ نمونه ناهمزمان است. یک تکنیک ساده (اگرچه برای کیفیت صدا ایدهآل نیست) برای تبدیل نرخ نمونه ناهمزمان، کپی کردن یا رها کردن نمونهها در صورت نیاز در نزدیکی نقطه صفر است. تبدیل های پیچیده تر امکان پذیر است.
حالت های عملکرد
شروع با Android 7.1 (API Level 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));
امنیت و مجوزها
تا جایی که چه کسی می تواند چه کاری انجام دهد، امنیت در اندروید در سطح فرآیند انجام می شود. کد زبان برنامه نویسی جاوا نمی تواند کاری بیش از کد بومی انجام دهد و همچنین کد بومی نمی تواند کاری بیش از کد زبان برنامه نویسی جاوا انجام دهد. تنها تفاوت بین آنها API های موجود است.
برنامههایی که از OpenSL ES استفاده میکنند باید مجوزهایی را که برای APIهای غیربومی مشابه نیاز دارند درخواست کنند. به عنوان مثال، اگر برنامه شما صدا را ضبط می کند، به مجوز android.permission.RECORD_AUDIO
نیاز دارد. برنامههایی که از جلوههای صوتی استفاده میکنند به android.permission.MODIFY_AUDIO_SETTINGS
نیاز دارند. برنامه هایی که منابع URI شبکه را پخش می کنند به android.permission.NETWORK
نیاز دارند. برای اطلاعات بیشتر به کار با مجوزهای سیستم مراجعه کنید.
بسته به نسخه پلت فرم و پیاده سازی، تجزیه کننده های محتوای رسانه و کدک های نرم افزار ممکن است در زمینه برنامه Android که OpenSL ES را فراخوانی می کند اجرا شود (کدک های سخت افزاری انتزاعی هستند اما وابسته به دستگاه هستند). محتوای نادرست طراحی شده برای سوء استفاده از آسیب پذیری های تجزیه کننده و کدک یک بردار حمله شناخته شده است. توصیه می کنیم رسانه ها را فقط از منابع قابل اعتماد پخش کنید یا برنامه خود را به گونه ای پارتیشن بندی کنید که کدی که رسانه های منابع غیرقابل اعتماد را مدیریت می کند در یک محیط نسبتاً جعبه ایمنی اجرا شود. به عنوان مثال، می توانید رسانه ها را از منابع غیرقابل اعتماد در یک فرآیند جداگانه پردازش کنید. اگرچه هر دو فرآیند همچنان تحت یک UID اجرا می شوند، این جداسازی حمله را دشوارتر می کند.