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 函式擷取每個屬性值,會導致每個 View 需要額外呼叫許多函式,耗時 110 微秒。
因此,在 AOT 中啟用 ViewCapture 會對系統效能造成負面影響,並導致卡頓。由於這些效能和記憶體限制,這項做法尚未準備好採用 AOT。我們建議您只在實驗室和本機偵錯時使用 ViewCapture。
記憶體
Perfetto 的 ViewCapture 追蹤記錄方法會使用單一環形緩衝區,該緩衝區具有預先定義的記憶體占用空間,可避免過度使用記憶體。這種做法可避免為每個視窗使用個別的環緩衝區,進而避免過度耗用記憶體,但無法解決在每個影格中,為每個狀態在 Perfetto 中儲存整個檢視區塊階層的問題。錄製單一視窗 (例如 NexusLauncher) 時,可在 10 MB 緩衝區中產生超過 30 秒的 ViewCapture 資料。不過,從系統使用者介面擷取超過 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 例項,如以下範例所示: