Tiện ích WindowManager

Thư viện Jetpack WindowManager cho phép nhà phát triển ứng dụng hỗ trợ các kiểu dáng thiết bị mới cũng như môi trường nhiều cửa sổ.

Tiện ích WindowManager (Extensions) là một mô-đun nền tảng Android không bắt buộc, cho phép sử dụng nhiều tính năng của Jetpack WindowManager. Mô-đun này được triển khai trong AOSP trong frameworks/base/libs/WindowManager/Jetpack và được vận chuyển trên các thiết bị hỗ trợ các tính năng của WindowManager.

Phân phối mô-đun tiện ích

Các tiện ích được biên dịch thành thư viện .jar và được đặt trong phân vùng system_ext trên thiết bị nếu bạn bật Tiện ích trong tệp makefile của thiết bị.

Để bật Tiện ích trên một thiết bị, hãy thêm nội dung sau vào tệp makefile của thiết bị sản phẩm:

$(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions.mk)

Thao tác này sẽ bật các gói androidx.window.extensionsandroidx.window.sidecar trên thiết bị và đặt thuộc tính persist.wm.extensions.enabled. Việc đưa các gói này vào tệp makefile cũng đặt các nội dung khai báo trong etc/permissions/, giúp các gói này có sẵn cho các quy trình ứng dụng. Thông thường, các mô-đun được tải vào và thực thi như một phần của quy trình ứng dụng trong thời gian chạy khi được thư viện Jetpack WindowManager sử dụng, giúp hoạt động tương tự như mã khung phía máy khách, như minh hoạ trong hình sau:

Hình 1. Tiện ích WindowManager được tải vào quy trình ứng dụng tương tự như mã nền tảng.

Mô-đun androidx.window.extensions là mô-đun Tiện ích hiện đang được phát triển tích cực. Mô-đun androidx.window.sidecar là một mô-đun cũ được đưa vào để tương thích với các phiên bản Jetpack WindowManager sớm nhất, nhưng sidecar không còn được duy trì nữa.

Hình sau đây cho thấy logic xác định việc sử dụng androidx.window.extensions hoặc androidx.window.sidecar.

Hình 2. Cây quyết định để truy cập vào androidx.window.extensions hoặc androidx.window.sidecar.

Mô-đun tiện ích

Tiện ích cung cấp các tính năng tạo cửa sổ cho thiết bị có màn hình lớn có thể gập lại và các thiết bị hỗ trợ tạo cửa sổ trên màn hình ngoài. Các khu vực tính năng bao gồm:

Việc triển khai Tiện ích của OEM có thể cung cấp các thành phần rỗng hoặc các thành phần có phương thức triển khai mặc định hoặc mô phỏng trong giao diện WindowExtensions nếu phần cứng thiết bị không hỗ trợ các tính năng tương ứng, trừ phi tính năng đó được yêu cầu cụ thể trong Tài liệu định nghĩa về khả năng tương thích (CDD) 7.1.1.1.

Tiện ích và API Jetpack

Mô-đun Tiện ích WindowManager cung cấp giao diện API riêng ngoài các API nền tảng công khai. Mô-đun Tiện ích được phát triển công khai trong thư viện Jetpack androidx.window.extensions không dành cho nhà phát triển để Jetpack WindowManager (androidx.window) có thể liên kết với mô-đun đó tại thời điểm biên dịch. Nền tảng API tiện ích thường cung cấp các API cấp thấp hơn.

Các API mà Tiện ích cung cấp chỉ dành cho thư viện Jetpack WindowManager. Các nhà phát triển ứng dụng không nên trực tiếp gọi API tiện ích. Bạn không được thêm thư viện Tiện ích làm phần phụ thuộc cho một ứng dụng trong tệp bản dựng Gradle để đảm bảo chức năng chính xác. Tránh biên dịch trước thư viện Tiện ích vào một ứng dụng; thay vào đó, hãy dựa vào tính năng tải thời gian chạy để tránh trường hợp tải kết hợp các lớp Tiện ích được biên dịch trước và do thời gian chạy cung cấp.

Jetpack WindowManager (androidx.window) được thêm vào dưới dạng phần phụ thuộc của ứng dụng và cung cấp các API dành cho nhà phát triển công khai, bao gồm cả các API cho các tính năng của Tiện ích WindowManager. Thư viện WindowManager tự động tải Tiện ích vào quy trình ứng dụng và gói các API Tiện ích cấp thấp vào các giao diện trừu tượng cấp cao hơn và tập trung hơn. API Jetpack WindowManager tuân theo các tiêu chuẩn phát triển ứng dụng Android hiện đại và nhằm cung cấp khả năng tương tác thuận tiện bằng cách tích hợp tốt với các cơ sở mã sử dụng các thư viện AndroidX khác.

