1 /*
2 * Copyright (C) 2016, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "aidl.h"
18 #include "aidl_to_java.h"
19 #include "generate_java.h"
20 #include "logging.h"
21 #include "options.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <algorithm>
28 #include <unordered_set>
29 #include <utility>
30 #include <vector>
31
32 #include <android-base/stringprintf.h>
33
34 using android::base::Join;
35 using android::base::StringPrintf;
36
37 using std::string;
38 using std::unique_ptr;
39 using std::vector;
40
41 namespace android {
42 namespace aidl {
43 namespace java {
44
45 // =================================================
46 class VariableFactory {
47 public:
48 using Variable = ::android::aidl::java::Variable;
49
VariableFactory(const std::string & base)50 explicit VariableFactory(const std::string& base) : base_(base), index_(0) {}
Get(const AidlTypeSpecifier & type,const AidlTypenames & typenames)51 std::shared_ptr<Variable> Get(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
52 auto v = std::make_shared<Variable>(JavaSignatureOf(type, typenames),
53 StringPrintf("%s%d", base_.c_str(), index_));
54 vars_.push_back(v);
55 index_++;
56 return v;
57 }
58
Get(int index)59 std::shared_ptr<Variable> Get(int index) { return vars_[index]; }
60
61 private:
62 std::vector<std::shared_ptr<Variable>> vars_;
63 std::string base_;
64 int index_;
65 };
66
67 // =================================================
68 class StubClass : public Class {
69 public:
70 StubClass(const AidlInterface* interfaceType, const Options& options);
71 ~StubClass() override = default;
72
73 // non-copyable, non-movable
74 StubClass(const StubClass&) = delete;
75 StubClass(StubClass&&) = delete;
76 StubClass& operator=(const StubClass&) = delete;
77 StubClass& operator=(StubClass&&) = delete;
78
79 std::shared_ptr<Variable> transact_code;
80 std::shared_ptr<Variable> transact_data;
81 std::shared_ptr<Variable> transact_reply;
82 std::shared_ptr<Variable> transact_flags;
83 std::shared_ptr<SwitchStatement> transact_switch;
84 std::shared_ptr<StatementBlock> transact_statements;
85 std::shared_ptr<SwitchStatement> code_to_method_name_switch;
86
87 // Where onTransact cases should be generated as separate methods.
88 bool transact_outline;
89 // Specific methods that should be outlined when transact_outline is true.
90 std::unordered_set<const AidlMethod*> outline_methods;
91 // Number of all methods.
92 size_t all_method_count;
93
94 // Finish generation. This will add a default case to the switch.
95 void finish();
96
97 std::shared_ptr<Expression> get_transact_descriptor(const AidlMethod* method);
98
99 private:
100 void make_as_interface(const AidlInterface* interfaceType);
101
102 std::shared_ptr<Variable> transact_descriptor;
103 const Options& options_;
104 };
105
StubClass(const AidlInterface * interfaceType,const Options & options)106 StubClass::StubClass(const AidlInterface* interfaceType, const Options& options)
107 : Class(), options_(options) {
108 transact_descriptor = nullptr;
109 transact_outline = false;
110 all_method_count = 0; // Will be set when outlining may be enabled.
111
112 this->comment = "/** Local-side IPC implementation stub class. */";
113 this->modifiers = PUBLIC | ABSTRACT | STATIC;
114 this->what = Class::CLASS;
115 this->type = interfaceType->GetCanonicalName() + ".Stub";
116 this->extends = "android.os.Binder";
117 this->interfaces.push_back(interfaceType->GetCanonicalName());
118
119 // ctor
120 auto ctor = std::make_shared<Method>();
121 ctor->modifiers = PUBLIC;
122 ctor->comment =
123 "/** Construct the stub at attach it to the "
124 "interface. */";
125 ctor->name = "Stub";
126 ctor->statements = std::make_shared<StatementBlock>();
127 if (interfaceType->IsVintfStability()) {
128 auto stability = std::make_shared<LiteralStatement>("this.markVintfStability();\n");
129 ctor->statements->Add(stability);
130 }
131 auto attach = std::make_shared<MethodCall>(
132 THIS_VALUE, "attachInterface",
133 std::vector<std::shared_ptr<Expression>>{THIS_VALUE,
134 std::make_shared<LiteralExpression>("DESCRIPTOR")});
135 ctor->statements->Add(attach);
136 this->elements.push_back(ctor);
137
138 // asInterface
139 make_as_interface(interfaceType);
140
141 // asBinder
142 auto asBinder = std::make_shared<Method>();
143 asBinder->modifiers = PUBLIC | OVERRIDE;
144 asBinder->returnType = "android.os.IBinder";
145 asBinder->name = "asBinder";
146 asBinder->statements = std::make_shared<StatementBlock>();
147 asBinder->statements->Add(std::make_shared<ReturnStatement>(THIS_VALUE));
148 this->elements.push_back(asBinder);
149
150 if (options_.GenTransactionNames()) {
151 // getDefaultTransactionName
152 auto getDefaultTransactionName = std::make_shared<Method>();
153 getDefaultTransactionName->comment = "/** @hide */";
154 getDefaultTransactionName->modifiers = PUBLIC | STATIC;
155 getDefaultTransactionName->returnType = "java.lang.String";
156 getDefaultTransactionName->name = "getDefaultTransactionName";
157 auto code = std::make_shared<Variable>("int", "transactionCode");
158 getDefaultTransactionName->parameters.push_back(code);
159 getDefaultTransactionName->statements = std::make_shared<StatementBlock>();
160 this->code_to_method_name_switch = std::make_shared<SwitchStatement>(code);
161 getDefaultTransactionName->statements->Add(this->code_to_method_name_switch);
162 this->elements.push_back(getDefaultTransactionName);
163
164 // getTransactionName
165 auto getTransactionName = std::make_shared<Method>();
166 getTransactionName->comment = "/** @hide */";
167 getTransactionName->modifiers = PUBLIC;
168 getTransactionName->returnType = "java.lang.String";
169 getTransactionName->name = "getTransactionName";
170 auto code2 = std::make_shared<Variable>("int", "transactionCode");
171 getTransactionName->parameters.push_back(code2);
172 getTransactionName->statements = std::make_shared<StatementBlock>();
173 getTransactionName->statements->Add(std::make_shared<ReturnStatement>(
174 std::make_shared<MethodCall>(THIS_VALUE, "getDefaultTransactionName",
175 std::vector<std::shared_ptr<Expression>>{code2})));
176 this->elements.push_back(getTransactionName);
177 }
178
179 // onTransact
180 this->transact_code = std::make_shared<Variable>("int", "code");
181 this->transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
182 this->transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
183 this->transact_flags = std::make_shared<Variable>("int", "flags");
184 auto onTransact = std::make_shared<Method>();
185 onTransact->modifiers = PUBLIC | OVERRIDE;
186 onTransact->returnType = "boolean";
187 onTransact->name = "onTransact";
188 onTransact->parameters.push_back(this->transact_code);
189 onTransact->parameters.push_back(this->transact_data);
190 onTransact->parameters.push_back(this->transact_reply);
191 onTransact->parameters.push_back(this->transact_flags);
192 onTransact->statements = std::make_shared<StatementBlock>();
193 transact_statements = onTransact->statements;
194 onTransact->exceptions.push_back("android.os.RemoteException");
195 this->elements.push_back(onTransact);
196 this->transact_switch = std::make_shared<SwitchStatement>(this->transact_code);
197 }
198
finish()199 void StubClass::finish() {
200 auto default_case = std::make_shared<Case>();
201
202 auto superCall = std::make_shared<MethodCall>(
203 SUPER_VALUE, "onTransact",
204 std::vector<std::shared_ptr<Expression>>{this->transact_code, this->transact_data,
205 this->transact_reply, this->transact_flags});
206 default_case->statements->Add(std::make_shared<ReturnStatement>(superCall));
207 transact_switch->cases.push_back(default_case);
208
209 transact_statements->Add(this->transact_switch);
210
211 // getTransactionName
212 if (options_.GenTransactionNames()) {
213 // Some transaction codes are common, e.g. INTERFACE_TRANSACTION or DUMP_TRANSACTION.
214 // Common transaction codes will not be resolved to a string by getTransactionName. The method
215 // will return NULL in this case.
216 auto code_switch_default_case = std::make_shared<Case>();
217 code_switch_default_case->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
218 this->code_to_method_name_switch->cases.push_back(code_switch_default_case);
219 }
220 }
221
222 // The the expression for the interface's descriptor to be used when
223 // generating code for the given method. Null is acceptable for method
224 // and stands for synthetic cases.
get_transact_descriptor(const AidlMethod * method)225 std::shared_ptr<Expression> StubClass::get_transact_descriptor(const AidlMethod* method) {
226 if (transact_outline) {
227 if (method != nullptr) {
228 // When outlining, each outlined method needs its own literal.
229 if (outline_methods.count(method) != 0) {
230 return std::make_shared<LiteralExpression>("DESCRIPTOR");
231 }
232 } else {
233 // Synthetic case. A small number is assumed. Use its own descriptor
234 // if there are only synthetic cases.
235 if (outline_methods.size() == all_method_count) {
236 return std::make_shared<LiteralExpression>("DESCRIPTOR");
237 }
238 }
239 }
240
241 // When not outlining, store the descriptor literal into a local variable, in
242 // an effort to save const-string instructions in each switch case.
243 if (transact_descriptor == nullptr) {
244 transact_descriptor = std::make_shared<Variable>("java.lang.String", "descriptor");
245 transact_statements->Add(std::make_shared<VariableDeclaration>(
246 transact_descriptor, std::make_shared<LiteralExpression>("DESCRIPTOR")));
247 }
248 return transact_descriptor;
249 }
250
make_as_interface(const AidlInterface * interfaceType)251 void StubClass::make_as_interface(const AidlInterface* interfaceType) {
252 auto obj = std::make_shared<Variable>("android.os.IBinder", "obj");
253
254 auto m = std::make_shared<Method>();
255 m->comment = "/**\n * Cast an IBinder object into an ";
256 m->comment += interfaceType->GetCanonicalName();
257 m->comment += " interface,\n";
258 m->comment += " * generating a proxy if needed.\n */";
259 m->modifiers = PUBLIC | STATIC;
260 m->returnType = interfaceType->GetCanonicalName();
261 m->name = "asInterface";
262 m->parameters.push_back(obj);
263 m->statements = std::make_shared<StatementBlock>();
264
265 auto ifstatement = std::make_shared<IfStatement>();
266 ifstatement->expression = std::make_shared<Comparison>(obj, "==", NULL_VALUE);
267 ifstatement->statements = std::make_shared<StatementBlock>();
268 ifstatement->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
269 m->statements->Add(ifstatement);
270
271 // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
272 auto queryLocalInterface = std::make_shared<MethodCall>(obj, "queryLocalInterface");
273 queryLocalInterface->arguments.push_back(std::make_shared<LiteralExpression>("DESCRIPTOR"));
274 auto iin = std::make_shared<Variable>("android.os.IInterface", "iin");
275 auto iinVd = std::make_shared<VariableDeclaration>(iin, queryLocalInterface);
276 m->statements->Add(iinVd);
277
278 // Ensure the instance type of the local object is as expected.
279 // One scenario where this is needed is if another package (with a
280 // different class loader) runs in the same process as the service.
281
282 // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>)
283 // iin;
284 auto iinNotNull = std::make_shared<Comparison>(iin, "!=", NULL_VALUE);
285 auto instOfCheck = std::make_shared<Comparison>(
286 iin, " instanceof ", std::make_shared<LiteralExpression>(interfaceType->GetCanonicalName()));
287 auto instOfStatement = std::make_shared<IfStatement>();
288 instOfStatement->expression = std::make_shared<Comparison>(iinNotNull, "&&", instOfCheck);
289 instOfStatement->statements = std::make_shared<StatementBlock>();
290 instOfStatement->statements->Add(std::make_shared<ReturnStatement>(
291 std::make_shared<Cast>(interfaceType->GetCanonicalName(), iin)));
292 m->statements->Add(instOfStatement);
293
294 auto ne = std::make_shared<NewExpression>(interfaceType->GetCanonicalName() + ".Stub.Proxy");
295 ne->arguments.push_back(obj);
296 m->statements->Add(std::make_shared<ReturnStatement>(ne));
297
298 this->elements.push_back(m);
299 }
300
301 // =================================================
302 class ProxyClass : public Class {
303 public:
304 ProxyClass(const AidlInterface* interfaceType, const Options& options);
305 ~ProxyClass() override;
306
307 std::shared_ptr<Variable> mRemote;
308 };
309
ProxyClass(const AidlInterface * interfaceType,const Options & options)310 ProxyClass::ProxyClass(const AidlInterface* interfaceType, const Options& options) : Class() {
311 this->modifiers = PRIVATE | STATIC;
312 this->what = Class::CLASS;
313 this->type = interfaceType->GetCanonicalName() + ".Stub.Proxy";
314 this->interfaces.push_back(interfaceType->GetCanonicalName());
315
316 // IBinder mRemote
317 mRemote = std::make_shared<Variable>("android.os.IBinder", "mRemote");
318 this->elements.push_back(std::make_shared<Field>(PRIVATE, mRemote));
319
320 // Proxy()
321 auto remote = std::make_shared<Variable>("android.os.IBinder", "remote");
322 auto ctor = std::make_shared<Method>();
323 ctor->name = "Proxy";
324 ctor->statements = std::make_shared<StatementBlock>();
325 ctor->parameters.push_back(remote);
326 ctor->statements->Add(std::make_shared<Assignment>(mRemote, remote));
327 this->elements.push_back(ctor);
328
329 if (options.Version() > 0) {
330 std::ostringstream code;
331 code << "private int mCachedVersion = -1;\n";
332 this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
333 }
334 if (!options.Hash().empty()) {
335 std::ostringstream code;
336 code << "private String mCachedHash = \"-1\";\n";
337 this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
338 }
339
340 // IBinder asBinder()
341 auto asBinder = std::make_shared<Method>();
342 asBinder->modifiers = PUBLIC | OVERRIDE;
343 asBinder->returnType = "android.os.IBinder";
344 asBinder->name = "asBinder";
345 asBinder->statements = std::make_shared<StatementBlock>();
346 asBinder->statements->Add(std::make_shared<ReturnStatement>(mRemote));
347 this->elements.push_back(asBinder);
348 }
349
~ProxyClass()350 ProxyClass::~ProxyClass() {}
351
352 // =================================================
generate_new_array(const AidlTypeSpecifier & type,const AidlTypenames & typenames,std::shared_ptr<StatementBlock> addTo,std::shared_ptr<Variable> v,std::shared_ptr<Variable> parcel)353 static void generate_new_array(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
354 std::shared_ptr<StatementBlock> addTo, std::shared_ptr<Variable> v,
355 std::shared_ptr<Variable> parcel) {
356 auto len = std::make_shared<Variable>("int", v->name + "_length");
357 addTo->Add(
358 std::make_shared<VariableDeclaration>(len, std::make_shared<MethodCall>(parcel, "readInt")));
359 auto lencheck = std::make_shared<IfStatement>();
360 lencheck->expression =
361 std::make_shared<Comparison>(len, "<", std::make_shared<LiteralExpression>("0"));
362 lencheck->statements->Add(std::make_shared<Assignment>(v, NULL_VALUE));
363 lencheck->elseif = std::make_shared<IfStatement>();
364 lencheck->elseif->statements->Add(std::make_shared<Assignment>(
365 v, std::make_shared<NewArrayExpression>(InstantiableJavaSignatureOf(type, typenames), len)));
366 addTo->Add(lencheck);
367 }
368
generate_write_to_parcel(const AidlTypeSpecifier & type,std::shared_ptr<StatementBlock> addTo,std::shared_ptr<Variable> v,std::shared_ptr<Variable> parcel,bool is_return_value,const AidlTypenames & typenames)369 static void generate_write_to_parcel(const AidlTypeSpecifier& type,
370 std::shared_ptr<StatementBlock> addTo,
371 std::shared_ptr<Variable> v, std::shared_ptr<Variable> parcel,
372 bool is_return_value, const AidlTypenames& typenames) {
373 string code;
374 CodeWriterPtr writer = CodeWriter::ForString(&code);
375 CodeGeneratorContext context{
376 .writer = *(writer.get()),
377 .typenames = typenames,
378 .type = type,
379 .parcel = parcel->name,
380 .var = v->name,
381 .is_return_value = is_return_value,
382 };
383 WriteToParcelFor(context);
384 writer->Close();
385 addTo->Add(std::make_shared<LiteralStatement>(code));
386 }
387
generate_int_constant(Class * interface,const std::string & name,const std::string & value)388 static void generate_int_constant(Class* interface, const std::string& name,
389 const std::string& value) {
390 auto code = StringPrintf("public static final int %s = %s;\n", name.c_str(), value.c_str());
391 interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
392 }
393
generate_string_constant(Class * interface,const std::string & name,const std::string & value)394 static void generate_string_constant(Class* interface, const std::string& name,
395 const std::string& value) {
396 auto code = StringPrintf("public static final String %s = %s;\n", name.c_str(), value.c_str());
397 interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
398 }
399
generate_interface_method(const AidlMethod & method,const AidlTypenames & typenames)400 static std::shared_ptr<Method> generate_interface_method(const AidlMethod& method,
401 const AidlTypenames& typenames) {
402 auto decl = std::make_shared<Method>();
403 decl->comment = method.GetComments();
404 decl->modifiers = PUBLIC;
405 decl->returnType = JavaSignatureOf(method.GetType(), typenames);
406 decl->name = method.GetName();
407 decl->annotations = generate_java_annotations(method.GetType());
408
409 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
410 auto var = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
411 var->annotations = generate_java_annotations(arg->GetType());
412 decl->parameters.push_back(var);
413 }
414
415 decl->exceptions.push_back("android.os.RemoteException");
416
417 return decl;
418 }
419
generate_stub_code(const AidlInterface & iface,const AidlMethod & method,bool oneway,std::shared_ptr<Variable> transact_data,std::shared_ptr<Variable> transact_reply,const AidlTypenames & typenames,std::shared_ptr<StatementBlock> statement_block,std::shared_ptr<StubClass> stubClass,const Options & options)420 static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
421 std::shared_ptr<Variable> transact_data,
422 std::shared_ptr<Variable> transact_reply,
423 const AidlTypenames& typenames,
424 std::shared_ptr<StatementBlock> statement_block,
425 std::shared_ptr<StubClass> stubClass, const Options& options) {
426 // try and finally
427 auto tryStatement = std::make_shared<TryStatement>();
428 auto finallyStatement = std::make_shared<FinallyStatement>();
429 auto& statements = statement_block;
430
431 if (options.GenTraces()) {
432 statements->Add(tryStatement);
433 statements->Add(finallyStatement);
434 statements = tryStatement->statements;
435 tryStatement->statements->Add(std::make_shared<MethodCall>(
436 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
437 std::vector<std::shared_ptr<Expression>>{
438 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
439 std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
440 "::" + method.GetName() + "::server")}));
441 finallyStatement->statements->Add(std::make_shared<MethodCall>(
442 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
443 std::vector<std::shared_ptr<Expression>>{
444 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
445 }
446
447 auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName());
448
449 // interface token validation is the very first thing we do
450 statements->Add(std::make_shared<MethodCall>(
451 transact_data, "enforceInterface",
452 std::vector<std::shared_ptr<Expression>>{stubClass->get_transact_descriptor(&method)}));
453
454 // args
455 VariableFactory stubArgs("_arg");
456 {
457 // keep this across different args in order to create the classloader
458 // at most once.
459 bool is_classloader_created = false;
460 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
461 std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType(), typenames);
462
463 statements->Add(std::make_shared<VariableDeclaration>(v));
464
465 if (arg->GetDirection() & AidlArgument::IN_DIR) {
466 string code;
467 CodeWriterPtr writer = CodeWriter::ForString(&code);
468 CodeGeneratorContext context{.writer = *(writer.get()),
469 .typenames = typenames,
470 .type = arg->GetType(),
471 .parcel = transact_data->name,
472 .var = v->name,
473 .is_classloader_created = &is_classloader_created};
474 CreateFromParcelFor(context);
475 writer->Close();
476 statements->Add(std::make_shared<LiteralStatement>(code));
477 } else {
478 if (!arg->GetType().IsArray()) {
479 statements->Add(std::make_shared<Assignment>(
480 v, std::make_shared<NewExpression>(
481 InstantiableJavaSignatureOf(arg->GetType(), typenames))));
482 } else {
483 generate_new_array(arg->GetType(), typenames, statements, v, transact_data);
484 }
485 }
486
487 realCall->arguments.push_back(v);
488 }
489 }
490
491 // the real call
492 if (method.GetType().GetName() == "void") {
493 statements->Add(realCall);
494
495 if (!oneway) {
496 // report that there were no exceptions
497 auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
498 statements->Add(ex);
499 }
500 } else {
501 auto _result =
502 std::make_shared<Variable>(JavaSignatureOf(method.GetType(), typenames), "_result");
503 statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
504
505 if (!oneway) {
506 // report that there were no exceptions
507 auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
508 statements->Add(ex);
509 }
510
511 // marshall the return value
512 generate_write_to_parcel(method.GetType(), statements, _result, transact_reply, true,
513 typenames);
514 }
515
516 // out parameters
517 int i = 0;
518 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
519 std::shared_ptr<Variable> v = stubArgs.Get(i++);
520
521 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
522 generate_write_to_parcel(arg->GetType(), statements, v, transact_reply, true, typenames);
523 }
524 }
525
526 // return true
527 statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
528 }
529
generate_stub_case(const AidlInterface & iface,const AidlMethod & method,const std::string & transactCodeName,bool oneway,std::shared_ptr<StubClass> stubClass,const AidlTypenames & typenames,const Options & options)530 static void generate_stub_case(const AidlInterface& iface, const AidlMethod& method,
531 const std::string& transactCodeName, bool oneway,
532 std::shared_ptr<StubClass> stubClass, const AidlTypenames& typenames,
533 const Options& options) {
534 auto c = std::make_shared<Case>(transactCodeName);
535
536 generate_stub_code(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply,
537 typenames, c->statements, stubClass, options);
538
539 stubClass->transact_switch->cases.push_back(c);
540 }
541
generate_stub_case_outline(const AidlInterface & iface,const AidlMethod & method,const std::string & transactCodeName,bool oneway,std::shared_ptr<StubClass> stubClass,const AidlTypenames & typenames,const Options & options)542 static void generate_stub_case_outline(const AidlInterface& iface, const AidlMethod& method,
543 const std::string& transactCodeName, bool oneway,
544 std::shared_ptr<StubClass> stubClass,
545 const AidlTypenames& typenames, const Options& options) {
546 std::string outline_name = "onTransact$" + method.GetName() + "$";
547 // Generate an "outlined" method with the actual code.
548 {
549 auto transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
550 auto transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
551 auto onTransact_case = std::make_shared<Method>();
552 onTransact_case->modifiers = PRIVATE;
553 onTransact_case->returnType = "boolean";
554 onTransact_case->name = outline_name;
555 onTransact_case->parameters.push_back(transact_data);
556 onTransact_case->parameters.push_back(transact_reply);
557 onTransact_case->statements = std::make_shared<StatementBlock>();
558 onTransact_case->exceptions.push_back("android.os.RemoteException");
559 stubClass->elements.push_back(onTransact_case);
560
561 generate_stub_code(iface, method, oneway, transact_data, transact_reply, typenames,
562 onTransact_case->statements, stubClass, options);
563 }
564
565 // Generate the case dispatch.
566 {
567 auto c = std::make_shared<Case>(transactCodeName);
568
569 auto helper_call =
570 std::make_shared<MethodCall>(THIS_VALUE, outline_name,
571 std::vector<std::shared_ptr<Expression>>{
572 stubClass->transact_data, stubClass->transact_reply});
573 c->statements->Add(std::make_shared<ReturnStatement>(helper_call));
574
575 stubClass->transact_switch->cases.push_back(c);
576 }
577 }
578
generate_proxy_method(const AidlInterface & iface,const AidlMethod & method,const std::string & transactCodeName,bool oneway,std::shared_ptr<ProxyClass> proxyClass,const AidlTypenames & typenames,const Options & options)579 static std::shared_ptr<Method> generate_proxy_method(
580 const AidlInterface& iface, const AidlMethod& method, const std::string& transactCodeName,
581 bool oneway, std::shared_ptr<ProxyClass> proxyClass, const AidlTypenames& typenames,
582 const Options& options) {
583 auto proxy = std::make_shared<Method>();
584 proxy->comment = method.GetComments();
585 proxy->modifiers = PUBLIC | OVERRIDE;
586 proxy->returnType = JavaSignatureOf(method.GetType(), typenames);
587 proxy->name = method.GetName();
588 proxy->statements = std::make_shared<StatementBlock>();
589 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
590 proxy->parameters.push_back(
591 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
592 }
593 proxy->exceptions.push_back("android.os.RemoteException");
594
595 // the parcels
596 auto _data = std::make_shared<Variable>("android.os.Parcel", "_data");
597 proxy->statements->Add(std::make_shared<VariableDeclaration>(
598 _data, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
599 std::shared_ptr<Variable> _reply = nullptr;
600 if (!oneway) {
601 _reply = std::make_shared<Variable>("android.os.Parcel", "_reply");
602 proxy->statements->Add(std::make_shared<VariableDeclaration>(
603 _reply, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
604 }
605
606 // the return value
607 std::shared_ptr<Variable> _result = nullptr;
608 if (method.GetType().GetName() != "void") {
609 _result = std::make_shared<Variable>(*proxy->returnType, "_result");
610 proxy->statements->Add(std::make_shared<VariableDeclaration>(_result));
611 }
612
613 // try and finally
614 auto tryStatement = std::make_shared<TryStatement>();
615 proxy->statements->Add(tryStatement);
616 auto finallyStatement = std::make_shared<FinallyStatement>();
617 proxy->statements->Add(finallyStatement);
618
619 if (options.GenTraces()) {
620 tryStatement->statements->Add(std::make_shared<MethodCall>(
621 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
622 std::vector<std::shared_ptr<Expression>>{
623 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
624 std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
625 "::" + method.GetName() + "::client")}));
626 }
627
628 // the interface identifier token: the DESCRIPTOR constant, marshalled as a
629 // string
630 tryStatement->statements->Add(std::make_shared<MethodCall>(
631 _data, "writeInterfaceToken",
632 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("DESCRIPTOR")}));
633
634 // the parameters
635 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
636 auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
637 AidlArgument::Direction dir = arg->GetDirection();
638 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
639 auto checklen = std::make_shared<IfStatement>();
640 checklen->expression = std::make_shared<Comparison>(v, "==", NULL_VALUE);
641 checklen->statements->Add(std::make_shared<MethodCall>(
642 _data, "writeInt",
643 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("-1")}));
644 checklen->elseif = std::make_shared<IfStatement>();
645 checklen->elseif->statements->Add(std::make_shared<MethodCall>(
646 _data, "writeInt",
647 std::vector<std::shared_ptr<Expression>>{std::make_shared<FieldVariable>(v, "length")}));
648 tryStatement->statements->Add(checklen);
649 } else if (dir & AidlArgument::IN_DIR) {
650 generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
651 typenames);
652 }
653 }
654
655 // the transact call
656 auto call = std::make_shared<MethodCall>(
657 proxyClass->mRemote, "transact",
658 std::vector<std::shared_ptr<Expression>>{
659 std::make_shared<LiteralExpression>("Stub." + transactCodeName), _data,
660 _reply ? _reply : NULL_VALUE,
661 std::make_shared<LiteralExpression>(oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0")});
662 auto _status = std::make_shared<Variable>("boolean", "_status");
663 tryStatement->statements->Add(std::make_shared<VariableDeclaration>(_status, call));
664
665 // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall
666 // back to the local method in the default impl, if set before.
667 vector<string> arg_names;
668 for (const auto& arg : method.GetArguments()) {
669 arg_names.emplace_back(arg->GetName());
670 }
671 bool has_return_type = method.GetType().GetName() != "void";
672 tryStatement->statements->Add(std::make_shared<LiteralStatement>(
673 android::base::StringPrintf(has_return_type ? "if (!_status && getDefaultImpl() != null) {\n"
674 " return getDefaultImpl().%s(%s);\n"
675 "}\n"
676 : "if (!_status && getDefaultImpl() != null) {\n"
677 " getDefaultImpl().%s(%s);\n"
678 " return;\n"
679 "}\n",
680 method.GetName().c_str(), Join(arg_names, ", ").c_str())));
681
682 // throw back exceptions.
683 if (_reply) {
684 auto ex = std::make_shared<MethodCall>(_reply, "readException");
685 tryStatement->statements->Add(ex);
686 }
687
688 // returning and cleanup
689 if (_reply != nullptr) {
690 // keep this across return value and arguments in order to create the
691 // classloader at most once.
692 bool is_classloader_created = false;
693 if (_result != nullptr) {
694 string code;
695 CodeWriterPtr writer = CodeWriter::ForString(&code);
696 CodeGeneratorContext context{.writer = *(writer.get()),
697 .typenames = typenames,
698 .type = method.GetType(),
699 .parcel = _reply->name,
700 .var = _result->name,
701 .is_classloader_created = &is_classloader_created};
702 CreateFromParcelFor(context);
703 writer->Close();
704 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
705 }
706
707 // the out/inout parameters
708 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
709 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
710 string code;
711 CodeWriterPtr writer = CodeWriter::ForString(&code);
712 CodeGeneratorContext context{.writer = *(writer.get()),
713 .typenames = typenames,
714 .type = arg->GetType(),
715 .parcel = _reply->name,
716 .var = arg->GetName(),
717 .is_classloader_created = &is_classloader_created};
718 ReadFromParcelFor(context);
719 writer->Close();
720 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
721 }
722 }
723
724 finallyStatement->statements->Add(std::make_shared<MethodCall>(_reply, "recycle"));
725 }
726 finallyStatement->statements->Add(std::make_shared<MethodCall>(_data, "recycle"));
727
728 if (options.GenTraces()) {
729 finallyStatement->statements->Add(std::make_shared<MethodCall>(
730 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
731 std::vector<std::shared_ptr<Expression>>{
732 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
733 }
734
735 if (_result != nullptr) {
736 proxy->statements->Add(std::make_shared<ReturnStatement>(_result));
737 }
738
739 return proxy;
740 }
741
generate_methods(const AidlInterface & iface,const AidlMethod & method,Class * interface,std::shared_ptr<StubClass> stubClass,std::shared_ptr<ProxyClass> proxyClass,int index,const AidlTypenames & typenames,const Options & options)742 static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
743 std::shared_ptr<StubClass> stubClass,
744 std::shared_ptr<ProxyClass> proxyClass, int index,
745 const AidlTypenames& typenames, const Options& options) {
746 const bool oneway = method.IsOneway();
747
748 // == the TRANSACT_ constant =============================================
749 string transactCodeName = "TRANSACTION_";
750 transactCodeName += method.GetName();
751
752 auto transactCode =
753 std::make_shared<Field>(STATIC | FINAL, std::make_shared<Variable>("int", transactCodeName));
754 transactCode->value =
755 StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
756 stubClass->elements.push_back(transactCode);
757
758 // getTransactionName
759 if (options.GenTransactionNames()) {
760 auto c = std::make_shared<Case>(transactCodeName);
761 c->statements->Add(std::make_shared<ReturnStatement>(
762 std::make_shared<StringLiteralExpression>(method.GetName())));
763 stubClass->code_to_method_name_switch->cases.push_back(c);
764 }
765
766 // == the declaration in the interface ===================================
767 std::shared_ptr<ClassElement> decl;
768 if (method.IsUserDefined()) {
769 decl = generate_interface_method(method, typenames);
770 } else {
771 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
772 std::ostringstream code;
773 code << "public int " << kGetInterfaceVersion << "() "
774 << "throws android.os.RemoteException;\n";
775 decl = std::make_shared<LiteralClassElement>(code.str());
776 }
777 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
778 std::ostringstream code;
779 code << "public String " << kGetInterfaceHash << "() "
780 << "throws android.os.RemoteException;\n";
781 decl = std::make_shared<LiteralClassElement>(code.str());
782 }
783 }
784 interface->elements.push_back(decl);
785
786 // == the stub method ====================================================
787 if (method.IsUserDefined()) {
788 bool outline_stub =
789 stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
790 if (outline_stub) {
791 generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, typenames,
792 options);
793 } else {
794 generate_stub_case(iface, method, transactCodeName, oneway, stubClass, typenames, options);
795 }
796 } else {
797 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
798 auto c = std::make_shared<Case>(transactCodeName);
799 std::ostringstream code;
800 code << "data.enforceInterface(descriptor);\n"
801 << "reply.writeNoException();\n"
802 << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
803 << "return true;\n";
804 c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
805 stubClass->transact_switch->cases.push_back(c);
806 }
807 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
808 auto c = std::make_shared<Case>(transactCodeName);
809 std::ostringstream code;
810 code << "data.enforceInterface(descriptor);\n"
811 << "reply.writeNoException();\n"
812 << "reply.writeString(" << kGetInterfaceHash << "());\n"
813 << "return true;\n";
814 c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
815 stubClass->transact_switch->cases.push_back(c);
816 }
817 }
818
819 // == the proxy method ===================================================
820 std::shared_ptr<ClassElement> proxy = nullptr;
821 if (method.IsUserDefined()) {
822 proxy = generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, typenames,
823 options);
824
825 } else {
826 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
827 std::ostringstream code;
828 code << "@Override\n"
829 << "public int " << kGetInterfaceVersion << "()"
830 << " throws "
831 << "android.os.RemoteException {\n"
832 << " if (mCachedVersion == -1) {\n"
833 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
834 << " android.os.Parcel reply = android.os.Parcel.obtain();\n"
835 << " try {\n"
836 << " data.writeInterfaceToken(DESCRIPTOR);\n"
837 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
838 << "data, reply, 0);\n"
839 << " if (!_status) {\n"
840 << " if (getDefaultImpl() != null) {\n"
841 << " return getDefaultImpl().getInterfaceVersion();\n"
842 << " }\n"
843 << " }\n"
844 << " reply.readException();\n"
845 << " mCachedVersion = reply.readInt();\n"
846 << " } finally {\n"
847 << " reply.recycle();\n"
848 << " data.recycle();\n"
849 << " }\n"
850 << " }\n"
851 << " return mCachedVersion;\n"
852 << "}\n";
853 proxy = std::make_shared<LiteralClassElement>(code.str());
854 }
855 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
856 std::ostringstream code;
857 code << "@Override\n"
858 << "public synchronized String " << kGetInterfaceHash << "()"
859 << " throws "
860 << "android.os.RemoteException {\n"
861 << " if (\"-1\".equals(mCachedHash)) {\n"
862 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
863 << " android.os.Parcel reply = android.os.Parcel.obtain();\n"
864 << " try {\n"
865 << " data.writeInterfaceToken(DESCRIPTOR);\n"
866 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
867 << "data, reply, 0);\n"
868 << " if (!_status) {\n"
869 << " if (getDefaultImpl() != null) {\n"
870 << " return getDefaultImpl().getInterfaceHash();\n"
871 << " }\n"
872 << " }\n"
873 << " reply.readException();\n"
874 << " mCachedHash = reply.readString();\n"
875 << " } finally {\n"
876 << " reply.recycle();\n"
877 << " data.recycle();\n"
878 << " }\n"
879 << " }\n"
880 << " return mCachedHash;\n"
881 << "}\n";
882 proxy = std::make_shared<LiteralClassElement>(code.str());
883 }
884 }
885 if (proxy != nullptr) {
886 proxyClass->elements.push_back(proxy);
887 }
888 }
889
generate_interface_descriptors(const Options & options,const AidlInterface * iface,Class * interface,std::shared_ptr<StubClass> stub,std::shared_ptr<ProxyClass> proxy)890 static void generate_interface_descriptors(const Options& options, const AidlInterface* iface,
891 Class* interface, std::shared_ptr<StubClass> stub,
892 std::shared_ptr<ProxyClass> proxy) {
893 // the interface descriptor transaction handler
894 auto c = std::make_shared<Case>("INTERFACE_TRANSACTION");
895 c->statements->Add(std::make_shared<MethodCall>(
896 stub->transact_reply, "writeString",
897 std::vector<std::shared_ptr<Expression>>{stub->get_transact_descriptor(nullptr)}));
898 c->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
899 stub->transact_switch->cases.push_back(c);
900
901 // and the proxy-side method returning the descriptor directly
902 auto getDesc = std::make_shared<Method>();
903 getDesc->modifiers = PUBLIC;
904 getDesc->returnType = "java.lang.String";
905 getDesc->name = "getInterfaceDescriptor";
906 getDesc->statements = std::make_shared<StatementBlock>();
907 getDesc->statements->Add(
908 std::make_shared<ReturnStatement>(std::make_shared<LiteralExpression>("DESCRIPTOR")));
909 proxy->elements.push_back(getDesc);
910
911 // add the DESCRIPTOR field to the interface class
912 Class* classToAddDescriptor = interface;
913 static std::set<std::string> greylist = {
914 #include "hiddenapi-greylist"
915 };
916 if (greylist.find(iface->GetCanonicalName()) != greylist.end()) {
917 // For app compatibility, we keep DESCRIPTOR to the stub class for
918 // the interfaces that are in the greylist.
919 classToAddDescriptor = stub.get();
920 }
921 auto descriptor = std::make_shared<Field>(
922 STATIC | FINAL | PUBLIC, std::make_shared<Variable>("java.lang.String", "DESCRIPTOR"));
923 if (options.IsStructured()) {
924 // mangle the interface name at build time and demangle it at runtime, to avoid
925 // being renamed by jarjar. See b/153843174
926 std::string name = iface->GetCanonicalName();
927 std::replace(name.begin(), name.end(), '.', '$');
928 descriptor->value = "\"" + name + "\".replace('$', '.')";
929 } else {
930 descriptor->value = "\"" + iface->GetCanonicalName() + "\"";
931 }
932 classToAddDescriptor->elements.push_back(descriptor);
933 }
934
935 // Check whether (some) methods in this interface should be "outlined," that
936 // is, have specific onTransact methods for certain cases. Set up StubClass
937 // metadata accordingly.
938 //
939 // Outlining will be enabled if the interface has more than outline_threshold
940 // methods. In that case, the methods are sorted by number of arguments
941 // (so that more "complex" methods come later), and the first non_outline_count
942 // number of methods not outlined (are kept in the onTransact() method).
943 //
944 // Requirements: non_outline_count <= outline_threshold.
compute_outline_methods(const AidlInterface * iface,const std::shared_ptr<StubClass> stub,size_t outline_threshold,size_t non_outline_count)945 static void compute_outline_methods(const AidlInterface* iface,
946 const std::shared_ptr<StubClass> stub, size_t outline_threshold,
947 size_t non_outline_count) {
948 CHECK_LE(non_outline_count, outline_threshold);
949 // We'll outline (create sub methods) if there are more than min_methods
950 // cases.
951 stub->transact_outline = iface->GetMethods().size() > outline_threshold;
952 if (stub->transact_outline) {
953 stub->all_method_count = iface->GetMethods().size();
954 std::vector<const AidlMethod*> methods;
955 methods.reserve(iface->GetMethods().size());
956 for (const std::unique_ptr<AidlMethod>& ptr : iface->GetMethods()) {
957 methods.push_back(ptr.get());
958 }
959
960 std::stable_sort(
961 methods.begin(),
962 methods.end(),
963 [](const AidlMethod* m1, const AidlMethod* m2) {
964 return m1->GetArguments().size() < m2->GetArguments().size();
965 });
966
967 stub->outline_methods.insert(methods.begin() + non_outline_count,
968 methods.end());
969 }
970 }
971
generate_default_impl_method(const AidlMethod & method,const AidlTypenames & typenames)972 static shared_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method,
973 const AidlTypenames& typenames) {
974 auto default_method = std::make_shared<Method>();
975 default_method->comment = method.GetComments();
976 default_method->modifiers = PUBLIC | OVERRIDE;
977 default_method->returnType = JavaSignatureOf(method.GetType(), typenames);
978 default_method->name = method.GetName();
979 default_method->statements = std::make_shared<StatementBlock>();
980 for (const auto& arg : method.GetArguments()) {
981 default_method->parameters.push_back(
982 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
983 }
984 default_method->exceptions.push_back("android.os.RemoteException");
985
986 if (method.GetType().GetName() != "void") {
987 const string& defaultValue = DefaultJavaValueOf(method.GetType(), typenames);
988 default_method->statements->Add(
989 std::make_shared<LiteralStatement>(StringPrintf("return %s;\n", defaultValue.c_str())));
990 }
991 return default_method;
992 }
993
generate_default_impl_class(const AidlInterface & iface,const AidlTypenames & typenames,const Options & options)994 static shared_ptr<Class> generate_default_impl_class(const AidlInterface& iface,
995 const AidlTypenames& typenames,
996 const Options& options) {
997 auto default_class = std::make_shared<Class>();
998 default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
999 default_class->modifiers = PUBLIC | STATIC;
1000 default_class->what = Class::CLASS;
1001 default_class->type = iface.GetCanonicalName() + ".Default";
1002 default_class->interfaces.emplace_back(iface.GetCanonicalName());
1003
1004 for (const auto& m : iface.GetMethods()) {
1005 if (m->IsUserDefined()) {
1006 default_class->elements.emplace_back(generate_default_impl_method(*m.get(), typenames));
1007 } else {
1008 // These are called only when the remote side does not implement these
1009 // methods, which is normally impossible, because these methods are
1010 // automatically declared in the interface class and not implementing
1011 // them on the remote side causes a compilation error. But if the remote
1012 // side somehow managed to not implement it, that's an error and we
1013 // report the case by returning an invalid value here.
1014 if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
1015 std::ostringstream code;
1016 code << "@Override\n"
1017 << "public int " << kGetInterfaceVersion << "() {\n"
1018 << " return 0;\n"
1019 << "}\n";
1020 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1021 }
1022 if (m->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1023 std::ostringstream code;
1024 code << "@Override\n"
1025 << "public String " << kGetInterfaceHash << "() {\n"
1026 << " return \"\";\n"
1027 << "}\n";
1028 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1029 }
1030 }
1031 }
1032
1033 default_class->elements.emplace_back(
1034 std::make_shared<LiteralClassElement>("@Override\n"
1035 "public android.os.IBinder asBinder() {\n"
1036 " return null;\n"
1037 "}\n"));
1038
1039 return default_class;
1040 }
1041
generate_binder_interface_class(const AidlInterface * iface,const AidlTypenames & typenames,const Options & options)1042 std::unique_ptr<Class> generate_binder_interface_class(const AidlInterface* iface,
1043 const AidlTypenames& typenames,
1044 const Options& options) {
1045 // the interface class
1046 auto interface = std::make_unique<Class>();
1047 interface->comment = iface->GetComments();
1048 interface->modifiers = PUBLIC;
1049 interface->what = Class::INTERFACE;
1050 interface->type = iface->GetCanonicalName();
1051 interface->interfaces.push_back("android.os.IInterface");
1052 interface->annotations = generate_java_annotations(*iface);
1053
1054 if (options.Version()) {
1055 std::ostringstream code;
1056 code << "/**\n"
1057 << " * The version of this interface that the caller is built against.\n"
1058 << " * This might be different from what {@link #getInterfaceVersion()\n"
1059 << " * getInterfaceVersion} returns as that is the version of the interface\n"
1060 << " * that the remote object is implementing.\n"
1061 << " */\n"
1062 << "public static final int VERSION = " << options.Version() << ";\n";
1063 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1064 }
1065 if (!options.Hash().empty()) {
1066 std::ostringstream code;
1067 code << "public static final String HASH = \"" << options.Hash() << "\";\n";
1068 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1069 }
1070
1071 // the default impl class
1072 auto default_impl = generate_default_impl_class(*iface, typenames, options);
1073 interface->elements.emplace_back(default_impl);
1074
1075 // the stub inner class
1076 auto stub = std::make_shared<StubClass>(iface, options);
1077 interface->elements.push_back(stub);
1078
1079 compute_outline_methods(iface,
1080 stub,
1081 options.onTransact_outline_threshold_,
1082 options.onTransact_non_outline_count_);
1083
1084 // the proxy inner class
1085 auto proxy = std::make_shared<ProxyClass>(iface, options);
1086 stub->elements.push_back(proxy);
1087
1088 // stub and proxy support for getInterfaceDescriptor()
1089 generate_interface_descriptors(options, iface, interface.get(), stub, proxy);
1090
1091 // all the declared constants of the interface
1092 for (const auto& constant : iface->GetConstantDeclarations()) {
1093 const AidlConstantValue& value = constant->GetValue();
1094 auto comment = constant->GetType().GetComments();
1095 if (comment.length() != 0) {
1096 auto code = StringPrintf("%s\n", comment.c_str());
1097 interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
1098 }
1099 switch (value.GetType()) {
1100 case AidlConstantValue::Type::STRING: {
1101 generate_string_constant(interface.get(), constant->GetName(),
1102 constant->ValueString(ConstantValueDecorator));
1103 break;
1104 }
1105 case AidlConstantValue::Type::BOOLEAN: // fall-through
1106 case AidlConstantValue::Type::INT8: // fall-through
1107 case AidlConstantValue::Type::INT32: {
1108 generate_int_constant(interface.get(), constant->GetName(),
1109 constant->ValueString(ConstantValueDecorator));
1110 break;
1111 }
1112 default: {
1113 LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
1114 }
1115 }
1116 }
1117
1118 // all the declared methods of the interface
1119
1120 for (const auto& item : iface->GetMethods()) {
1121 generate_methods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames,
1122 options);
1123 }
1124
1125 // additional static methods for the default impl set/get to the
1126 // stub class. Can't add them to the interface as the generated java files
1127 // may be compiled with Java < 1.7 where static interface method isn't
1128 // supported.
1129 // TODO(b/111417145) make this conditional depending on the Java language
1130 // version requested
1131 const string i_name = iface->GetCanonicalName();
1132 stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
1133 StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
1134 " // Only one user of this interface can use this function\n"
1135 " // at a time. This is a heuristic to detect if two different\n"
1136 " // users in the same process use this function.\n"
1137 " if (Stub.Proxy.sDefaultImpl != null) {\n"
1138 " throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
1139 " }\n"
1140 " if (impl != null) {\n"
1141 " Stub.Proxy.sDefaultImpl = impl;\n"
1142 " return true;\n"
1143 " }\n"
1144 " return false;\n"
1145 "}\n",
1146 i_name.c_str())));
1147 stub->elements.emplace_back(
1148 std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n"
1149 " return Stub.Proxy.sDefaultImpl;\n"
1150 "}\n",
1151 i_name.c_str())));
1152
1153 // the static field is defined in the proxy class, not in the interface class
1154 // because all fields in an interface class are by default final.
1155 proxy->elements.emplace_back(std::make_shared<LiteralClassElement>(
1156 StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
1157
1158 stub->finish();
1159
1160 return interface;
1161 }
1162
1163 } // namespace java
1164 } // namespace aidl
1165 } // namespace android
1166