Tiện ích WindowManager

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

Tiện ích WindowManager (Tiện ích) 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 (Dự án nguồn mở Android) ở 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 WindowManager.

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

Các tiện ích được biên dịch vào thư viện .jar và đặt vào phân vùng system_ext trên thiết bị nếu Tiện ích được bật 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 đoạn mã sau vào tệp makefile trên thiết bị của 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 sẽ đặt nội dung khai báo trong etc/permissions/, giúp các quy trình xử lý ứng dụng có thể sử dụng các gói này. 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. Các tiện ích WindowManager được tải vào quy trình của ứ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ũ đi kèm để tương thích với các phiên bản Jetpack WindowManager cũ nhất, nhưng tệp trợ giúp không còn được duy trì tích cực 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 tính năng tạo cửa sổ cho các thiết bị có thể gập lại có màn hình lớn và các thiết bị hỗ trợ 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 này 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. Nhà phát triển ứng dụng không gọi trực tiếp 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 ứng dụng trong tệp bản dựng Gradle để đảm bảo chức năng hoạt động chính xác. Tránh biên dịch trước trực tiếp 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 trong thời gian chạy để ngăn 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 hiệu quả với các cơ sở mã sử dụng các thư viện AndroidX khác.

Các phiên bản và bản cập nhật của tiện ích

Mô-đun Tiện ích có thể được cập nhật 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. Bản cập nhật hằng quý cho phép tăng cấp độ API Extensions giữa các bản cập nhật API trên nền tảng Android, cho phép lặp lại nhanh hơn và cung cấp cho OEM (Nhà sản xuất thiết bị gốc) 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 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à tiến

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 ký, 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ệ một ứng dụng không gặp sự cố trong thời gian chạy, WindowManager cũng thực hiện hoạt động kiểm tra phản chiếu Java trong thời gian chạy của các API Tiện ích hiện có theo cấp độ API Tiện ích đã khai báo. Nếu thông tin không khớp, WindowManager có thể tắt việc sử dụng Tiện ích (một phần hoặc toàn bộ) và báo cáo các tính năng có liên quan là không được cung cấp cho ứng dụng.

Tiện ích WindowManager được triển khai dưới dạng một mô-đun system_ext sử dụng 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 Tiện ích.

Có thể không duy trì khả năng tương thích với các phiên bản phát hành trước của Tiện ích 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 mà các phiên bản được hoàn tất. Bạn có thể xem toàn bộ nhật ký của API Extensions trong tệp văn bản API window:extensions:extensions trong 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 Extensions đều chỉ thêm 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 mở rộng được lưu vào bộ nhớ đệm trong trình tải lớp hệ thống không phải-bootclasspath kể từ Android 14 (API cấp 34). Do đó, 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 riêng lẻ của mô-đun có thể ảnh hưởng đôi chút đến đặc điểm hiệu suất của ứng dụng khi thực hiện các lệnh gọi IPC khác 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 cung cấp một tập hợp các tính năng cho phép các ứng dụng sắp xếp bản trình bày cửa sổ hoạt động trong các giới hạn của ứng dụng mẹ. Điều này bao gồm việc hiển thị 2 hoạt động cùng lúc cạnh nhau trong một bố cục nhiều ngăn, hỗ trợ quá trình tối ưu hoá màn hình lớn cho các ứng dụng cũ.

Thành phần nhúng hoạt động phải có trên tất cả thiết bị có màn hình tích hợp có kích thước bằng hoặc lớn hơn sw600 dp. 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 bên ngoài, vì ứng dụng có thể hiển thị ở kích thước lớn hơn khi màn hình bên 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à thiết bị 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ề vượt qua một 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ế độ mặt bàn trên thiết bị có thể gập lại. Hãy xem bài viết 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í bản lề và giới hạn phải được báo cáo tương ứng với cửa sổ ứng dụng do Context truyền vào API xác định. 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 chú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 một cửa sổ ứng dụng ở chế độ nhiều cửa sổ hoặc chế độ hiệu ứng 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 các bản 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 sẽ không vượt quá giới hạn bản lề.

Cấu hình thiết bị

Để hỗ trợ triển khai tính năng gập, OEM (Nhà sản xuất thiết bị gốc) 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ị, thì 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 có trong frameworks/base/core/res/res/values/config.xml trong lớp phủ thiết bị).

    Định dạng đúng của chuỗi là:

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

    type có thể là fold hoặc hinge. Giá trị của left, top, rightbottom là các toạ độ pixel số nguyên trong không gian toạ độ hiển thị 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 hợp lệ của mỗi mục nhập là:

    <device_specific_state_identifier>:<Jetpack WindowManager state identifier>

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

    • 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 này có thể là trạng thái đóng của thiết bị gập thông thường với 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 có dạng phẳng. Ví dụ: đó có thể là trạng thái mở của thiết bị gập 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ể 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ư xác định trong CommonFoldingFeature.java

    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 máy ảnh 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 tương thích với Android (theo xác định của Android CDD về các thuộc tính như kích thước, mật độ và các thành phần điều hướng có sẵn) phù hợp với camera sau của thiết bị phải 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ợ triển khai tính năng gập, OEM (Nhà sản xuất thiết bị gốc) 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 để 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 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ị gập 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ị gập hỗ trợ trạng thái gập một nửa (bản lề được 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 ứ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. Nhà sản xuất thiết bị gốc (OEM) có thể sử dụng các chương trình kiểm thử và kiểm thử CTS sử dụ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 chương trình 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 dành cho 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 từ dòng lệnh, hãy làm như sau:

  1. Cắm một thiết bị đã bật các 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 các 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ả sẽ được lưu ở một vị trí tiêu chuẩn và nhà phân tích có thể viết một tập lệnh để tự động hoá việc phân tích kết quả.