• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2
3# Copyright (C) 2018 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import os
18import sys
19
20# list (pretty, cpp)
21data_types = [
22    ("Int32", "int32_t"),
23    ("Uint32", "uint32_t"),
24    ("Int64", "int64_t"),
25    ("Uint64", "uint64_t"),
26    ("Float", "float"),
27    ("Double", "double"),
28    ("Bool", "bool"),
29    ("Char", "char16_t"),
30    ("Byte", "int8_t"),
31]
32
33non_contiguously_addressable = {"Bool"}
34
35def replaceFileTags(path, content, start_tag, end_tag):
36    print("Updating", path)
37    with open(path, "r+") as f:
38        lines = f.readlines()
39
40        start = lines.index("// @" + start_tag + "\n")
41        end = lines.index("// @" + end_tag + "\n")
42
43        if end <= start or start < 0 or end < 0:
44            print("Failed to find tags in", path)
45            exit(1)
46
47        f.seek(0)
48        f.write("".join(lines[:start+1]) + content + "".join(lines[end:]))
49        f.truncate()
50
51def main():
52    if len(sys.argv) != 1:
53        print("No arguments.")
54        exit(1)
55
56    ABT = os.environ.get('ANDROID_BUILD_TOP', None)
57    if ABT is None:
58        print("Can't get ANDROID_BUILD_TOP. Lunch?")
59        exit(1)
60    ROOT = ABT + "/frameworks/native/libs/binder/ndk/"
61
62    print("Updating auto-generated code")
63
64    pre_header = ""
65    header = ""
66    source = ""
67    cpp_helper = ""
68
69    for pretty, cpp in data_types:
70        header += "/**\n"
71        header += " * Writes " + cpp + " value to the next location in a non-null parcel.\n"
72        header += " *\n"
73        header += " * \\param parcel the parcel to write to.\n"
74        header += " * \\param value the value to write to the parcel.\n"
75        header += " *\n"
76        header += " * \\return STATUS_OK on successful write.\n"
77        header += " */\n"
78        header += "binder_status_t AParcel_write" + pretty + "(AParcel* parcel, " + cpp + " value) __INTRODUCED_IN(29);\n\n"
79        source += "binder_status_t AParcel_write" + pretty + "(AParcel* parcel, " + cpp + " value) {\n"
80        source += "    status_t status = parcel->get()->write" + pretty + "(value);\n"
81        source += "    return PruneStatusT(status);\n"
82        source += "}\n\n"
83
84    for pretty, cpp in data_types:
85        header += "/**\n"
86        header += " * Reads into " + cpp + " value from the next location in a non-null parcel.\n"
87        header += " *\n"
88        header += " * \\param parcel the parcel to read from.\n"
89        header += " * \\param value the value to read from the parcel.\n"
90        header += " *\n"
91        header += " * \\return STATUS_OK on successful read.\n"
92        header += " */\n"
93        header += "binder_status_t AParcel_read" + pretty + "(const AParcel* parcel, " + cpp + "* value) __INTRODUCED_IN(29);\n\n"
94        source += "binder_status_t AParcel_read" + pretty + "(const AParcel* parcel, " + cpp + "* value) {\n"
95        source += "    status_t status = parcel->get()->read" + pretty + "(value);\n"
96        source += "    return PruneStatusT(status);\n"
97        source += "}\n\n"
98
99    for pretty, cpp in data_types:
100        nca = pretty in non_contiguously_addressable
101
102        arg_types = "const " + cpp + "* arrayData, int32_t length"
103        if nca: arg_types = "const void* arrayData, int32_t length, AParcel_" + pretty.lower() + "ArrayGetter getter"
104        args = "arrayData, length"
105        if nca: args = "arrayData, length, getter, &Parcel::write" + pretty
106
107        header += "/**\n"
108        header += " * Writes an array of " + cpp + " to the next location in a non-null parcel.\n"
109        if nca:
110            header += " *\n"
111            header += " * getter(arrayData, i) will be called for each i in [0, length) in order to get the underlying values to write "
112            header += "to the parcel.\n"
113        header += " *\n"
114        header += " * \\param parcel the parcel to write to.\n"
115        if nca:
116            header += " * \\param arrayData some external representation of an array.\n"
117            header += " * \\param length the length of arrayData (or -1 if this represents a null array).\n"
118            header += " * \\param getter the callback to retrieve data at specific locations in the array.\n"
119        else:
120            header += " * \\param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).\n"
121            header += " * \\param length the length of arrayData or -1 if this represents a null array.\n"
122        header += " *\n"
123        header += " * \\return STATUS_OK on successful write.\n"
124        header += " */\n"
125        header += "binder_status_t AParcel_write" + pretty + "Array(AParcel* parcel, " + arg_types + ") __INTRODUCED_IN(29);\n\n"
126        source += "binder_status_t AParcel_write" + pretty + "Array(AParcel* parcel, " + arg_types + ") {\n"
127        source += "    return WriteArray<" + cpp + ">(parcel, " + args + ");\n";
128        source += "}\n\n"
129
130    for pretty, cpp in data_types:
131        nca = pretty in non_contiguously_addressable
132
133        read_func = "AParcel_read" + pretty + "Array"
134        write_func = "AParcel_write" + pretty + "Array"
135        allocator_type = "AParcel_" + pretty.lower() + "ArrayAllocator"
136        getter_type = "AParcel_" + pretty.lower() + "ArrayGetter"
137        setter_type = "AParcel_" + pretty.lower() + "ArraySetter"
138
139        if nca:
140            pre_header += "/**\n"
141            pre_header += " * This allocates an array of size 'length' inside of arrayData and returns whether or not there was "
142            pre_header += "a success. If length is -1, then this should allocate some representation of a null array.\n"
143            pre_header += " *\n"
144            pre_header += " * See also " + read_func + "\n"
145            pre_header += " *\n"
146            pre_header += " * \\param arrayData some external representation of an array of " + cpp + ".\n"
147            pre_header += " * \\param length the length to allocate arrayData to (or -1 if this represents a null array).\n"
148            pre_header += " *\n"
149            pre_header += " * \\return whether the allocation succeeded.\n"
150            pre_header += " */\n"
151            pre_header += "typedef bool (*" + allocator_type + ")(void* arrayData, int32_t length);\n\n"
152
153            pre_header += "/**\n"
154            pre_header += " * This is called to get the underlying data from an arrayData object at index.\n"
155            pre_header += " *\n"
156            pre_header += " * See also " + write_func + "\n"
157            pre_header += " *\n"
158            pre_header += " * \\param arrayData some external representation of an array of " + cpp + ".\n"
159            pre_header += " * \\param index the index of the value to be retrieved.\n"
160            pre_header += " *\n"
161            pre_header += " * \\return the value of the array at index index.\n"
162            pre_header += " */\n"
163            pre_header += "typedef " + cpp + " (*" + getter_type + ")(const void* arrayData, size_t index);\n\n"
164
165            pre_header += "/**\n"
166            pre_header += " * This is called to set an underlying value in an arrayData object at index.\n"
167            pre_header += " *\n"
168            pre_header += " * See also " + read_func + "\n"
169            pre_header += " *\n"
170            pre_header += " * \\param arrayData some external representation of an array of " + cpp + ".\n"
171            pre_header += " * \\param index the index of the value to be set.\n"
172            pre_header += " * \\param value the value to set at index index.\n"
173            pre_header += " */\n"
174            pre_header += "typedef void (*" + setter_type + ")(void* arrayData, size_t index, " + cpp + " value);\n\n"
175        else:
176            pre_header += "/**\n"
177            pre_header += " * This is called to get the underlying data from an arrayData object.\n"
178            pre_header += " *\n"
179            pre_header += " * The implementation of this function should allocate a contiguous array of size 'length' and "
180            pre_header += "return that underlying buffer to be filled out. If there is an error or length is 0, null may be "
181            pre_header += "returned. If length is -1, this should allocate some representation of a null array.\n"
182            pre_header += " *\n"
183            pre_header += " * See also " + read_func + "\n"
184            pre_header += " *\n"
185            pre_header += " * \\param arrayData some external representation of an array of " + cpp + ".\n"
186            pre_header += " * \\param length the length to allocate arrayData to.\n"
187            pre_header += " * \\param outBuffer a buffer of " + cpp + " of size 'length' (if length is >= 0, if length is 0, "
188            pre_header += "this may be nullptr).\n"
189            pre_header += " *\n"
190            pre_header += " * \\return whether or not the allocation was successful (or whether a null array is represented when length is -1).\n"
191            pre_header += " */\n"
192            pre_header += "typedef bool (*" + allocator_type + ")(void* arrayData, int32_t length, " + cpp + "** outBuffer);\n\n"
193
194        read_array_args = [("const AParcel*", "parcel")]
195        read_array_args += [("void*", "arrayData")]
196        read_array_args += [(allocator_type, "allocator")]
197        if nca: read_array_args += [(setter_type, "setter")]
198
199        read_type_args = ", ".join((varType + " " + name for varType, name in read_array_args))
200        read_call_args = ", ".join((name for varType, name in read_array_args))
201
202        header += "/**\n"
203        header += " * Reads an array of " + cpp + " from the next location in a non-null parcel.\n"
204        header += " *\n"
205        if nca:
206            header += " * First, allocator will be called with the length of the array. Then, for every i in [0, length), "
207            header += "setter(arrayData, i, x) will be called where x is the value at the associated index.\n"
208        else:
209            header += " * First, allocator will be called with the length of the array. If the allocation succeeds and the "
210            header += "length is greater than zero, the buffer returned by the allocator will be filled with the corresponding data\n"
211        header += " *\n"
212        header += " * \\param parcel the parcel to read from.\n"
213        header += " * \\param arrayData some external representation of an array.\n"
214        header += " * \\param allocator the callback that will be called to allocate the array.\n"
215        if nca:
216            header += " * \\param setter the callback that will be called to set a value at a specific location in the array.\n"
217        header += " *\n"
218        header += " * \\return STATUS_OK on successful read.\n"
219        header += " */\n"
220        header += "binder_status_t " + read_func + "(" + read_type_args + ") __INTRODUCED_IN(29);\n\n"
221        source += "binder_status_t " + read_func + "(" + read_type_args + ") {\n"
222        additional_args = ""
223        if nca: additional_args = ", &Parcel::read" + pretty
224        source += "    return ReadArray<" + cpp + ">(" + read_call_args + additional_args + ");\n";
225        source += "}\n\n"
226
227        cpp_helper += "/**\n"
228        cpp_helper += " * Writes a vector of " + cpp + " to the next location in a non-null parcel.\n"
229        cpp_helper += " */\n"
230        cpp_helper += "inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<" + cpp + ">& vec) {\n"
231        write_args = "vec.data(), vec.size()"
232        if nca: write_args = "static_cast<const void*>(&vec), vec.size(), AParcel_stdVectorGetter<" + cpp + ">"
233        cpp_helper += "    return AParcel_write" + pretty + "Array(parcel, " + write_args + ");\n"
234        cpp_helper += "}\n\n"
235
236        cpp_helper += "/**\n"
237        cpp_helper += " * Writes an optional vector of " + cpp + " to the next location in a non-null parcel.\n"
238        cpp_helper += " */\n"
239        cpp_helper += "inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::optional<std::vector<" + cpp + ">>& vec) {\n"
240        extra_args = ""
241        if nca: extra_args = ", AParcel_stdVectorGetter<" + cpp + ">"
242        cpp_helper += "    if (!vec) return AParcel_write" + pretty + "Array(parcel, nullptr, -1" + extra_args + ");\n"
243        cpp_helper += "    return AParcel_writeVector(parcel, *vec);\n"
244        cpp_helper += "}\n\n"
245
246        cpp_helper += "/**\n"
247        cpp_helper += " * Reads a vector of " + cpp + " from the next location in a non-null parcel.\n"
248        cpp_helper += " */\n"
249        cpp_helper += "inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<" + cpp + ">* vec) {\n"
250        cpp_helper += "    void* vectorData = static_cast<void*>(vec);\n"
251        read_args = []
252        read_args += ["parcel"]
253        read_args += ["vectorData"]
254        if nca:
255            read_args += ["AParcel_stdVectorExternalAllocator<bool>"]
256            read_args += ["AParcel_stdVectorSetter<" + cpp + ">"]
257        else:
258            read_args += ["AParcel_stdVectorAllocator<" + cpp + ">"]
259        cpp_helper += "    return AParcel_read" + pretty + "Array(" + ", ".join(read_args) + ");\n"
260        cpp_helper += "}\n\n"
261
262        cpp_helper += "/**\n"
263        cpp_helper += " * Reads an optional vector of " + cpp + " from the next location in a non-null parcel.\n"
264        cpp_helper += " */\n"
265        cpp_helper += "inline binder_status_t AParcel_readVector(const AParcel* parcel, std::optional<std::vector<" + cpp + ">>* vec) {\n"
266        cpp_helper += "    void* vectorData = static_cast<void*>(vec);\n"
267        read_args = []
268        read_args += ["parcel"]
269        read_args += ["vectorData"]
270        if nca:
271            read_args += ["AParcel_nullableStdVectorExternalAllocator<bool>"]
272            read_args += ["AParcel_nullableStdVectorSetter<" + cpp + ">"]
273        else:
274            read_args += ["AParcel_nullableStdVectorAllocator<" + cpp + ">"]
275        cpp_helper += "    return AParcel_read" + pretty + "Array(" + ", ".join(read_args) + ");\n"
276        cpp_helper += "}\n\n"
277
278    replaceFileTags(ROOT + "include_ndk/android/binder_parcel.h", pre_header, "START-PRIMITIVE-VECTOR-GETTERS", "END-PRIMITIVE-VECTOR-GETTERS")
279    replaceFileTags(ROOT + "include_ndk/android/binder_parcel.h", header, "START-PRIMITIVE-READ-WRITE", "END-PRIMITIVE-READ-WRITE")
280    replaceFileTags(ROOT + "parcel.cpp", source, "START", "END")
281    replaceFileTags(ROOT + "include_ndk/android/binder_parcel_utils.h", cpp_helper, "START", "END")
282
283    print("Updating DONE.")
284
285if __name__ == "__main__":
286    main()
287