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