ViewCapture는 연결된 창에 연결된 뷰의 속성 (예: 위치, 크기, 크기 조정, 공개 상태)을 캡처하는 소프트웨어 도구입니다. ViewCapture는 창 내의 다양한 뷰와 속성에 관한 정보를 캡처하여 특정 시점의 사용자 환경 상태를 파악하고 시간 경과에 따른 변경사항을 추적할 수 있도록 합니다.
화면 녹화는 특정 시점의 뷰 상태를 시각화하고 변경되는 방식을 보여줄 수 있지만 상당한 CPU 리소스를 요구하며 성능에 영향을 줄 수 있습니다. ViewCapture 도구는 리소스 영향을 덜 미치며 더 자주 사용 설정할 수 있습니다. 또한 ViewCapture는 뷰 수준에서 프레임별로 시각화를 표시하므로 화면 녹화와 비교하여 특정 순간의 뷰 상태를 더 간편하게 검사할 수 있습니다.
이 페이지에서는 시스템 앱에서 ViewCapture를 온보딩하는 방법을 설명합니다.
사용
ViewCapture.java
는 onDrawListener
의 인스턴스를 구현하고 그리기 프로세스 중에 ViewCapture 트레이스를 수집합니다. 각 프레임 다시 그리기는 창의 루트 뷰에서 시작하여 뷰 트리 계층 구조의 순회를 트리거합니다.
ViewCapture는 공개 View.java
getter 메서드를 사용하여 값을 가져와 백그라운드 스레드에 복사하여 성능을 개선합니다. ViewCapture 구현은 captureViewTree
를 사용하여 뷰가 더러워졌는지 또는 무효화되었는지 확인하여 이 프로세스를 최적화하므로 전체 뷰 계층 구조를 탐색하지 않아도 됩니다. captureViewTree
는 시스템 앱에서만 사용할 수 있으며 UnsupportedAppUsage API의 일부입니다.
이 API는 타겟 SDK 버전을 기반으로 하는 앱으로 제한됩니다.
제한사항
다음 섹션에서는 ViewCapture 실행의 성능 및 메모리 제한사항을 설명합니다.
성능
ViewCapture 성능의 평균 기본 스레드 오버헤드는 195μs입니다. 하지만 최악의 경우 약 5밀리초가 걸릴 수 있습니다. Perfetto 트레이스의 vc#onDraw
슬라이스를 참고하세요.
오버헤드 비용은 주로 다음 작업으로 인해 발생합니다.
- 계층 구조를 탐색하는 데는 잘라내기 후에도 50μs가 소요됩니다.
- 뷰 속성 사본을 저장하기 위해 사용 가능 목록 할당자에서 객체를 가져오는 데 20μs가 소요됩니다.
- getter 함수를 통해 각 속성 값을 가져오면 뷰당 많은 추가 함수 호출이 발생하여 110μs가 소요됩니다.
따라서 올웨이즈온 트레이스 (AOT)에서 ViewCapture를 사용 설정하면 시스템 성능에 부정적인 영향을 미치고 버벅거림이 발생합니다. 이러한 성능 및 메모리 제한으로 인해 이 접근 방식은 AOT에 적합하지 않습니다. 실험실 및 로컬 디버깅에만 ViewCapture를 사용하는 것이 좋습니다.
메모리
ViewCapture 트레이스를 위한 Perfetto의 메서드는 과도한 메모리 사용을 방지하기 위해 사전 정의된 메모리 공간이 있는 단일 링 버퍼를 사용합니다. 이 접근 방식은 각 창에 별도의 링 버퍼를 사용하지 않음으로써 과도한 메모리 소비를 방지하지만 각 프레임에 대해 Perfetto에 모든 상태의 전체 뷰 계층 구조를 저장하는 문제는 해결하지 못합니다. NexusLauncher와 같은 단일 창을 녹화하면 10MB 버퍼에 30초가 넘는 ViewCapture 데이터가 생성될 수 있습니다. 하지만 시스템 UI에서 30개가 넘는 창을 캡처하려면 더 큰 버퍼 또는 녹화 시간 창을 상당히 줄여야 합니다.
안내
시스템 앱에서 ViewCapture를 온보딩하려면 다음 안내를 따르세요.
런처 코드와 같이
Android.bp
파일에 종속 항목을 추가합니다.android_library { name: "YourLib", static_libs: [ ... "//frameworks/libs/systemui:view_capture", ... ], platform_apis: true, privileged: true, }
창을 만들 때 ViewCapture 인스턴스를 만듭니다. 예를 들면 다음과 같습니다.
예 1:
private SafeCloseable mViewCapture; @Override protected void onCreate(Bundle savedInstanceState) { ... mViewCapture = ViewCaptureFactory.getInstance(this).startCapture(getWindow()); }
예 2:
private SafeCloseable mViewCapture; @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (enableViewCaptureTracing()) { mViewCaptureCloseable = ViewCaptureFactory.getInstance(getContext()) .startCapture(getRootView(), ".NotificationShadeWindowView"); } ... }
다음 예와 같이 창을 소멸할 때 ViewCapture 인스턴스를 닫습니다.