Hỗ trợ trang trí hệ thống

Các bản cập nhật được thực hiện cho các khu vực dành riêng cho màn hình này được cung cấp bên dưới:

Trang trí hệ thống

Android 10 bổ sung hỗ trợ định cấu hình màn hình phụ để hiển thị một số trang trí hệ thống nhất định, chẳng hạn như hình nền, thanh điều hướng và trình khởi chạy. Theo mặc định, màn hình chính hiển thị tất cả các trang trí hệ thống và màn hình phụ hiển thị những trang trí được kích hoạt tùy chọn. Hỗ trợ cho Trình chỉnh sửa phương thức nhập (IME) có thể được đặt riêng biệt với các trang trí hệ thống khác.

Sử dụng DisplayWindowSettings#setShouldShowSystemDecorsLocked() để thêm hỗ trợ cho các trang trí hệ thống trên một màn hình cụ thể hoặc cung cấp giá trị mặc định trong /data/system/display_settings.xml . Ví dụ, hãy xem Cài đặt cửa sổ hiển thị .

Thực hiện

DisplayWindowSettings#setShouldShowSystemDecorsLocked() cũng được hiển thị trong WindowManager#setShouldShowSystemDecors() để thử nghiệm. Việc kích hoạt phương pháp này với mục đích cho phép hệ thống trang trí không thêm các cửa sổ trang trí đã bị thiếu trước đó hoặc loại bỏ chúng nếu chúng đã có trước đó. Trong hầu hết các trường hợp, việc thay đổi hỗ trợ trang trí hệ thống chỉ có hiệu lực sau khi thiết bị khởi động lại.

Kiểm tra sự hỗ trợ của trang trí hệ thống trong cơ sở mã WindowManager thường đi qua DisplayContent#supportsSystemDecorations() trong khi kiểm tra các dịch vụ bên ngoài (chẳng hạn như Giao diện người dùng hệ thống để kiểm tra xem thanh điều hướng có được hiển thị hay không) sử dụng WindowManager#shouldShowSystemDecors() . Để hiểu những gì được kiểm soát bởi cài đặt này, hãy khám phá các điểm gọi của các phương thức này.

Cửa sổ trang trí giao diện người dùng hệ thống

Android 10 chỉ thêm hỗ trợ cửa sổ trang trí hệ thống cho thanh điều hướng, vì thanh điều hướng rất cần thiết để điều hướng giữa các hoạt động và ứng dụng. Theo mặc định, thanh điều hướng hiển thị các khoản chi trả cho Back và Home. Điều này chỉ được bao gồm nếu màn hình đích hỗ trợ trang trí hệ thống (xem DisplayWindowSettings ).

Thanh trạng thái là một cửa sổ hệ thống phức tạp hơn, vì nó cũng chứa Bóng thông báo, Cài đặt nhanh và Màn hình khóa. Trong Android 10, thanh trạng thái không được hỗ trợ trên màn hình phụ. Do đó, các thông báo, cài đặt và khóa phím đầy đủ chỉ có sẵn trên màn hình chính.

Cửa sổ hệ thống Tổng quan / Gần đây không được hỗ trợ trên màn hình phụ. Trong Android 10, AOSP chỉ hiển thị Gần đây trên màn hình mặc định và chứa các hoạt động từ tất cả các màn hình. Khi khởi chạy từ Gần đây, theo mặc định, một hoạt động trên màn hình phụ sẽ được đưa lên phía trước trên màn hình đó. Cách tiếp cận này có một số vấn đề đã biết, chẳng hạn như không cập nhật ngay lập tức khi ứng dụng xuất hiện trên các màn hình khác.

Thực hiện

Để triển khai các tính năng bổ sung của Giao diện người dùng hệ thống, các nhà sản xuất thiết bị nên sử dụng một thành phần Giao diện người dùng hệ thống duy nhất để lắng nghe việc bổ sung / loại bỏ màn hình và trình bày nội dung phù hợp.

Thành phần Giao diện người dùng hệ thống hỗ trợ Đa hiển thị (MD) sẽ xử lý các trường hợp sau:

  • Khởi tạo nhiều màn hình khi khởi động
  • Hiển thị được thêm vào thời gian chạy
  • Hiển thị bị xóa trong thời gian chạy