Phiên bản và bản cập nhật tiện ích

Bạn có thể cập nhật mô-đun Tiện ích cùng với các bản cập nhật hằng năm hoặc hằng quý của nền tảng Android. Các bản cập nhật hằng quý cho phép tăng cấp độ API Tiện ích giữa các bản cập nhật API nền tảng Android, cho phép lặp lại nhanh hơn và mang đến cho OEM cơ hội thêm quyền truy cập API chính thức vào các tính năng mới gần với thời điểm ra mắt phần cứng.

Bảng sau đây liệt kê các phiên bản API androidx.window.extensions cho nhiều bản phát hành Android.

Phiên bản của Nền tảng Android Cấp độ API của Tiện ích WindowManager Phiên bản API androidx.window.extensions
Android 15 6 1.5.0 (sắp ra mắt)
Android 14 QPR3 5 1.4.0 (sắp ra mắt)
Android 14 QPR1 4 1.3.0
Android 14 3 1.2.0
Android 13 QPR3 2 1.1.0
Android 13 1 1.0.0
Android 12L 1 1.0.0

Cấp độ API của tiện ích (cột giữa) sẽ tăng lên mỗi khi có thêm một API ổn định hiện có (cột bên phải).

Khả năng tương thích ngược và tương thích chuyển tiếp

Jetpack WindowManager xử lý sự phức tạp của việc xử lý các bản cập nhật cấp độ API thường xuyên, quá trình phát triển API nhanh chóng và khả năng tương thích ngược. Khi mã thư viện được thực thi trong quá trình ứng dụng, thư viện sẽ kiểm tra cấp độ API Tiện ích đã khai báo và cấp quyền truy cập vào các tính năng theo cấp độ đã khai báo.

Để bảo vệ ứng dụng không gặp sự cố trong thời gian chạy, WindowManager cũng thực hiện một quy trình kiểm tra phản chiếu Java trong thời gian chạy của các API tiện ích có sẵn theo cấp độ API tiện ích đã khai báo. Nếu có sự không khớp, WindowManager có thể tắt việc sử dụng Tiện ích (một phần hoặc hoàn toàn) và báo cáo các tính năng liên quan là không có sẵn cho ứng dụng.

Tiện ích WindowManager được triển khai dưới dạng mô-đun system_ext sử dụng các API nền tảng riêng tư để gọi vào lõi WindowManager, DeviceStateManager và các dịch vụ hệ thống khác trong quá trình triển khai các tính năng của Tiện ích.

Khả năng tương thích có thể không được duy trì với các phiên bản Tiện ích phát hành trước bản phát hành nền tảng Android hằng quý hoặc hằng năm tương ứng với các phiên bản đã hoàn thiện. Bạn có thể tìm thấy toàn bộ nhật ký của API Tiện ích trong các tệp văn bản API window:extensions:extensions của nhánh phát hành.

Các phiên bản Tiện ích mới hơn phải tiếp tục hoạt động với các phiên bản WindowManager cũ được biên dịch vào ứng dụng để duy trì khả năng tương thích chuyển tiếp. Để đảm bảo điều này, mọi phiên bản mới của API Tiện ích chỉ thêm các API mới và không xoá các API cũ. Do đó, các ứng dụng có phiên bản WindowManager cũ có thể tiếp tục sử dụng các API tiện ích cũ mà ứng dụng được biên dịch.

Quy trình xác minh CTS đảm bảo rằng đối với mọi phiên bản API tiện ích đã khai báo trên thiết bị, tất cả API cho phiên bản đó và các phiên bản trước đều có và hoạt động.

Hiệu suất

Theo mặc định, mô-đun Tiện ích được lưu vào bộ nhớ đệm trong trình tải lớp hệ thống không phải đường dẫn khởi động từ Android 14 (API cấp 34) trở đi, vì vậy, việc tải mô-đun vào bộ nhớ khi khởi động ứng dụng sẽ không ảnh hưởng đến hiệu suất. Việc sử dụng các tính năng mô-đun riêng lẻ có thể ảnh hưởng nhẹ đến các đặc điểm hiệu suất của ứng dụng khi các lệnh gọi IPC bổ sung được thực hiện giữa ứng dụng và máy chủ.

Mô-đun

Nhúng hoạt động

