Skip to content

HAL Version Use Cases

Ulrond edited this page Oct 1, 2026 · 8 revisions

Every version of an interface is released the same way: the version is tagged, and a new <component>/<version>/ directory is created for it. That released directory never changes. This is what "frozen" means, and it is the same before and after stable AIDL. What changes at stable AIDL is the compatibility rule, not how a version is released:

Era Version Compatibility rule
Pre-release (era 0, today) 0.<major>.<minor>.<bugfix> A breaking change is allowed and bumps the major. Compatible within one major only
Stable AIDL (era 1+) Single integer counting up: V1, V2, V3 … Additive only. Every version stays backwards compatible, so every pairing is compatible

In era 0 the vendor must be on the same major as the MW, at or above its minor (Versioning Guide). Cases 1–16 are era 0.

Requirement IDs refer to Requirements at the end of this page.

Blue = MW. Amber = vendor. Solid arrow = works. Dotted arrow = does not.


Client supports current

1. Same version

OK.

Requirements: VER-1, CON-1, CON-2, BLD-3

flowchart LR
    MW["MW<br/>videodecoder 0.2.1.0"]:::mw -- "ok" --> V["Vendor<br/>videodecoder 0.2.1.0"]:::ven
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef ven fill:#fef3c7,stroke:#b45309,color:#000
Loading

2. Vendor higher minor

OK.

Requirements: VER-1, VER-2, CON-2

flowchart LR
    MW["MW<br/>videodecoder 0.2.1.0"]:::mw -- "ok — vendor ahead" --> V["Vendor<br/>videodecoder 0.2.3.0"]:::ven
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef ven fill:#fef3c7,stroke:#b45309,color:#000
Loading

3. Vendor higher bugfix

OK.

Requirements: VER-1, VER-2, VER-4, CON-2

flowchart LR
    MW["MW<br/>videodecoder 0.2.1.0"]:::mw -- "ok — interface unchanged" --> V["Vendor<br/>videodecoder 0.2.1.1"]:::ven
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef ven fill:#fef3c7,stroke:#b45309,color:#000
Loading

4. Several MW consumers on different minors

OK. The vendor is at or above every consumer.

Requirements: VER-2, CON-1, BLD-4

flowchart LR
    subgraph MW["MW"]
        P["player<br/>0.2.0.0"]:::mw
        R["recorder<br/>0.2.1.0"]:::mw
        D["diagnostics<br/>0.2.3.0"]:::mw
    end
    P -- "ok" --> V["Vendor<br/>videodecoder 0.2.3.0"]:::ven
    R -- "ok" --> V
    D -- "ok" --> V
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef ven fill:#fef3c7,stroke:#b45309,color:#000
    style MW fill:#f8fafc,stroke:#94a3b8,color:#000
Loading

5. SoC and OEM layers deliver on different cadences

OK. Alignment is per component, not per layer.

Requirements: VER-3, CON-2, CON-4, BLD-4

flowchart LR
    subgraph MW["MW pins"]
        M1["videodecoder 0.2.1.0"]:::mw
        M2["audiodecoder 0.3.0.0"]:::mw
        M3["hdmicec 0.2.0.0"]:::mw
        M4["panel 0.4.1.0"]:::mw
    end
    subgraph VV["Vendor vertical"]
        subgraph SOC["SoC layer"]
            S1["videodecoder 0.2.2.0"]:::ven
            S2["audiodecoder 0.3.0.0"]:::ven
        end
        subgraph OEM["OEM layer"]
            O1["hdmicec 0.2.0.1"]:::ven
            O2["panel 0.4.1.0"]:::ven
        end
    end
    M1 -- "ok" --> S1
    M2 -- "ok" --> S2
    M3 -- "ok" --> O1
    M4 -- "ok" --> O2
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef ven fill:#fef3c7,stroke:#b45309,color:#000
    style MW fill:#f8fafc,stroke:#94a3b8,color:#000
    style VV fill:#f8fafc,stroke:#94a3b8,color:#000
    style SOC fill:#f8fafc,stroke:#94a3b8,color:#000
    style OEM fill:#f8fafc,stroke:#94a3b8,color:#000
