Merge "Enhance AIDL to take an explicit id for methods"

This commit is contained in:
Maurice Chu
2012-10-19 10:34:10 -07:00
committed by Android (Google) Code Review
5 changed files with 132 additions and 4 deletions

View File

@@ -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) {

View File

@@ -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 {

View File

@@ -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; }

View File

@@ -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:

View File

@@ -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++;