summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMaurice Chu <mochu@google.com>2012-10-18 14:47:13 -0700
committerMaurice Chu <mochu@google.com>2012-10-18 14:47:13 -0700
commit02822d059031d539f4b4b69ae0ee6c4ad52388f2 (patch)
tree142e0033575f86c8793903d17d2e32d0c455c292 /tools
parentf78283324400487a9acdb5d32536295fa85bd8f3 (diff)
downloadframeworks_base-02822d059031d539f4b4b69ae0ee6c4ad52388f2.zip
frameworks_base-02822d059031d539f4b4b69ae0ee6c4ad52388f2.tar.gz
frameworks_base-02822d059031d539f4b4b69ae0ee6c4ad52388f2.tar.bz2
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
Diffstat (limited to 'tools')
-rw-r--r--tools/aidl/aidl.cpp78
-rw-r--r--tools/aidl/aidl_language.h4
-rw-r--r--tools/aidl/aidl_language_l.l4
-rw-r--r--tools/aidl/aidl_language_y.y45
-rw-r--r--tools/aidl/generate_java_binder.cpp5
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++;