RFC-0155:可選的功能路徑

RFC-0155:選用能力路徑
狀態已接受
區域
  • 元件架構
說明

我們在元件資訊清單的「offer」和「use」部分新增了一個欄位,用來表示特定能力可能不存在的情況。

問題
Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2022-02-07
審查日期 (年-月-日)2022-04-14

摘要

我們已在元件資訊清單的提供和使用部分新增了一個欄位,用於指出特定能力可能不存在的情況。

提振精神

核心領域分片

使用核心區塊時,會出現能力路徑來源或目標不存在的情況。例如:

  • 元件 /core/wlancfg 使用 fuchsia.location.sensor.WlanBaseStationWatcher 通訊協定,但部分產品並未提供這項通訊協定。
  • 元件 /core/bt-a2dp 必須使用 fuchsia.power.battery.BatteryManager 能力 (如果有提供的話),但這項功能並非所有產品都支援。
  • 如果可用,/core/omaha-client-service 元件必須使用 fuchsia.update.config.OptOut 通訊協定,但這項功能並非適用於所有產品。
  • 如果有影片,CommsAgent 套件必須使用影片,但部分產品沒有影片。
  • 追蹤記錄提供者是提供 fuchsia.tracing.provider.Registry 能力的元件。這對於開發用途很有幫助,但不應納入使用者版本。

上述情境是我們希望日後支援的元件設定,但目前元件架構中有一些地方會引入與此相關的粗糙邊緣:

  • 如果提供的元件不在資訊清單中,則會導致資訊清單驗證失敗。
  • 如果從不公開功能的元件提供能力,會導致審查驗證失敗。
  • 能力路徑失敗 (例如嘗試使用未提供的功能) 會導致元件管理員 (正確地) 發出警告級別記錄,這可能會讓人感到擔心,因此在調查刻意省略功能的產品問題時,會造成誤導。

透過集合驗證路徑

Scrutiny 是元件路徑驗證工具,可確保指定元件樹狀結構中所有使用的功能都有有效的能力路徑。除了提供系統正確性斷言之外,這也是開發人員實用的工具,因為它可將路徑驗證從執行階段移至建構階段,縮短開發週期。

目前,我們維護許可清單,可停用對特定能力路徑的審查檢查。這樣一來,當元件使用無法使用的能力時,建構作業就能成功,但不幸的是,當能力路徑在能力用的建構中設定錯誤時,建構作業也能成功。

此外,一旦 https://fxbug.dev/42174612 解決,審查也會驗證來自工作階段領域的能力路徑。通常,工作階段元件會依賴工作階段外部產生的功能,如果其中一個元件希望加入審查許可清單,就會增加摩擦,因為這些元件可能會在 fuchsia.git 之外開發。

相關人員

誰會受到這項 RFC 是否通過的影響?(此為選用部分,但建議您填寫)。

主持人:Hunter Freyer (hjfreyer@google.com)

FEC 指派的人員,負責引導此 RFC 通過 RFC 程序。

審查者:

  • Mark Dittmer (markdittmer@google.com) - 安全性
  • Gary Bressler (geb@google.com) - 元件架構
  • Marc Khouri (mnck@google.com) - WLAN
  • Ani Ramakrishnan (aniramakri@google.com) - 藍牙
  • Yaar Schnitman (yaar@google.com) - 產品

社會化:

在收到 https://fxbug.dev/42168255 的相關規定,並向特定人士徵詢意見後,我們已將此 RFC 的早期版本提供給相關人士。

設計

系統會在使用宣告中新增名為 availability 的新欄位。這個欄位的預設值為 required,表示元件預期會提供該能力,如果無法提供,則可能會發生故障。這份 RFC 不會對 required 功能的行為進行任何變更,這些功能的行為會與目前所有功能的行為相同

{
    use: [
        {
            protocol: "fuchsia.logger.LogSink",
            availability: "required",
        },
        {
            directory: "config-data",
            path: "/config",
            rights: [ "r*" ],
            // The `availability` field defaults to `required` when omitted.
        },
    ],
}

您也可以將用途宣告中的 availability 欄位設為 optional,以反映元件在無法使用該能力 (可能會修改行為) 時的正常運作情形。

{
    use: [
        {
            // Emergency location is not present in all products.
            protocol: "fuchsia.location.sensor.WlanBaseStationWatcher",
            availability: "optional",
        },
    ],
}

系統會將名為 void 的新來源新增至可能的優惠宣告來源清單。

{
    offer: [
        {
            protocol: "fuchsia.update.config.OptOut",
            from: "void",
        },
    ],
}

使用宣告為選用的功能,可以從現有元件或「void」提供。需要使用宣告的功能可能會從 void 提供,因為這可能會導致元件發生故障。

