Trade Study: Metric Key Set — Android HAL evidence - rdkcentral/rdk-halif-aidl GitHub Wiki

  • Type: Evidence sheet, companion to Trade Study: Metric Key Set — how it is carried
  • Audience: Anyone checking a claim about what Android HALs do with a list of reportable items
  • Purpose: Every HAL in hardware/interfaces at android-17.0.0_r1 that reports a set of named figures, statuses or parameters, sorted by where it keeps the list, with what each frozen version bump carried and which teams changed shape

Overview

What this is. Every HAL in hardware/interfaces at android-17.0.0_r1 that reports a set of named figures, statuses or parameters, sorted by where it keeps the list of what can be asked for, with what each frozen version bump carried.

What it covers. Six HALs that type the list into the interface, seven that keep it beside the interface, the size and version history of each, which HALs changed shape between Android 8 and 17, what Android's own guidance says, and two telemetry paths that are not HALs. No argument, no recommendation.

Who it is for. Anyone deciding whether the getMetrics() key set belongs inside the interface or beside it, and wanting to see which Android HALs do which.

Every figure is read from an AOSP tree at android-17.0.0_r1, the current Android release, by the method stated beside it, and every file quoted is linked at that commit. Counts were produced on 2026-09-21.


Two shapes of static interface

Every Android 17 HAL is a static interface: methods, parcelables and a .hash frozen per version. The HALs differ in one thing only — whether the list of what can be asked for is part of what freezes.

flowchart LR
    subgraph S1["Shape 1 — the list is typed into the interface"]
        direction TB
        A1["<b>frozen interface vN</b><br/>methods · envelope · <b>the list</b><br/>an enum, or one struct member per figure"]
        A2["<b>interface vN+1</b>"]
        A1 -->|"one new item"| A2
    end
    subgraph S2["Shape 2 — the list is beside the interface"]
        direction TB
        B1["<b>frozen interface vN</b><br/>methods · envelope<br/>selector: int[] · String[] · byte[]"]
        B2["<b>the list</b><br/>a header · a schema file ·<br/>a separate package · runtime data"]
        B3["the list, revised"]
        B1 -.->|"names items from"| B2
        B2 -->|"one new item"| B3
    end
    style A1 fill:#FCF3CF,color:#1a1a1a,stroke:#8a6d1f
    style A2 fill:#F5B7B1,color:#1a1a1a,stroke:#922b21
    style B1 fill:#FCF3CF,color:#1a1a1a,stroke:#8a6d1f
    style B2 fill:#ABEBC6,color:#1a1a1a,stroke:#1e7a4d
    style B3 fill:#ABEBC6,color:#1a1a1a,stroke:#1e7a4d
    style S1 fill:#FFFDF3,color:#1a1a1a,stroke:#8a6d1f
    style S2 fill:#F4FBF6,color:#1a1a1a,stroke:#1e7a4d
Loading

Android 17 uses both. Which one a HAL uses tracks three properties of its list:

Shape 1 — typed in Shape 2 — beside
HALs TV tuner, TV media quality, health, thermal, sensors, power power stats, Codec2, camera, vehicle, gralloc, audio core, DRM
Size of the list 21 – 112 items 146 parameters, 374 camera tags, or unbounded runtime data
Who adds to it Google alone Google and vendors — each reserves a vendor range or leaves the list to the product
When it moves with the platform release — no HAL here cut more than one version per Android release whenever the header, schema file or product changes
Cost of one new item one frozen interface version none to the interface

Shape 1 — the list is typed into the interface

HAL What the interface declares Size of the list Newest frozen version at Android 13 · 14 · 15 · 16 · 17
TV tuner (android.hardware.tv.tuner) FrontendStatus[] getStatus(in FrontendStatusType[] statusTypes) — an array of enumerators selects, a union answers FrontendStatusType: 42 → 47 → 48 across versions 1 → 2 → 3 1 · 2 · 2 · 3 · 3
TV media quality (android.hardware.tv.mediaquality) getParamCaps(in ParameterName[] paramNames, out ParamCapability[] caps), with getVendorParamCaps(in VendorParameterIdentifier[] names, …) beside it for what vendors add, over a ParcelableHolder ParameterName: 96 → 112 across versions 1 → 2 – · – · – · 1 · 2
Health (android.hardware.health) HealthInfo getHealthInfo() — a parcelable with one member per figure, plus one getter per figure such as getChargeCounterUah() one struct 1 · 2 · 3 · 4 · 5
Thermal (android.hardware.thermal) Temperature[] getTemperaturesWithType(in TemperatureType type) TemperatureType: 15 → 21 → 21 – · 1 · 2 · 3 · 3
Sensors (android.hardware.sensors) SensorInfo { SensorType type; … } SensorType: 43 → 43 → 44 1 · 2 · 2 · 3 · 3
Power (android.hardware.power) setMode(in Mode type, …), setBoost(in Boost type, …) closed enums 3 · 4 · 5 · 6 · 7

