Skip to content

Commit 02822d0

Browse files
author
Maurice Chu
committed
Enhance AIDL to take an explicit id for methods
This adds an annotation to methods in AIDL of the form "void myMethod() = 3;" to explicitly set the onTransact id for the method. Either all methods must have explicitly annotated id's or none of them should be explicitly annotated. There is error checking in the AIDL compiler for duplicate id's and id's outside of the valid range. Bug: 7353910 Change-Id: I868045e3f112c9a279c573cea368a621116cbf77
1 parent f782833 commit 02822d0

File tree

5 files changed

+132
-4
lines changed

5 files changed

+132
-4
lines changed

tools/aidl/aidl.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
# define O_BINARY 0
2424
#endif
2525

26+
// The following are gotten as the offset from the allowable id's between
27+
// android.os.IBinder.FIRST_CALL_TRANSACTION=1 and
28+
// android.os.IBinder.LAST_CALL_TRANSACTION=16777215
29+
#define MIN_USER_SET_METHOD_ID 0
30+
#define MAX_USER_SET_METHOD_ID 16777214
31+
2632
using namespace std;
2733

2834
static void
@@ -847,6 +853,72 @@ parse_preprocessed_file(const string& filename)
847853
return 0;
848854
}
849855

856+
static int
857+
check_and_assign_method_ids(const char * filename, interface_item_type* first_item)
858+
{
859+
// Check whether there are any methods with manually assigned id's and any that are not.
860+
// Either all method id's must be manually assigned or all of them must not.
861+
// Also, check for duplicates of user set id's and that the id's are within the proper bounds.
862+
set<int> usedIds;
863+
interface_item_type* item = first_item;
864+
bool hasUnassignedIds = false;
865+
bool hasAssignedIds = false;
866+
while (item != NULL) {
867+
if (item->item_type == METHOD_TYPE) {
868+
method_type* method_item = (method_type*)item;
869+
if (method_item->hasId) {
870+
hasAssignedIds = true;
871+
method_item->assigned_id = atoi(method_item->id.data);
872+
// Ensure that the user set id is not duplicated.
873+
if (usedIds.find(method_item->assigned_id) != usedIds.end()) {
874+
// We found a duplicate id, so throw an error.
875+
fprintf(stderr,
876+
"%s:%d Found duplicate method id (%d) for method: %s\n",
877+
filename, method_item->id.lineno,
878+
method_item->assigned_id, method_item->name.data);
879+
return 1;
880+
}
881+
// Ensure that the user set id is within the appropriate limits
882+
if (method_item->assigned_id < MIN_USER_SET_METHOD_ID ||
883+
method_item->assigned_id > MAX_USER_SET_METHOD_ID) {
884+
fprintf(stderr, "%s:%d Found out of bounds id (%d) for method: %s\n",
885+
filename, method_item->id.lineno,
886+
method_item->assigned_id, method_item->name.data);
887+
fprintf(stderr, " Value for id must be between %d and %d inclusive.\n",
888+
MIN_USER_SET_METHOD_ID, MAX_USER_SET_METHOD_ID);
889+
return 1;
890+
}
891+
usedIds.insert(method_item->assigned_id);
892+
} else {
893+
hasUnassignedIds = true;
894+
}
895+
if (hasAssignedIds && hasUnassignedIds) {
896+
fprintf(stderr,
897+
"%s: You must either assign id's to all methods or to none of them.\n",
898+
filename);
899+
return 1;
900+
}
901+
}
902+
item = item->next;
903+
}
904+
905+
// In the case that all methods have unassigned id's, set a unique id for them.
906+
if (hasUnassignedIds) {
907+
int newId = 0;
908+
item = first_item;
909+
while (item != NULL) {
910+
if (item->item_type == METHOD_TYPE) {
911+
method_type* method_item = (method_type*)item;
912+
method_item->assigned_id = newId++;
913+
}
914+
item = item->next;
915+
}
916+
}
917+
918+
// success
919+
return 0;
920+
}
921+
850922
// ==========================================================
851923
static int
852924
compile_aidl(Options& options)
@@ -937,6 +1009,12 @@ compile_aidl(Options& options)
9371009
bool onlyParcelable = false;
9381010
err |= exactly_one_interface(options.inputFileName.c_str(), mainDoc, options, &onlyParcelable);
9391011