Khi giao diện người dùng Hệ thống phát hiện việc bổ sung một màn hình trước WindowManager, nó sẽ tạo ra một điều kiện đua. Điều này có thể tránh được bằng cách triển khai một lệnh gọi lại tùy chỉnh từ WindowManager tới Giao diện người dùng hệ thống khi một màn hình được thêm vào thay vì đăng ký các sự kiện DisplayManager .DisplayListener . Để biết cách triển khai tham khảo, hãy xem CommandQueue.Callbacks#onDisplayReady để hỗ trợ thanh điều hướng và WallpaperManagerInternal#onDisplayReady cho hình nền.

Ngoài ra, Android 10 cung cấp các bản cập nhật sau:

  • Lớp NavigationBarController kiểm soát tất cả các chức năng cụ thể cho các thanh điều hướng.
  • Để xem thanh điều hướng tùy chỉnh, hãy xem CarStatusBar .
  • TYPE_NAVIGATION_BAR không còn bị giới hạn trong một phiên bản duy nhất và có thể được sử dụng trên mỗi màn hình.
  • IWindowManager#hasNavigationBar() được cập nhật để chỉ bao gồm tham số displayId cho Giao diện người dùng hệ thống.

Trình khởi chạy

Trong Android 10, mỗi màn hình được định cấu hình để hỗ trợ trang trí hệ thống có một ngăn xếp trang chủ dành riêng cho các hoạt động của trình khởi chạy với loại WindowConfiguration#ACTIVITY_TYPE_HOME , theo mặc định. Mỗi màn hình sử dụng một phiên bản hoạt động trình khởi chạy riêng biệt.

Hình 1. Ví dụ về trình khởi chạy đa hiển thị cho platform/development/samples/MultiDisplay

Hầu hết các trình khởi chạy hiện tại không hỗ trợ nhiều phiên bản và không được tối ưu hóa cho kích thước màn hình lớn. Ngoài ra, một loại trải nghiệm khác thường được mong đợi trên màn hình phụ / bên ngoài. Để cung cấp hoạt động dành riêng cho màn hình phụ, Android 10 giới thiệu danh mục SECONDARY_HOME trong bộ lọc ý định. Các phiên bản của hoạt động này được sử dụng trên tất cả các màn hình có hỗ trợ trang trí hệ thống, một bản cho mỗi màn hình.

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

Hoạt động phải có chế độ khởi chạy không ngăn chặn nhiều trường hợp và dự kiến ​​sẽ thích ứng với các kích thước màn hình khác nhau. Chế độ khởi chạy không được là singleInstance hoặc singleTask .

Thực hiện

Trong Android 10, RootActivityContainer#startHomeOnDisplay() tự động chọn thành phần và mục đích mong muốn tùy thuộc vào hiển thị nơi màn hình chính được khởi chạy. RootActivityContainer#resolveSecondaryHomeActivity() chứa logic để tra cứu thành phần hoạt động của trình khởi chạy tùy thuộc vào trình khởi chạy hiện được chọn và có thể sử dụng mặc định của hệ thống, nếu cần (xem ActivityTaskManagerService#getSecondaryHomeIntent() ).

Hạn chế bảo mật

Ngoài các hạn chế áp dụng cho các hoạt động trên màn hình phụ, để tránh khả năng một ứng dụng độc hại tạo ra màn hình ảo với trang trí Hệ thống được bật và đọc thông tin nhạy cảm của người dùng từ bề mặt, trình khởi chạy chỉ xuất hiện trên màn hình ảo do hệ thống sở hữu. Trình khởi chạy không hiển thị nội dung trên màn hình ảo không thuộc hệ thống.

Hình nền

Trong Android 10 (trở lên), hình nền được hỗ trợ trên màn hình phụ:

Hình 2. Hình nền động trên màn hình bên trong (bên trên) và bên ngoài (bên dưới)

Các nhà phát triển có thể tuyên bố hỗ trợ tính năng hình nền bằng cách cung cấp android:supportsMultipleDisplays="true" trong định nghĩa XML WallpaperInfo . Các nhà phát triển hình nền cũng dự kiến ​​sẽ tải nội dung bằng cách sử dụng ngữ cảnh hiển thị trong WallpaperService.Engine#getDisplayContext() .