中間商品 (從父項到子項) 也可能將 availability 欄位設為下列其中一個值:

  • required (預設):子項「必須」取得此能力的存取權,無論子項是否能處理缺少此功能的情況 (可能不會從祖系中的空白提供)。
  • optional:子項「必須」能夠處理缺少這項能力的情況 (提供鏈結結尾處的使用宣告必須為選用項)。
  • same_as_target:商品的選用性與目標相同。如果目標需要這項能力,這項產品就會規定目標必須接收這項能力。如果目標對這項能力有選用用途,則這項商品會規定目標可以或不可以接收這項能力。
{
    offer: [
        {
            protocol: "fuchsia.power.battery.BatterManager",
            from: "parent",
            to: "bt-a2dp",
            // Emit a build-time error if this protocol is not correctly routed
            // to this child (including offers from void).
            availability: "required",
        },
        {
            protocol: "fuchsia.location.sensor.WlanBaseStationWatcher",
            from: "parent",
            to: "wlancfg",
            // Emit a build-time error if this child is unable to handle the
            // absence of this protocol.
            availability: "required",
        },
    ],
}

如果元件使用 optional,且其父項提供的能力為 required,則如果能力的路徑無效或結尾為「offer from void」,就會產生建構時錯誤。如果元件使用 required,且其父項提供的能力為 optional,則會產生建構時錯誤。這個欄位可能未設定,在這種情況下系統會忽略該欄位。

核心領域組裝

RFC-0089 所述,核心領域會從「核心區塊」組合而成,這些區塊是 CML 片段,會在建構期間與核心領域合併。核心區塊的確切組合由產品定義設定。

一般來說,建議您將指定子項的優惠,納入與子項宣告相同的核心區塊。這有助於確保如果子項包含在版本中,則其所需的功能也能供其使用。

如果商品希望擁有可選納入建構內容的來源,在子項所在的區塊中加入子項商品會變得複雜。如果指定子項 a 的商品有子項 b 的來源,但 b 也位於區段中,則 a 的區段可能只會納入 b 的區段,或是因為商品來自不存在的子項,導致資訊清單驗證錯誤在建構期間產生。

為了讓子項商品與子項宣告位於相同的核心區塊 (無論來源為何),我們將推出一個名為 source_availability 的新欄位,用於提供宣告。這個欄位的預設值為 present,但可以設為 unknown

source_availability 設為 unknown 時,如果優惠宣告參照的來源不在資訊清單中,就會通過資訊清單驗證。在資訊清單編譯期間,缺少的優惠宣告來源會替換為 void 來源,讓任何路徑結束於此優惠宣告的使用宣告,能夠將可用性設為 optional,藉此通過路徑驗證,反映出並非所有產品都具備這項能力。

{
    offer: [ {
        protocol: "fuchsia.examples.Echo",
        from: "#child-that-might-not-be-declared",
        to: "#echo-user",
        source_availability: "unknown",
    } ],
}

這可讓平台設定維護者依賴核心區塊組合,做為核心領域中提供哪些功能和元件的單一可靠資料來源。省略核心分片不僅會從核心領域移除子系統,還會精確更新任何提供子系統的來源,以便在 void 中提供。如此一來,如果有任何子系統可供選擇的用途,在刻意從系統中排除這些子系統時,這些子系統就不會收到存取權 (但在這種情況下,任何必要用途仍會導致錯誤)。

範例

核心領域中的元件,具有選用能力

在本例中,我們將根據建議設計,說明 wlancfg 的資訊清單和核心領域區塊會如何變更。

fuchsia.location.sensor.WlanBaseStationWatcher 通訊協定適用的商品會從 emergency.core_shard.cml 移至 wlancfg.core_shard.cmlsource_availability 欄位則設為 unknown (因為緊急救援核心區塊和緊急救援元件,可能會或可能不會納入與 wlancfg 相同的平台設定)。

// src/connectivity/location/emergency/meta/emergency.core_shard.cml
{
    offer: [
        // This is removed
        {
            protocol: "fuchsia.location.sensor.WlanBaseStationWatcher",
            from: "#emergency",
            to: "#wlancfg",
        },
    ],
}
// src/connectivity/wlan/wlancfg/meta/wlancfg.core_shard.cml
{
    offer: [
        // This is added
        {
            protocol: "fuchsia.location.sensor.WlanBaseStationWatcher",
            from: "#emergency",
            to: "#wlancfg",
            source_availability: "unknown",
        },
    ],
}

為讓 source_availability 欄位正常運作,必須將優惠宣告移至 wlancfg 的核心分片,這也是核心分片最佳做法的建議做法。

除了核心分片變更之外,wlancfg 中此通訊協定使用的宣告也會更新為 optional

// src/connectivity/wlan/wlancfg/meta/wlancfg.cml
{
    use: [
        {
            protocol: "fuchsia.location.sensor.WlanBaseStationWatcher",
            // This line is added
            availability: "optional",
        },
    ],
}

如今,如果建構作業中未納入 emergency.core_shard.cml 檔案,由於 wlancfg 無法存取 fuchsia.location.sensor.WlanBaseStationWatcher 通訊協定,因此不會發生建構階段錯誤。這表示系統可能會將通訊協定從審查的許可清單中移除,且任何導致通訊協定無法在可用的平台設定中提供給 wlancfg 的設定錯誤,都會導致建構期間錯誤。

工作階段中含有選用能力的元件

