Winscope를 사용하여 창 전환을 추적하세요.

Winscope는 애니메이션 및 전환 중과 후에 여러 시스템 서비스의 상태를 기록, 재생, 분석할 수 있는 웹 도구입니다. Winscope는 이와 관련된 모든 시스템 서비스 상태를 트레이스 파일로 기록합니다. 트레이스 파일과 함께 Winscope UI를 사용하면 전환을 재생, 단계별로 실행, 디버그하여 화면 녹화가 있든 없든 각 애니메이션 프레임의 이러한 서비스 상태를 검사할 수 있습니다.

지원되는 트레이스

Winscope는 다양한 트레이스(시스템 서비스 상태의 시퀀스)를 수집하고 시각적으로 나타내는 기능을 제공합니다. 오버헤드가 낮은 것부터 세부정보가 많은 것까지 특정 사용 사례에 맞게 이러한 트레이스를 구성할 수 있습니다. Winscope는 다음 트레이스를 지원합니다.

  • EventLog: EventLog를 사용하여 시스템 진단 이벤트 레코드를 수집합니다. Winscope에서 이 정보는 CUJ 표시를 식별하고 표시하는 데만 사용됩니다.
  • IME: IMS, IMMS, IME 클라이언트를 비롯한 입력 방식 편집기 (IME) 파이프라인의 트레이스 이벤트를 추적합니다.
  • Input: 입력 이벤트 파이프라인의 여러 부분에서 입력 이벤트를 추적합니다.
  • ProtoLog: 클라이언트 프로세스에서 실행되는 시스템 서비스 및 시스템 서비스의 코드에서 ProtoLog 메시지를 수집합니다.
  • Screen recording: 트레이스와 함께 화면 녹화를 수집합니다.
  • Shell transitions: 창 및 활동 전환 시스템 세부정보를 기록합니다.
  • SurfaceFlinger: 위치, 버퍼, 조합과 같은 노출 영역 (레이어)에 관한 정보가 포함된 SurfaceFlinger 트레이스를 수집합니다.
  • 트랜잭션: 조합을 위해 SurfaceFlinger에서 수신한 원자적 변경사항 집합을 추적합니다. SurfaceControl 사용
  • ViewCapture: 시스템 UI 및 런처와 같이 ViewCapture를 지원하는 시스템 창의 모든 뷰에서 속성 범위를 캡처합니다.
  • 창 관리자: 입력 및 포커스 이벤트, 화면 방향, 전환, 애니메이션, 위치 지정, 변환을 비롯한 창과 관련된 세부정보가 포함된 창 관리자 상태를 추적합니다.

지원되는 덤프

Winscope는 사용자가 정의한 특정 시점에 가져온 기기 상태의 스냅샷인 상태 덤프를 수집하고 표시할 수 있습니다. 기기 사용 중에 지속적으로 수집되어 성능에 영향을 줄 수 있는 트레이스와 달리 덤프는 성능과 세부정보가 손상되지 않도록 이러한 사용자 정의 시점에만 가져옵니다. 이를 통해 특정 시점에 기기 상태를 더 집중적이고 효율적으로 분석할 수 있습니다. Winscope는 다음 덤프를 지원합니다.

  • Window Manager: 단일 창 관리자 상태를 덤프합니다.
  • SurfaceFlinger: 단일 SurfaceFlinger 스냅샷을 덤프합니다.
  • Screenshot: 덤프와 함께 스크린샷을 수집합니다.

리소스

Winscope 빌드 및 실행에 관한 자세한 내용은 Winscope 실행을 참고하세요.

트레이스 수집에 관한 자세한 내용은 트레이스 캡처를 참고하세요.

Winscope 웹 UI를 사용하여 트레이스를 로드하는 방법에 관한 자세한 내용은 트레이스 로드를 참고하세요.

트레이스 분석에 관한 자세한 내용은 트레이스 분석을 참고하세요.

다음 예에서는 깜박임 테스트 실패와 사용자가 신고한 버그를 디버그하는 방법을 설명합니다.

깜박임 테스트 실패

이 예에서는 Winscope를 사용하여 깜박임 테스트 실패를 디버그하는 방법을 보여줍니다.

테스트 실패 검사