Loading

6. Different vendor verticals, one MW build

OK. The MW pins the lowest minor that every platform delivers.

Requirements: VER-3, CON-3, BLD-6

flowchart LR
    MW["Common MW<br/>videodecoder 0.2.1.0"]:::mw
    MW -- "ok" --> A["Platform A vertical<br/>videodecoder 0.2.3.0"]:::ven
    MW -- "ok" --> B["Platform B vertical<br/>videodecoder 0.2.1.0"]:::ven
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef ven fill:#fef3c7,stroke:#b45309,color:#000
Loading

Client supports next

7. MW higher minor

Not supported. The MW may call methods the vendor does not implement. isCompatible() rejects it.

Requirements: VER-2, VER-6

flowchart LR
    MW["MW<br/>videodecoder 0.2.3.0"]:::mw -. "rejected — vendor behind" .-> V["Vendor<br/>videodecoder 0.2.1.0"]:::bad
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef bad fill:#fee2e2,stroke:#b91c1c,color:#000
Loading

8. MW higher major

Not supported.

Requirements: VER-3, VER-6, CON-7

flowchart LR
    MW["MW<br/>videodecoder 0.3.0.0"]:::mw -. "rejected — major not aligned" .-> V["Vendor<br/>videodecoder 0.2.3.0"]:::bad
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef bad fill:#fee2e2,stroke:#b91c1c,color:#000
Loading

9. Vendor higher major

Not supported.

Requirements: VER-3, VER-6, CON-7

flowchart LR
    MW["MW<br/>videodecoder 0.2.3.0"]:::mw -. "rejected — major not aligned" .-> V["Vendor<br/>videodecoder 0.3.0.0"]:::bad
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef bad fill:#fee2e2,stroke:#b91c1c,color:#000
Loading

Client supports current + next

10. One MW consumer moves to the next major

Undecided. One vendor server serves one major. Either every consumer moves together, or the vendor serves both majors.

Requirements: VER-3, CON-1, CON-6, CON-7, CON-8

flowchart LR
    subgraph MW["MW"]
        P["player<br/>0.3.0.0"]:::mw
        R["recorder<br/>0.2.1.0"]:::mw
    end
    P -. "rejected" .-> V["Vendor<br/>videodecoder 0.2.3.0"]:::ven
    R -- "ok" --> V
    P -. "option: vendor also serves 0.3.x.x" .-> V3["Vendor<br/>videodecoder 0.3.0.0"]:::ven
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef ven fill:#fef3c7,stroke:#b45309,color:#000
    style MW fill:#f8fafc,stroke:#94a3b8,color:#000
Loading

11. One vendor layer late on a major bump

OK. The MW moves the components that are delivered and holds the rest.

Requirements: VER-3, CON-2, CON-4, CON-7, CON-8

flowchart LR
    subgraph MW["MW pins"]
        M1["audiodecoder 0.4.0.0 — next"]:::mw
        M2["hdmicec 0.2.0.0 — held"]:::mw
    end
    subgraph VV["Vendor vertical"]
        S1["SoC<br/>audiodecoder 0.4.0.0 — delivered"]:::ven
        O1["OEM<br/>hdmicec 0.2.0.1 — 0.3.0.0 late"]:::ven
    end
    M1 -- "ok" --> S1
    M2 -- "ok" --> O1
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef ven fill:#fef3c7,stroke:#b45309,color:#000
    style MW fill:#f8fafc,stroke:#94a3b8,color:#000
    style VV fill:#f8fafc,stroke:#94a3b8,color:#000
Loading

12. One platform a major behind, common MW

Undecided. Either the MW holds 0.2.x.x everywhere, or it carries both majors and selects one at runtime, or it is built per platform.

Requirements: VER-3, CON-3, CON-6, CON-7, CON-8, BLD-6