在本例中,我們將說明如何根據建議設計,變更從 /core/battery_manager/core/session_manager/session:session/workstation_session/login_shell/ermine_shell 取得 fuchsia.power.battery.BatteryManager 通訊協定時,所涉及的資訊清單和核心領域區塊。

workstation.core_shard.cml 檔案中通訊協定的產品會更新,將 source_availability 設為 unknown

// src/session/bin/session_manager/meta/workstation.core_shard.cml
{
    offer: [
            protocol: "fuchsia.power.battery.BatteryManager",
            from: "#battery_manager",
            to: "#session-manager",
            // This line is added
            source_availability: "unknown",
    ],
}

coreermine_shell 之間的商品無須變更,而 ermine_shell 資訊清單會更新,將 availability 欄位設為通訊協定的 optional

// src/experiences/session_shells/ermine/shell/meta/ermine.cml
{
    use: [
        {
            protocol: "fuchsia.power.battery.BatteryManager",
            availability: "optional",
        },
    ],
}

在進行這些變更後,workstation.core.shard.cml 檔案可納入平台設定,而無須 battery_manager.core_shard.cml,也不會導致建構期間審查錯誤,或將這項能力加入許可清單。這表示在平台設定中,可安全地將電池管理器元件排除,以便在沒有電池的硬體上執行工作站工作階段。

工作階段擁有者想要確保選用能力一律

可供使用

以上述範例為基礎,請考慮名為 workstation-on-laptops 的虛構工作階段,該工作階段與 workstation 工作階段相同,但具有額外的筆電專屬功能。如果這個工作階段的擁有者希望使用 workstation 工作階段中相同的 ermine 元件,但希望確保該元件「一律」可存取 fuchsia.power.battery.BatteryManager 通訊協定 (由建構時錯誤強制執行),則工作階段擁有者可以將此通訊協定以 required 的形式提供給 ermine

// src/experiences/session_shells/ermine/session/meta/workstation_on_laptops_session.cml
{
    offer: [
            protocol: "fuchsia.power.battery.BatteryManager",
            from: "parent",
            // login_shell offers the capability to ermine
            to: "#login_shell",
            availability: "required",
    ],
}

在這個範例中,如果 workstation-on-laptops 工作階段與提供 fuchsia.power.battery.BatteryManager 通訊協定的平台設定進行比較 (也就是不包含 battery_manager.core_shard.cml),系統就會發出建構時間錯誤,即使 ermine.cml 可選擇使用該通訊協定。void

工作階段擁有者希望確保元件能夠處理以下情況:

選用能力

同樣地,以「ermine 可選擇使用 BatteryManager」為例,如果工作站工作階段的擁有者希望確保 ermine 一律都能處理 fuchsia.power.battery.BatteryManager 通訊協定的缺少情形 (無論通訊協定目前是否可用),則可將此通訊協定做為 optional 提供給 ermine

// src/experiences/session_shells/ermine/session/meta/workstation_session.cml
{
    offer: [
            protocol: "fuchsia.power.battery.BatteryManager",
            from: "parent",
            // login_shell offers the capability to ermine
            to: "#login_shell",
            availability: "optional",
    ],
}

這項選用商品不會影響建構或執行階段行為,因為 ermine 也提供該能力的選用用途。不過,如果 ermine 曾經變更為需要這項能力,那麼無論能力路徑是否有效,或結尾為「來自 void 的優惠」,審查程序都會產生建構時錯誤。

實作

如要實作這些變更,fuchsia.component.decl.Component FIDL 資料表和 CML JSON 結構定義必須更新,以納入新的欄位,並更新 CMC、cm_fidl_validator 和 Scrutiny,以正確處理設計部分所述的 optional 語意。

成效

由於在這些資訊清單中攜帶額外列舉的成本非常低,因此建議的變更不會對建構時間或大小造成任何重大影響。此外,元件管理員中建議的執行階段行為變更不會對效能造成任何重大影響,因為在這項工作開始時,實作新命名空間組合邏輯所需的資訊都會儲存在記憶體中。

人體工學

這項變更應可大幅改善任何元件作者的使用者體驗,因為他們目前需要與許可清單互動,才能抑制審查驗證錯誤,而預期驗證錯誤的內容會有所改善,因此審查作業不會產生這些預期錯誤。

回溯相容性

這項變更純粹是針對 FIDL 資料表和 JSON 格式新增內容,因此不會影響回溯相容性。

安全性考量

這項異動可讓元件作者在不必取得安全性團隊核准的情況下,停用未路由功能的 Scrutiny 錯誤,因為允許清單將不再用於控制未路由功能的 Scrutiny 錯誤抑制。

這項提案不會影響建立或變更元件路徑的審查程序,因此我們認為這項提案是可接受的。

隱私權注意事項

所提議的變更不會影響使用者資料的收集、處理或儲存方式,因此不會有任何隱私權疑慮。

測試

我們已進行大量測試,涵蓋元件資訊清單管道。這些測試將會修改,納入這項新功能的測試範圍。

說明文件

我們會更新元件資訊清單說明文件,說明新欄位及其對驗證的影響。

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

既有技術與參考資料

TODO