The tuner is an AV HAL, and its status read is the typed-in shape at its plainest: an enum array in, typed values out. It also answers capability per item, through getFrontendStatusReadiness(in FrontendStatusType[] statusTypes) returning UNDEFINED, UNAVAILABLE, UNSTABLE, STABLE or UNSUPPORTED for each.

What each version bump carried, where the bump is six added lines or fewer:

HAL Bump Files changed The whole content of the version
Power 6 → 7 1 of 22 AUDIO_PERFORMANCE,
Power 2 → 3 1 of 5 GAME = 15, GAME_LOADING = 16,
Sensors 2 → 3 1 of 8 MOISTURE_INTRUSION = 43,
Power stats 1 → 2 1 of 11 CAMERA, — added to its one closed enum
Health 4 → 5 2 of 13 batteryManufacturer, batteryModelName, batteryVoltageMinDesignUv, FORCE_FULL_CHARGE
Thermal 2 → 3 2 of 9 one method and one callback
TV tuner 2 → 3 4 of 193 one status type, STANDARD_EXT, with its union member and the enum it returns

Health cut a version at every Android release from 13 to 17, and versions 3, 4 and 5 each consist of members added to the reporting parcelables.

The tuner's HIDL history shows what the shape costs once a list is frozen and the language cannot extend it. [email protected] froze getStatus(vec<FrontendStatusType>) over 22 status types. Adding 15 more in [email protected] took a second enum, FrontendStatusTypeExt1_1, and a second method beside the first, getStatusExt1_1(vec<FrontendStatusTypeExt1_1>). The AIDL rewrite merged them into one enum of 42.

Shape 2 — the list is beside the interface

Power stats, the metrics HAL

android.hardware.power.stats measures power. Searching every .aidl file in hardware/interfaces for an interface whose subject is metrics, statistics or telemetry returns this one and nothing else.

PowerEntity[]             getPowerEntityInfo();
StateResidencyResult[]    getStateResidency(in int[] powerEntityIds);
EnergyConsumer[]          getEnergyConsumerInfo();
EnergyConsumerResult[]    getEnergyConsumed(in int[] energyConsumerIds);
Channel[]                 getEnergyMeterInfo();
EnergyMeasurement[]       readEnergyMeter(in int[] channelIds);

Three lists, three reads. Each list is returned at runtime as { int id; String name; … }; each read names what it wants with an int[] of those ids. Nothing the product measures is a type in the interface, so a product that measures more returns a longer list under the same frozen version.

The package uses both shapes side by side. Its one enum, EnergyConsumerType, classifies a consumer as OTHER, BLUETOOTH, CPU_CLUSTER, DISPLAY, GNSS, MOBILE_RADIO or WIFI, and that enum is the only thing its second version changed: ten of eleven files are byte-identical, and the eleventh gained CAMERA.

Android discovers this list at runtime, where a declared key set derives identifiers ahead of time. Both keep the list out of what freezes. getStateResidency documents EX_ILLEGAL_ARGUMENT for an invalid id, which works because a caller reads the list from the same product before naming anything from it; a caller built against a newer declaration than the product needs NOT_SUPPORTED instead.

The rest