flowchart LR
    subgraph MW["Common MW"]
        C["videodecoder 0.2.1.0 — current"]:::mw
        N["videodecoder 0.3.0.0 — next"]:::mw
    end
    N -- "ok" --> A["Platform A vertical<br/>videodecoder 0.3.0.0"]:::ven
    C -- "ok" --> B["Platform B vertical<br/>videodecoder 0.2.3.0"]:::ven
    N -. "rejected" .-> B
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef ven fill:#fef3c7,stroke:#b45309,color:#000
    style MW fill:#f8fafc,stroke:#94a3b8,color:#000
Loading

13. Two versions of a shared component in one process

Not supported. Both libraries export identical symbols. The first one loaded wins, silently.

Requirements: CON-5

flowchart LR
    subgraph PROC["One MW process"]
        H["hdmicec<br/>built against common 0.1.0.0"]:::mw
        AD["audiodecoder<br/>built against common 0.2.0.0"]:::mw
    end
    H --> L1["libcommon-v0.1.0.0-cpp.so"]:::bad
    AD --> L2["libcommon-v0.2.0.0-cpp.so"]:::bad
    L1 -. "same symbols — first loaded wins" .- L2
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef bad fill:#fee2e2,stroke:#b91c1c,color:#000
    style PROC fill:#f8fafc,stroke:#94a3b8,color:#000
Loading

Build

14. Building one vertical's collection

OK. Each layer builds from its own manifest. One library per (component, version), installed to that layer's mount.

Requirements: VER-5, VER-9, BLD-1, BLD-2, BLD-5, BLD-8

%%{init: {"flowchart": {"wrappingWidth": 400}}}%%
flowchart LR
    SM["SoC manifest<br/>videodecoder 0.2.2.0<br/>audiodecoder 0.3.0.0"]:::ven --> VB
    OM["OEM manifest<br/>hdmicec 0.2.0.1<br/>panel 0.4.1.0"]:::ven --> VB
    MM["MW manifest<br/>videodecoder 0.2.1.0<br/>audiodecoder 0.3.0.0<br/>hdmicec 0.2.0.0<br/>panel 0.4.1.0"]:::mw --> MB
    VB["vendor build"] --> VL["/vendor/usr/lib<br/>libvideodecoder-v0.2.2.0-cpp.so<br/>libaudiodecoder-v0.3.0.0-cpp.so<br/>libhdmicec-v0.2.0.1-cpp.so<br/>libpanel-v0.4.1.0-cpp.so"]:::ven
    MB["MW build"] --> ML["/mw/usr/lib<br/>libvideodecoder-v0.2.1.0-cpp.so<br/>libaudiodecoder-v0.3.0.0-cpp.so<br/>libhdmicec-v0.2.0.0-cpp.so<br/>libpanel-v0.4.1.0-cpp.so"]:::mw
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef ven fill:#fef3c7,stroke:#b45309,color:#000
Loading

15. Cross-layer import at a different version

OK across processes. Not supported in one process (case 13).

Requirements: CON-5, BLD-2

flowchart LR
    subgraph OEM["OEM layer"]
        VS["videosink<br/>imports videodecoder 0.2.0.0"]:::ven
    end
    subgraph SOC["SoC layer"]
        VD["videodecoder 0.2.0.1"]:::ven
    end
    VS -- "ok over binder — separate processes" --> VD
    VS -. "rejected — same process" .-> VD
    classDef ven fill:#fef3c7,stroke:#b45309,color:#000
    style OEM fill:#f8fafc,stroke:#94a3b8,color:#000
    style SOC fill:#f8fafc,stroke:#94a3b8,color:#000
Loading

16. Development build

Not supported in production. A build from current/ is unreleased and reports hash notfrozen. It is accepted only on dev images, with allowUnfrozen.

Requirements: VER-6, BLD-7, BLD-8

flowchart LR
    MW["MW<br/>videodecoder 0.2.1.0"]:::mw
    MW -. "rejected — production" .-> V["Vendor<br/>videodecoder current/<br/>hash notfrozen"]:::bad
    MW -- "ok — dev image, allowUnfrozen" --> V
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef bad fill:#fee2e2,stroke:#b91c1c,color:#000
Loading

