여러 화면 재생 빈도

Android 11에서는 여러 화면 재생 빈도의 기기 지원을 추가했습니다. 이 기능에는 세 가지 기본 구성요소가 있습니다.

  • android.hardware.graphics.composer@2.4에 도입된 새로운 HAL API
  • 다양한 새로고침 빈도의 기기 설정을 파싱하고 원하는 새로고침 빈도를 설정하는 플랫폼 코드
  • 앱이 원하는 프레임 속도를 설정할 수 있는 새로운 SDK 및 NDK API

구현

새로고침 빈도 전환을 위한 전용 지원이 android.hardware.graphics.composer@2.4 HAL에 추가되었습니다. 이전 버전의 컴포저 HAL에서는 새로고침 빈도 전환을 제한적으로 지원하므로, 이 버전을 사용하는 것이 좋습니다.

구성 적용 그룹

getDisplayAttribute_2_4 API를 사용하여 쿼리할 수 있는 IComposerClient::Attribute에 새 속성 CONFIG_GROUP이 추가되었습니다. 공급업체는 이 속성을 통해 디스플레이 구성을 그룹화할 수 있습니다. 동일한 그룹의 구성을 사용하면 대부분의 경우 원활한 전환이 가능합니다. 구성 적용 그룹은 구성의 다른 속성이 아닌 새로고침 빈도를 전환하기 위해 플랫폼에서 전환할 수 있는 구성을 구분하는 데 사용합니다.

다음 예를 통해 4가지 디스플레이 구성을 지원하는 기기에서 구성 적용 그룹을 사용하는 이점을 살펴보겠습니다.

  • 1080p@60Hz
  • 1080p@90Hz
  • 1080i@72Hz
  • 1080i@48Hz

기기가 48Hz, 60Hz, 72Hz, 90Hz 새로고침 빈도를 지원하더라도 디스플레이는 다른 모드로 작동하고 60Hz에서 72Hz로 전환하면 디스플레이 구성이 1080p에서 1080i로 변경되며 이러한 변경은 의도한 동작이 아닐 수도 있습니다. 이 문제는 구성 적용 그룹을 사용하여 해결합니다. 60Hz와 90Hz를 하나의 구성 적용 그룹에 그룹화하고 48Hz와 72Hz를 다른 구성 적용 그룹에 그룹화하면 됩니다. 플랫폼은 60Hz와 90Hz 간, 그리고 48Hz와 72Hz 간에 전환할 수 있지만 60Hz와 72Hz 간에 전환할 수 없음을 인지합니다. 60Hz와 72Hz 간 전환의 경우 새로고침 빈도를 변경하는 것이 아니라 구성 변경이 발생하기 때문입니다.

Composer API 업데이트

getDisplayVsyncPeriod
새로고침 빈도를 변경할 때 제어와 예측 가능성을 향상하기 위해 getDisplayVsyncPeriod 를 추가했습니다. getDisplayVsyncPeriod는 현재 디스플레이가 작동하는 새로고침 빈도(vsync 기간)를 반환합니다. 새로고침 빈도와 현재 새로고침 빈도 간에 전환하는 경우 플랫폼에서 다음 프레임을 시작할 시기를 결정하는 데 특히 유용합니다.
setActiveConfigWithConstraints
setActiveConfigWithConstraints 메서드는 기존 setActiveConfig 메서드를 새롭게 확장한 것으로, 구성 변경에 관한 추가 정보를 제공합니다. 제약조건은 vsyncPeriodChangeConstraints 매개변수의 일부로 지정되며 다음 매개변수를 포함합니다.
    desiredTimeNanos
    CLOCK_MONOTONIC의 시간으로, 이 시간 후에 vsync 기간이 변경될 수 있습니다(즉, 이 시간 전에는 vsync 기간이 변경되면 안 됨). 플랫폼이 새로고침 빈도 변경을 미리 계획하고자 하지만 큐에 이미 제공할 버퍼가 있는 경우에 유용합니다. 플랫폼은 이러한 버퍼를 감안하고 새로고침 빈도 전환이 최대한 원활하게 이루어지도록 적절하게 이 시간을 설정합니다.
    seamlessRequired
    true인 경우 vsync 기간 변경이 눈에 띄는 시각적 아티팩트 없이 원활하게 이루어져야 합니다. 이 플래그는 콘텐츠 변경(예: 기기가 유휴 상태일 때 애니메이션이 시작됨)으로 인해 새로고침 빈도를 변경해야 할 때 플랫폼에서 사용됩니다. 이러한 플래그 사용을 통해 공급업체는 눈에 띄는 시각적 아티팩트로 이어질 수 있는 특정 구성 변경을 허용하지 않을 수 있습니다. 구성을 원활하게 변경할 수 없는 경우 seamlessRequiredtrue로 설정되어 있으면 구현에서 반환 코드로 SEAMLESS_NOT_POSSIBLE을 반환하고 새로운 구성 변경을 원활하게 처리할 수 있을 때 새 onSeamlessPossible 콜백을 호출해야 합니다.

