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