| #!/usr/bin/env python3 |
| |
| # Copyright (C) 2018 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| import os |
| import sys |
| |
| # list (pretty, cpp) |
| data_types = [ |
| ("Int32", "int32_t"), |
| ("Uint32", "uint32_t"), |
| ("Int64", "int64_t"), |
| ("Uint64", "uint64_t"), |
| ("Float", "float"), |
| ("Double", "double"), |
| ("Bool", "bool"), |
| ("Char", "char16_t"), |
| ("Byte", "int8_t"), |
| ] |
| |
| non_contiguously_addressable = {"Bool"} |
| |
| def replaceFileTags(path, content, start_tag, end_tag): |
| print("Updating", path) |
| with open(path, "r+") as f: |
| lines = f.readlines() |
| |
| start = lines.index("// @" + start_tag + "\n") |
| end = lines.index("// @" + end_tag + "\n") |
| |
| if end <= start or start < 0 or end < 0: |
| print("Failed to find tags in", path) |
| exit(1) |
| |
| f.seek(0) |
| f.write("".join(lines[:start+1]) + content + "".join(lines[end:])) |
| f.truncate() |
| |
| def main(): |
| if len(sys.argv) != 1: |
| print("No arguments.") |
| exit(1) |
| |
| ABT = os.environ.get('ANDROID_BUILD_TOP', None) |
| if ABT is None: |
| print("Can't get ANDROID_BUILD_TOP. Lunch?") |
| exit(1) |
| ROOT = ABT + "/frameworks/native/libs/binder/ndk/" |
| |
| print("Updating auto-generated code") |
| |
| pre_header = "" |
| header = "" |
| source = "" |
| cpp_helper = "" |
| |
| for pretty, cpp in data_types: |
| header += "/**\n" |
| header += " * Writes " + cpp + " value to the next location in a non-null parcel.\n" |
| header += " */\n" |
| header += "binder_status_t AParcel_write" + pretty + "(AParcel* parcel, " + cpp + " value) __INTRODUCED_IN(29);\n\n" |
| source += "binder_status_t AParcel_write" + pretty + "(AParcel* parcel, " + cpp + " value) {\n" |
| source += " status_t status = parcel->get()->write" + pretty + "(value);\n" |
| source += " return PruneStatusT(status);\n" |
| source += "}\n\n" |
| |
| for pretty, cpp in data_types: |
| header += "/**\n" |
| header += " * Reads into " + cpp + " value from the next location in a non-null parcel.\n" |
| header += " */\n" |
| header += "binder_status_t AParcel_read" + pretty + "(const AParcel* parcel, " + cpp + "* value) __INTRODUCED_IN(29);\n\n" |
| source += "binder_status_t AParcel_read" + pretty + "(const AParcel* parcel, " + cpp + "* value) {\n" |
| source += " status_t status = parcel->get()->read" + pretty + "(value);\n" |
| source += " return PruneStatusT(status);\n" |
| source += "}\n\n" |
| |
| for pretty, cpp in data_types: |
| nca = pretty in non_contiguously_addressable |
| |
| arg_type = "const " + cpp + "* value" |
| if nca: arg_type = "const void* arrayData, AParcel_" + pretty.lower() + "ArrayGetter getter" |
| args = "value, length" |
| if nca: args = "arrayData, getter, length, &Parcel::write" + pretty |
| |
| header += "/**\n" |
| header += " * Writes an array of " + cpp + " to the next location in a non-null parcel.\n" |
| if nca: |
| header += " *\n" |
| header += " * getter(arrayData, i) will be called for each i in [0, length) in order to get the underlying values to write " |
| header += "to the parcel.\n" |
| header += " */\n" |
| header += "binder_status_t AParcel_write" + pretty + "Array(AParcel* parcel, " + arg_type + ", size_t length) __INTRODUCED_IN(29);\n\n" |
| source += "binder_status_t AParcel_write" + pretty + "Array(AParcel* parcel, " + arg_type + ", size_t length) {\n" |
| source += " return WriteArray<" + cpp + ">(parcel, " + args + ");\n"; |
| source += "}\n\n" |
| |
| for pretty, cpp in data_types: |
| nca = pretty in non_contiguously_addressable |
| |
| read_func = "AParcel_read" + pretty + "Array" |
| write_func = "AParcel_write" + pretty + "Array" |
| allocator_type = "AParcel_" + pretty.lower() + "Allocator" |
| getter_type = "AParcel_" + pretty.lower() + "ArrayGetter" |
| setter_type = "AParcel_" + pretty.lower() + "ArraySetter" |
| |
| if nca: |
| pre_header += "/**\n" |
| pre_header += " * This allocates an array of length length inside of arrayData and returns whether or not there was " |
| pre_header += "a success.\n" |
| pre_header += " *\n" |
| pre_header += " * See also " + read_func + "\n" |
| pre_header += " */\n" |
| pre_header += "typedef bool (*" + allocator_type + ")(void* arrayData, size_t length);\n\n" |
| |
| pre_header += "/**\n" |
| pre_header += " * This is called to get the underlying data from an arrayData object at index.\n" |
| pre_header += " *\n" |
| pre_header += " * See also " + write_func + "\n" |
| pre_header += " */\n" |
| pre_header += "typedef " + cpp + " (*" + getter_type + ")(const void* arrayData, size_t index);\n\n" |
| |
| pre_header += "/**\n" |
| pre_header += " * This is called to set an underlying value in an arrayData object at index.\n" |
| pre_header += " *\n" |
| pre_header += " * See also " + read_func + "\n" |
| pre_header += " */\n" |
| pre_header += "typedef void (*" + setter_type + ")(void* arrayData, size_t index, " + cpp + " value);\n\n" |
| else: |
| pre_header += "/**\n" |
| pre_header += " * This is called to get the underlying data from an arrayData object.\n" |
| pre_header += " *\n" |
| pre_header += " * The implementation of this function should allocate a contiguous array of length length and " |
| pre_header += "return that underlying buffer to be filled out. If there is an error or length is 0, null may be " |
| pre_header += "returned.\n" |
| pre_header += " *\n" |
| pre_header += " * See also " + read_func + "\n" |
| pre_header += " */\n" |
| pre_header += "typedef " + cpp + "* (*" + allocator_type + ")(void* arrayData, size_t length);\n\n" |
| |
| read_array_args = [("const AParcel*", "parcel")] |
| read_array_args += [("void*", "arrayData")] |
| read_array_args += [(allocator_type, "allocator")] |
| if nca: read_array_args += [(setter_type, "setter")] |
| |
| read_type_args = ", ".join((varType + " " + name for varType, name in read_array_args)) |
| read_call_args = ", ".join((name for varType, name in read_array_args)) |
| |
| header += "/**\n" |
| header += " * Reads an array of " + cpp + " from the next location in a non-null parcel.\n" |
| header += " *\n" |
| if nca: |
| header += " * First, allocator will be called with the length of the array. Then, for every i in [0, length), " |
| header += "setter(arrayData, i, x) will be called where x is the value at the associated index.\n" |
| else: |
| header += " * First, allocator will be called with the length of the array. If the allocation succeeds and the " |
| header += "length is greater than zero, the buffer returned by the allocator will be filled with the corresponding data\n" |
| header += " */\n" |
| header += "binder_status_t " + read_func + "(" + read_type_args + ") __INTRODUCED_IN(29);\n\n" |
| source += "binder_status_t " + read_func + "(" + read_type_args + ") {\n" |
| additional_args = "" |
| if nca: additional_args = ", &Parcel::read" + pretty |
| source += " return ReadArray<" + cpp + ">(" + read_call_args + additional_args + ");\n"; |
| source += "}\n\n" |
| |
| cpp_helper += "/**\n" |
| cpp_helper += " * Writes a vector of " + cpp + " to the next location in a non-null parcel.\n" |
| cpp_helper += " */\n" |
| cpp_helper += "inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<" + cpp + ">& vec) {\n" |
| write_args = "vec.data()" |
| if nca: write_args = "static_cast<const void*>(&vec), AParcel_stdVectorGetter<" + cpp + ">" |
| cpp_helper += " return AParcel_write" + pretty + "Array(parcel, " + write_args + ", vec.size());\n" |
| cpp_helper += "}\n\n" |
| |
| cpp_helper += "/**\n" |
| cpp_helper += " * Reads a vector of " + cpp + " from the next location in a non-null parcel.\n" |
| cpp_helper += " */\n" |
| cpp_helper += "inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<" + cpp + ">* vec) {\n" |
| cpp_helper += " void* vectorData = static_cast<void*>(vec);\n" |
| read_args = [] |
| read_args += ["parcel"] |
| read_args += ["vectorData"] |
| if nca: |
| read_args += ["AParcel_stdVectorBoolAllocator"] |
| read_args += ["AParcel_stdVectorSetter<" + cpp + ">"] |
| else: |
| read_args += ["AParcel_stdVectorAllocator<" + cpp + ">"] |
| cpp_helper += " return AParcel_read" + pretty + "Array(" + ", ".join(read_args) + ");\n" |
| cpp_helper += "}\n\n" |
| |
| replaceFileTags(ROOT + "include_ndk/android/binder_parcel.h", pre_header, "START-PRIMITIVE-VECTOR-GETTERS", "END-PRIMITIVE-VECTOR-GETTERS") |
| replaceFileTags(ROOT + "include_ndk/android/binder_parcel.h", header, "START-PRIMITIVE-READ-WRITE", "END-PRIMITIVE-READ-WRITE") |
| replaceFileTags(ROOT + "parcel.cpp", source, "START", "END") |
| replaceFileTags(ROOT + "include_ndk/android/binder_parcel_utils.h", cpp_helper, "START", "END") |
| |
| print("Updating DONE.") |
| |
| if __name__ == "__main__": |
| main() |