RFC-0147:檢視系統

RFC-0147:檢視系統
狀態已接受
區域
  • 圖形
  • HCI
  • 查看系統
說明

說明 Fuchsia 平台的視窗系統,並確認其在平台中的角色。

問題
Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2021-11-03
審查日期 (年-月-日)2022-01-05

摘要

本 RFC 概要說明 Fuchsia 檢視區塊系統:這組 API 可用於推斷及與視覺區域 (「檢視區塊」) 及其生命週期互動。這組功能在其他平台通常也稱為視窗系統。本 RFC 的範圍僅限於具有單一螢幕的產品。日後 RFC 將涵蓋為無螢幕裝置和/或多個螢幕進行調整的變更。

View 是指圖像內容的區域,也是 Fuchsia 上的基本圖像和使用者互動單元。檢視區塊會連結形成檢視區塊樹狀結構階層,並以可區分的根檢視區塊為首。Fuchsia 的圖像合成器 Scenic 會從檢視區塊樹狀結構中,轉譯每個檢視區塊的圖像內容,產生顯示器輸出內容。Scenic 和輸入管道負責將以 UI 為目標的使用者輸入內容 (例如鍵盤、滑鼠和觸控) 傳送至正確的 View。

View System 是 Fuchsia 平台支援「自備執行階段」的重要部分,也是產品開發人員用來建構安全視覺化使用者體驗的機制,可透過多個執行階段的圖像內容在 Fuchsia 上建構安全視覺化使用者體驗。Fuchsia 的組合 API (Flatland 和 GFX) 是以 View 系統為基礎建構而成。

提振精神

這項 RFC 的目標是記錄並批准「世界現況」,以利檢視系統。具體來說,我們希望核准下列決定。

  1. 如要在 Fuchsia 上顯示圖像,元件必須使用 View 系統建立 View。但單一視窗公用程式 UI (例如 Virtcon 和 Recovery UI) 是例外,這類 UI 不會使用視窗功能,且設計為在 Scenic 未執行時,於資源受限的情況下執行。這些 UI 會直接與螢幕控制器通訊。
  2. 元件只能透過 View 系統與 Fuchsia 平台整合,以支援使用者觸控、滑鼠和鍵盤,以及無障礙服務。
  3. View System 不會管您使用的組合策略 (GFX 與 Flatland),並為 Fuchsia 上的所有 Compositor 實作項目提供共用基礎。

如要修改這些決策,必須提出額外的 RFC 和/或更新此 RFC。

利害關係人

協助人員:

hjfreyer@google.com

審查者:

這個部分預計會在審查期間更新

  • 圖片:reveman@google.com、jjosh@google.com、emircan@google.com
  • 輸入:quiche@google.com
  • 元件:ypomortsev@google.com
  • 安全性:kostyak@google.com
  • 一般:wez@google.com

已諮詢:

sanjayc@google.com、hjfreyer@google.com、jjosh@google.com、lindkvist@google.com、geb@google.com

社交:

草擬文件已傳送給 Scenic 和 Input 團隊討論。

詞彙解釋

  • 風景
    • Fuchsia 平台中的圖形 compositing 元件
    • View System API 的唯一實作工具,包括與圖形組合 API 和 HCI API 的連結。
  • 查看
    • 圖像內容的視覺區域。
    • 透過 View 樹狀結構,它具有座標系統、周框方塊,以及與祖先定義的空間關係。
  • 查看樹狀結構
    • 系統上的 View 結構,由父子關係連結。檢視區塊樹狀結構的根 View 通常會附加至螢幕。
  • 螢幕
    • 以像素為基礎的輸出裝置,又稱為螢幕。View System 目前一次只能支援一個連接至系統的螢幕。
    • 螢幕由螢幕控制器管理。
  • 顯示控制器
    • 管理連線至電腦的螢幕。
    • 只會與 Scenic 對話。
    • 不適用於樹狀結構外的用戶端。
  • 場景管理工具
    • 將根目錄檢視畫面附加至螢幕的平台元件。
  • 無障礙管理員
    • 實作無障礙 API 的平台元件。
    • 可存取「查看系統」權限。
  • 系統殼層 (「系統 UI」)
    • 負責產品使用者體驗的元件,例如 Ermine。這個元件通常適用於特定產品。
    • 系統殼層負責視窗管理,包括焦點處理和頂層檢視區塊管理,而檢視區塊系統則負責視窗系統
  • 開發人員殼層 (「tiles」、「present_view」)
    • 用於測試的系統殼層。開發人員通常可藉此獨立啟動 Fuchsia 元件。
  • UI 用戶端
    • 這是指檢視區塊擁有者的通用方式,本 RFC 全文都會使用這個詞彙。
    • 示例:Flutter 應用程式、具有多個頂層檢視區塊的 Chromium。

