• 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));
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