ViewCapture 是一種軟體工具,可擷取附加至所連結視窗的檢視區塊屬性 (例如位置、大小、比例和可見性)。ViewCapture 會擷取視窗中各種檢視區塊的相關資訊和屬性,讓您瞭解特定時間點的使用者體驗狀態,並追蹤一段時間內的變化。
螢幕錄影功能可以顯示特定時間的檢視區塊狀態,以及狀態的變化情形,但會耗用大量 CPU 資源,可能影響效能。ViewCapture 工具對資源的影響較小,因此可以更頻繁地啟用。此外,ViewCapture 會在檢視區塊層級逐格顯示視覺化內容框架,因此相較於螢幕錄影,檢查特定時刻的檢視區塊狀態更直接。
本頁說明如何在系統應用程式中導入 ViewCapture。
使用
ViewCapture.java 會實作 onDrawListener 的執行個體,並在繪圖程序期間收集 ViewCapture 追蹤記錄。每次重繪影格時,系統都會從視窗的根層級檢視畫面開始,遍歷檢視區塊樹狀結構階層。ViewCapture 會使用公開 View.java getter 方法,擷取值並複製到背景執行緒,以提升效能。ViewCapture 實作項目會使用 captureViewTree 檢查檢視區塊是否髒污或失效,藉此避免遍歷整個檢視區塊階層,進而最佳化這個程序。captureViewTree 僅適用於系統應用程式,且屬於 UnsupportedAppUsage API。只有目標 SDK 版本符合條件的應用程式,才能使用這項 API。
限制
本節說明 ViewCapture 的效能和記憶體限制。
效能
ViewCapture 效能的平均主執行緒負荷為 195 微秒。不過,在最糟的情況下,可能需要約 5 毫秒。請參閱 Perfetto 追蹤記錄中的 vc#onDraw 切片。
主要造成額外費用的動作如下:
- 即使經過修剪,遍歷階層仍需 50 微秒。
- 從自由表分配器提取物件來儲存檢視區塊屬性副本的費用為 20 微秒。
- 透過 getter 函式擷取每個屬性值,會導致每個檢視區塊產生許多額外的函式呼叫,耗費 110 微秒。
因此,在永遠追蹤 (AOT) 模式中啟用 ViewCapture 會對系統效能造成負面影響,並導致抖動。由於這些效能和記憶體限制,這種方法還不適用於 AOT。建議只在實驗室和本機偵錯時使用 ViewCapture。
記憶體
Perfetto 的 ViewCapture 追蹤方法會使用單一環形緩衝區和預先定義的記憶體用量,避免記憶體用量過高。這種做法可避免為每個視窗建立個別的環形緩衝區,進而防止記憶體耗用過多。不過,這無法解決在每個影格的 Perfetto 中,儲存每個狀態的完整檢視區塊階層的問題。錄製單一視窗 (例如 NexusLauncher) 時,10 MB 的緩衝區可能會產生超過 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 執行個體: 
