xref: /aosp_15_r20/system/chre/api_parser/README.md (revision 84e339476a462649f82315436d70fd732297a399)
1*84e33947SAndroid Build Coastguard Worker# CHRE API Parser + Code Generator for CHPP
2*84e33947SAndroid Build Coastguard Worker
3*84e33947SAndroid Build Coastguard WorkerSince one of the main use cases of CHPP is to support remoting a CHRE PAL
4*84e33947SAndroid Build Coastguard Workerimplementation to a peripheral component, we leverage the CHRE PAL API
5*84e33947SAndroid Build Coastguard Workerdefinitions for the platform-specific implementation of those services, such
6*84e33947SAndroid Build Coastguard Workeras the WWAN service. However, the structures used in the CHRE PAL APIs are the
7*84e33947SAndroid Build Coastguard Workersame as those used in the CHRE API for nanoapps, which are not inherently
8*84e33947SAndroid Build Coastguard Workerserializable, as they include things like pointers to other structures. So we
9*84e33947SAndroid Build Coastguard Workermust create slightly updated versions of these to send over the wire with CHPP.
10*84e33947SAndroid Build Coastguard Worker
11*84e33947SAndroid Build Coastguard WorkerThe `chre_api_to_chpp.py` script in this directory parses CHRE APIs according
12*84e33947SAndroid Build Coastguard Workerto instructions given in `chre_api_annotations.json` and generates structures
13*84e33947SAndroid Build Coastguard Workerand conversion code used for serialization and deserialization.
14*84e33947SAndroid Build Coastguard Worker
15*84e33947SAndroid Build Coastguard Worker## Serialization format
16*84e33947SAndroid Build Coastguard Worker
17*84e33947SAndroid Build Coastguard Worker_TL;DR: The CHPP format is just a packed and flattened version of the CHRE
18*84e33947SAndroid Build Coastguard Workerstructures, replacing pointers with offsets._
19*84e33947SAndroid Build Coastguard Worker
20*84e33947SAndroid Build Coastguard WorkerThe serialized output is meant to match the source CHRE structure as closely as
21*84e33947SAndroid Build Coastguard Workerpossible, however some special handling is needed to be able to send them over
22*84e33947SAndroid Build Coastguard Workerthe wire to a different processor in the system. The general process for
23*84e33947SAndroid Build Coastguard Worker generating a serializable CHPP version of a CHRE structure is as follows:
24*84e33947SAndroid Build Coastguard Worker
25*84e33947SAndroid Build Coastguard Worker 1. Rewrite the name to start with "Chpp" instead of "chre" and mark it packed,
26*84e33947SAndroid Build Coastguard Worker    to ensure there's no padding between fields (which is compiler-dependent)
27*84e33947SAndroid Build Coastguard Worker 1. Flatten the structure by replacing pointers to nested structures/arrays with
28*84e33947SAndroid Build Coastguard Worker    a ChppOffset which describes the location in the payload where the nested
29*84e33947SAndroid Build Coastguard Worker    data resides.
30*84e33947SAndroid Build Coastguard Worker 1. A CHPP application layer header is allocated for convenience when used in
31*84e33947SAndroid Build Coastguard Worker    CHPP. The header values need to be set by CHPP and they are not zeroed out.
32*84e33947SAndroid Build Coastguard Worker    The header length is not included in the offset calculation.
33*84e33947SAndroid Build Coastguard Worker
34*84e33947SAndroid Build Coastguard WorkerChppOffset is a collection of a 16-bit offset from the beginning of the payload,
35*84e33947SAndroid Build Coastguard Workerand a length. While we could implicitly derive the offset, the length cannot
36*84e33947SAndroid Build Coastguard Workerexceed 16 bits due to limitations in the encapsulating CHPP protocol
37*84e33947SAndroid Build Coastguard Worker(and we don't expect to bump up against this limit anyways), and including the
38*84e33947SAndroid Build Coastguard Workeroffset field helps simplify decoding.
39*84e33947SAndroid Build Coastguard Worker
40*84e33947SAndroid Build Coastguard WorkerThis approach allows for a highly optimized, in-place encoding and decoding that
41*84e33947SAndroid Build Coastguard Workeronly requires converting between pointer and ChppOffset types, if the following
42*84e33947SAndroid Build Coastguard Workerconditions are met:
43*84e33947SAndroid Build Coastguard Worker
44*84e33947SAndroid Build Coastguard Worker 1. The size of the CHRE and CHPP structures are the same, and the offsets to
45*84e33947SAndroid Build Coastguard Worker    all contained fields are the same, and the same property holds for all
46*84e33947SAndroid Build Coastguard Worker    nested structures/unions
47*84e33947SAndroid Build Coastguard Worker 1. (Encoding only) All nested structures appear in contiguous memory - for
48*84e33947SAndroid Build Coastguard Worker    example, if a structure has a pointer to an array, then the array appears
49*84e33947SAndroid Build Coastguard Worker    immediately after the structure in memory, with no padding
50*84e33947SAndroid Build Coastguard Worker 1. (Decoding only) Processor alignment constraints are met for all fields, such
51*84e33947SAndroid Build Coastguard Worker    that they can be safely accessed through normal means at the location in
52*84e33947SAndroid Build Coastguard Worker    memory at which they reside, when accounting for any headers, etc.
53*84e33947SAndroid Build Coastguard Worker
54*84e33947SAndroid Build Coastguard WorkerIf conditions 2 or 3 are not met, then optimized encode/decode is still possible
55*84e33947SAndroid Build Coastguard Workerafter copying the memory to a separate allocation. So in-place conversion can't
56*84e33947SAndroid Build Coastguard Workerbe done, but the only translation needed is between pointer and ChppOffset. If
57*84e33947SAndroid Build Coastguard Workerthe first condition is not met, then conversion is done using field-wise
58*84e33947SAndroid Build Coastguard Workerassignment, which allows the compiler to generate the necessary instructions to
59*84e33947SAndroid Build Coastguard Workerhandle differences in alignment and packing.
60*84e33947SAndroid Build Coastguard Worker
61*84e33947SAndroid Build Coastguard WorkerAll generated code currently assumes that it's running on a little endian CPU,
62*84e33947SAndroid Build Coastguard Workeras the wire format requires little endian byte order.
63*84e33947SAndroid Build Coastguard Worker
64*84e33947SAndroid Build Coastguard WorkerTODO: The script currently only generates code for the pessimistic case, where
65*84e33947SAndroid Build Coastguard Workernone of the constraints are met. By generating code that checks sizeof/offsetof
66*84e33947SAndroid Build Coastguard Workeron all fields and placing the optimized path in an if/else condition, the
67*84e33947SAndroid Build Coastguard Workercompiler can evaluate condition 1 and prune away code for the less-optimal path.
68*84e33947SAndroid Build Coastguard Worker
69*84e33947SAndroid Build Coastguard Worker## Annotations
70*84e33947SAndroid Build Coastguard Worker
71*84e33947SAndroid Build Coastguard WorkerAs the C API does not have enough information for the script to know how to
72*84e33947SAndroid Build Coastguard Workerhandle things like variable-length arrays (VLAs), we use the
73*84e33947SAndroid Build Coastguard Worker`chre_api_annotations.json` file to provide this detail. The supported fields
74*84e33947SAndroid Build Coastguard Worker are explained in the illustrated example below:
75*84e33947SAndroid Build Coastguard Worker
76*84e33947SAndroid Build Coastguard Worker```json
77*84e33947SAndroid Build Coastguard Worker[// A list of entries for each input file
78*84e33947SAndroid Build Coastguard Worker{
79*84e33947SAndroid Build Coastguard Worker  // Path starting at <android_root>/system/chre to the input file
80*84e33947SAndroid Build Coastguard Worker  "filename": "chre_api/include/chre_api/chre/wwan.h",
81*84e33947SAndroid Build Coastguard Worker  // List of #includes that also need to be parsed, e.g. because they provide
82*84e33947SAndroid Build Coastguard Worker  // struct definitions that are used in the file
83*84e33947SAndroid Build Coastguard Worker  "includes": [
84*84e33947SAndroid Build Coastguard Worker    "chre_api/include/chre_api/chre/common.h"
85*84e33947SAndroid Build Coastguard Worker  ],
86*84e33947SAndroid Build Coastguard Worker  // Which files the output header should pull in to satisfy dependencies
87*84e33947SAndroid Build Coastguard Worker  "output_includes": [
88*84e33947SAndroid Build Coastguard Worker    "chpp/common/common_types.h",
89*84e33947SAndroid Build Coastguard Worker    "chre_api/chre/wwan.h"
90*84e33947SAndroid Build Coastguard Worker  ],
91*84e33947SAndroid Build Coastguard Worker  // A list of entries providing additional information for structs/unions that
92*84e33947SAndroid Build Coastguard Worker  // appear in the input
93*84e33947SAndroid Build Coastguard Worker  "struct_info": [
94*84e33947SAndroid Build Coastguard Worker    {
95*84e33947SAndroid Build Coastguard Worker      "name": "chreWwanCellInfoResult",
96*84e33947SAndroid Build Coastguard Worker      // List of annotations for fields within the struct
97*84e33947SAndroid Build Coastguard Worker      "annotations": [
98*84e33947SAndroid Build Coastguard Worker        // Instead of copying the input, always force setting a specific value
99*84e33947SAndroid Build Coastguard Worker        // for a field. The value is whatever should appear in the code for the
100*84e33947SAndroid Build Coastguard Worker        // assignment statement, or the value to memset it to for an array type.
101*84e33947SAndroid Build Coastguard Worker        {
102*84e33947SAndroid Build Coastguard Worker          // Which field within the struct this annotation applies to
103*84e33947SAndroid Build Coastguard Worker          "field": "version",
104*84e33947SAndroid Build Coastguard Worker          // The type of annotation we're supplying
105*84e33947SAndroid Build Coastguard Worker          "annotation": "fixed_value",
106*84e33947SAndroid Build Coastguard Worker          // Additional information is dependent upon the annotation type
107*84e33947SAndroid Build Coastguard Worker          "value": "CHRE_WWAN_CELL_INFO_RESULT_VERSION"
108*84e33947SAndroid Build Coastguard Worker        },
109*84e33947SAndroid Build Coastguard Worker        // Since the 'cookie' field here is a void*, we're rewriting to a
110*84e33947SAndroid Build Coastguard Worker        // uint32_t to keep the same structure size + field offsets (on 32-bit
111*84e33947SAndroid Build Coastguard Worker        // architectures) - in practice we'll also force the value to 0
112*84e33947SAndroid Build Coastguard Worker        {
113*84e33947SAndroid Build Coastguard Worker          "field": "cookie",
114*84e33947SAndroid Build Coastguard Worker          "annotation": "rewrite_type",
115*84e33947SAndroid Build Coastguard Worker          "type_override": "uint32_t"
116*84e33947SAndroid Build Coastguard Worker        },
117*84e33947SAndroid Build Coastguard Worker        // Indicates a variable length array field, with the number of elements
118*84e33947SAndroid Build Coastguard Worker        // given by another field in the same structure called cellInfoCount
119*84e33947SAndroid Build Coastguard Worker        {
120*84e33947SAndroid Build Coastguard Worker          "field": "cells",
121*84e33947SAndroid Build Coastguard Worker          "annotation": "var_len_array",
122*84e33947SAndroid Build Coastguard Worker          "length_field": "cellInfoCount"
123*84e33947SAndroid Build Coastguard Worker        }
124*84e33947SAndroid Build Coastguard Worker      ]
125*84e33947SAndroid Build Coastguard Worker    },
126*84e33947SAndroid Build Coastguard Worker    {
127*84e33947SAndroid Build Coastguard Worker      "name": "chreWwanCellInfo",
128*84e33947SAndroid Build Coastguard Worker      "annotations": [
129*84e33947SAndroid Build Coastguard Worker        // In this case, we have a union field, where only one of the members is
130*84e33947SAndroid Build Coastguard Worker        // used, according to the provided mapping on the adjacent discriminator
131*84e33947SAndroid Build Coastguard Worker        // field
132*84e33947SAndroid Build Coastguard Worker        {
133*84e33947SAndroid Build Coastguard Worker          "field": "CellInfo",
134*84e33947SAndroid Build Coastguard Worker          "annotation": "union_variant",
135*84e33947SAndroid Build Coastguard Worker          "discriminator": "cellInfoType",
136*84e33947SAndroid Build Coastguard Worker          "mapping": [
137*84e33947SAndroid Build Coastguard Worker            ["CHRE_WWAN_CELL_INFO_TYPE_GSM", "gsm"],
138*84e33947SAndroid Build Coastguard Worker            ["CHRE_WWAN_CELL_INFO_TYPE_CDMA", "cdma"],
139*84e33947SAndroid Build Coastguard Worker            ["CHRE_WWAN_CELL_INFO_TYPE_LTE", "lte"],
140*84e33947SAndroid Build Coastguard Worker            ["CHRE_WWAN_CELL_INFO_TYPE_WCDMA", "wcdma"],
141*84e33947SAndroid Build Coastguard Worker            ["CHRE_WWAN_CELL_INFO_TYPE_TD_SCDMA", "tdscdma"],
142*84e33947SAndroid Build Coastguard Worker            ["CHRE_WWAN_CELL_INFO_TYPE_NR", "nr"]
143*84e33947SAndroid Build Coastguard Worker          ]
144*84e33947SAndroid Build Coastguard Worker        }
145*84e33947SAndroid Build Coastguard Worker      ]
146*84e33947SAndroid Build Coastguard Worker    }
147*84e33947SAndroid Build Coastguard Worker  ],
148*84e33947SAndroid Build Coastguard Worker  // The list of top-level structures appearing in the input that we should
149*84e33947SAndroid Build Coastguard Worker  // create conversion routines for
150*84e33947SAndroid Build Coastguard Worker  "root_structs": [
151*84e33947SAndroid Build Coastguard Worker    "chreWwanCellInfoResult"
152*84e33947SAndroid Build Coastguard Worker  ]
153*84e33947SAndroid Build Coastguard Worker}]
154*84e33947SAndroid Build Coastguard Worker```
155*84e33947SAndroid Build Coastguard Worker
156*84e33947SAndroid Build Coastguard Worker## Requirements
157*84e33947SAndroid Build Coastguard Worker
158*84e33947SAndroid Build Coastguard WorkerTested with Python 3.7, but most versions of Python 3 should work.
159*84e33947SAndroid Build Coastguard Worker
160*84e33947SAndroid Build Coastguard WorkerRequires pyclibrary - see requirements.txt.
161