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