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