ViewCapture trong ứng dụng hệ thống

ViewCapture là một công cụ phần mềm ghi lại các thuộc tính của thành phần hiển thị (chẳng hạn như vị trí, kích thước, tỷ lệ và chế độ hiển thị) được đính kèm vào các cửa sổ mà công cụ này được nối vào. ViewCapture ghi lại thông tin về các thành phần hiển thị trong một cửa sổ và các thuộc tính của các thành phần hiển thị đó, cho bạn biết trạng thái của trải nghiệm người dùng tại các thời điểm cụ thể và theo dõi các thay đổi theo thời gian.

Bản ghi màn hình có thể trực quan hoá trạng thái của một thành phần hiển thị tại một thời điểm cụ thể và cho thấy cách trạng thái đó thay đổi, nhưng các bản ghi này đòi hỏi tài nguyên CPU đáng kể và có thể ảnh hưởng đến hiệu suất. Công cụ ViewCapture có ít tác động hơn đến tài nguyên và có thể được bật thường xuyên hơn. Ngoài ra, ViewCapture hiển thị hình ảnh trực quan theo từng khung hình ở cấp chế độ xem, giúp bạn dễ dàng kiểm tra trạng thái chế độ xem tại những thời điểm cụ thể hơn so với bản ghi màn hình.

Trang này mô tả cách sử dụng ViewCapture trong các ứng dụng hệ thống.

Mục đích sử dụng

ViewCapture.java triển khai một thực thể của onDrawListener và thu thập dấu vết ViewCapture trong quá trình vẽ. Mỗi lần vẽ lại khung sẽ kích hoạt một quá trình duyệt qua hệ phân cấp cây thành phần hiển thị bắt đầu từ thành phần hiển thị gốc của cửa sổ. ViewCapture sử dụng các phương thức getter View.java công khai để tìm nạp và sao chép các giá trị vào luồng trong nền nhằm cải thiện hiệu suất. Việc triển khai ViewCapture tối ưu hoá quy trình này bằng cách kiểm tra xem một thành phần hiển thị có bị bẩn hoặc không hợp lệ hay không bằng cách sử dụng captureViewTree, nhờ đó tránh được việc duyệt qua toàn bộ hệ phân cấp thành phần hiển thị. captureViewTree chỉ dành cho các ứng dụng hệ thống và là một phần của API UnsupportedAppUsage. Việc sử dụng API này chỉ giới hạn ở các ứng dụng dựa trên phiên bản SDK mục tiêu của ứng dụng.

Các điểm hạn chế

Các phần sau đây mô tả các giới hạn về hiệu suất và bộ nhớ khi chạy ViewCapture.

Hiệu suất

Mức hao tổn trung bình của luồng chính đối với hiệu suất ViewCapture là 195 μs. Tuy nhiên, trong trường hợp xấu nhất, quá trình này có thể mất khoảng 5 mili giây. Hãy tham khảo lát cắt vc#onDraw trong dấu vết Perfetto.

Chi phí hao tổn chủ yếu là do các hành động sau:

  1. Việc duyệt qua hệ phân cấp mất 50 μs, ngay cả khi đã được cắt bớt.
  2. Việc kéo các đối tượng từ trình phân bổ danh sách tự do để lưu trữ bản sao của các thuộc tính thành phần hiển thị sẽ mất 20 μs.
  3. Việc tìm nạp từng giá trị thuộc tính thông qua hàm getter sẽ dẫn đến nhiều lệnh gọi hàm bổ sung trên mỗi thành phần hiển thị, tốn 110 μs.

Do đó, việc bật ViewCapture ở chế độ luôn theo dõi (AOT) sẽ ảnh hưởng tiêu cực đến hiệu suất của hệ thống và dẫn đến hiện tượng giật. Do những giới hạn về hiệu suất và bộ nhớ này, phương pháp này chưa sẵn sàng cho AOT. Bạn chỉ nên sử dụng ViewCapture cho phòng thí nghiệm và gỡ lỗi cục bộ.

Bộ nhớ

Phương thức của Perfetto cho các dấu vết ViewCapture sử dụng một bộ đệm vòng duy nhất, có mức sử dụng bộ nhớ được xác định trước để ngăn việc sử dụng bộ nhớ quá mức. Phương pháp này ngăn việc tiêu thụ quá nhiều bộ nhớ bằng cách tránh sử dụng vùng đệm vòng riêng biệt cho mỗi cửa sổ, nhưng không giải quyết được vấn đề lưu trữ toàn bộ hệ phân cấp chế độ xem cho mọi trạng thái trong Perfetto cho mỗi khung. Việc ghi một cửa sổ duy nhất, chẳng hạn như NexusLauncher, có thể tạo ra hơn 30 giây dữ liệu ViewCapture trong bộ đệm 10 MB. Tuy nhiên, việc chụp hơn 30 cửa sổ từ giao diện người dùng hệ thống cần có bộ đệm lớn hơn hoặc khoảng thời gian ghi ngắn hơn đáng kể.

Hướng dẫn

Hãy làm theo các hướng dẫn sau để sử dụng ViewCapture trong các ứng dụng hệ thống:

  1. Thêm phần phụ thuộc vào tệp Android.bp, như trong Mã trình chạy.

    android_library {
        name: "YourLib",
        static_libs: [
              ...
            "//frameworks/libs/systemui:view_capture",
              ...
        ],
        platform_apis: true,
        privileged: true,
    }
    
  2. Tạo một thực thể ViewCapture khi tạo cửa sổ, ví dụ:

    • Ví dụ 1:

      private SafeCloseable mViewCapture;
      
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        ...
        mViewCapture = ViewCaptureFactory.getInstance(this).startCapture(getWindow());
      }
      
    • Ví dụ 2:

      private SafeCloseable mViewCapture;
      
      @Override
      protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (enableViewCaptureTracing()) {
            mViewCaptureCloseable = ViewCaptureFactory.getInstance(getContext())
              .startCapture(getRootView(), ".NotificationShadeWindowView");
        }
        ...
      }
      
  3. Đóng thực thể ViewCapture khi huỷ bỏ cửa sổ, như trong các ví dụ sau:

    • Ví dụ 1:

      @Override
      public void onDestroy() {
        ...
        if (mViewCapture != null) mViewCapture.close();
      }
      
    • Ví dụ 2:

      @Override
      protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mViewCaptureCloseable != null) {
            mViewCaptureCloseable.close();
       }
        ...
      }