設計

「觀看」的定義

Fuchsia View 是 Fuchsia 上的基本圖像和互動單位。View 會定義顯示圖形內容的視覺區域。並非所有檢視畫面都會同時顯示。每個 View 的圖像內容都由 Fuchsia 元件提供。Scenic 會實作平台支援功能,管理檢視區塊並將內容合成到畫面上。

各個檢視:

  • 可併入另一個檢視區塊 (子項檢視區塊) 的內容,形成檢視區塊樹狀結構
  • 定義用於放置子項內容的座標系統。
  • 具有定義該檢視畫面可見 (和選用互動式) 部分的定界框。
  • 可連線至美景樹狀結構,也可從中斷連線。(可能存在未連線的檢視區塊,但這些檢視區塊的內容不會顯示在畫面上,也不會接收輸入內容)。

Scenic 支援的任何圖形組合 API (例如 fuchsia.ui.compositionfuchsia.ui.scenic) 都必須提供建立 View 和管理其生命週期的方法。日後的所有組合 API 也必須在 View 系統上運作。Fuchsia 平台 HCI API (例如指標鍵盤) 會使用 Views 轉送輸入內容。(詳情請參閱下方的「輸入」一節)。

查看樹狀結構

Scenic 擁有並實作一個全域檢視區塊樹狀結構。View 樹狀結構具有可連線至螢幕的根層級 View。Scenic 是唯一能直接操控所有檢視區塊及其位置的 Fuchsia 元件。

檢視畫面樹狀結構中的每個檢視畫面,都會在自己的座標系統中定義界線,並在上層檢視畫面的座標系統中表示位置和方向。這些屬性共同決定最終在畫面上顯示圖形內容的區域,以及回應使用者輸入內容的區域。

孩童檢視模式

View 可以在自己的座標系統中建立空白預留位置,從另一個 View 嵌入其他圖像內容;預留位置稱為「檢視區塊」。這兩個 View 會在 View 樹狀結構中形成父項子項關係,其中父項 View 的 Viewport 會嵌入子項 View 的圖像內容。如要建立關係,家長和孩子必須在建立 View 和 Viewport 時提供相符的權杖。這些權杖會實作為核心物件,且無法複製。父項和子項可透過各種方式取得這些相符的權杖,但這些方式與檢視系統無關。

將父項 View 附加至 View 樹狀結構或從中分離時,系統也會附加/分離其子項 View。即使子樹狀結構從全域檢視樹狀結構中分離,子樹狀結構內的檢視區塊之間的連線仍會保留。

查看隔離

雖然 View 可以嵌入另一個 View,但 View 系統不會讓 View 存取任何其他 View 的圖像內容。這項隔離保證是檢視安全性的基礎之一。

將風景地圖檢視畫面投放到螢幕上

Scenic 是唯一與螢幕控制器通訊的元件。這項工具會擷取整個檢視區塊樹狀結構的圖像內容,以及樹狀結構中編碼的關係,然後建立單一圖片 (可能包含多個圖層)。然後,程式會設定硬體,顯示最終的螢幕畫面。

查看擁有權

View 中的內容會透過單一 FIDL 管道提供給圖形組合 API,而該 API 是由 Scenic 實作。FIDL 管道的每個用戶端端點 (Scenic) 都稱為「UI 用戶端」,而 UI 用戶端最多只能建立一個檢視區塊。

檢視畫面可能來自各種元件,包括面向使用者的元件 (例如瀏覽器)、系統 UI,以及 Fuchsia 平台的一部分元件,例如無障礙管理員。元件可能會建立多個管道,因此也會建立多個檢視區塊。因此,在某些情況下,單一元件可能會同時提供父項 View 和該 View 的子項 View。

如要合併多個元件的圖像,開發人員應在每個元件中建立一或多個 View,並使用子項 View 和 View 樹狀結構合併這些圖像。請注意,檢視區塊樹狀結構階層不必與元件執行個體階層相符。在許多情況下,這些結構刻意設計成大不相同。

Runtimes

如果是以較高階語言 (例如 Dart 或 JavaScript) 編寫的元件,執行元件實作通常會負責建立及管理 View。以這些語言開發的開發人員可能不瞭解基礎 OS 的許多詳細資料;執行元件有責任將 View 生命週期轉換為特定語言或特定執行階段的機制。

