• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)) << 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     if (!AST::isInterface()) {
112         return generateJavaTypes(outputPath, limitToType);
113     }
114 
115     const Interface* iface = mRootScope.getInterface();
116     std::string ifaceName = iface->localName();
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 << "\n@java.lang.FunctionalInterface\npublic interface " << method->name()
276                 << "Callback {\n";
277 
278             out.indent();
279 
280             out << "public void onValues(";
281             method->emitJavaResultSignature(out);
282             out << ");\n";
283 
284             out.unindent();
285             out << "}\n\n";
286         }
287 
288         if (returnsValue && !needsCallback) {
289             out << method->results()[0]->type().getJavaType();
290         } else {
291             out << "void";
292         }
293 
294         out << " "
295             << method->name()
296             << "(";
297         method->emitJavaArgSignature(out);
298 
299         if (needsCallback) {
300             if (!method->args().empty()) {
301                 out << ", ";
302             }
303 
304             out << method->name()
305                 << "Callback _hidl_cb";
306         }
307 
308         out << ")\n";
309         out.indent();
310         out << "throws android.os.RemoteException;\n";
311         out.unindent();
312     }
313 
314     out << "\npublic static final class Proxy implements "
315         << ifaceName
316         << " {\n";
317 
318     out.indent();
319 
320     out << "private android.os.IHwBinder mRemote;\n\n";
321     out << "public Proxy(android.os.IHwBinder remote) {\n";
322     out.indent();
323     out << "mRemote = java.util.Objects.requireNonNull(remote);\n";
324     out.unindent();
325     out << "}\n\n";
326 
327     out << "@Override\npublic android.os.IHwBinder asBinder() {\n";
328     out.indent();
329     out << "return mRemote;\n";
330     out.unindent();
331     out << "}\n\n";
332 
333 
334     out << "@Override\npublic String toString() ";
335     out.block([&] {
336         out.sTry([&] {
337             out << "return this.interfaceDescriptor() + \"@Proxy\";\n";
338         }).sCatch("android.os.RemoteException ex", [&] {
339             out << "/* ignored; handled below. */\n";
340         }).endl();
341         out << "return \"[class or subclass of \" + "
342             << ifaceName << ".kInterfaceName + \"]@Proxy\";\n";
343     }).endl().endl();
344 
345     const Interface *prevInterface = nullptr;
346     for (const auto &tuple : iface->allMethodsFromRoot()) {
347         const Method *method = tuple.method();
348 
349         if (method->isHiddenFromJava()) {
350             continue;
351         }
352 
353         const Interface *superInterface = tuple.interface();
354         if (prevInterface != superInterface) {
355             out << "// Methods from "
356                 << superInterface->fullName()
357                 << " follow.\n";
358             prevInterface = superInterface;
359         }
360         const bool returnsValue = !method->results().empty();
361         const bool needsCallback = method->results().size() > 1;
362 
363         out << "@Override\npublic ";
364         if (returnsValue && !needsCallback) {
365             out << method->results()[0]->type().getJavaType();
366         } else {
367             out << "void";
368         }
369 
370         out << " "
371             << method->name()
372             << "(";
373         method->emitJavaArgSignature(out);
374 
375         if (needsCallback) {
376             if (!method->args().empty()) {
377                 out << ", ";
378             }
379 
380             out << method->name()
381                 << "Callback _hidl_cb";
382         }
383 
384         out << ")\n";
385         out.indent();
386         out.indent();
387         out << "throws android.os.RemoteException {\n";
388         out.unindent();
389 
390         if (method->isHidlReserved() && method->overridesJavaImpl(IMPL_PROXY)) {
391             method->javaImpl(IMPL_PROXY, out);
392             out.unindent();
393             out << "}\n";
394             continue;
395         }
396         out << "android.os.HwParcel _hidl_request = new android.os.HwParcel();\n";
397         out << "_hidl_request.writeInterfaceToken("
398             << superInterface->fullJavaName()
399             << ".kInterfaceName);\n";
400 
401         for (const auto &arg : method->args()) {
402             emitJavaReaderWriter(
403                     out,
404                     "_hidl_request",
405                     arg,
406                     false /* isReader */,
407                     false /* addPrefixToName */);
408         }
409 
410         out << "\nandroid.os.HwParcel _hidl_reply = new android.os.HwParcel();\n";
411 
412         out.sTry([&] {
413             out << "mRemote.transact("
414                 << method->getSerialId()
415                 << " /* "
416                 << method->name()
417                 << " */, _hidl_request, _hidl_reply, ";
418 
419             if (method->isOneway()) {
420                 out << "android.os.IHwBinder.FLAG_ONEWAY";
421             } else {
422                 out << "0 /* flags */";
423             }
424 
425             out << ");\n";
426 
427             if (!method->isOneway()) {
428                 out << "_hidl_reply.verifySuccess();\n";
429             } else {
430                 CHECK(!returnsValue);
431             }
432 
433             out << "_hidl_request.releaseTemporaryStorage();\n";
434 
435             if (returnsValue) {
436                 out << "\n";
437 
438                 for (const auto &arg : method->results()) {
439                     emitJavaReaderWriter(
440                             out,
441                             "_hidl_reply",
442                             arg,
443                             true /* isReader */,
444                             true /* addPrefixToName */);
445                 }
446 
447                 if (needsCallback) {
448                     out << "_hidl_cb.onValues(";
449 
450                     bool firstField = true;
451                     for (const auto &arg : method->results()) {
452                         if (!firstField) {
453                             out << ", ";
454                         }
455 
456                         out << "_hidl_out_" << arg->name();
457                         firstField = false;
458                     }
459 
460                     out << ");\n";
461                 } else {
462                     const std::string returnName = method->results()[0]->name();
463                     out << "return _hidl_out_" << returnName << ";\n";
464                 }
465             }
466         }).sFinally([&] {
467             out << "_hidl_reply.release();\n";
468         }).endl();
469 
470         out.unindent();
471         out << "}\n\n";
472     }
473 
474     out.unindent();
475     out << "}\n";
476 
477     ////////////////////////////////////////////////////////////////////////////
478 
479     out << "\npublic static abstract class Stub extends android.os.HwBinder "
480         << "implements "
481         << ifaceName << " {\n";
482 
483     out.indent();
484 
485     out << "@Override\npublic android.os.IHwBinder asBinder() {\n";
486     out.indent();
487     out << "return this;\n";
488     out.unindent();
489     out << "}\n\n";
490 
491     for (Method *method : iface->hidlReservedMethods()) {
492         if (method->isHiddenFromJava()) {
493             continue;
494         }
495 
496         // b/32383557 this is a hack. We need to change this if we have more reserved methods.
497         CHECK_LE(method->results().size(), 1u);
498         std::string resultType = method->results().size() == 0 ? "void" :
499                 method->results()[0]->type().getJavaType();
500         out << "@Override\npublic final "
501             << resultType
502             << " "
503             << method->name()
504             << "(";
505         method->emitJavaArgSignature(out);
506         out << ") {\n";
507 
508         out.indent();
509         method->javaImpl(IMPL_INTERFACE, out);
510         out.unindent();
511         out << "\n}\n\n";
512     }
513 
514     out << "@Override\n"
515         << "public android.os.IHwInterface queryLocalInterface(String descriptor) {\n";
516     out.indent();
517     // XXX what about potential superClasses?
518     out << "if (kInterfaceName.equals(descriptor)) {\n";
519     out.indent();
520     out << "return this;\n";
521     out.unindent();
522     out << "}\n";
523     out << "return null;\n";
524     out.unindent();
525     out << "}\n\n";
526 
527     out << "public void registerAsService(String serviceName) throws android.os.RemoteException {\n";
528     out.indent();
529 
530     out << "registerService(serviceName);\n";
531 
532     out.unindent();
533     out << "}\n\n";
534 
535     out << "@Override\npublic String toString() ";
536     out.block([&] {
537         out << "return this.interfaceDescriptor() + \"@Stub\";\n";
538     }).endl().endl();
539 
540     out << "@Override\n"
541         << "public void onTransact("
542         << "int _hidl_code, "
543         << "android.os.HwParcel _hidl_request, "
544         << "final android.os.HwParcel _hidl_reply, "
545         << "int _hidl_flags)\n";
546     out.indent();
547     out.indent();
548     out << "throws android.os.RemoteException {\n";
549     out.unindent();
550 
551     out << "switch (_hidl_code) {\n";
552 
553     out.indent();
554 
555     for (const auto &tuple : iface->allMethodsFromRoot()) {
556         const Method *method = tuple.method();
557 
558         const Interface *superInterface = tuple.interface();
559         const bool returnsValue = !method->results().empty();
560         const bool needsCallback = method->results().size() > 1;
561 
562         out << "case "
563             << method->getSerialId()
564             << " /* "
565             << method->name()
566             << " */:\n{\n";
567 
568         out.indent();
569 
570         if (method->isHidlReserved() && method->overridesJavaImpl(IMPL_STUB)) {
571             method->javaImpl(IMPL_STUB, out);
572             out.unindent();
573             out << "break;\n";
574             out << "}\n\n";
575             continue;
576         }
577 
578         out << "_hidl_request.enforceInterface("
579             << superInterface->fullJavaName()
580             << ".kInterfaceName);\n\n";
581 
582         if (method->isHiddenFromJava()) {
583             // This is a method hidden from the Java side of things, it must not
584             // return any value and will simply signal success.
585             CHECK(!returnsValue);
586 
587             out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
588             out << "_hidl_reply.send();\n";
589             out << "break;\n";
590             out.unindent();
591             out << "}\n\n";
592             continue;
593         }
594 
595         for (const auto &arg : method->args()) {
596             emitJavaReaderWriter(
597                     out,
598                     "_hidl_request",
599                     arg,
600                     true /* isReader */,
601                     false /* addPrefixToName */);
602         }
603 
604         if (!needsCallback && returnsValue) {
605             const TypedVar *returnArg = method->results()[0];
606 
607             out << returnArg->type().getJavaType()
608                 << " _hidl_out_"
609                 << returnArg->name()
610                 << " = ";
611         }
612 
613         out << method->name()
614             << "(";
615 
616         bool firstField = true;
617         for (const auto &arg : method->args()) {
618             if (!firstField) {
619                 out << ", ";
620             }
621 
622             out << arg->name();
623 
624             firstField = false;
625         }
626 
627         if (needsCallback) {
628             if (!firstField) {
629                 out << ", ";
630             }
631 
632             out << "new " << method->name() << "Callback() {\n";
633             out.indent();
634 
635             out << "@Override\n"
636                 << "public void onValues(";
637             method->emitJavaResultSignature(out);
638             out << ") {\n";
639 
640             out.indent();
641             out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
642 
643             for (const auto &arg : method->results()) {
644                 emitJavaReaderWriter(
645                         out,
646                         "_hidl_reply",
647                         arg,
648                         false /* isReader */,
649                         false /* addPrefixToName */);
650                 // no need to add _hidl_out because out vars are are scoped
651             }
652 
653             out << "_hidl_reply.send();\n"
654                       << "}}";
655 
656             out.unindent();
657             out.unindent();
658         }
659 
660         out << ");\n";
661 
662         if (!needsCallback && !method->isOneway()) {
663             out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
664 
665             if (returnsValue) {
666                 const TypedVar *returnArg = method->results()[0];
667 
668                 emitJavaReaderWriter(
669                         out,
670                         "_hidl_reply",
671                         returnArg,
672                         false /* isReader */,
673                         true /* addPrefixToName */);
674             }
675 
676             out << "_hidl_reply.send();\n";
677         }
678 
679         out << "break;\n";
680         out.unindent();
681         out << "}\n\n";
682     }
683 
684     out.unindent();
685     out << "}\n";
686 
687     out.unindent();
688     out << "}\n";
689 
690     out.unindent();
691     out << "}\n";
692 
693     out.unindent();
694     out << "}\n";
695 
696     return OK;
697 }
698 
emitJavaTypeDeclarations(Formatter & out) const699 status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
700     return mRootScope.emitJavaTypeDeclarations(out, false /* atTopLevel */);
701 }
702 
703 }  // namespace android
704