اعتبارًا من 27 آذار (مارس) 2025، ننصحك باستخدام android-latest-release بدلاً من aosp-main لإنشاء AOSP والمساهمة فيه. لمزيد من المعلومات، يُرجى الاطّلاع على التغييرات في AOSP.
تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
تتيح عناصر العرض للتطبيقات عرض الصور على الشاشات.
تتيح واجهات SurfaceHolder للتطبيقات تعديل مساحات العرض والتحكّم فيها.
السطح
السطح هو واجهة يتيح من خلالها المنتج تبادل وحدات التخزين المؤقت
مع المستهلك.
يتم عادةً ضبط BufferQueue لسطح العرض على
التخزين المؤقت الثلاثي. يتم تخصيص وحدات التخزين المؤقت عند الطلب، لذا إذا كان المنتج
ينشئ وحدات التخزين المؤقت ببطء كافٍ، مثلاً بمعدّل 30 لقطة في الثانية على شاشة تتعذّر فيها عرض سوى 60 لقطة في الثانية، قد لا يكون هناك سوى وحدتَي تخزين مؤقت مخصّصتَين في "قائمة المحتوى التالي".
يساعد تخصيص وحدات التخزين المؤقت عند الطلب في
تقليل استهلاك الذاكرة. يمكنك الاطّلاع على ملخّص للمخازن المؤقتة المرتبطة
بكل طبقة في إخراج dumpsys SurfaceFlinger.
يعرض معظم العملاء المحتوى على مساحات العرض باستخدام OpenGL ES أو Vulkan. ومع ذلك، يعرض بعض العملاء المحتوى
على مساحات العرض باستخدام لوحة.
عرض اللوحة
يتم تنفيذ اللوحة من خلال
مكتبة Skia Graphics Library.
إذا كنت تريد رسم مستطيل، يمكنك استدعاء واجهة برمجة التطبيقات Canvas API التي تضبط وحدات البايت في ملف دوار بشكلٍ مناسب. لضمان عدم تعديل اثنين من العملاء للذاكرة المؤقتة في
وقت واحد أو الكتابة فيها أثناء عرضها، عليك قفل الذاكرة المؤقتة للوصول إليها. استخدِم الأوامر التالية للعمل مع أقفال لوحة الصورة:
lockCanvas() يُقفِل المخزن المؤقت للعرض على وحدة المعالجة المركزية ويعرِض لوحة للاستخدام في الرسم.
lockHardwareCanvas() يُقفِل المخزن المؤقت للعرض على
وحدة معالجة الرسومات ويُرجِع لوحة للاستخدام في الرسم.
في المرة الأولى التي يطلب فيها المنتج ذاكرة تخزين مؤقت من BufferQueue، يتم تخصيص ملف التخزين المؤقت وإعداده على القيمة صفر. إنّ عملية الإعداد ضرورية لتجنُّب
مشاركة البيانات عن غير قصد بين العمليات. ومع ذلك، في حال إعادة استخدام ذاكرة التخزين المؤقت،
سيظل المحتوى السابق متوفّرًا. إذا ضغطت بشكل متكرر على رمزَي
lockCanvas() وunlockCanvasAndPost() بدون
رسم أي شيء، ينتقل المنتج بين اللقطات التي تم عرضها سابقًا.
يحتفظ رمز قفل السطح أو فتح قفله بإشارة إلى ملف التخزين المؤقت الذي تم عرضه سابقًا. في حال تحديد منطقة غير محدَّدة عند قفل السطح، يتم نسخ
الوحدات البكسل غير غير المحدَّدة من المخزن المؤقت السابق. عادةً ما يدير SurfaceFlinger أو HWC ملف التخزين المؤقت، ولكن بما أنّنا نحتاج فقط إلى القراءة من ملف التخزين المؤقت، ليس من الضروري الانتظار للحصول على إذن وصول حصري.
SurfaceHolder
SurfaceHolder هي واجهة يستخدمها النظام لمشاركة ملكية سطح مع التطبيقات. يتطلّب بعض العملاء الذين يعملون مع مساحات العرض الحصول على SurfaceHolder،
لأنّ واجهات برمجة التطبيقات للحصول على مَعلمات مساحات العرض وضبطها يتم تنفيذها من خلال
SurfaceHolder. يحتوي SurfaceView على
SurfaceHolder.
تتضمن معظم المكوّنات التي تتفاعل مع عرض عنصر SurfaceHolder.
تعمل بعض واجهات برمجة التطبيقات الأخرى، مثل MediaCodec، على السطح نفسه.
يخضع كل من المحتوى وعيّنات التعليمات البرمجية في هذه الصفحة للتراخيص الموضحّة في ترخيص استخدام المحتوى. إنّ Java وOpenJDK هما علامتان تجاريتان مسجَّلتان لشركة Oracle و/أو الشركات التابعة لها.
تاريخ التعديل الأخير: 2025-07-27 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-07-27 (حسب التوقيت العالمي المتفَّق عليه)"],[],[],null,["# Surface and SurfaceHolder\n\nSurface objects enable apps to render images to be presented on screens.\nSurfaceHolder interfaces enable apps to edit and control surfaces.\n\nSurface\n-------\n\nA [surface](https://developer.android.com/reference/android/view/Surface.html) is an interface for a producer to exchange buffers\nwith a consumer.\n\nThe BufferQueue for a display surface is typically configured for\ntriple-buffering. Buffers are allocated on demand, so if the producer\ngenerates buffers slowly enough, such as at 30 fps on a 60 fps\ndisplay, there might only be two allocated buffers in the queue.\nAllocating buffers on demand helps\nminimize memory consumption. You can see a summary of the buffers associated\nwith every layer in the `dumpsys SurfaceFlinger` output.\n\nMost clients render onto surfaces using [OpenGL ES](/docs/core/graphics/arch-egl-opengl) or [Vulkan](/docs/core/graphics/arch-vulkan). However, some clients render\nonto surfaces using a canvas.\n\n\n### Canvas rendering\n\nThe canvas implementation is provided by the\n[Skia Graphics Library](https://skia.org/).\nIf you want to draw a rectangle, you call the Canvas API, which sets bytes in a\nbuffer appropriately. To ensure that a buffer isn't updated by two clients at\nonce, or written to while being displayed, lock the buffer to access\nit. Use the following commands to work with canvas locks:\n\n- [`lockCanvas()`](https://developer.android.com/reference/android/view/Surface.html#lockCanvas(android.graphics.Rect)) locks the buffer for rendering on the CPU and returns a Canvas to use for drawing.\n- [`unlockCanvasAndPost()`](https://developer.android.com/reference/android/view/Surface.html#unlockCanvasAndPost(android.graphics.Canvas)) unlocks the buffer and sends it to the compositor.\n- [`lockHardwareCanvas()`](https://developer.android.com/reference/android/view/Surface.html#lockHardwareCanvas()) locks the buffer for rendering on the GPU and returns a canvas to use for drawing.\n\n| **Note:** The canvas obtained when an app locks a surface with `lockCanvas()` is never hardware accelerated.\n| **Caution:** You can't draw on a surface with GLES or send it frames from a video decoder if you've ever called `lockCanvas()`. `lockCanvas()` connects the CPU renderer to the producer side of the BufferQueue and doesn't disconnect until the surface is destroyed. The canvas-based CPU renderer can't be disconnected and reconnected to a surface, unlike most producers (like GLES or Vulkan).\n\nThe first time the producer requests a buffer from a BufferQueue, the\nbuffer is\nallocated and initialized to zero. Initialization is necessary to avoid\ninadvertently sharing data between processes. However, if you reuse a buffer,\nthe previous contents are still present. If you repeatedly call\n`lockCanvas()` and `unlockCanvasAndPost()` without\ndrawing anything, the producer cycles between previously rendered frames.\n\nThe surface lock/unlock code keeps a reference to the previously rendered\nbuffer. If you specify a dirty region when locking the surface, it copies\nthe nondirty pixels from the previous buffer. SurfaceFlinger or HWC typically\nhandle the buffer; but because we only need to read from\nthe buffer, there's no need to wait for exclusive access.\n\nSurfaceHolder\n-------------\n\nA [SurfaceHolder](https://developer.android.com/reference/android/view/SurfaceHolder.html) is an interface the system uses to share ownership of\nsurfaces with apps. Some clients that work with surfaces want a SurfaceHolder,\nbecause APIs to get and set surface parameters are implemented through a\nSurfaceHolder. A [SurfaceView](/docs/core/graphics/arch-sv-glsv) contains\na SurfaceHolder.\n\nMost components that interact with a view involve a SurfaceHolder.\nSome other APIs, such as MediaCodec, operate on the surface itself."]]