Home | History | Annotate | Download | only in scripts
      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 
     17 import os
     18 import sys
     19 
     20 # list (pretty, cpp)
     21 data_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 
     33 non_contiguously_addressable = {"Bool"}
     34 
     35 def 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 
     51 def 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 
    285 if __name__ == "__main__":
    286     main()
    287