Khung công tác tạo một phiên bản WallpaperService.Engine trên mỗi màn hình, vì vậy mỗi công cụ có bề mặt và bối cảnh hiển thị riêng. Nhà phát triển cần đảm bảo rằng mỗi công cụ có thể vẽ độc lập, ở các tốc độ khung hình khác nhau, tôn trọng VSYNC.

Chọn hình nền cho từng màn hình

Android 10 không cung cấp hỗ trợ nền tảng trực tiếp để chọn hình nền cho từng màn hình. Để thực hiện điều này, cần có mã nhận dạng màn hình ổn định để duy trì cài đặt hình nền trên mỗi màn hình. Display#getDisplayId() là động, vì vậy không có gì đảm bảo rằng màn hình vật lý sẽ có cùng một ID sau khi khởi động lại.

Tuy nhiên, Android 10 đã thêm DisplayInfo.mAddress , chứa các số nhận dạng ổn định cho màn hình vật lý và có thể được sử dụng để triển khai đầy đủ trong tương lai. Thật không may, đã quá muộn để triển khai logic cho Android 10. Giải pháp được đề xuất:

  1. Sử dụng API WallpaperManager để đặt hình nền.
  2. WallpaperManager được lấy từ một đối tượng Context và mỗi đối tượng Context có thông tin về hiển thị tương ứng ( Context#getDisplay()/getDisplayId() ). Do đó, bạn có thể lấy displayId từ một phiên bản WallpaperManager mà không cần thêm các phương thức mới.
  3. Về phía khung công tác, sử dụng displayId thu được từ một đối tượng Context và ánh xạ nó tới một định danh tĩnh (chẳng hạn như một cổng của màn hình vật lý). Sử dụng mã định danh tĩnh để duy trì hình nền đã chọn.

Cách giải quyết này sử dụng các triển khai hiện có cho bộ chọn hình nền. Nếu nó được mở trên một màn hình cụ thể và sử dụng đúng ngữ cảnh, thì khi nó gọi đặt hình nền, hệ thống có thể tự động nhận dạng màn hình.

Nếu cần đặt hình nền cho màn hình khác với màn hình hiện tại, thì hãy tạo một đối tượng Context mới cho màn hình đích ( Context#createDisplayContext ) và lấy thể hiện WallpaperManager từ màn hình đó.

Hạn chế bảo mật

Hệ thống sẽ không hiển thị hình nền trên màn hình ảo mà nó không sở hữu. Điều này là do lo ngại về bảo mật rằng một ứng dụng độc hại có thể tạo màn hình ảo với hỗ trợ trang trí hệ thống được kích hoạt và đọc thông tin nhạy cảm của người dùng từ bề mặt (chẳng hạn như ảnh cá nhân).

Thực hiện

Trong Android 10, giao diện IWallpaperConnection#attachEngine()IWallpaperService#attach() chấp nhận tham số displayId để tạo kết nối trên mỗi màn hình. WallpaperManagerService.DisplayConnector đóng gói một công cụ và kết nối hình nền trên mỗi màn hình. Trong WindowManager, bộ điều khiển hình nền được tạo cho từng đối tượng DisplayContent lúc xây dựng thay vì một WallpaperController duy nhất cho tất cả các màn hình.

Một số triển khai phương thức WallpaperManager công khai (chẳng hạn như WallpaperManager#getDesiredMinimumWidth() ) đã được cập nhật để tính toán và cung cấp thông tin cho các màn hình tương ứng. WallpaperInfo#supportsMultipleDisplays() và một thuộc tính tài nguyên tương ứng đã được thêm vào để các nhà phát triển ứng dụng có thể báo cáo hình nền nào đã sẵn sàng cho nhiều màn hình.

Nếu dịch vụ hình nền hiển thị trên màn hình mặc định không hỗ trợ nhiều màn hình, thì hệ thống sẽ hiển thị hình nền mặc định trên màn hình phụ.

Hình 3. Logic dự phòng hình nền cho màn hình phụ