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