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 "AST.h"
18
19 #include "Coordinator.h"
20 #include "Interface.h"
21 #include "Method.h"
22 #include "Reference.h"
23 #include "Scope.h"
24
25 #include <hidl-util/Formatter.h>
26 #include <android-base/logging.h>
27
28 namespace android {
29
emitJavaReaderWriter(Formatter & out,const std::string & parcelObj,const NamedReference<Type> * arg,bool isReader,bool addPrefixToName) const30 void AST::emitJavaReaderWriter(Formatter& out, const std::string& parcelObj,
31 const NamedReference<Type>* arg, bool isReader,
32 bool addPrefixToName) const {
33 if (isReader) {
34 out << arg->type().getJavaType()
35 << " "
36 << (addPrefixToName ? "_hidl_out_" : "")
37 << arg->name()
38 << " = ";
39 }
40
41 arg->type().emitJavaReaderWriter(out, parcelObj,
42 (addPrefixToName ? "_hidl_out_" : "") + arg->name(),
43 isReader);
44 }
45
generateJavaTypes(Formatter & out,const std::string & limitToType) const46 void AST::generateJavaTypes(Formatter& out, const std::string& limitToType) const {
47 // Splits types.hal up into one java file per declared type.
48 CHECK(!limitToType.empty()) << getFilename();
49
50 for (const auto& type : mRootScope.getSubTypes()) {
51 std::string typeName = type->localName();
52
53 if (type->isTypeDef()) continue;
54 if (typeName != limitToType) continue;
55
56 std::vector<std::string> packageComponents;
57 getPackageAndVersionComponents(
58 &packageComponents, true /* cpp_compatible */);
59
60 out << "package " << mPackage.javaPackage() << ";\n\n\n";
61
62 type->emitJavaTypeDeclarations(out, true /* atTopLevel */);
63 return;
64 }
65
66 CHECK(false) << "generateJavaTypes could not find limitToType type";
67 }
68
emitGetService(Formatter & out,const std::string & ifaceName,const std::string & fqName,bool isRetry)69 void emitGetService(
70 Formatter& out,
71 const std::string& ifaceName,
72 const std::string& fqName,
73 bool isRetry) {
74 out << "public static "
75 << ifaceName
76 << " getService(String serviceName";
77 if (isRetry) {
78 out << ", boolean retry";
79 }
80 out << ") throws android.os.RemoteException ";
81 out.block([&] {
82 out << "return "
83 << ifaceName
84 << ".asInterface(android.os.HwBinder.getService(\""
85 << fqName
86 << "\", serviceName";
87 if (isRetry) {
88 out << ", retry";
89 }
90 out << "));\n";
91 }).endl().endl();
92
93 out << "public static "
94 << ifaceName
95 << " getService(";
96 if (isRetry) {
97 out << "boolean retry";
98 }
99 out << ") throws android.os.RemoteException ";
100 out.block([&] {
101 out << "return getService(\"default\"";
102 if (isRetry) {
103 out << ", retry";
104 }
105 out <<");\n";
106 }).endl().endl();
107 }
108
generateJava(Formatter & out,const std::string & limitToType) const109 void AST::generateJava(Formatter& out, const std::string& limitToType) const {
110 CHECK(isJavaCompatible()) << getFilename();
111
112 if (!AST::isInterface()) {
113 generateJavaTypes(out, limitToType);
114 return;
115 }
116
117 const Interface* iface = mRootScope.getInterface();
118 const std::string ifaceName = iface->localName();
119 const std::string baseName = iface->getBaseName();
120
121 std::vector<std::string> packageComponents;
122 getPackageAndVersionComponents(
123 &packageComponents, true /* cpp_compatible */);
124
125 out << "package " << mPackage.javaPackage() << ";\n\n";
126
127 out.setNamespace(mPackage.javaPackage() + ".");
128
129 const Interface *superType = iface->superType();
130
131 out << "public interface " << ifaceName << " extends ";
132
133 if (superType != NULL) {
134 out << superType->fullJavaName();
135 } else {
136 out << "android.os.IHwInterface";
137 }
138
139 out << " {\n";
140 out.indent();
141
142 out << "public static final String kInterfaceName = \""
143 << mPackage.string()
144 << "::"
145 << ifaceName
146 << "\";\n\n";
147
148 out << "/* package private */ static "
149 << ifaceName
150 << " asInterface(android.os.IHwBinder binder) {\n";
151
152 out.indent();
153
154 out << "if (binder == null) {\n";
155 out.indent();
156 out << "return null;\n";
157 out.unindent();
158 out << "}\n\n";
159
160 out << "android.os.IHwInterface iface =\n";
161 out.indent();
162 out.indent();
163 out << "binder.queryLocalInterface(kInterfaceName);\n\n";
164 out.unindent();
165 out.unindent();
166
167 out << "if ((iface != null) && (iface instanceof "
168 << ifaceName
169 << ")) {\n";
170
171 out.indent();
172 out << "return (" << ifaceName << ")iface;\n";
173 out.unindent();
174 out << "}\n\n";
175
176 out << ifaceName << " proxy = new " << ifaceName << ".Proxy(binder);\n\n";
177 out << "try {\n";
178 out.indent();
179 out << "for (String descriptor : proxy.interfaceChain()) {\n";
180 out.indent();
181 out << "if (descriptor.equals(kInterfaceName)) {\n";
182 out.indent();
183 out << "return proxy;\n";
184 out.unindent();
185 out << "}\n";
186 out.unindent();
187 out << "}\n";
188 out.unindent();
189 out << "} catch (android.os.RemoteException e) {\n";
190 out.indent();
191 out.unindent();
192 out << "}\n\n";
193
194 out << "return null;\n";
195
196 out.unindent();
197 out << "}\n\n";
198
199 out << "public static "
200 << ifaceName
201 << " castFrom(android.os.IHwInterface iface) {\n";
202 out.indent();
203
204 out << "return (iface == null) ? null : "
205 << ifaceName
206 << ".asInterface(iface.asBinder());\n";
207
208 out.unindent();
209 out << "}\n\n";
210
211 out << "@Override\npublic android.os.IHwBinder asBinder();\n\n";
212
213 emitGetService(out, ifaceName, iface->fqName().string(), true /* isRetry */);
214 emitGetService(out, ifaceName, iface->fqName().string(), false /* isRetry */);
215
216 emitJavaTypeDeclarations(out);
217
218 for (const auto &method : iface->methods()) {
219 if (method->isHiddenFromJava()) {
220 continue;
221 }
222
223 const bool returnsValue = !method->results().empty();
224 const bool needsCallback = method->results().size() > 1;
225
226 if (needsCallback) {
227 out << "\n@java.lang.FunctionalInterface\npublic interface " << method->name()
228 << "Callback {\n";
229
230 out.indent();
231
232 out << "public void onValues(";
233 method->emitJavaResultSignature(out);
234 out << ");\n";
235
236 out.unindent();
237 out << "}\n\n";
238 }
239
240 method->emitDocComment(out);
241
242 if (returnsValue && !needsCallback) {
243 out << method->results()[0]->type().getJavaType();
244 } else {
245 out << "void";
246 }
247
248 out << " "
249 << method->name()
250 << "(";
251 method->emitJavaArgSignature(out);
252
253 if (needsCallback) {
254 if (!method->args().empty()) {
255 out << ", ";
256 }
257
258 out << method->name()
259 << "Callback _hidl_cb";
260 }
261
262 out << ")\n";
263 out.indent();
264 out << "throws android.os.RemoteException;\n";
265 out.unindent();
266 }
267
268 out << "\npublic static final class Proxy implements "
269 << ifaceName
270 << " {\n";
271
272 out.indent();
273
274 out << "private android.os.IHwBinder mRemote;\n\n";
275 out << "public Proxy(android.os.IHwBinder remote) {\n";
276 out.indent();
277 out << "mRemote = java.util.Objects.requireNonNull(remote);\n";
278 out.unindent();
279 out << "}\n\n";
280
281 out << "@Override\npublic android.os.IHwBinder asBinder() {\n";
282 out.indent();
283 out << "return mRemote;\n";
284 out.unindent();
285 out << "}\n\n";
286
287
288 out << "@Override\npublic String toString() ";
289 out.block([&] {
290 out.sTry([&] {
291 out << "return this.interfaceDescriptor() + \"@Proxy\";\n";
292 }).sCatch("android.os.RemoteException ex", [&] {
293 out << "/* ignored; handled below. */\n";
294 }).endl();
295 out << "return \"[class or subclass of \" + "
296 << ifaceName << ".kInterfaceName + \"]@Proxy\";\n";
297 }).endl().endl();
298
299 // Equals when internal binder object is equal (even if the interface Proxy object
300 // itself is different). This is similar to interfacesEqual in C++.
301 out << "@Override\npublic final boolean equals(java.lang.Object other) ";
302 out.block([&] {
303 out << "return android.os.HidlSupport.interfacesEqual(this, other);\n";
304 }).endl().endl();
305
306 out << "@Override\npublic final int hashCode() ";
307 out.block([&] {
308 out << "return this.asBinder().hashCode();\n";
309 }).endl().endl();
310
311 const Interface *prevInterface = nullptr;
312 for (const auto &tuple : iface->allMethodsFromRoot()) {
313 const Method *method = tuple.method();
314
315 if (method->isHiddenFromJava()) {
316 continue;
317 }
318
319 const Interface *superInterface = tuple.interface();
320 if (prevInterface != superInterface) {
321 out << "// Methods from "
322 << superInterface->fullName()
323 << " follow.\n";
324 prevInterface = superInterface;
325 }
326 const bool returnsValue = !method->results().empty();
327 const bool needsCallback = method->results().size() > 1;
328
329 out << "@Override\npublic ";
330 if (returnsValue && !needsCallback) {
331 out << method->results()[0]->type().getJavaType();
332 } else {
333 out << "void";
334 }
335
336 out << " "
337 << method->name()
338 << "(";
339 method->emitJavaArgSignature(out);
340
341 if (needsCallback) {
342 if (!method->args().empty()) {
343 out << ", ";
344 }
345
346 out << method->name()
347 << "Callback _hidl_cb";
348 }
349
350 out << ")\n";
351 out.indent();
352 out.indent();
353 out << "throws android.os.RemoteException {\n";
354 out.unindent();
355
356 if (method->isHidlReserved() && method->overridesJavaImpl(IMPL_PROXY)) {
357 method->javaImpl(IMPL_PROXY, out);
358 out.unindent();
359 out << "}\n";
360 continue;
361 }
362 out << "android.os.HwParcel _hidl_request = new android.os.HwParcel();\n";
363 out << "_hidl_request.writeInterfaceToken("
364 << superInterface->fullJavaName()
365 << ".kInterfaceName);\n";
366
367 for (const auto &arg : method->args()) {
368 emitJavaReaderWriter(
369 out,
370 "_hidl_request",
371 arg,
372 false /* isReader */,
373 false /* addPrefixToName */);
374 }
375
376 out << "\nandroid.os.HwParcel _hidl_reply = new android.os.HwParcel();\n";
377
378 out.sTry([&] {
379 out << "mRemote.transact("
380 << method->getSerialId()
381 << " /* "
382 << method->name()
383 << " */, _hidl_request, _hidl_reply, ";
384
385 if (method->isOneway()) {
386 out << Interface::FLAG_ONEWAY << " /* oneway */";
387 } else {
388 out << "0 /* flags */";
389 }
390
391 out << ");\n";
392
393 if (!method->isOneway()) {
394 out << "_hidl_reply.verifySuccess();\n";
395 } else {
396 CHECK(!returnsValue);
397 }
398
399 out << "_hidl_request.releaseTemporaryStorage();\n";
400
401 if (returnsValue) {
402 out << "\n";
403
404 for (const auto &arg : method->results()) {
405 emitJavaReaderWriter(
406 out,
407 "_hidl_reply",
408 arg,
409 true /* isReader */,
410 true /* addPrefixToName */);
411 }
412
413 if (needsCallback) {
414 out << "_hidl_cb.onValues(";
415
416 bool firstField = true;
417 for (const auto &arg : method->results()) {
418 if (!firstField) {
419 out << ", ";
420 }
421
422 out << "_hidl_out_" << arg->name();
423 firstField = false;
424 }
425
426 out << ");\n";
427 } else {
428 const std::string returnName = method->results()[0]->name();
429 out << "return _hidl_out_" << returnName << ";\n";
430 }
431 }
432 }).sFinally([&] {
433 out << "_hidl_reply.release();\n";
434 }).endl();
435
436 out.unindent();
437 out << "}\n\n";
438 }
439
440 out.unindent();
441 out << "}\n";
442
443 ////////////////////////////////////////////////////////////////////////////
444
445 out << "\npublic static abstract class Stub extends android.os.HwBinder "
446 << "implements "
447 << ifaceName << " {\n";
448
449 out.indent();
450
451 out << "@Override\npublic android.os.IHwBinder asBinder() {\n";
452 out.indent();
453 // If we change this behavior in the future and asBinder does not return "this",
454 // equals and hashCode should also be overridden.
455 out << "return this;\n";
456 out.unindent();
457 out << "}\n\n";
458
459 for (Method *method : iface->hidlReservedMethods()) {
460 if (method->isHiddenFromJava()) {
461 continue;
462 }
463
464 // b/32383557 this is a hack. We need to change this if we have more reserved methods.
465 CHECK_LE(method->results().size(), 1u);
466 std::string resultType = method->results().size() == 0 ? "void" :
467 method->results()[0]->type().getJavaType();
468 out << "@Override\npublic final "
469 << resultType
470 << " "
471 << method->name()
472 << "(";
473 method->emitJavaArgSignature(out);
474 out << ") {\n";
475
476 out.indent();
477 method->javaImpl(IMPL_INTERFACE, out);
478 out.unindent();
479 out << "\n}\n\n";
480 }
481
482 out << "@Override\n"
483 << "public android.os.IHwInterface queryLocalInterface(String descriptor) {\n";
484 out.indent();
485 // XXX what about potential superClasses?
486 out << "if (kInterfaceName.equals(descriptor)) {\n";
487 out.indent();
488 out << "return this;\n";
489 out.unindent();
490 out << "}\n";
491 out << "return null;\n";
492 out.unindent();
493 out << "}\n\n";
494
495 out << "public void registerAsService(String serviceName) throws android.os.RemoteException {\n";
496 out.indent();
497
498 out << "registerService(serviceName);\n";
499
500 out.unindent();
501 out << "}\n\n";
502
503 out << "@Override\npublic String toString() ";
504 out.block([&] {
505 out << "return this.interfaceDescriptor() + \"@Stub\";\n";
506 }).endl().endl();
507
508 out << "@Override\n"
509 << "public void onTransact("
510 << "int _hidl_code, "
511 << "android.os.HwParcel _hidl_request, "
512 << "final android.os.HwParcel _hidl_reply, "
513 << "int _hidl_flags)\n";
514 out.indent();
515 out.indent();
516 out << "throws android.os.RemoteException {\n";
517 out.unindent();
518
519 out << "switch (_hidl_code) {\n";
520
521 out.indent();
522
523 for (const auto &tuple : iface->allMethodsFromRoot()) {
524 const Method *method = tuple.method();
525
526 const Interface *superInterface = tuple.interface();
527 const bool returnsValue = !method->results().empty();
528 const bool needsCallback = method->results().size() > 1;
529
530 out << "case "
531 << method->getSerialId()
532 << " /* "
533 << method->name()
534 << " */:\n{\n";
535
536 out.indent();
537
538 out << "boolean _hidl_is_oneway = (_hidl_flags & " << Interface::FLAG_ONEWAY
539 << " /* oneway */) != 0\n;";
540 out << "if (_hidl_is_oneway != " << (method->isOneway() ? "true" : "false") << ") ";
541 out.block([&] {
542 out << "_hidl_reply.writeStatus(" << UNKNOWN_ERROR << ");\n";
543 out << "_hidl_reply.send();\n";
544 out << "break;\n";
545 });
546
547 if (method->isHidlReserved() && method->overridesJavaImpl(IMPL_STUB)) {
548 method->javaImpl(IMPL_STUB, out);
549 out.unindent();
550 out << "break;\n";
551 out << "}\n\n";
552 continue;
553 }
554
555 out << "_hidl_request.enforceInterface("
556 << superInterface->fullJavaName()
557 << ".kInterfaceName);\n\n";
558
559 if (method->isHiddenFromJava()) {
560 // This is a method hidden from the Java side of things, it must not
561 // return any value and will simply signal success.
562 CHECK(!returnsValue);
563
564 out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
565 out << "_hidl_reply.send();\n";
566 out << "break;\n";
567 out.unindent();
568 out << "}\n\n";
569 continue;
570 }
571
572 for (const auto &arg : method->args()) {
573 emitJavaReaderWriter(
574 out,
575 "_hidl_request",
576 arg,
577 true /* isReader */,
578 false /* addPrefixToName */);
579 }
580
581 if (!needsCallback && returnsValue) {
582 const NamedReference<Type>* returnArg = method->results()[0];
583
584 out << returnArg->type().getJavaType()
585 << " _hidl_out_"
586 << returnArg->name()
587 << " = ";
588 }
589
590 out << method->name()
591 << "(";
592
593 bool firstField = true;
594 for (const auto &arg : method->args()) {
595 if (!firstField) {
596 out << ", ";
597 }
598
599 out << arg->name();
600
601 firstField = false;
602 }
603
604 if (needsCallback) {
605 if (!firstField) {
606 out << ", ";
607 }
608
609 out << "new " << method->name() << "Callback() {\n";
610 out.indent();
611
612 out << "@Override\n"
613 << "public void onValues(";
614 method->emitJavaResultSignature(out);
615 out << ") {\n";
616
617 out.indent();
618 out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
619
620 for (const auto &arg : method->results()) {
621 emitJavaReaderWriter(
622 out,
623 "_hidl_reply",
624 arg,
625 false /* isReader */,
626 false /* addPrefixToName */);
627 // no need to add _hidl_out because out vars are are scoped
628 }
629
630 out << "_hidl_reply.send();\n"
631 << "}}";
632
633 out.unindent();
634 out.unindent();
635 }
636
637 out << ");\n";
638
639 if (!needsCallback && !method->isOneway()) {
640 out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
641
642 if (returnsValue) {
643 const NamedReference<Type>* returnArg = method->results()[0];
644
645 emitJavaReaderWriter(
646 out,
647 "_hidl_reply",
648 returnArg,
649 false /* isReader */,
650 true /* addPrefixToName */);
651 }
652
653 out << "_hidl_reply.send();\n";
654 }
655
656 out << "break;\n";
657 out.unindent();
658 out << "}\n\n";
659 }
660
661 out.unindent();
662 out << "}\n";
663
664 out.unindent();
665 out << "}\n";
666
667 out.unindent();
668 out << "}\n";
669
670 out.unindent();
671 out << "}\n";
672 }
673
emitJavaTypeDeclarations(Formatter & out) const674 void AST::emitJavaTypeDeclarations(Formatter& out) const {
675 mRootScope.emitJavaTypeDeclarations(out, false /* atTopLevel */);
676 }
677
678 } // namespace android
679