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