Era change

17. One side pre-release, the other stable AIDL

Not supported. The era must match.

Requirements: VER-8

flowchart LR
    MW["MW<br/>videodecoder 0.2.3.0"]:::mw -. "rejected — era not aligned" .-> V["Vendor<br/>videodecoder V1"]:::bad
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef bad fill:#fee2e2,stroke:#b91c1c,color:#000
Loading

18. Both in era 1

OK, in either direction. A vendor ahead serves every earlier client. An MW ahead is supported only if it implements the full stable AIDL version check and fallback in Client Usage of Stable AIDL.

Requirements: VER-7

flowchart LR
    V["Vendor<br/>videodecoder V2"]:::ven
    M1["MW<br/>V1"]:::mw -- "ok — vendor ahead" --> V
    M2["MW<br/>V2"]:::mw -- "ok — exact" --> V
    M3["MW<br/>V3"]:::mw -- "ok — MW does full AIDL version checks" --> V
    classDef mw fill:#dbeafe,stroke:#1d4ed8,color:#000
    classDef ven fill:#fef3c7,stroke:#b45309,color:#000
Loading

Requirements

Draft. Requirements marked Proposed are not yet agreed.

Each case above lists the requirements it shows. MUST, MUST NOT, SHOULD and MAY are as defined in RFC 2119 / RFC 8174. Status: Met: the repository does it today. Gap: required, not yet done; the issue tracks it. Proposed: a programme position not yet written into the SOP.

flowchart LR
    T["Ticket<br/>Interface Effect · Priority · Milestone"] --> PR["PR<br/>one change-class label"]
    PR --> B{"Breaking?"}
    B -- "no" --> MI["minor bump<br/>0.2.1.0 → 0.2.2.0"]
    B -- "yes" --> MA["major bump<br/>0.2.x.x → 0.3.0.0"]
    MI --> AP["Approved and released"]
    MA --> AP
    AP --> S["Released snapshot<br/>immutable"]
    MA -. "older major stays consumed" .-> PL["Planned move of every party<br/>to the new major"]
    S --> R["RAG<br/>per component"]
    S --> P["MW and vendor pins<br/>per layer manifest"]
    P --> C{"Same major,<br/>vendor ≥ MW?"}
    C -- "yes" --> OK["Runs"]
    C -- "no" --> NO["Rejected by<br/>halcompat::isCompatible()"]
Loading

Versioning

ID Requirement UC Status
VER-1 Each component MUST be versioned and released independently, as 0.<major>.<minor>.<bugfix> before stable AIDL. A component's version MUST NOT move because another component changed, except through a declared import (common@0.2.0.0). 1–3 Met
VER-2 A backwards-compatible pre-release change MUST bump minor. 2, 3, 4, 7 Met
VER-3 A pre-release change MAY break compatibility, and MUST bump major. The new major is developed while clients keep consuming the older released major. 5, 6, 8–12 Met
VER-4 A bugfix bump MUST NOT change the interface surface. 3 Met
VER-5 A released snapshot <component>/<version>/ MUST NOT be modified after release. This applies to pre-release snapshots, not only to stable versions. 14 Met
VER-9 A released snapshot MUST carry the contract only: AIDL, declared pins, hash and documentation. Its build files MUST be a symlink to the shared build, not a copy inside the snapshot. 14 Gap #828
VER-6 Every service MUST report its version and contract hash. A client MUST check compatibility with isCompatible() before use. An unreleased build (hash notfrozen) MUST be rejected in production. 7–9, 16 Met
VER-7 A component MAY move to stable AIDL once its criteria are met (SOP §7). Its first stable release is V1; from then its version is an integer from V1, changes are additive only, and every client/server pairing is compatible. A client ahead of the server MUST do full version checking and fallback. 18 Gap #857
VER-8 A pre-release side and a stable side of the same component MUST be treated as incompatible. 17 Met

Consumption