視窗管理、視窗系統和合成

Fuchsia 會將其他平台有時會合併的三個函式分開。

  • 視窗管理會納入產品專屬政策,以及視窗行為的特定選擇。在 Fuchsia 上,這項工作由系統 UI 負責,完全位於平台外部。
  • 視窗系統是指低層級視窗管理。在 Fuchsia 上,這項作業由 View System 處理。
  • 合成是指結合多個來源的圖片,產生要顯示的圖片。目前這也是 Scenic 元件的責任,但日後可能會有所變更。

選擇將視窗系統和組合分開,可提供圖形呈現的快速路徑,並實現有效率的實作方式。雖然目前 View System 和 Compositor 主要是在 Scenic 內實作,但兩者在 API 和程式碼方面都是獨立的。這種分離方式可讓 View System 支援多種組合策略 (Flatland 和 GFX)。

將視窗管理設為產品層級的考量因素,可確保政策邏輯位於平台外部,明確區分平台和產品。

輸入

View System 是 Fuchsia 平台的主要機制,可決定如何轉送使用者輸入內容,例如指標事件或鍵盤事件。Fuchsia 的使用者輸入 API 經過設計,每個管道的範圍都限定在特定檢視區塊。系統會根據目前的檢視畫面焦點 (適用於鍵盤事件),以及/或與輸入事件位置對應的一或多個檢視畫面 (適用於觸控或滑鼠事件),將輸入內容傳送至檢視畫面。只有在連線至 ViewTree 時,View 才能接收使用者輸入內容。

多個 View 可能會參與同一個事件的輸入處理程序。特定產品的視窗管理員可能會根據產品政策設定這項路徑,例如將滑鼠事件的全域存取權授予系統 UI。如需更多詳細資料,請參閱「使用者輸入架構」。這個系統可讓使用者在多個執行階段的 Views 中享有流暢體驗,包括消除觸控手勢的歧義

這項做法的重要影響之一,是 Fuchsia 平台以外的元件無法直接存取驅動程式庫的輸入事件。他們必須透過 View 系統中介接收這項資訊。

查看目標

在任何時間點,檢視區塊樹狀結構都有一個顯著的檢視區塊,稱為「聚焦」檢視區塊。使用者通常會預期焦點檢視區塊會接收使用者輸入內容。Fuchsia 的輸入子系統會依據 View 焦點,判斷輸入內容的傳送路徑。詳情請參閱 Focus Chain 說明文件。父項 View 擁有者可以控制子樹狀結構中的 View 焦點。

ViewRef

平台會使用稱為「ViewRefs」ViewRefs的權杖來識別及傳達有關 Views 的資訊。ViewRef 是特定 View 的專屬參照,在系統重新啟動前不會重複。這項功能是以核心物件的形式實作,其控制代碼可任意複製,並透過任意通訊協定傳送至其他元件。

View 系統 API 會大量使用 ViewRef,為每個 View 提供穩定的跨元件參照。ViewRef 也用於發出相關聯 View 的生命週期事件信號。這可讓平台內外的其他元件,針對 Views、生命週期進行通訊,並將使用者輸入內容和無障礙通訊協定路徑傳送至 Views。

實作

Scenic 是 View 系統的授權來源,因為 View Tree 和核心 View 管理 API 都是在 Scenic 中實作。每個用戶端都會使用自己的 ViewRef 註冊,以接收相關聯 View 的使用者輸入和無障礙事件。Scenic 目前支援兩種圖像組合 API:fuchsia.ui.scenic (舊版) 和 fuchsia.ui.composition (開發中)。View 系統與每個系統各自獨立,但會緊密搭配運作。

API 實作細節不在本 RFC 的討論範圍內,但相關 API 如下。值得注意的是,這些 API 經過多年演進,日後可能會簡化部分程序。

檢視系統涉及的平台元件

  • 風景
  • 輸入管道
  • 場景管理員 (或舊版系統的根簡報者)
  • 無障礙管理員
  • 文字管理工具

檢視管理 API

使用者輸入內容適用的 API

無障礙 API

效能

檢視系統的許多層面都會影響圖像和輸入效能。下文將說明幾個重要層面。

  • 所有執行階段都相同:Fuchsia 的「自備執行階段」原則表示,Fuchsia 上的所有執行階段都使用相同的事件轉送,且沒有任何執行階段享有優先待遇。
  • 轉譯一次:Scenic 可結合不同檢視區塊的圖像內容,不必重新轉譯,因為 Scenic 知道檢視區塊位置,且可將圖像內容正確轉送至顯示器驅動程式庫。
  • 有效率的調度:Scenic 會公開焦點資訊,讓非圖像化使用者輸入內容 (例如鍵盤事件) 直接從參與處理的元件調度。