성공하는 경우 새로고침 빈도 변경이 발생할 예상 시점을 플랫폼에 알리는 VsyncPeriodChangeTimeline이 반환됩니다. newVsyncAppliedTimeNanos 매개변수는 새 디스플레이가 새 vsync 기간에서 새로고침되기 시작하는 CLOCK_MONOTONIC의 시간으로 설정해야 합니다. 이 매개변수를 desiredTimeNanos와 함께 사용하면 플랫폼에서 새로고침 빈도 전환을 미리 계획하고 앱에 새 새로고침 빈도를 적용할 시간을 계산하기 시작할 수 있습니다. 이렇게 하면 새로고침 빈도를 원활하게 전환할 수 있습니다.

일부 구현에서는 새로고침 빈도를 전송하기 전에 새로고침 프레임을 전송해야 합니다. 따라서 HAL에는 새로고침 프레임이 필요함을 나타내는 refreshRequired 매개변수와 새로고침 프레임을 전송해야 하는 기준이 되는 첫 번째 vsync를 나타내는 refreshTimeNanos 매개변수가 있습니다.

onVsyncPeriodTimingChanged [콜백]
타임라인의 일부 매개변수가 변경되었으며 플랫폼에서 타임라인을 조정해야 함을 나타내기 위해 HAL이 호출할 수 있는 새 콜백입니다. 어떤 이유로든 HAL의 오랜 처리 시간 또는 늦은 새로고침 프레임으로 인해 이전 타임라인이 누락된 경우 이 콜백을 호출해야 합니다.

플랫폼에서 새로고침 빈도를 변경하기로 결정하는 방법

새로고침 빈도 선택은 다음 두 가지 시스템 서비스에서 이루어집니다.

DisplayManager
DisplayManager는 새로고침 빈도와 관련된 최상위 정책을 설정합니다. 컴포저 HAL 구성과 동일한 기본 디스플레이 구성을 설정합니다. 또한 새로고침 빈도로 선택할 SurfaceFlinger의 최솟값과 최댓값 범위를 설정합니다.
SurfaceFlinger
기본 구성과 동일한 구성 적용 그룹에 있는 구성을 설정하고 최소/최대 범위 내의 새로고침 빈도를 사용하여 새로고침 빈도를 결정합니다.