ID Requirement UC Status
CON-1 Each consumer MUST choose, per component, the version it builds against: current, next, or both through a transition. The choice MUST stay in effect until that consumer changes it. 1, 4, 10 Met
CON-2 The vendor MUST deliver, per component, the same major as the MW, at or above the MW's minor. 1–3, 5, 11 Met (runtime check)
CON-3 The MW is common across vendor verticals. Its pin per component MUST be at or below the lowest minor that every target vertical delivers, on the same major. 6, 12 Proposed
CON-4 Alignment MUST be per component, not per layer or per vertical. A layer late on one component MUST NOT hold back the others. 5, 11 Met
CON-5 One process MUST hold one version of each component, until symbols are made version-distinct. 13, 15 Gap: decision needed
CON-6 A consumer moving to a new major while others stay on the old one MUST have a declared outcome: lockstep, or the vendor serves both majors. 10, 12 Gap: decision needed
CON-7 Every released major MUST stay available for consumption until every party consuming it has moved off it. 8–12 Proposed
CON-8 Moving to a later major MUST be planned across every party: each MW consumer and each vendor layer in each vertical. The plan states where each party is, the version it needs to reach, and when. 10–12 Proposed

Build

ID Requirement UC Status
BLD-1 Each layer MUST build from its own versions manifest. The manifest is identifiable and reproducible: the released cohort at a repo tag. 14 Met
BLD-2 The closure MUST build every (component, version) a dependent links, one lib<comp>-v<ver>-cpp.so per version, installed under that layer's mount. 14, 15 Met
BLD-3 Client and server MUST each be buildable and testable in isolation against a chosen version, without the other side or a full product build. 1 Met
BLD-4 A common integration build MUST build MW and vendor against one baseline and call every interface over binder. 4, 5 Gap #817, #815
BLD-5 Each layer MUST resolve its own libraries at runtime (per-layer RUNPATH). 14 Met
BLD-6 The alignment in CON-2 MUST be checked with halcompat::isCompatible(), so a mismatch is reported, not found by failure. 6, 12 Met
BLD-7 Development builds (CI and merges to develop) MAY build any revision, pre-release and current/ included. They are the development cycle and release nothing. 16 Met
BLD-8 The tip of the interface repository is not for consumption. A production build MUST consume approved, released, versioned component snapshots, chosen per component by that component's release strategy. It MUST NOT consume develop or current/. 14, 16 Met

Change control

ID Requirement Status
CHG-1 Every change MUST start as a GitHub issue, on a branch feature/{issue}-{synopsis}, merged through a PR. Met
CHG-2 Every PR MUST carry exactly one change-class label. The label determines the version bump. Met
CHG-3 The project's Interface Effect field (Major, CR-Major, New Interface, Minor, BugFix, Documentation, Infrastructure) MUST agree with the labels. One of the two is authoritative for the bump. Gap #825, #827
CHG-4 A Major or CR-Major change MUST link to the adoption plan for its new major (CON-8). Proposed
CHG-5 Every programme ticket MUST carry its Jira link in the project's Jira field, and its committed date in End date. Met

Prioritisation

ID Requirement Status
PRI-1 Every ticket scheduled into a milestone MUST carry a Priority (P0–P3) and a T-shirt estimate. Proposed
PRI-2 Priority MUST follow delivery impact. P0: blocks a vendor or MW delivery of an aligned major. P1: an open breaking change against a GREEN component. P2: additive change. P3: documentation and infrastructure. Proposed
PRI-3 A ticket closed or merged MUST carry the current milestone, never a future one, on both the PR and its linked issue. Proposed

RAG

ID Requirement Status
RAG-1 Every component MUST carry RED / AMBER / GREEN in metadata.yaml per SOP §4. GREEN means implementable by vendors at its current version. Met
RAG-2 The RAG report MUST show open Major or CR changes against a GREEN component. Gap #802
RAG-3 A major bump on a GREEN component MUST go through a new review cycle before it merges. Met (SOP §4)
RAG-4 Every RAG change MUST be diffed against the previous snapshot, so each upgrade and downgrade is explicit. Met (daily snapshots)

Clone this wiki locally