安全性和隱私權注意事項

View System 可確保在 Fuchsia 上安全地組合圖像內容,而這些保證是安全 UX 的基礎。不過,單靠 View System 無法保證每個 UX 都安全無虞,只能確保 View System 遵守自身的安全保障。

View 系統會嘗試透過下列方式啟用安全的使用者體驗:

  • 將 View Tree 的擁有權和操控權全權委派給 Scenic。
  • 將在畫面上顯示圖像內容的唯一責任委派給 Scenic。
  • 禁止 UI 用戶端在沒有相符的 Viewport 或 ViewRef 的情況下,操控其他 View。
  • 禁止 UI 用戶端使用 View 系統檢查任何其他 UI 用戶端 View 的內容。
  • 只允許 UI 用戶端將輸入內容插入其 View 子樹狀結構。
  • 只允許檢視畫面在連線至檢視畫面樹狀結構時取得焦點並接收輸入內容。

UI 安全性取決於元件架構在能力轉送方面提供的保證。View security 的詳細資料將在日後的 RFC 中說明。

測試

檢視系統是在多個抽象層級實作,因此測試時會採用分層方法。

在 fuchsia.git 中:

  • 在 Scenic 元件的程式碼集區中,對檢視區塊樹狀結構和檢視區塊生命週期進行單元測試。
  • /src/ui/tests 中的 UI 整合測試,會運用 View 系統 API 周圍的合約。
    • 這些 API 由 Scenic、Scene Manager、Input Pipeline、Accessibility Manager 和 Text Manager 等平台元件提供及使用。
  • 樹狀結構內整合測試會使用 fuchsia.ui.observation.test API,檢查檢視畫面系統行為。

樹狀結構外:

  • Chromium 和 Flutter 等執行階段會編寫整合測試,以執行 View 系統 API
  • 產品會編寫端對端測試,間接運用 View 系統。

說明文件

本 RFC 簡要說明 View 系統的角色和責任。我們會撰寫文件和可能額外的 RFC,以解決詳細資料。

根據這項 RFC 和 Flatland 即將發生的變化,部分 Scenic 說明文件也需要更新。

缺點、替代方案和未知事項

已知限制

View 系統目前缺少在多個 View 之間同步更新的機制。

View 系統部分負責將功能路由至公開檢視區塊 (使用 ViewRef) 的執行階段。這與透過 Fuchsia 的元件架構進行能力轉送的概念有些重疊,但目前完全是分開的。日後在元件架構中支援 View 功能,或許會帶來優勢。

目前的 API 只允許檢視畫面擁有者建立子項檢視畫面。如果應用程式想建立多個頂層視窗,這就不是理想做法。

由於 View 系統 API 在多年間自然演進,且有許多不同的貢獻者,因此目前執行階段開發人員的認知負擔相當高。日後,我們將提供更完善的文件和範例,並盡可能簡化 API,以解決這個問題。

替代方案

View System 架構會做出多項架構選擇。

  • 任何含有圖像的產品都必須使用 View System。
    • 或者,Scenic 也可以是選用項目,產品可包含自己的合成器。這需要從樹狀結構中公開許多低階 API。
    • 目前做法的優點:
    • 跨執行階段的同質行為 (包括無障礙功能和輸入)
    • 一致的安全保障
    • Display API 可持續發展,不會破壞用戶端
    • 目前做法的缺點:
    • 產品自訂程度較低
    • 執行階段整合的複雜度
    • 如果以 Fuchsia 為基礎建構的產品需要,這項設定日後可能會變更。
  • View 系統會分散到多個元件,包括 Scenic 和輸入管道。
    • 或者,我們也可以將整個 View 系統建構到 Scenic 中。
    • 目前做法的優點:
    • 關注點分離:圖形組合、視窗管理、產品政策皆為獨立項目。
    • 透過委派組合,實現高效能的圖形路徑
    • 與 UI 相關的元件可獨立演進
    • 即使子系統 (例如文字輸入) 發生當機情形,圖形仍可繼續運作
    • 目前做法的缺點:
    • 多個程序可能會透過 IPC 增加延遲
    • 元件間的協調/同步複雜度增加

既有技術和參考資料