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 "Location.h"
22 #include "Method.h"
23 #include "Reference.h"
24 #include "Scope.h"
25 
26 #include <hidl-util/Formatter.h>
27 #include <android-base/logging.h>
28 
29 namespace android {
30 
emitJavaReaderWriter(Formatter & out,const std::string & parcelObj,const NamedReference<Type> * arg,bool isReader,bool addPrefixToName) const31 void AST::emitJavaReaderWriter(Formatter& out, const std::string& parcelObj,
32                                const NamedReference<Type>* arg, bool isReader,
33                                bool addPrefixToName) const {
34     if (isReader) {
35         out << arg->type().getJavaType()
36             << " "
37             << (addPrefixToName ? "_hidl_out_" : "")
38             << arg->name()
39             << " = ";
40     }
41 
42     arg->type().emitJavaReaderWriter(out, parcelObj,
43             (addPrefixToName ? "_hidl_out_" : "") + arg->name(),
44             isReader);
45 }
46 
generateJavaTypes(Formatter & out,const std::string & limitToType) const47 void AST::generateJavaTypes(Formatter& out, const std::string& limitToType) const {
48     // Splits types.hal up into one java file per declared type.
49     CHECK(!limitToType.empty()) << getFilename();
50 
51     for (const auto& type : mRootScope.getSubTypes()) {
52         std::string typeName = type->definedName();
53 
54         if (type->isTypeDef()) continue;
55         if (typeName != limitToType) continue;
56 
57         out << "package " << mPackage.javaPackage() << ";\n\n\n";
58 
59         type->emitJavaTypeDeclarations(out, true /* atTopLevel */);
60         return;
61     }
62 
63     CHECK(false) << "generateJavaTypes could not find limitToType type";
64 }
65 
emitGetService(Formatter & out,const std::string & ifaceName,const std::string & fqName,bool isRetry)66 void emitGetService(
67         Formatter& out,
68         const std::string& ifaceName,
69         const std::string& fqName,
70         bool isRetry) {
71     if (isRetry) {
72         DocComment(
73                 "This will invoke the equivalent of the C++ getService(std::string) if retry is\n"
74                 "true or tryGetService(std::string) if retry is false. If the service is\n"
75                 "available on the device and retry is true, this will wait for the service to\n"
76                 "start.\n\n@throws NoSuchElementException if this service is not available",
77                 HIDL_LOCATION_HERE)
78                 .emit(out);
79     } else {
80         DocComment(
81                 "@throws NoSuchElementException if this service is not available\n"
82                 "@deprecated this will not wait for the interface to come up if it hasn't yet\n"
83                 "    started. See getService(String,boolean) instead.\n",
84                 HIDL_LOCATION_HERE)
85                 .emit(out);
86         out << "@Deprecated\n";
87     }
88     out << "public static "
89         << ifaceName
90         << " getService(String serviceName";
91     if (isRetry) {
92         out << ", boolean retry";
93     }
94     out << ") throws android.os.RemoteException ";
95     out.block([&] {
96         out << "return "
97             << ifaceName
98             << ".asInterface(android.os.HwBinder.getService(\""
99             << fqName
100             << "\", serviceName";
101         if (isRetry) {
102             out << ", retry";
103         }
104         out << "));\n";
105     }).endl().endl();
106 
107     if (isRetry) {
108         DocComment("Calls getService(\"default\",retry).", HIDL_LOCATION_HERE).emit(out);
109     } else {
110         DocComment(
111                 "@throws NoSuchElementException if this service is not available\n"
112                 "@deprecated this will not wait for the interface to come up if it hasn't yet\n"
113                 "    started. See getService(boolean) instead.\n",
114                 HIDL_LOCATION_HERE)
115                 .emit(out);
116         out << "@Deprecated\n";
117     }
118     out << "public static "
119         << ifaceName
120         << " getService(";
121     if (isRetry) {
122         out << "boolean retry";
123     }
124     out << ") throws android.os.RemoteException ";
125     out.block([&] {
126         out << "return getService(\"default\"";
127         if (isRetry) {
128             out << ", retry";
129         }
130         out <<");\n";
131     }).endl().endl();
132 }
133 
generateJava(Formatter & out,const std::string & limitToType) const134 void AST::generateJava(Formatter& out, const std::string& limitToType) const {
135     CHECK(isJavaCompatible()) << getFilename();
136 
137     if (!AST::isInterface()) {
138         generateJavaTypes(out, limitToType);
139         return;
140     }
141 
142     const Interface* iface = mRootScope.getInterface();
143     const std::string ifaceName = iface->definedName();
144     const std::string baseName = iface->getBaseName();
145 
146     out << "package " << mPackage.javaPackage() << ";\n\n";
147 
148     const Interface *superType = iface->superType();
149 
150     iface->emitDocComment(out);
151 
152     out << "public interface " << ifaceName << " extends ";
153 
154     if (superType != nullptr) {
155         out << superType->fullJavaName();
156     } else {
157         out << "android.os.IHwInterface";
158     }
159 
160     out << " {\n";
161     out.indent();
162 
163     DocComment("Fully-qualified interface name for this interface.", HIDL_LOCATION_HERE).emit(out);
164     out << "public static final String kInterfaceName = \""
165         << mPackage.string()
166         << "::"
167         << ifaceName
168         << "\";\n\n";
169 
170     DocComment("Does a checked conversion from a binder to this class.", HIDL_LOCATION_HERE)
171             .emit(out);
172     out << "/* package private */ static "
173         << ifaceName
174         << " asInterface(android.os.IHwBinder binder) {\n";
175 
176     out.indent();
177 
178     out << "if (binder == null) {\n";
179     out.indent();
180     out << "return null;\n";
181     out.unindent();
182     out << "}\n\n";
183 
184     out << "android.os.IHwInterface iface =\n";
185     out.indent();
186     out.indent();
187     out << "binder.queryLocalInterface(kInterfaceName);\n\n";
188     out.unindent();
189     out.unindent();
190 
191     out << "if ((iface != null) && (iface instanceof "
192         << ifaceName
193         << ")) {\n";
194 
195     out.indent();
196     out << "return (" << ifaceName << ")iface;\n";
197     out.unindent();
198     out << "}\n\n";
199 
200     out << ifaceName << " proxy = new " << ifaceName << ".Proxy(binder);\n\n";
201     out << "try {\n";
202     out.indent();
203     out << "for (String descriptor : proxy.interfaceChain()) {\n";
204     out.indent();
205     out << "if (descriptor.equals(kInterfaceName)) {\n";
206     out.indent();
207     out << "return proxy;\n";
208     out.unindent();
209     out << "}\n";
210     out.unindent();
211     out << "}\n";
212     out.unindent();
213     out << "} catch (android.os.RemoteException e) {\n";
214     out.indent();
215     out.unindent();
216     out << "}\n\n";
217 
218     out << "return null;\n";
219 
220     out.unindent();
221     out << "}\n\n";
222 
223     DocComment("Does a checked conversion from any interface to this class.", HIDL_LOCATION_HERE)
224             .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 needsCallback = method->results().size() > 1;
246 
247         if (needsCallback) {
248             out << "\n@java.lang.FunctionalInterface\npublic interface " << method->name()
249                 << "Callback {\n";
250 
251             out.indent();
252 
253             out << "public void onValues(";
254             method->emitJavaResultSignature(out);
255             out << ");\n";
256 
257             out.unindent();
258             out << "}\n\n";
259         }
260 
261         method->emitDocComment(out);
262 
263         method->emitJavaSignature(out);
264 
265         out << "\n";
266         out.indent();
267         out << "throws android.os.RemoteException;\n";
268         out.unindent();
269     }
270 
271     out << "\npublic static final class Proxy implements "
272         << ifaceName
273         << " {\n";
274 
275     out.indent();
276 
277     out << "private android.os.IHwBinder mRemote;\n\n";
278     out << "public Proxy(android.os.IHwBinder remote) {\n";
279     out.indent();
280     out << "mRemote = java.util.Objects.requireNonNull(remote);\n";
281     out.unindent();
282     out << "}\n\n";
283 
284     out << "@Override\npublic android.os.IHwBinder asBinder() {\n";
285     out.indent();
286     out << "return mRemote;\n";
287     out.unindent();
288     out << "}\n\n";
289 
290 
291     out << "@Override\npublic String toString() ";
292     out.block([&] {
293         out.sTry([&] {
294             out << "return this.interfaceDescriptor() + \"@Proxy\";\n";
295         }).sCatch("android.os.RemoteException ex", [&] {
296             out << "/* ignored; handled below. */\n";
297         }).endl();
298         out << "return \"[class or subclass of \" + "
299             << ifaceName << ".kInterfaceName + \"]@Proxy\";\n";
300     }).endl().endl();
301 
302     // Equals when internal binder object is equal (even if the interface Proxy object
303     // itself is different). This is similar to interfacesEqual in C++.
304     out << "@Override\npublic final boolean equals(java.lang.Object other) ";
305     out.block([&] {
306         out << "return android.os.HidlSupport.interfacesEqual(this, other);\n";
307     }).endl().endl();
308 
309     out << "@Override\npublic final int hashCode() ";
310     out.block([&] {
311         out << "return this.asBinder().hashCode();\n";
312     }).endl().endl();
313 
314     const Interface *prevInterface = nullptr;
315     for (const auto &tuple : iface->allMethodsFromRoot()) {
316         const Method *method = tuple.method();
317 
318         const Interface *superInterface = tuple.interface();
319         if (prevInterface != superInterface) {
320             out << "// Methods from "
321                 << superInterface->fullName()
322                 << " follow.\n";
323             prevInterface = superInterface;
324         }
325         const bool returnsValue = !method->results().empty();
326         const bool needsCallback = method->results().size() > 1;
327 
328         out << "@Override\npublic ";
329         method->emitJavaSignature(out);
330 
331         out << "\n";
332         out.indent();
333         out.indent();
334         out << "throws android.os.RemoteException {\n";
335         out.unindent();
336 
337         if (method->isHidlReserved() && method->overridesJavaImpl(IMPL_PROXY)) {
338             method->javaImpl(IMPL_PROXY, out);
339             out.unindent();
340             out << "}\n";
341             continue;
342         }
343         out << "android.os.HwParcel _hidl_request = new android.os.HwParcel();\n";
344         out << "_hidl_request.writeInterfaceToken("
345             << superInterface->fullJavaName()
346             << ".kInterfaceName);\n";
347 
348         for (const auto &arg : method->args()) {
349             emitJavaReaderWriter(
350                     out,
351                     "_hidl_request",
352                     arg,
353                     false /* isReader */,
354                     false /* addPrefixToName */);
355         }
356 
357         out << "\nandroid.os.HwParcel _hidl_reply = new android.os.HwParcel();\n";
358 
359         out.sTry([&] {
360             out << "mRemote.transact("
361                 << method->getSerialId()
362                 << " /* "
363                 << method->name()
364                 << " */, _hidl_request, _hidl_reply, ";
365 
366             if (method->isOneway()) {
367                 out << Interface::FLAG_ONE_WAY->javaValue();
368             } else {
369                 out << "0 /* flags */";
370             }
371 
372             out << ");\n";
373 
374             if (!method->isOneway()) {
375                 out << "_hidl_reply.verifySuccess();\n";
376             } else {
377                 CHECK(!returnsValue);
378             }
379 
380             out << "_hidl_request.releaseTemporaryStorage();\n";
381 
382             if (returnsValue) {
383                 out << "\n";
384 
385                 for (const auto &arg : method->results()) {
386                     emitJavaReaderWriter(
387                             out,
388                             "_hidl_reply",
389                             arg,
390                             true /* isReader */,
391                             true /* addPrefixToName */);
392                 }
393 
394                 if (needsCallback) {
395                     out << "_hidl_cb.onValues(";
396 
397                     bool firstField = true;
398                     for (const auto &arg : method->results()) {
399                         if (!firstField) {
400                             out << ", ";
401                         }
402 
403                         out << "_hidl_out_" << arg->name();
404                         firstField = false;
405                     }
406 
407                     out << ");\n";
408                 } else {
409                     const std::string returnName = method->results()[0]->name();
410                     out << "return _hidl_out_" << returnName << ";\n";
411                 }
412             }
413         }).sFinally([&] {
414             out << "_hidl_reply.release();\n";
415         }).endl();
416 
417         out.unindent();
418         out << "}\n\n";
419     }
420 
421     out.unindent();
422     out << "}\n";
423 
424     ////////////////////////////////////////////////////////////////////////////
425 
426     out << "\npublic static abstract class Stub extends android.os.HwBinder "
427         << "implements "
428         << ifaceName << " {\n";
429 
430     out.indent();
431 
432     out << "@Override\npublic android.os.IHwBinder asBinder() {\n";
433     out.indent();
434     // If we change this behavior in the future and asBinder does not return "this",
435     // equals and hashCode should also be overridden.
436     out << "return this;\n";
437     out.unindent();
438     out << "}\n\n";
439 
440     for (Method *method : iface->hidlReservedMethods()) {
441         // b/32383557 this is a hack. We need to change this if we have more reserved methods.
442         CHECK_LE(method->results().size(), 1u);
443         std::string resultType = method->results().size() == 0 ? "void" :
444                 method->results()[0]->type().getJavaType();
445 
446         bool canBeOverriden = method->name() == "debug";
447 
448         out << "@Override\npublic " << (canBeOverriden ? "" : "final ") << resultType << " "
449             << method->name() << "(";
450         method->emitJavaArgSignature(out);
451         out << ") {\n";
452 
453         out.indent();
454         method->javaImpl(IMPL_INTERFACE, out);
455         out.unindent();
456         out << "\n}\n\n";
457     }
458 
459     out << "@Override\n"
460         << "public android.os.IHwInterface queryLocalInterface(String descriptor) {\n";
461     out.indent();
462     // XXX what about potential superClasses?
463     out << "if (kInterfaceName.equals(descriptor)) {\n";
464     out.indent();
465     out << "return this;\n";
466     out.unindent();
467     out << "}\n";
468     out << "return null;\n";
469     out.unindent();
470     out << "}\n\n";
471 
472     out << "public void registerAsService(String serviceName) throws android.os.RemoteException {\n";
473     out.indent();
474 
475     out << "registerService(serviceName);\n";
476 
477     out.unindent();
478     out << "}\n\n";
479 
480     out << "@Override\npublic String toString() ";
481     out.block([&] {
482         out << "return this.interfaceDescriptor() + \"@Stub\";\n";
483     }).endl().endl();
484 
485     out << "@Override\n"
486         << "public void onTransact("
487         << "int _hidl_code, "
488         << "android.os.HwParcel _hidl_request, "
489         << "final android.os.HwParcel _hidl_reply, "
490         << "int _hidl_flags)\n";
491     out.indent();
492     out.indent();
493     out << "throws android.os.RemoteException {\n";
494     out.unindent();
495 
496     out << "switch (_hidl_code) {\n";
497 
498     out.indent();
499 
500     for (const auto &tuple : iface->allMethodsFromRoot()) {
501         const Method *method = tuple.method();
502 
503         const Interface *superInterface = tuple.interface();
504         const bool returnsValue = !method->results().empty();
505         const bool needsCallback = method->results().size() > 1;
506 
507         out << "case "
508             << method->getSerialId()
509             << " /* "
510             << method->name()
511             << " */:\n{\n";
512 
513         out.indent();
514 
515         if (method->isHidlReserved() && method->overridesJavaImpl(IMPL_STUB)) {
516             method->javaImpl(IMPL_STUB, out);
517             out.unindent();
518             out << "break;\n";
519             out << "}\n\n";
520             continue;
521         }
522 
523         out << "_hidl_request.enforceInterface("
524             << superInterface->fullJavaName()
525             << ".kInterfaceName);\n\n";
526 
527         for (const auto &arg : method->args()) {
528             emitJavaReaderWriter(
529                     out,
530                     "_hidl_request",
531                     arg,
532                     true /* isReader */,
533                     false /* addPrefixToName */);
534         }
535 
536         if (!needsCallback && returnsValue) {
537             const NamedReference<Type>* returnArg = method->results()[0];
538 
539             out << returnArg->type().getJavaType()
540                 << " _hidl_out_"
541                 << returnArg->name()
542                 << " = ";
543         }
544 
545         out << method->name()
546             << "(";
547 
548         bool firstField = true;
549         for (const auto &arg : method->args()) {
550             if (!firstField) {
551                 out << ", ";
552             }
553 
554             out << arg->name();
555 
556             firstField = false;
557         }
558 
559         if (needsCallback) {
560             if (!firstField) {
561                 out << ", ";
562             }
563 
564             out << "new " << method->name() << "Callback() {\n";
565             out.indent();
566 
567             out << "@Override\n"
568                 << "public void onValues(";
569             method->emitJavaResultSignature(out);
570             out << ") {\n";
571 
572             out.indent();
573             out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
574 
575             for (const auto &arg : method->results()) {
576                 emitJavaReaderWriter(
577                         out,
578                         "_hidl_reply",
579                         arg,
580                         false /* isReader */,
581                         false /* addPrefixToName */);
582                 // no need to add _hidl_out because out vars are are scoped
583             }
584 
585             out << "_hidl_reply.send();\n"
586                       << "}}";
587 
588             out.unindent();
589             out.unindent();
590         }
591 
592         out << ");\n";
593 
594         if (!needsCallback && !method->isOneway()) {
595             out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
596 
597             if (returnsValue) {
598                 const NamedReference<Type>* returnArg = method->results()[0];
599 
600                 emitJavaReaderWriter(
601                         out,
602                         "_hidl_reply",
603                         returnArg,
604                         false /* isReader */,
605                         true /* addPrefixToName */);
606             }
607 
608             out << "_hidl_reply.send();\n";
609         }
610 
611         out << "break;\n";
612         out.unindent();
613         out << "}\n\n";
614     }
615 
616     out.unindent();
617     out << "}\n";
618 
619     out.unindent();
620     out << "}\n";
621 
622     out.unindent();
623     out << "}\n";
624 
625     out.unindent();
626     out << "}\n";
627 }
628 
629 }  // namespace android
630