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