다음 단계에 따라 문제 유형을 확인하고 테스트 실패 메시지를 검사합니다.

  1. 테스트 및 클래스 이름을 검사하여 문제 유형을 확인합니다.

    테스트 및 클래스 이름:

    FlickerTestsNotification com.android.server.wm.flicker.notification.OpenAppFromLockscreenNotificationColdTest#appLayerBecomesVisible[ROTATION_0_GESTURAL_NAV]
    

    문제 유형:

    • CUJ는 잠금 화면 알림에서 앱을 실행하는 것을 나타냅니다(OpenAppFromLockscreenNotificationColdTest).
    • 테스트에서는 앱이 표시될 것으로 예상합니다 (#appLayerBecomesVisible).
  2. 테스트 실패 메시지를 검사합니다. 여기에는 다음을 비롯한 실패에 관한 포괄적인 정보가 제공됩니다.

    • 예상 결과와 실제 표시 결과 비교
    • 실패가 발생한 시점을 정확히 파악하는 데 도움이 되는 타임스탬프
    • 실패와 연결된 아티팩트 또는 파일의 이름
    • 실패를 이해하고 디버그하는 데 관련된 추가 컨텍스트 정보
    android.tools.flicker.subject.exceptions.IncorrectVisibilityException: com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity# should be visible
    
    Where?
        Timestamp(UNIX=2024-05-10T11:04:14.227572545(1715339054227572545ns), UPTIME=37m21s184ms79178ns(2241184079178ns), ELAPSED=0ns)
    
    What?
        Expected: com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity#
        Actual: [e636ecd com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity#3457: Buffer is empty, Visible region calculated by Composition Engine is empty, com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity#3458: Visible region calculated by Composition Engine is empty]
    
    Other information
        Artifact: FAIL__OpenAppFromLockscreenNotificationColdTest_ROTATION_0_GESTURAL_NAV.zip
    
    Check the test run artifacts for trace files
    
        at android.tools.flicker.subject.layers.LayerTraceEntrySubject.isVisible(LayerTraceEntrySubject.kt:187)
        at android.tools.flicker.subject.layers.LayersTraceSubject$isVisible$1$1.invoke(LayersTraceSubject.kt:151)
        at android.tools.flicker.subject.layers.LayersTraceSubject$isVisible$1$1.invoke(LayersTraceSubject.kt:150)
        at android.tools.flicker.assertions.NamedAssertion.invoke(NamedAssertion.kt:32)
        at android.tools.flicker.assertions.CompoundAssertion.invoke(CompoundAssertion.kt:42)
        at android.tools.flicker.assertions.AssertionsChecker.test(AssertionsChecker.kt:79)
        at android.tools.flicker.subject.FlickerTraceSubject.forAllEntries(FlickerTraceSubject.kt:59)
        at android.tools.flicker.assertions.AssertionDataFactory$createTraceAssertion$closedAssertion$1.invoke(AssertionDataFactory.kt:46)
        at android.tools.flicker.assertions.AssertionDataFactory$createTraceAssertion$closedAssertion$1.invoke(AssertionDataFactory.kt:43)
        at android.tools.flicker.assertions.AssertionDataImpl.checkAssertion(AssertionDataImpl.kt:33)
        at android.tools.flicker.assertions.ReaderAssertionRunner.doRunAssertion(ReaderAssertionRunner.kt:35)
        at android.tools.flicker.assertions.ReaderAssertionRunner.runAssertion(ReaderAssertionRunner.kt:29)
        at android.tools.flicker.assertions.BaseAssertionRunner.runAssertion(BaseAssertionRunner.kt:36)
        at android.tools.flicker.legacy.LegacyFlickerTest.doProcess(LegacyFlickerTest.kt:59)
        at android.tools.flicker.assertions.BaseFlickerTest.assertLayers(BaseFlickerTest.kt:89)
        at com.android.server.wm.flicker.notification.OpenAppTransition.appLayerBecomesVisible_coldStart(OpenAppTransition.kt:51)
        at com.android.server.wm.flicker.notification.OpenAppFromNotificationColdTest.appLayerBecomesVisible(OpenAppFromNotificationColdTest.kt:64)
    

    이 출력 샘플은 다음을 나타냅니다.

    • 문제는 2024-05-10T11:04:14.227572545에 발생합니다.
    • NotificationActivity가 표시될 것으로 예상되지만 표시되지 않습니다.
    • 디버깅을 위한 트레이스가 포함된 아티팩트 파일의 이름은 FAIL__OpenAppFromLockscreenNotificationColdTest_ROTATION_0_GESTURAL_NAV입니다.

디버그

다음 단계에 따라 깜박임의 원인을 확인합니다.

  1. 트레이스 파일을 다운로드하고 Winscope에 로드합니다. Winscope가 SurfaceFlinger가 자동으로 선택된 상태로 열립니다.

    SurfaceFlinger 뷰가 있는 Winscope 방문 페이지

    그림 1. SurfaceFlinger 뷰가 있는 Winscope 방문 페이지

  2. 예외 메시지의 타임스탬프를 복사하여 타임스탬프 필드에 붙여넣어 문제가 발생하는 타임스탬프로 이동합니다. 사람이 읽을 수 있는 형식의 타임스탬프(2024-05-10T11:04:14.227572545)를 복사하여 첫 번째 필드에 붙여넣거나 나노초 단위의 타임스탬프 (1715339054227572545ns)를 복사하여 두 번째 필드에 붙여넣을 수 있습니다.

    타임스탬프 대화상자

    그림 2. 타임스탬프 대화상자

  3. 왼쪽 화살표 키를 눌러 이전 프레임으로 이동합니다. 이 상태에서 NotificationActivity 앱이 동영상에 올바르게 표시되고 앱과 스플래시 화면 노출 영역이 모두 표시됩니다. 이는 3D 뷰의 녹색 직사각형과 계층 구조 요소의 V 칩으로 표시됩니다.

    앱 및 스플래시 화면 노출 영역 이름은 다음과 같습니다.

    com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity#3458`
    
    Splash Screen com.android.server.wm.flicker.testapp#3453
    

    이는 화면이 검은색으로 바뀌었을 때 앱이 실행 중이었고 스플래시 화면이 계속 표시되므로 이 이벤트가 앱 실행 중에 발생하고 있음을 나타냅니다.

    앱 실행 시

    그림 3. 앱 실행 시

  4. 오른쪽 화살표 키를 눌러 깜박임이 발생하는 다음 프레임으로 다시 이동합니다. 직사각형 뷰에서 앱 대신 화면에 NotificationShade가 표시됩니다. 이 프레임에는 다음 노출 영역이 표시됩니다.

    • 화면 장식 오버레이 (상단 및 하단)
    • 탐색 메뉴
    • 포인터 위치 (화면 녹화에서)

    플리커 활동

    그림 4. 깜박임 활동

  5. 계층 구조 뷰에서 앱 활동을 선택합니다. 찾을 수 없는 경우 V만 표시 를 선택 해제합니다. 그런 다음 속성 뷰를 검사합니다.

    앱 노출 영역 이름은 다음과 같습니다.

    com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity#3458`
    

    앱 속성

    그림 5. 앱 속성

    앱 활동이 표시되고 불투명하게 설정되어 있지만 조합 중에 다른 불투명 노출 영역이 앞에 배치되었기 때문에 Invisible due to: null visible region 오류로 인해 노출 영역이 표시되지 않습니다. 이 가설은 3D 뷰에서 `NotificationShade` 직사각형이 `NotificationActivity` 직사각형 앞에 있고 표시되는(녹색) `NotificationShade`가 선택된 레이어일 수 있다는 데서 비롯됩니다. 이 가설은 3D 뷰에서 NotificationShade 직사각형이 NotificationActivity 직사각형 앞에 있고 표시되는 (녹색) NotificationShade이 선택된 레이어일 수 있다는 점에서 비롯됩니다.

  6. 이 가설을 검증하려면 현재 프레임에서 보이는 NotificationShade 표면을 선택하고 해당 속성을 확인합니다. 플래그가 OPAQUE|ENABLE_BACKPRESSURE (0x102)로 설정되었습니다. NotificationShade 노출 영역 이름은 NotificationShade#3447입니다. 다음으로 왼쪽 화살표를 눌러 이전 프레임 (깜박임 전)으로 돌아가 NotificationShade 노출 영역의 속성을 다시 검사합니다. 이를 통해 앱 실행이 완전히 끝나기 전에 가 불투명해짐을 확인할 수 있습니다.OPAQUEENABLE_BACKPRESSURE (0x100) NotificationShade가 `NotificationActivity` 앞에 있으므로 앱이 표시되지 않습니다. NotificationShadeNotificationActivity 앞에 있으므로 앱이 표시되지 않습니다. 코드에서 NotificationShade가 너무 일찍 불투명해지는 이유를 파악합니다.

  7. 코드에서 NotificationShade가 너무 일찍 불투명해지는 이유를 파악합니다.

사용자가 신고한 버그는 자세한 정보가 없는 경우가 많으므로 디버그하기 어려울 수 있습니다.

특정 타임스탬프, 요소 세부정보, 화면 녹화를 제공하는 깜박임 테스트 실패와 달리 사용자가 신고한 버그에는 일반적으로 문제에 관한 간단한 설명만 포함됩니다. 사례 연구에서 제공되는 정보는 _분할 화면에서 앱을 다시 열 때 화면이 깜박임_ 이라는 제목과 _2024년 4월 18일 오후 3시 51분(GMT-04:00)_ 이라는 대략적인 타임스탬프뿐입니다.

다음 단계에 따라 사용자가 신고한 버그를 디버그합니다.

Winscope에 트레이스 파일을 로드합니다.

  1. Winscope가 SurfaceFlinger가 자동으로 선택된 상태로 열립니다. **그림 6.**

    SurfaceFlinger 뷰가 있는 Winscope 방문 페이지

    그림 6. SurfaceFlinger 뷰가 있는 Winscope 방문 페이지.

  2. 사용자가 보고한 대략적인 타임스탬프(이 경우 3:50 PM GMT-04:00)로 이동하려면 사람이 읽을 수 있는 타임스탬프 필드에 15:50:00를 입력합니다.

    타임스탬프 대화상자

    그림 7. 직사각형 뷰를 사용하여 화면에 그려진 항목을 식별합니다.

  3. 더 잘 보려면 _회전_ 슬라이더를 사용하여 직사각형 관점을 변경합니다. 더 나은 뷰를 보려면 회전 슬라이더를 사용하여 사각형 원근을 변경하세요. 계층 구조 보기에서 V만 표시플랫을 선택하면 배경화면, 화면 장식 오버레이, 레터박스, 런처, 연락처, 다이얼러 표면이 표시됩니다.

    런처: `com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#40602`

    • 런처: com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#40602
    • 연락처: com.google.android.contacts/com.android.contacts.activities.PeopleActivity#40565
    • 전화 걸기: com.google.android.dialer/com.google.android.dialer.extensions.GoogleDialtactsActivity#40564

    표시 가능성을 개선하려면 `ScreenDecorHwcOverlay#64` 노출 영역 옆에 있는 (![](/static/docs/core/graphics/images/visibility_icon.png))를 클릭하여 해당 직사각형을 숨기고 뒤에 있는 노출 영역을 표시합니다. 가시성을 개선하려면 ScreenDecorHwcOverlay#64 표면 옆에 있는 (공개 상태 아이콘) 을 클릭하여 해당 사각형을 숨기고 뒤에 있는 표면을 표시합니다. **그림 8.**

    사용자 보고서

    사용자 보고서 분할 화면 뷰에 관련된 노출 영역을 식별한 후 전환 트레이스를 사용하여 다양한 사용자 작업을 단계별로 실행하고 깜박임을 찾습니다.

  4. 분할 화면 보기에 어떤 화면이 포함되는지 확인한 후 전환 추적을 사용하여 다양한 사용자 작업을 단계별로 실행하고 깜박임을 찾습니다. 그림 9.

    전이

    전환 이 프레임 중에 재생된 전환은 파란색으로 강조 표시됩니다.

    이 경우 전환 플래그에는 `TRANSIT_FLAG_IS_RECENTS`가 포함되어 있으며 이는 사용자가 최근 항목 화면으로 이동하고 있음을 나타냅니다. 이 경우 전환 플래그에는 사용자가 최근 화면으로 진입하고 있음을 나타내는 TRANSIT_FLAG_IS_RECENTS가 포함됩니다.

  5. Dispatch Time 열 (이 경우 2024-04-18, 15:50:57.205)의 링크를 클릭하여 해당 시점으로 이동하고 Surface Flinger 탭에서 직사각형을 확인합니다. 오른쪽 화살표 키를 사용하여 전환 단계를 진행하고 사각형을 관찰하여 기기 상태의 정확성을 확인합니다.

    분할 화면 앱(분할선) 사이에 그려진 항목이 없으므로 배경화면이 이미 표시되어 있습니다. 한 프레임 전 (15:50:57.212)에는 배경화면이 표시되지 않고 분할선이 표시됩니다. 이는 애니메이션이 적용되지 않을 때 분할 화면이 표시되는 방식입니다. 한 프레임 전 (15:50:57.212)에는 배경화면이 보이지 않고 분할 화면이 애니메이션 효과 없이 표시됩니다.

    깜박임 전 화면

    깜박임 이벤트 전 화면 다음 전환을 확인하려면 타임라인을 직접 클릭합니다.

  6. 다음 전환을 확인하려면 타임라인을 직접 클릭하세요. 전환은 분홍색 블록 행으로 표시됩니다. **그림 11.**

    첫 번째 전환 종료

    첫 번째 전환 종료 다음 전환의 시작 위치에서 SurfaceFlinger 행을 클릭합니다.

    다음 전환의 시작 위치에서 SurfaceFlinger 행을 클릭합니다. 그림 11에서 커서의 수직 위치는 얇은 파란색 선으로 표시됩니다. 오른쪽 화살표 키로 전환을 단계별로 실행하여 깜박임이 발생하는지 확인합니다. 오른쪽 화살표 키를 사용하여 전환 단계를 진행하며 깜박임이 발생하는지 확인합니다. **참고:** 트레이스의 타임라인 행을 클릭하면 _활성_ 상태가 됩니다. 즉, 왼쪽 또는 오른쪽 화살표 키로 해당 트레이스의 항목에만 도달할 수 있습니다.

  7. 대신 다음 이미지의 커서로 표시된 대로 다음 더 긴 전환의 시작 위치에서 SurfaceFlinger 행의 타임라인을 클릭합니다. 대신 다음 이미지에서 커서로 표시된 것처럼 다음으로 더 긴 전환의 시작 위치에 있는 SurfaceFlinger 행의 타임라인을 클릭합니다.

    두 번째 전환 종료

    그림 12. 이 전환 중에 `15:51:13.239`에서 두 앱, 연락처, 다이얼러의 `스플래시 화면` 레이어가 디스플레이의 같은 쪽에 있음을 확인합니다.

    이 전환 중에 15:51:13.239에서 두 앱(연락처 및 전화 앱)의 Splash Screen 레이어가 디스플레이의 같은 쪽에 있는 것을 확인하세요.

    스플래시 화면

    그림 13. 잘못된 쪽에 있는 앱을 명확히 합니다.

  8. 나중에 이 프레임으로 다시 이동하는 데 도움이 되도록 **ns** 입력란 옆에 있는 플래그 아이콘을 클릭하여 현재 위치에 북마크를 추가합니다. 그림 14.

    북마크 추가

    그림 14. 타임라인을 직접 클릭하여 전환이 끝나는 프레임으로 이동합니다(예: `15:51:13.859`).

  9. 전환 끝에 있는 프레임으로 이동하려면 타임라인 을 직접 클릭하세요. 예를 들어 15:51:13.859로 이동합니다. **그림 15.**

    최종 화면 분할

    최종 분할 화면 타임라인에서 북마크의 플래그를 클릭하여 깜박임이 있는 프레임으로 돌아갑니다.

  10. **그림 16.**

    북마크 타임라인

    그림 16. 두 앱이 모두 오른쪽에 있으므로 다이얼러가 잘못된 위치에 있음을 나타냅니다.

    다이얼러의 스플래시 화면을 클릭하여 속성을 확인합니다.

  11. 선별된 **속성** 뷰에서 변환 속성을 구체적으로 살펴봅니다. 그림 17.

    변환 속성

    변환 속성 계산된 변환은 이 노출 영역에 적용되지만 이 수준에서는 설정되지 않습니다.

    계산된 열과 요청된 열의 값이 다르므로 변환이 상위 노출 영역에서 상속되고 있음을 나타냅니다. 계산된 열과 요청된 열의 값이 다릅니다. 이는 변환이 상위 노출 영역에서 상속되고 있음을 나타냅니다.

  12. 계층 구조 보기에서 플랫을 선택 해제하여 전체 계층 구조 트리를 표시하고, 앱 표면의 상위 노드로 이동하여 계산됨요청됨 변환이 모두 동일해질 때까지 이동합니다. 그러면 요청된 변환이 Surface(name=Task=7934)/@0x1941191_transition-leash#40670 표면에 표시됩니다.

  13. 제목 옆에 있는 아이콘을 클릭하여 선별된 속성을 접습니다. **그림 18.**

    선별된 속성을 접습니다.

    그림 18. **Proto Dump** 뷰에서 **차이점 표시** 를 선택하여 이 프레임에서 변경되는 속성을 강조 표시합니다.

  14. 이 프레임에서 변경되는 속성을 강조 표시하려면 Proto Dump 보기에서 Show diff를 선택합니다. **그림 19.** Type transform into the text search field to filter the properties:

    차이점 표시

    차이점 표시 변환은 이 프레임에서 `transition-leash`의 경우 `IDENTITY`에서 `SCALE|TRANSLATE|ROT_270`으로 설정됩니다.

    이 정보는 변환이 다이얼러 분할 화면 앱의 애니메이션 리드에 적용되었을 때 깜박임이 발생했음을 보여줍니다.IDENTITYSCALE|TRANSLATE|ROT_270transition-leash

    **그림 20.**

    깜박임 식별

    그림 20. 코드에서 이 변환이 분할 화면 전환 리드로 설정되는 이유를 파악합니다.

  15. 이 변환이 분할 화면 전환 리드로 설정된 이유를 코드에서 확인합니다.