diff options
Diffstat (limited to 'tools/aidl')
-rw-r--r-- | tools/aidl/aidl.cpp | 78 | ||||
-rw-r--r-- | tools/aidl/aidl_language.h | 4 | ||||
-rw-r--r-- | tools/aidl/aidl_language_l.l | 4 | ||||
-rw-r--r-- | tools/aidl/aidl_language_y.y | 45 | ||||
-rw-r--r-- | tools/aidl/generate_java_binder.cpp | 5 |
5 files changed, 132 insertions, 4 deletions
diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp index 0728246..071a8d7 100644 --- a/tools/aidl/aidl.cpp +++ b/tools/aidl/aidl.cpp @@ -23,6 +23,12 @@ # define O_BINARY 0 #endif +// The following are gotten as the offset from the allowable id's between +// android.os.IBinder.FIRST_CALL_TRANSACTION=1 and +// android.os.IBinder.LAST_CALL_TRANSACTION=16777215 +#define MIN_USER_SET_METHOD_ID 0 +#define MAX_USER_SET_METHOD_ID 16777214 + using namespace std; static void @@ -847,6 +853,72 @@ parse_preprocessed_file(const string& filename) return 0; } +static int +check_and_assign_method_ids(const char * filename, interface_item_type* first_item) +{ + // Check whether there are any methods with manually assigned id's and any that are not. + // Either all method id's must be manually assigned or all of them must not. + // Also, check for duplicates of user set id's and that the id's are within the proper bounds. + set<int> usedIds; + interface_item_type* item = first_item; + bool hasUnassignedIds = false; + bool hasAssignedIds = false; + while (item != NULL) { + if (item->item_type == METHOD_TYPE) { + method_type* method_item = (method_type*)item; + if (method_item->hasId) { + hasAssignedIds = true; + method_item->assigned_id = atoi(method_item->id.data); + // Ensure that the user set id is not duplicated. + if (usedIds.find(method_item->assigned_id) != usedIds.end()) { + // We found a duplicate id, so throw an error. + fprintf(stderr, + "%s:%d Found duplicate method id (%d) for method: %s\n", + filename, method_item->id.lineno, + method_item->assigned_id, method_item->name.data); + return 1; + } + // Ensure that the user set id is within the appropriate limits + if (method_item->assigned_id < MIN_USER_SET_METHOD_ID || + method_item->assigned_id > MAX_USER_SET_METHOD_ID) { + fprintf(stderr, "%s:%d Found out of bounds id (%d) for method: %s\n", + filename, method_item->id.lineno, + method_item->assigned_id, method_item->name.data); + fprintf(stderr, " Value for id must be between %d and %d inclusive.\n", + MIN_USER_SET_METHOD_ID, MAX_USER_SET_METHOD_ID); + return 1; + } + usedIds.insert(method_item->assigned_id); + } else { + hasUnassignedIds = true; + } + if (hasAssignedIds && hasUnassignedIds) { + fprintf(stderr, + "%s: You must either assign id's to all methods or to none of them.\n", + filename); + return 1; + } + } + item = item->next; + } + + // In the case that all methods have unassigned id's, set a unique id for them. + if (hasUnassignedIds) { + int newId = 0; + item = first_item; + while (item != NULL) { + if (item->item_type == METHOD_TYPE) { + method_type* method_item = (method_type*)item; + method_item->assigned_id = newId++; + } + item = item->next; + } + } + + // success + return 0; +} + // ========================================================== static int compile_aidl(Options& options) @@ -937,6 +1009,12 @@ compile_aidl(Options& options) bool onlyParcelable = false; err |= exactly_one_interface(options.inputFileName.c_str(), mainDoc, options, &onlyParcelable); + // If this includes an interface definition, then assign method ids and validate. + if (!onlyParcelable) { + err |= check_and_assign_method_ids(options.inputFileName.c_str(), + ((interface_type*)mainDoc)->interface_items); + } + // after this, there shouldn't be any more errors because of the // input. if (err != 0 || mainDoc == NULL) { diff --git a/tools/aidl/aidl_language.h b/tools/aidl/aidl_language.h index f203dbb..de1370c 100644 --- a/tools/aidl/aidl_language.h +++ b/tools/aidl/aidl_language.h @@ -57,9 +57,13 @@ typedef struct method_type { buffer_type open_paren_token; arg_type* args; buffer_type close_paren_token; + bool hasId; + buffer_type equals_token; + buffer_type id; // XXX missing comments/copy text here buffer_type semicolon_token; buffer_type* comments_token; // points into this structure, DO NOT DELETE + int assigned_id; } method_type; enum { diff --git a/tools/aidl/aidl_language_l.l b/tools/aidl/aidl_language_l.l index 7c5290c..3d33e7a 100644 --- a/tools/aidl/aidl_language_l.l +++ b/tools/aidl/aidl_language_l.l @@ -36,6 +36,7 @@ static void do_package_statement(const char* importText); identifier [_a-zA-Z][_a-zA-Z0-9\.]* whitespace ([ \t\n\r]+) brackets \[{whitespace}?\] +idvalue (0|[1-9][0-9]*) %% @@ -77,6 +78,7 @@ brackets \[{whitespace}?\] \( { SET_BUFFER('('); return '('; } \) { SET_BUFFER(')'); return ')'; } , { SET_BUFFER(','); return ','; } += { SET_BUFFER('='); return '='; } /* keywords */ parcelable { SET_BUFFER(PARCELABLE); return PARCELABLE; } @@ -89,7 +91,7 @@ inout { SET_BUFFER(INOUT); return INOUT; } oneway { SET_BUFFER(ONEWAY); return ONEWAY; } {brackets}+ { SET_BUFFER(ARRAY); return ARRAY; } - +{idvalue} { SET_BUFFER(IDVALUE); return IDVALUE; } {identifier} { SET_BUFFER(IDENTIFIER); return IDENTIFIER; } {identifier}\<{whitespace}*{identifier}({whitespace}*,{whitespace}*{identifier})*{whitespace}*\> { SET_BUFFER(GENERIC); return GENERIC; } diff --git a/tools/aidl/aidl_language_y.y b/tools/aidl/aidl_language_y.y index cc04d15..9b40d28 100644 --- a/tools/aidl/aidl_language_y.y +++ b/tools/aidl/aidl_language_y.y @@ -15,6 +15,7 @@ static int count_brackets(const char*); %token IMPORT %token PACKAGE %token IDENTIFIER +%token IDVALUE %token GENERIC %token ARRAY %token PARCELABLE @@ -211,13 +212,16 @@ method_decl: method_type *method = (method_type*)malloc(sizeof(method_type)); method->interface_item.item_type = METHOD_TYPE; method->interface_item.next = NULL; - method->type = $1.type; method->oneway = false; + method->type = $1.type; memset(&method->oneway_token, 0, sizeof(buffer_type)); method->name = $2.buffer; method->open_paren_token = $3.buffer; method->args = $4.arg; method->close_paren_token = $5.buffer; + method->hasId = false; + memset(&method->equals_token, 0, sizeof(buffer_type)); + memset(&method->id, 0, sizeof(buffer_type)); method->semicolon_token = $6.buffer; method->comments_token = &method->type.type; $$.method = method; @@ -233,10 +237,49 @@ method_decl: method->open_paren_token = $4.buffer; method->args = $5.arg; method->close_paren_token = $6.buffer; + method->hasId = false; + memset(&method->equals_token, 0, sizeof(buffer_type)); + memset(&method->id, 0, sizeof(buffer_type)); method->semicolon_token = $7.buffer; method->comments_token = &method->oneway_token; $$.method = method; } + | type IDENTIFIER '(' arg_list ')' '=' IDVALUE ';' { + method_type *method = (method_type*)malloc(sizeof(method_type)); + method->interface_item.item_type = METHOD_TYPE; + method->interface_item.next = NULL; + method->oneway = false; + memset(&method->oneway_token, 0, sizeof(buffer_type)); + method->type = $1.type; + method->name = $2.buffer; + method->open_paren_token = $3.buffer; + method->args = $4.arg; + method->close_paren_token = $5.buffer; + method->hasId = true; + method->equals_token = $6.buffer; + method->id = $7.buffer; + method->semicolon_token = $8.buffer; + method->comments_token = &method->type.type; + $$.method = method; + } + | ONEWAY type IDENTIFIER '(' arg_list ')' '=' IDVALUE ';' { + method_type *method = (method_type*)malloc(sizeof(method_type)); + method->interface_item.item_type = METHOD_TYPE; + method->interface_item.next = NULL; + method->oneway = true; + method->oneway_token = $1.buffer; + method->type = $2.type; + method->name = $3.buffer; + method->open_paren_token = $4.buffer; + method->args = $5.arg; + method->close_paren_token = $6.buffer; + method->hasId = true; + method->equals_token = $7.buffer; + method->id = $8.buffer; + method->semicolon_token = $9.buffer; + method->comments_token = &method->oneway_token; + $$.method = method; + } ; arg_list: diff --git a/tools/aidl/generate_java_binder.cpp b/tools/aidl/generate_java_binder.cpp index f80a388..f291ceb 100644 --- a/tools/aidl/generate_java_binder.cpp +++ b/tools/aidl/generate_java_binder.cpp @@ -260,7 +260,7 @@ generate_method(const method_type* method, Class* interface, string transactCodeName = "TRANSACTION_"; transactCodeName += method->name.data; - char transactCodeValue[50]; + char transactCodeValue[60]; sprintf(transactCodeValue, "(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index); Field* transactCode = new Field(STATIC | FINAL, @@ -548,7 +548,8 @@ generate_binder_interface_class(const interface_type* iface) interface_item_type* item = iface->interface_items; while (item != NULL) { if (item->item_type == METHOD_TYPE) { - generate_method((method_type*)item, interface, stub, proxy, index); + method_type * method_item = (method_type*) item; + generate_method(method_item, interface, stub, proxy, method_item->assigned_id); } item = item->next; index++; |