디스플레이 관리자는 다음 단계에 따라 정책을 결정합니다.

  • SurfaceFlinger에서 활성 구성을 쿼리하여 기본 구성 ID 찾기
  • 시스템 조건을 반복하여 최소값과 최대값의 범위 제한
    • 기본 새로고침 빈도 설정: 기본 새로고침 빈도 값은 R.integer.config_defaultRefreshRate 구성 오버레이에서 설정됩니다. 이 값은 애니메이션 및 터치 상호작용과 관련하여 표준 기기 새로고침 빈도를 결정하는 데 사용됩니다.
    • 최대 새로고침 빈도 설정: 최대 새로고침 빈도 값은 Settings.System.PEAK_REFRESH_RATE에서 읽습니다. 이 값은 현재 기기 설정(예: 메뉴 옵션의 설정)을 반영하여 런타임에 변경됩니다. 기본값은 R.integer.config_defaultPeakRefreshRate 구성 오버레이에서 설정됩니다.
    • 최소 새로고침 빈도 설정: 최소 새로고침 빈도 값은 Settings.System.MIN_REFRESH_RATE에서 읽습니다. 이 값은 현재 기기 설정(예: 메뉴 옵션의 설정)을 반영하여 런타임에 변경될 수 있습니다. 기본값은 0이므로, 기본 최소값이 없습니다.
    • 애플리케이션에서 요청된 ModeId: 앱이 디스플레이가 작동하는 기본 구성을 반영하도록 WindowManager.LayoutParams.preferredDisplayModeId를 설정할 수 있습니다. 대부분의 조건에서 DisplayManager는 적절하게 기본 구성 ID를 설정하고 구성의 새로고침 빈도와 일치하도록 새로고침 빈도 최소값과 최대값을 설정합니다.
    • 절전 모드: 기기가 저전력 모드일 때 화면 재생 빈도는 60Hz 이하로 제한되고 Settings.Global.LOW_POWER_MODE.를 통해 표시됩니다.

DisplayManager가 정책을 설정하면 SurfaceFlinger는 활성 레이어(프레임 업데이트 대기열을 만드는 레이어)를 기반으로 새로고침 빈도를 설정합니다. 레이어 소유자가 프레임 속도를 설정하면 SurfaceFlinger는 프레임 속도의 배수인 새로고침 빈도를 설정하려고 시도합니다. 예를 들어 두 활성 레이어에서 프레임 속도를 24 및 60으로 설정했다면 SurfaceFlinger는 사용 가능한 경우 120Hz를 선택합니다. 이러한 새로고침 빈도를 사용할 수 없는 경우에는 SurfaceFlinger가 프레임 속도에 최소한의 오류가 있는 새로고침 빈도를 선택합니다. 자세한 내용은 developer.android.com의 개발자 문서를 참고하세요.

SurfaceFlinger는 다음 플래그를 유지관리하여 새로고침 빈도가 결정되는 방식을 제어합니다.

  • ro.surface_flinger.use_content_detection_for_refresh_rate: 설정하는 경우 프레임 속도가 설정되지 않은 경우에도 새로고침 빈도는 활성 레이어에 따라 결정됩니다. SurfaceFlinger는 버퍼에 연결된 프레젠테이션 타임스탬프를 확인하여 레이어가 버퍼를 게시하는 평균 fps를 찾는 휴리스틱을 유지관리합니다.
  • ro.surface_flinger.set_touch_timer_ms: 0보다 큰 경우, 구성된 제한 시간 내에 사용자가 화면을 터치하면 기본 새로고침 빈도가 사용됩니다. 이 휴리스틱은 처리되어 애니메이션의 기본 새로고침 빈도를 준비합니다.
  • ro.surface_flinger.set_idle_timer_ms: 0보다 큰 경우, 구성 제한 시간 동안 화면 업데이트가 없으면 최소 새로고침 빈도가 사용됩니다.
  • ro.surface_flinger.set_display_power_timer_ms: 0보다 큰 경우, 구성된 제한 시간 내에 디스플레이를 켜거나 AOD에서 벗어나면 기본 새로고침 빈도가 사용됩니다.

프레임 속도 API

프레임 속도 API는 Android 11을 타겟팅하는 앱에 사용할 수 있으며 앱은 이 API를 사용하여 의도한 프레임 속도를 Android 플랫폼에 알릴 수 있습니다. 프레임 속도 API에 관해 자세히 알아보려면 developer.android.com에서 개발자 문서를 참고하세요.

개발자 옵션

현재 새로고침 빈도로 디스플레이의 오버레이를 전환하는 새로운 개발자 옵션이 메뉴에 추가되었습니다. 새로운 옵션은 설정 > 시스템 > 개발자 옵션 > 새로고침 빈도 보기에 있습니다.