HAL What the interface declares Where the list lives Size, Android 10 → 17 Frozen interface versions
Codec2 (android.hardware.media.c2) QueryResult query(in int[] indices, in boolean mayBlock). HIDL 1.0 the same, over typedef uint32_t ParamIndex. enum C2ParamIndexKind in C2Config.h, in frameworks/av — a different repository from the HAL. Vendors take their own range from TYPE_INDEX_VENDOR_START = 0x00008000. 109 → 146 1 2 — the bump carried one line in IInputSurfaceConnection.aidl; query is unchanged
Camera (android.hardware.camera.device) parcelable CameraMetadata { byte[] metadata; } camera/docs/metadata_definitions.xml in system/media: a schema language Google defined, with its own generator producing headers and documentation 262 → 374 1 2 3 4
Vehicle (android.hardware.automotive.vehicle) VehiclePropValue { int prop; … }; getPropConfigs(in int[] props) VehicleProperty enum in the separate package android.hardware.automotive.vehicle.property — vehicle 1 2 3 4; property 1 2 3 4
Gralloc (IMapper 4.0 and stable-c) MetadataType { string name; int64_t value; }; C ABI getStandardMetadata(buffer, int64_t standardMetadataType, …) with listSupportedMetadataTypes() StandardMetadataType.aidl in the separately versioned package android.hardware.graphics.common — graphics.common: 1 2 3 4 5 6 7
Audio core (android.hardware.audio.core) getVendorParameters(in @utf8InCpp String[] ids); VendorParameter { String id; ParcelableHolder ext; } outside the AIDL entirely — 1 2 3 4
DRM (android.hardware.drm) List<DrmMetricGroup> getMetrics(); DrmMetric { String name; … } "The scope and definition of the metrics is defined by the plugin." — 1 2

Searching the HAL tree for a method that names what it wants with an array of identifiers returns twenty-four. Seven select from a list of this kind — Codec2 query, the three power-stats reads, vehicle getPropConfigs, broadcast radio getParameters(in String[] keys), audio core getVendorParameters — and the rest name runtime objects such as sensor handles, enrolment ids and stream ids.

Gralloc records why its list left the interface, in IMapper.hal:

In order to allow arbitrary vendor defined metadata, we could not use a HIDL enum as the buffer metadata token. Extending a HIDL enum requires a full HIDL extension. We also could not use a simple non-HIDL enum because vendor defined enums from different vendors could collide. […] The standard buffer metadata types are NOT defined as a HIDL enum because it would have required a new IMapper version just to add future standard buffer metadata types. By putting the enum in the stable AIDL (hardware/interfaces/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl), vendors will be able to optionally choose to support future standard buffer metadata types without upgrading HIDL versions.

The list moved out of the interface that carries it, and into another AIDL package rather than into a new definition language. That package, android.hardware.graphics.common, has seven frozen versions, and AOSP's versioning documentation names it: "In Android platform code android.hardware.graphics.common is the biggest example of this type of version upgrade."


Direction of travel, Android 8 to 17

No HAL history shows a general migration from one shape to the other. A HAL takes a shape when it is designed, most keep it, and the newest TV HAL took the typed one.

When HAL What happened Direction
Android 8 → 17 Health Typed throughout: HIDL 1.0, 2.0, 2.1, then AIDL versions 1–5 stayed typed
Android 11 → 17 TV tuner Typed throughout. The AIDL rewrite at Android 13 merged the two HIDL enums into one and kept the shape stayed typed
Android 16 TV media quality New HAL. 96 parameter names as an enum in the interface, 112 one version later, and a second method for vendor parameters took typed
Android 8 → 13 Audio HIDL read everything through getParameters(vec<ParameterValue> context, vec<string> keys). AIDL replaced the known set with typed methods and kept a string-id read for vendor parameters only strings → typed, vendor set left beside
Android 8 → 10 Power → power stats Statistics were methods on the Power HAL: getPlatformLowPowerStats() in [email protected], then a second method, getSubsystemLowPowerStats(), in [email protected]. [email protected] replaced both with product-returned lists read by vec<uint32_t> ids. The AIDL IPower carries no statistics typed → beside
Android 11 Gralloc IMapper 4.0 introduced buffer metadata with the list in a separate package, and recorded why designed beside
Android 13 → 14 Vehicle VehicleProperty moved out of the interface package into android.hardware.automotive.vehicle.property typed → beside

The vehicle move states its reason in the commit, 4247384b, 2023-01-05:

Split VHAL property definitions and enums out from the VHAL interface so that we can update the property separatly. This allows us to backport new property definition to older releases more easily.

The reason given is cadence — revising the list apart from the interface, and reaching releases already shipped — and the destination is a separate AIDL package rather than another definition language. The two packages have so far frozen together: version 2 at Android 14, 3 at 15, 4 at 16.

android.hardware.wifi.common (Android 15) and android.hardware.drm.common (Android 16) are also types-only packages split out of a HAL. Their commits give sharing between HALs as the reason, so they are not evidence on cadence.

