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