• 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 "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