The shape follows the owning team

Each HAL directory names its owners, and the shape tracks them. No owner is shared between a typed-in HAL and a beside HAL.

Owners, from each OWNERS file at android-17.0.0_r1 HALs Shape
quxiangfang, shubang — the TV team TV tuner, TV media quality both typed, both read by an enum array
ADPF_OWNERS in frameworks/base thermal, power both typed
apelosi, dvander, wjack, zhengdaniel health typed
darrenhsu, joaodias, krossmo, vincentwang power stats beside
the media codec authors — taklee, pawin, wonsik Codec2 beside
frameworks/av camera owners camera beside
the car services owners vehicle typed at Android 13, beside from 14
core graphics owners gralloc, graphics.common beside

So TV media quality taking the typed shape at Android 16 is the tuner's owners repeating their own design, not a second independent choice. The vehicle move runs the other way in the same sense: commit 4247384b was written by shanyu, the principal author of the vehicle AIDL HAL with 269 commits to it, so the team that had lived with the list inside its interface for a release is the team that moved it out.

Two people appear among the main authors of three or more of these HALs, smoreland in seven and devinmoore in four, both across typed and beside HALs alike. Nothing in the tree or the guidance assigns a shape centrally.

What Android's guidance says

Android publishes no statement that HALs should move from one shape to the other. It publishes the rule both shapes follow. From AIDL API guidelines and Stable AIDL on source.android.com, retrieved 2026-09-21:

Enums should be closed sets. Note: only the interface owner can add enum elements. If vendors or OEMs need to extend these fields, an alternative mechanism is needed.

Whenever a client or server of the API is released (for example, in a Mainline train), you need to take a snapshot and make a new version. For system-to-vendor APIs, this should happen with the yearly platform revision.

Generally, for types-only or common packages, this is safe because code needs to already be written to handle unknown types from IPC transactions. In Android platform code android.hardware.graphics.common is the biggest example of this type of version upgrade.

Use strongly typed parcelable objects instead of serialized strings or JSON over IPC.

An enum is for a list with one owner. A system-to-vendor interface is revised once a year. A list that must move otherwise goes into a types-only package, which is upgraded apart from the interfaces that import it. Every row of the history is consistent with that.


Telemetry paths that are not HALs

Path What the interface declares Where the list lives Size, Android 10 → 17 Interface versions
mediametrics oneway void submitStructuredItem(in android.media.metrics.StructuredItem p) — Property[], each { @utf8InCpp String mName; Value mValue; } over a union of int, long, double, String and a Rate pair. Android 12–16 carried submitBuffer(in byte[] buffer). Property names are free strings declared nowhere. Component keys — audiotrack, codec, mediadrm, videofreeze — are @utf8InCpp const String constants in the AIDL, not an enum. 26 → 46 android.media.mediacodec.* keys one method, its parameter replaced once at Android 17
IStats vendor atoms oneway void reportVendorAtom(in VendorAtom vendorAtom); VendorAtom { String reverseDomainName; int atomId; VendorAtomValue[] values; } .proto files outside the interface; Pixel's is pixelstats/pixelatoms.proto Pixel: 3 → 67 (Android 10 → 16; the project has no Android 17 tag) android.frameworks.stats: 1 2

What happened to the typed methods on IStats

The HIDL interface [email protected]::IStats declared ten oneway methods through Android 16: nine named for a particular event, plus a generic carrier. At android-17.0.0_r1 the HIDL interface is deleted and only the AIDL one remains.

reportSpeakerImpedance      reportBatteryHealthSnapshot    reportUsbPortOverheatEvent
reportHardwareFailed        reportSlowIo                   reportSpeechDspStat
reportPhysicalDropDetected  reportBatteryCausedShutdown    reportChargeCycles
                            reportVendorAtom

The AIDL interface declares one method:

@VintfStability
interface IStats {
    oneway void reportVendorAtom(in VendorAtom vendorAtom);
}

All nine of the typed methods are now entries in Pixel's vendor atom vocabulary, each carrying the annotation // moved from atoms.proto:

HIDL method Vendor atom Id
reportSpeakerImpedance VendorSpeakerImpedance 105013
reportChargeCycles VendorChargeCycles 105018
reportHardwareFailed VendorHardwareFailed 105019
reportSlowIo VendorSlowIo 105020
reportSpeechDspStat VendorSpeechDspStat 105021
reportPhysicalDropDetected VendorPhysicalDropDetected 105022
reportUsbPortOverheatEvent VendorUsbPortOverheat 105023
reportBatteryHealthSnapshot VendorBatteryHealthSnapshot 105026
reportBatteryCausedShutdown VendorBatteryCausedShutdown 105027

