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