2025년 3월 27일부터 AOSP를 빌드하고 기여하려면 aosp-main
대신 android-latest-release
를 사용하는 것이 좋습니다. 자세한 내용은 AOSP 변경사항을 참고하세요.
레이어 및 디스플레이
컬렉션을 사용해 정리하기
내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
레이어 및 디스플레이는 합성 작업, 그리고 디스플레이 하드웨어와의 상호작용을 나타내는 2개의 프리미티브입니다.
레이어
레이어는 가장 중요한 합성 단위입니다. 레이어는 노출 영역 및 SurfaceControl
의 인스턴스 조합입니다.
각 레이어에는 레이어가 다른 레이어와 상호작용하는 방식을 정의하는 속성 집합이 있습니다. 레이어 속성은 다음 표에 설명되어 있습니다.
속성 |
설명 |
위치 |
디스플레이에 레이어가 표시되는 위치를 정의합니다. 레이어 가장자리의 위치, 그리고 다른 레이어에 상대적인 Z 순서(다른 레이어의 앞이나 뒤에 위치해야 하는지 여부) 등의 정보를 포함합니다. |
콘텐츠 |
레이어에 표시된 콘텐츠가 위치 속성에서 정의한 경계 내에 어떻게 표시되어야 하는지를 정의합니다. 자르기(콘텐츠의 일부를 확장하여 레이어 경계를 채움) 및 변환(회전되었거나 뒤집힌 콘텐츠를 표시) 등의 정보를 포함합니다. |
구성 |
레이어를 어떻게 다른 레이어와 합성해야 하는지 정의합니다. 혼합 모드, 그리고 알파 합성의 전체 레이어 알파 값 등의 정보를 포함합니다. |
최적화 |
레이어를 올바르게 합성하는 데 꼭 필요하지는 않지만 HWC(Hardware Composer) 기기에서 합성 수행 방식을 최적화하는 데 사용할 수 있는 정보를 제공합니다. 레이어의 표시 영역, 그리고 이전 프레임 이후에 업데이트된 레이어의 부분 등에 대한 정보를 포함합니다. |
디스플레이
디스플레이 역시 중요한 합성 단위입니다. 시스템은 여러 개의 디스플레이를 보유할 수 있으며 디스플레이는 일반 시스템 작업 도중에 추가 또는 삭제 가능합니다. 디스플레이는 HWC 또는 프레임워크의 요청 시에 추가/삭제됩니다.
HWC 기기는 외부 디스플레이가 연결되거나 기기에서 연결 해제될 때 디스플레이를 추가 또는 삭제하도록 요청하며 이를 핫플러깅이라고 부릅니다. 클라이언트는 가상 디스플레이를 요청합니다. 가상 플레이의 콘텐츠는 실제 디스플레이 대신 오프스크린 버퍼에 렌더링됩니다.
가상 디스플레이
SurfaceFlinger는 내부 디스플레이(스마트폰 또는 태블릿에 내장됨), 외부 디스플레이(HDMI를 통해 연결된 TV 등), 그리고 시스템 내에서 합성된 출력을 제공하는 하나 이상의 가상 디스플레이를 지원합니다. 가상 디스플레이는 화면을 녹화하거나 네트워크를 통해 화면을 전송하는 데 사용할 수 있습니다. 가상 디스플레이에 대해 생성된 프레임은 BufferQueue에 작성됩니다.
가상 디스플레이는 기본 디스플레이(레이어 스택)와 같은 레이어 집합을 공유하거나 자체 집합을 소유할 수 있습니다. 가상 디스플레이에는 VSync가 없으므로 내부 디스플레이의 VSync가 모든 디스플레이의 합성을 트리거합니다.
가상 디스플레이를 지원하는 HWC 구현에서는 가상 디스플레이를 OpenGL ES(GLES), HWC 또는 GLES 및 HWC 둘 다와 합성할 수 있습니다.
지원하지 않는 구현에서는 가상 디스플레이가 항상 GLES를 사용하여 합성됩니다.
우수사례: screenrecord
screenrecord
명령어는 사용자가 화면에 표시되는 모든 콘텐츠를 디스크에 MP4 파일로 녹화할 수 있게 해줍니다. 이를 구현하기 위해 시스템은 SurfaceFlinger에서 합성된 프레임을 수신하여 동영상 인코더에 작성한 다음 인코딩된 동영상 데이터를 파일에 작성합니다. 동영상 코덱은 별도의 프로세스(mediaserver
)에 의해 관리되므로 대규모 그래픽 버퍼가 시스템 주변에서 움직여야 합니다. 보다 높은 수준의 구현을 위해 60fps 동영상을 전체 해상도로 녹화하는 것을 목표로 합니다. 이를 효율적으로 달성하기 위한 핵심은 BufferQueue입니다.
MediaCodec
클래스는 앱이 데이터를 버퍼의 원시 바이트나 노출 영역을 통해 제공할 수 있게 해줍니다. screenrecord
가 동영상 인코더 액세스를 요청하면 mediaserver
프로세스는 BufferQueue를 생성하고 자체적으로 소비자 측에 연결한 다음 생산자 측을 다시 screenrecord
에 노출 영역으로 전송합니다.
그러면 screenrecord
유틸리티는 기본 디스플레이를 미러링(같은 레이어를 전부 보유)하는 가상 디스플레이를 생성하도록 SurfaceFlinger에 요청하고, mediaserver
프로세스에서 가져온 노출 영역에 출력을 전송하도록 지시합니다. 이 경우 SurfaceFlinger는 버퍼의 소비자가 아닌 생산자입니다.
구성이 완료되면 screenrecord
는 인코딩된 데이터가 표시될 때 트리거됩니다. 앱이 그려지는 동안 버퍼는 SurfaceFlinger로 전송되며 SurfaceFlinger는 이를 하나의 버퍼로 합성한 후 mediaserver
프로세스의 동영상 인코더로 직접 전송합니다. 전체 프레임은 screenrecord
프로세스에 의해 절대 확인되지 않습니다. 내부적으로는 자체적으로 버퍼를 이동하고 핸들별로 데이터를 전달하여 오버헤드를 최소화하는 방식이 mediaserver
프로세스에 있습니다.
우수사례: 보조 디스플레이 시뮬레이션
WindowManager는 SurfaceFlinger에 SurfaceFlinger가 BufferQueue 소비자로 기능하는 표시 레이어를 생성하도록 요청할 수 있습니다. 또한 SurfaceFlinger가 BufferQueue 생산자로 기능하는 가상 디스플레이를 생성하도록 SurfaceFlinger에 요청할 수도 있습니다.
가상 디스플레이를 표시 레이어에 연결하면 합성된 화면이 표시되는 창의 위치에 폐쇄 루프가 생성됩니다. 이 창은 이제 합성된 출력의 일부이므로 다음 새로고침 시 창 내의 합성된 이미지에 창 콘텐츠도 표시됩니다. 실제 과정을 보려면 설정에서 개발자 옵션을 사용 설정하고 보조 디스플레이 시뮬레이션을 선택한 후 창을 사용 설정하세요. 보조 디스플레이가 작동하는 모습을 보려면 screenrecord
를 사용하여 디스플레이 사용 설정 작업을 캡처하고 이를 프레임별로 재생하세요.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-07-27(UTC)
[[["이해하기 쉬움","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(UTC)"],[],[],null,["# Layers and displays are two primitives that represent composition work\nand interactions with the display hardware.\n\nLayers\n------\n\nA *layer* is the most important unit of composition. A layer is a\ncombination of a [surface](/docs/core/graphics/arch-sh) and an instance of\n[`SurfaceControl`](https://developer.android.com/reference/android/view/SurfaceControl).\nEach layer has a set of properties that define how it interacts with other layers. Layer\nproperties are described in the following table:\n\n| Property | Description |\n|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Positional | Defines where the layer appears on its display. Includes information such as the positions of a layer's edges and its *Z order* relative to other layers (whether it should be in front of or behind other layers). |\n| Content | Defines how content displayed on the layer should be presented within the bounds defined by the positional properties. Includes information such as crop (to expand a portion of the content to fill the bounds of the layer) and transform (to show rotated or flipped content). |\n| Composition | Defines how the layer should be composited with other layers. Includes information such as blending mode and a layer-wide alpha value for [alpha compositing](https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending). |\n| Optimization | Provides information not strictly necessary to correctly composite the layer, but that can be used by the Hardware Composer (HWC) device to optimize how it performs composition. Includes information such as the visible region of the layer and which portion of the layer has been updated since the previous frame. |\n\nDisplays\n--------\n\nA *display* is another important unit of composition. A system can\nhave multiple displays and\ndisplays can be added or removed during normal system operations. Displays are\nadded or removed at the request of the HWC or at the request of the framework.\nThe HWC device requests displays be added or removed when an external\ndisplay is connected or disconnected from the device, which is called\n*hotplugging* . Clients request *virtual displays*, whose contents\nare rendered into an off-screen buffer instead of to a physical display.\n\n### Virtual displays\n\n[SurfaceFlinger](/docs/core/graphics/arch-sf-hwc#surfaceflinger)\nsupports an internal display (built into the phone or tablet), external displays\n(such as a television connected through HDMI), and one or more virtual displays\nthat make composited output available within the system. Virtual displays can\nbe used to record the screen or send the screen over a network. Frames generated\nfor a virtual display are written to a BufferQueue.\n\nVirtual displays may share the same set of layers as the main display\n(the layer stack) or have their own set. There's no VSync for a virtual display,\nso the VSync for the internal display triggers composition for all\ndisplays.\n\nOn HWC implementations that support them, virtual\ndisplays can be composited with OpenGL ES (GLES), HWC, or both GLES and HWC.\nOn nonsupporting implementations, virtual displays are always composited using\nGLES.\n\nCase study: screenrecord\n------------------------\n\nThe [`screenrecord` command](https://android.googlesource.com/platform/frameworks/av/+/android16-release/cmds/screenrecord/) allows the user to\nrecord everything that appears on the screen as an MP4 file on\ndisk. To implement this, the system receives composited frames from\nSurfaceFlinger, writes them to the video encoder, and then writes the encoded\nvideo data to a file. The video codecs are managed by a separate process\n(`mediaserver`), so large graphics buffers have to move around the\nsystem. To make it more challenging, the goal is to record 60 fps video at\nfull resolution. The key to making this work efficiently is BufferQueue.\n\nThe `MediaCodec` class allows an app to provide data as raw bytes in buffers,\nor through a surface. When `screenrecord` requests access to a video\nencoder, the `mediaserver` process creates a BufferQueue, connects\nitself to the consumer side, then passes the producer side back to\n`screenrecord` as a surface.\n\nThe `screenrecord` utility then asks SurfaceFlinger to create a\nvirtual display that mirrors the main display (that is, it has all of the same\nlayers), and directs it to send output to the surface that came from the\n`mediaserver` process. In this case, SurfaceFlinger is the producer\nof buffers rather than the consumer.\n\nAfter the configuration is complete, `screenrecord` triggers when\nthe encoded data appears. As apps draw, their buffers travel to SurfaceFlinger,\nwhich composites them into a single buffer that's sent directly to the video\nencoder in the `mediaserver` process. The full frames are never\nseen by the `screenrecord` process. Internally, the\n`mediaserver` process has its own way of moving buffers around that\nalso passes data by handle, minimizing overhead.\n\nCase study: simulate secondary displays\n---------------------------------------\n\nThe WindowManager can ask SurfaceFlinger to create a visible layer for which\nSurfaceFlinger acts as the BufferQueue consumer. It's also possible to ask\nSurfaceFlinger to create a virtual display, for which SurfaceFlinger acts as\nthe BufferQueue producer.\n\nIf you connect a virtual display to a visible layer, a closed loop is created\nwhere the composited screen appears in a window. That window is now part of the\ncomposited output, so on the next refresh the composited image inside the window\nshows the window contents as well. To see this in action, enable\n[Developer options](https://developer.android.com/studio/debug/dev-options) in **Settings** , select\n**Simulate secondary displays** , and enable a window. To see\nsecondary displays in action, use `screenrecord` to capture the act\nof enabling the display then play it back frame by frame."]]