Google published no statement of why the typed methods were dropped — the change landed on an internal Gerrit and the public commit log is not readable anonymously. The table is what the source records, and no motive is claimed beyond it.


What this does not show

  • Neither shape is the exception, and neither is being retired. Six HALs type their list into the interface and seven keep it beside; a claim that Android HALs do only one of these is wrong in either direction.
  • The TV tuner is the closest Android match to an enum-array selector on an AV HAL, and it is shape 1.
  • IStats is not a device HAL. It is a framework-provided service that vendor daemons call, and it does not appear in the device compatibility matrix. Anyone looking for IStats among the AV HAL implementations is right not to find it.
  • Audio core and DRM are vendor-scoped surfaces. Their vocabularies are explicitly outside any platform contract, which makes them weaker precedent than Codec2, camera or gralloc.
  • The vehicle HAL does not demonstrate independent cadence. Both its packages show four versions. It demonstrates the separation, not the benefit.
  • The core atoms.proto count is not comparable across the whole range. From Android 14 atoms increasingly live in per-module directories, so the in-file figure understates the vocabulary from then on: 370 in-file at Android 12 with no module directories, against 120 in-file and 110 module directories at Android 17.

Reproducing the figures

Every figure and quotation is read at android-17.0.0_r1, the current Android release and the newest state AOSP publishes. The main branch is not used: for hardware/interfaces it has not moved since 2025-03-26 and is 3,249 commits behind this baseline.

Commits the tables above were read at:

Project Commit
platform/hardware/interfaces 0162af698935100a590b7359581ac8b1b80693e5 — the android-17.0.0_r1 commit
platform/frameworks/av 475269ec44acec82792be6b01fb8e16357d4d2c8
platform/system/media 440eb272fd3da0ca7bdae932e61e7fd9be1fd324
platform/frameworks/hardware/interfaces 9de6d032a248523c22d0bd86e224d1762355c41e
platform/frameworks/proto_logging a07b791ea1e2a4dae1c535c8423235fdc22aaf02
platform/frameworks/native ae266dcb706d083868578cfedce381ef44488a07
platform/hardware/google/pixel b3d2fee9bf2b42569aef7318b84b17026adfc597 — the android-16.0.0_r1 commit, its newest

Files quoted, at those commits:

Claim File and line
Power stats reads and vocabulary IPowerStats.aidl:37-42 · PowerEntity.aidl:26 · EnergyConsumerType.aidl:21
Tuner status read and readiness IFrontend.aidl:107 · :170 · FrontendStatusType.aidl
Tuner HIDL second method 1.0/IFrontend.hal:132 · 1.1/IFrontend.hal:110 · 1.1/types.hal:594
Health, thermal, sensors, power IHealth.aidl:205 · IThermal.aidl:92 · SensorInfo.aidl:51 · IPower.aidl:45
TV media quality reads IMediaQuality.aidl:221 · :226
Power HAL statistics methods power/1.0/IPower.hal:87 · power/1.1/IPower.hal:34
Android guidance AIDL API guidelines · Stable AIDL, retrieved 2026-09-21
Codec2 AIDL selector IConfigurable.aidl:40
Codec2 HIDL selector IConfigurable.hal:93 · types.hal:82
Codec2 vendor range C2Param.h:140
Gralloc rationale IMapper.hal:391-406
Gralloc C ABI IMapper.h:500 · :592
Camera metadata parcelable CameraMetadata.aidl:28
Camera tag schema metadata_definitions.xml
Vehicle property id VehiclePropValue.aidl:41
Audio vendor parameters IModule.aidl:844 · :858
DRM metrics IDrmPlugin.aidl:43 · DrmMetric.aidl:29
mediametrics transport IMediaMetricsService.aidl · StructuredItem.aidl:64,100
IStats HIDL methods IStats.hal:31 at android-16.0.0_r1 — the file no longer exists at the baseline
IStats AIDL method IStats.aidl:34
Moved vendor atoms pixelatoms.proto:54


Document History

Date Author Comments
22nd September 2026 G. Weatherup Initial revision
⚠️ **GitHub.com Fallback** ⚠️