Thành phần nhúng hoạt động cho phép các ứng dụng tối ưu hoá giao diện người dùng cho các thiết bị màn hình lớn và màn hình ngoài. Tính năng nhúng hoạt động cho phép trình bày hai hoạt động cạnh nhau trong bố cục nhiều ngăn, tạo điều kiện cho việc phát triển ứng dụng thích ứng cho các ứng dụng cũ.

Thành phần nhúng hoạt động phải có trên tất cả các thiết bị có màn hình tích hợp bằng hoặc lớn hơn sw600dp. Bạn cũng phải bật tính năng nhúng hoạt động trên các thiết bị hỗ trợ kết nối màn hình ngoài, vì ứng dụng có thể hiển thị ở kích thước lớn hơn khi màn hình ngoài được kết nối trong thời gian chạy.

Cấu hình thiết bị

Bạn không cần phải định cấu hình thiết bị cụ thể nào ngoài việc bật mô-đun Tiện ích như mô tả trong phần Phân phối mô-đun Tiện ích. Bạn nên bật Tiện ích trên tất cả thiết bị hỗ trợ chế độ nhiều cửa sổ. Các phiên bản Android trong tương lai có thể yêu cầu Tiện ích trên các cấu hình thiết bị cầm tay và màn hình lớn phổ biến.

Thông tin về bố cục cửa sổ

Thành phần thông tin bố cục cửa sổ xác định vị trí và trạng thái của bản lề trên thiết bị có thể gập lại khi bản lề cắt ngang cửa sổ ứng dụng. Thông tin bố cục cửa sổ cho phép các ứng dụng phản hồi và hiển thị bố cục được tối ưu hoá ở chế độ trên mặt bàn trên thiết bị có thể gập lại. Hãy xem phần Giúp ứng dụng nhận biết chế độ gập để biết thông tin chi tiết về cách sử dụng.

Các thiết bị Android có thể gập lại có bản lề kết nối các khu vực bảng hiển thị riêng biệt hoặc liên tục phải cung cấp thông tin về bản lề cho các ứng dụng thông qua WindowLayoutComponent.

Vị trí và giới hạn bản lề phải được báo cáo tương ứng với cửa sổ ứng dụng được xác định bằng Context được truyền vào API. Nếu giới hạn cửa sổ ứng dụng không giao nhau với giới hạn bản lề, thì bạn không được báo cáo bản lề DisplayFeature. Bạn cũng có thể không báo cáo các tính năng hiển thị khi vị trí của các tính năng đó có thể không được báo cáo một cách đáng tin cậy, chẳng hạn như khi người dùng có thể tự do di chuyển cửa sổ ứng dụng ở chế độ nhiều cửa sổ hoặc chế độ hòm thư tương thích.

Đối với các tính năng gập, bạn phải báo cáo nội dung cập nhật trạng thái khi vị trí bản lề thay đổi giữa các trạng thái ổn định. Theo mặc định, ở trạng thái màn hình phẳng, API phải báo cáo FoldingFeature.State.FLAT. Nếu phần cứng của thiết bị có thể được để ở chế độ gập một nửa ở trạng thái ổn định, thì API phải báo cáo FoldingFeature.State.HALF_OPENED. Không có trạng thái đóng trong API, vì trong trường hợp như vậy, cửa sổ ứng dụng sẽ không hiển thị hoặc không vượt quá giới hạn bản lề.

Cấu hình thiết bị

