| RFC-0155:選用能力路徑 | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | 元件資訊清單的供應項目和使用部分會新增欄位,用來表示特定能力可能不存在。 |
| 問題 | |
| 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」提供。如果功能需要使用宣告,則不得從空白提供,否則可能會導致元件故障。
中繼方案 (從父項到子項) 也可將 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.cml,且 source_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",
},
],
}
將商品聲明移至 wlancfg 的核心分片,是 source_availability 欄位正常運作的必要條件,也符合核心分片的最佳做法。
除了核心分片變更外,這個通訊協定的使用宣告也會在 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 取得 fuchsia.power.battery.BatteryManager 通訊協定時,資訊清單和核心領域分片會如何變更。/core/session_manager/session:session/workstation_session/login_shell/ermine_shell
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",
],
}
core 和 ermine_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 通訊協定 (由建構時間錯誤強制執行),則工作階段擁有者可能會將這個通訊協定提供給 ermine 做為 required。
// 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 工作階段與提供 void 通訊協定的平台設定 (即不含 battery_manager.core_shard.cml) 進行比較,即使 ermine.cml 可選擇使用通訊協定,系統仍會發出建構時間錯誤。fuchsia.power.battery.BatteryManager
工作階段擁有者想確保元件可以處理
選用能力
再次以「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 經過修改而需要這項能力,則無論能力路徑是否有效或以「offer from void」結尾,審查都會發出建構時間錯誤。
實作
如要實作這些變更,必須更新 fuchsia.component.decl.Component FIDL 表格和 CML JSON 結構定義,加入新欄位,並更新 CMC、cm_fidl_validator 和 Scrutiny,正確處理設計部分所述的 optional 語意。
效能
由於在這些資訊清單中攜帶額外列舉的成本非常小,因此建議的變更不會對建構時間或大小造成任何重大影響。此外,元件管理員中建議的執行階段行為變更不會對效能造成任何重大影響,因為在開始這項工作時,實作新命名空間組件邏輯所需的資訊全都在記憶體中。
人體工學
這項變更可大幅提升人體工學,目前任何需要與許可清單互動的元件作者,都能藉此抑制審查驗證錯誤,因為預期驗證錯誤的環境會有所改善,審查完全不會發出這些預期錯誤。
回溯相容性
這項變更純粹是 FIDL 表格和 JSON 格式的加法,因此沒有回溯相容性問題。
安全性考量
這項異動後,元件作者就能停用未路由功能的 Scrutiny 錯誤,不必再取得安全團隊的核准,因為系統不會再使用許可清單來控管未路由功能的 Scrutiny 錯誤抑制功能。
這是可接受的,因為這項提案不會改變建立或變更元件路徑的審查程序。
隱私權注意事項
這些變更不會影響使用者資料的收集、處理或儲存方式,因此不會造成任何隱私權問題。
測試
目前已有涵蓋元件資訊清單管道的廣泛測試。這些測試將會修改,以涵蓋這項新功能。
說明文件
元件資訊清單說明文件將更新,說明新欄位及其對驗證的影響。
缺點、替代方案和未知事項
既有技術和參考資料
TODO