1012+
// If this includes an interface definition, then assign method ids and validate.
1013+
if (!onlyParcelable) {
1014+
err |= check_and_assign_method_ids(options.inputFileName.c_str(),
1015+
((interface_type*)mainDoc)->interface_items);
1016+
}
1017+
9401018
// after this, there shouldn't be any more errors because of the
9411019
// input.
9421020
if (err != 0 || mainDoc == NULL) {

tools/aidl/aidl_language.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,13 @@ typedef struct method_type {
5757
buffer_type open_paren_token;
5858
arg_type* args;
5959
buffer_type close_paren_token;
60+
bool hasId;
61+
buffer_type equals_token;
62+
buffer_type id;
6063
// XXX missing comments/copy text here
6164
buffer_type semicolon_token;
6265
buffer_type* comments_token; // points into this structure, DO NOT DELETE
66+
int assigned_id;
6367
} method_type;
6468

6569
enum {

tools/aidl/aidl_language_l.l

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ static void do_package_statement(const char* importText);
3636
identifier [_a-zA-Z][_a-zA-Z0-9\.]*
3737
whitespace ([ \t\n\r]+)
3838
brackets \[{whitespace}?\]
39+
idvalue (0|[1-9][0-9]*)
3940

4041
%%
4142

@@ -77,6 +78,7 @@ brackets \[{whitespace}?\]
7778
\( { SET_BUFFER('('); return '('; }
7879
\) { SET_BUFFER(')'); return ')'; }
7980
, { SET_BUFFER(','); return ','; }
81+
= { SET_BUFFER('='); return '='; }
8082

8183
/* keywords */
8284
parcelable { SET_BUFFER(PARCELABLE); return PARCELABLE; }
@@ -89,7 +91,7 @@ inout { SET_BUFFER(INOUT); return INOUT; }
8991
oneway { SET_BUFFER(ONEWAY); return ONEWAY; }
9092

9193
{brackets}+ { SET_BUFFER(ARRAY); return ARRAY; }
92-
94+
{idvalue} { SET_BUFFER(IDVALUE); return IDVALUE; }
9395
{identifier} { SET_BUFFER(IDENTIFIER); return IDENTIFIER; }
9496
{identifier}\<{whitespace}*{identifier}({whitespace}*,{whitespace}*{identifier})*{whitespace}*\> {
9597
SET_BUFFER(GENERIC); return GENERIC; }

tools/aidl/aidl_language_y.y

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ static int count_brackets(const char*);
1515
%token IMPORT
1616
%token PACKAGE
1717
%token IDENTIFIER
18+
%token IDVALUE
1819
%token GENERIC
1920
%token ARRAY
2021
%token PARCELABLE
@@ -211,13 +212,16 @@ method_decl:
211212
method_type *method = (method_type*)malloc(sizeof(method_type));
212213
method->interface_item.item_type = METHOD_TYPE;
213214
method->interface_item.next = NULL;
214-
method->type = $1.type;
215215
method->oneway = false;
216+
method->type = $1.type;
216217
memset(&method->oneway_token, 0, sizeof(buffer_type));
217218
method->name = $2.buffer;
218219
method->open_paren_token = $3.buffer;
219220
method->args = $4.arg;
220221
method->close_paren_token = $5.buffer;
222+
method->hasId = false;
223+
memset(&method->equals_token, 0, sizeof(buffer_type));
224+
memset(&method->id, 0, sizeof(buffer_type));
221225
method->semicolon_token = $6.buffer;
222226
method->comments_token = &method->type.type;
223227
$$.method = method;
@@ -233,10 +237,49 @@ method_decl:
233237
method->open_paren_token = $4.buffer;
234238
method->args = $5.arg;
235239
method->close_paren_token = $6.buffer;
240+
method->hasId = false;
241+
memset(&method->equals_token, 0, sizeof(buffer_type));
242+
memset(&method->id, 0, sizeof(buffer_type));
236243
method->semicolon_token = $7.buffer;
237244
method->comments_token = &method->oneway_token;
238245
$$.method = method;
239246
}
247+
| type IDENTIFIER '(' arg_list ')' '=' IDVALUE ';' {
248+
method_type *method = (method_type*)malloc(sizeof(method_type));
249+
method->interface_item.item_type = METHOD_TYPE;
250+
method->interface_item.next = NULL;
251+
method->oneway = false;
252+
memset(&method->oneway_token, 0, sizeof(buffer_type));
253+
method->type = $1.type;
254+
method->name = $2.buffer;
255+
method->open_paren_token = $3.buffer;
256+
method->args = $4.arg;
257+
method->close_paren_token = $5.buffer;
258+
method->hasId = true;
259+
method->equals_token = $6.buffer;
260+
method->id = $7.buffer;
261+
method->semicolon_token = $8.buffer;
262+
method->comments_token = &method->type.type;
263+
$$.method = method;
264+
}
265+
| ONEWAY type IDENTIFIER '(' arg_list ')' '=' IDVALUE ';' {
266+
method_type *method = (method_type*)malloc(sizeof(method_type));
267+
method->interface_item.item_type = METHOD_TYPE;
268+
method->interface_item.next = NULL;
269+
method->oneway = true;
270+
method->oneway_token = $1.buffer;
271+
method->type = $2.type;
272+
method->name = $3.buffer;
273+
method->open_paren_token = $4.buffer;
274+
method->args = $5.arg;
275+
method->close_paren_token = $6.buffer;
276+
method->hasId = true;
277+
method->equals_token = $7.buffer;
278+
method->id = $8.buffer;
279+
method->semicolon_token = $9.buffer;
280+
method->comments_token = &method->oneway_token;
281+
$$.method = method;
282+
}
240283
;
241284

242285
arg_list:

tools/aidl/generate_java_binder.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ generate_method(const method_type* method, Class* interface,
260260
string transactCodeName = "TRANSACTION_";
261261
transactCodeName += method->name.data;
262262

263-
char transactCodeValue[50];
263+
char transactCodeValue[60];
264264
sprintf(transactCodeValue, "(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
265265

266266
Field* transactCode = new Field(STATIC | FINAL,
@@ -548,7 +548,8 @@ generate_binder_interface_class(const interface_type* iface)
548548
interface_item_type* item = iface->interface_items;
549549
while (item != NULL) {
550550
if (item->item_type == METHOD_TYPE) {
551-
generate_method((method_type*)item, interface, stub, proxy, index);
551+
method_type * method_item = (method_type*) item;
552+
generate_method(method_item, interface, stub, proxy, method_item->assigned_id);
552553
}
553554
item = item->next;
554555
index++;

0 commit comments

Comments
 (0)