Để hỗ trợ việc triển khai tính năng gập, nhà sản xuất thiết bị gốc (OEM) phải làm như sau:

  • Định cấu hình trạng thái thiết bị trong device_state_configuration.xml để DeviceStateManagerService sử dụng. Hãy xem DeviceStateProviderImpl.java để tham khảo.

    Nếu các phương thức triển khai mặc định của DeviceStateProvider hoặc DeviceStatePolicy không phù hợp với thiết bị, bạn có thể sử dụng phương thức triển khai tuỳ chỉnh.

  • Bật mô-đun Tiện ích như mô tả trong phần Phân phối mô-đun Tiện ích.

  • Chỉ định vị trí của các tính năng hiển thị trong tài nguyên chuỗi com.android.internal.R.string.config_display_features (thường là trong frameworks/base/core/res/res/values/config.xml trong lớp phủ thiết bị).

    Định dạng dự kiến cho chuỗi này là:

    <type>-[<left>,<top>,<right>,<bottom>]

    type có thể là fold hoặc hinge. Giá trị của left, top, rightbottom là toạ độ pixel số nguyên trong không gian toạ độ màn hình theo hướng hiển thị tự nhiên. Chuỗi cấu hình có thể chứa nhiều tính năng hiển thị được phân tách bằng dấu chấm phẩy.

    Ví dụ:

    <!-- Jetpack WindowManager display features -->
    <string name="config_display_features" translatable="false">fold-[1000,0,1000,2000]</string>
    
  • Xác định mối liên kết giữa giá trị nhận dạng trạng thái thiết bị nội bộ được sử dụng trong DeviceStateManager và hằng số trạng thái công khai được gửi đến nhà phát triển trong com.android.internal.R.array.config_device_state_postures.

    Định dạng dự kiến cho mỗi mục nhập là:

    <device_specific_state_identifier>:<Jetpack WindowManager state identifier>

    Các giá trị nhận dạng trạng thái được hỗ trợ là:

    • COMMON_STATE_NO_FOLDING_FEATURES = 1: Trạng thái không có tính năng gập để báo cáo. Ví dụ: trạng thái đóng của thiết bị gập thông thường có màn hình chính ở bên trong.
    • COMMON_STATE_HALF_OPENED = 2: Tính năng gập đang mở một nửa.
    • COMMON_STATE_FLAT = 3: Tính năng gập phẳng. Ví dụ: trạng thái này có thể là trạng thái mở của thiết bị có thể gập lại thông thường với màn hình chính ở bên trong.
    • COMMON_STATE_USE_BASE_STATE = 1000: Trong Android 14, một giá trị có thể được dùng cho các trạng thái được mô phỏng, trong đó trạng thái bản lề được lấy từ trạng thái cơ sở, như được xác định trong CommonFoldingFeature.java

    Hãy xem DeviceStateManager.DeviceStateCallback#onBaseStateChanged(int) để biết thêm thông tin.

    Ví dụ:

    <!-- Map of System DeviceState supplied by DeviceStateManager to WindowManager posture.-->
    <string-array name="config_device_state_postures" translatable="false">
      <item>0:1</item>    <!-- CLOSED       : COMMON_STATE_NO_FOLDING_FEATURES -->
      <item>1:2</item>    <!-- HALF_OPENED  : COMMON_STATE_HALF_OPENED -->
      <item>2:3</item>    <!-- OPENED       : COMMON_STATE_FLAT -->
      <item>3:1</item>    <!-- REAR_DISPLAY : COMMON_STATE_NO_FOLDING_FEATURES -->
      <item>4:1000</item> <!-- CONCURRENT   : COMMON_STATE_USE_BASE_STATE -->
    </string-array>
    

Diện tích cửa sổ

Thành phần khu vực cửa sổ cung cấp một bộ tính năng cho phép các ứng dụng truy cập vào các màn hình và khu vực hiển thị bổ sung trên một số thiết bị có thể gập lại và nhiều màn hình.

Chế độ màn hình sau cho phép ứng dụng hiển thị giao diện người dùng xem trước của máy ảnh trên màn hình ngoài của thiết bị có thể gập lại để cho phép sử dụng camera chính của thiết bị để chụp ảnh chân dung tự chụp và quay video. Các thiết bị có màn hình bao phủ tương thích với Android (theo định nghĩa của CDD Android về các thuộc tính như kích thước, mật độ và các tính năng điều hướng có sẵn) căn chỉnh với máy ảnh sau của thiết bị phải cung cấp quyền truy cập vào chế độ màn hình sau.

Trên Android 14, chế độ màn hình đôi cho phép các ứng dụng chạy trên màn hình trong của thiết bị có thể gập lại hiển thị nội dung bổ sung trên màn hình ngoài hướng đến người dùng khác; ví dụ: màn hình ngoài có thể hiển thị bản xem trước của máy ảnh cho người đang được chụp ảnh hoặc quay video.

Cấu hình thiết bị

