• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..--

.gitignoreD23-Nov-202313 21

README.mdD23-Nov-20237.1 KiB161142

chre_api_annotations.jsonD23-Nov-20235.7 KiB258257

chre_api_to_chpp.pyD23-Nov-202349.3 KiB1,047787

parser_defines.hD23-Nov-2023991 231

requirements.txtD23-Nov-202333 32

README.md

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