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