Để hỗ trợ việc triển khai tính năng gập, nhà sản xuất thiết bị gốc (OEM) phải làm như sau:

  • Định cấu hình trạng thái thiết bị trong device_state_configuration.xml để DeviceStateManagerService sử dụng. Vui lòng xem DeviceStateProviderImpl.java để biết thêm thông tin.

    Nếu cách triển khai mặc định của DeviceStateProvider hoặc DeviceStatePolicy không phù hợp với thiết bị, bạn có thể sử dụng cách triển khai tuỳ chỉnh.

  • Đối với các thiết bị có thể gập lại hỗ trợ chế độ mở hoặc chế độ phẳng, hãy chỉ định giá trị nhận dạng trạng thái tương ứng trong com.android.internal.R.array.config_openDeviceStates.

  • Đối với các thiết bị có thể gập lại hỗ trợ trạng thái gập, hãy liệt kê các giá trị nhận dạng trạng thái tương ứng trong com.android.internal.R.array.config_foldedDeviceStates.

  • Đối với các thiết bị có thể gập lại hỗ trợ trạng thái gập một nửa (bản lề mở một nửa như máy tính xách tay), hãy liệt kê các trạng thái tương ứng trong com.android.internal.R.array.config_halfFoldedDeviceStates.

  • Đối với các thiết bị hỗ trợ chế độ màn hình sau:

    • Liệt kê các trạng thái tương ứng trong com.android.internal.R.array.config_rearDisplayDeviceStates cho DeviceStateManager.
    • Chỉ định địa chỉ hiển thị thực tế của màn hình sau trong com.android.internal.R.string.config_rearDisplayPhysicalAddress.
    • Chỉ định giá trị nhận dạng trạng thái trong com.android.internal.R.integer.config_deviceStateRearDisplay để Tiện ích sử dụng.
    • Thêm giá trị nhận dạng trạng thái trong com.android.internal.R.array.config_deviceStatesAvailableForAppRequests để cung cấp cho các ứng dụng.
  • Trên Android 14, đối với các thiết bị hỗ trợ chế độ hiển thị kép (đồng thời):

    • Đặt com.android.internal.R.bool.config_supportsConcurrentInternalDisplays thành true.
    • Chỉ định địa chỉ hiển thị thực tế của màn hình sau trong com.android.internal.R.config_deviceStateConcurrentRearDisplay.
    • Chỉ định giá trị nhận dạng trạng thái trong com.android.internal.R.integer.config_deviceStateConcurrentRearDisplay để Tiện ích sử dụng nếu giá trị nhận dạng đó được cung cấp cho các ứng dụng.
    • Thêm giá trị nhận dạng trạng thái trong com.android.internal.R.array.config_deviceStatesAvailableForAppRequests để cung cấp cho các ứng dụng.

Xác minh

Nhà sản xuất thiết bị gốc (OEM) phải xác minh việc triển khai để đảm bảo hành vi dự kiến trong các trường hợp phổ biến. Các nhà sản xuất thiết bị gốc (OEM) có thể sử dụng các bài kiểm thử CTS và kiểm thử bằng Jetpack WindowManager để kiểm thử việc triển khai.

Kiểm thử CTS

Để chạy các bài kiểm thử CTS, hãy xem phần Chạy các bài kiểm thử CTS. Các kiểm thử CTS liên quan đến Jetpack WindowManager nằm trong cts/tests/framework/base/windowmanager/jetpack/. Tên mô-đun kiểm thử là CtsWindowManagerJetpackTestCases.

Kiểm thử WindowManager

Để tải các bài kiểm thử Jetpack WindowManager xuống, hãy làm theo Hướng dẫn về Android Jetpack. Các bài kiểm thử nằm trong thư viện cửa sổ trong mô-đun window:window: window/window/src/androidTest/.

Để chạy kiểm thử thiết bị cho mô-đun window:window qua dòng lệnh, hãy làm như sau:

  1. Cắm một thiết bị đã bật tuỳ chọn cho nhà phát triển và tính năng gỡ lỗi qua USB.
  2. Cho phép máy tính gỡ lỗi thiết bị.
  3. Mở một shell trong thư mục gốc của kho lưu trữ androidx.
  4. Thay đổi thư mục thành framework/support.
  5. Chạy lệnh sau: ./gradlew window:window:connectedAndroidTest.
  6. Phân tích kết quả.

Để chạy các chương trình kiểm thử từ Android Studio, hãy làm như sau:

  1. Mở Android Studio
  2. Cắm một thiết bị đã bật tuỳ chọn cho nhà phát triển và tính năng gỡ lỗi qua USB.
  3. Cho phép máy tính gỡ lỗi thiết bị.
  4. Chuyển đến một chương trình kiểm thử trong thư viện cửa sổ của mô-đun cửa sổ.
  5. Mở một lớp kiểm thử và chạy bằng các mũi tên màu xanh lục ở bên phải trình chỉnh sửa.

Ngoài ra, bạn có thể tạo một cấu hình trong Android Studio để chạy một phương thức kiểm thử, một lớp kiểm thử hoặc tất cả các kiểm thử trong một mô-đun.

Bạn có thể phân tích kết quả theo cách thủ công bằng cách xem kết quả của shell. Một số quy trình kiểm thử sẽ bị bỏ qua nếu thiết bị không đáp ứng một số giả định nhất định. Kết quả được lưu ở một vị trí tiêu chuẩn và các nhà phân tích có thể viết một tập lệnh để tự động phân tích kết quả.