Merge "Enhance AIDL to take an explicit id for methods"
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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++;
|
||||
|
||||
Reference in New Issue
Block a user