blob: 909696a46bd15489332171ed46b05f96c6b6c152 [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
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
Andreas Huber2831d512016-08-15 09:33:47 -070017#include "AST.h"
18
19#include "Coordinator.h"
Andreas Huber2831d512016-08-15 09:33:47 -070020#include "Interface.h"
21#include "Method.h"
22#include "Scope.h"
23
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070024#include <hidl-util/Formatter.h>
Andreas Huber2831d512016-08-15 09:33:47 -070025#include <android-base/logging.h>
26
27namespace android {
28
Andreas Huber2831d512016-08-15 09:33:47 -070029void AST::emitJavaReaderWriter(
30 Formatter &out,
31 const std::string &parcelObj,
32 const TypedVar *arg,
33 bool isReader) const {
34 if (isReader) {
Yifan Hong4ed13472016-11-02 10:44:11 -070035 out << arg->type().getJavaType()
Andreas Huber2831d512016-08-15 09:33:47 -070036 << " "
37 << arg->name()
38 << " = ";
39 }
40
41 arg->type().emitJavaReaderWriter(out, parcelObj, arg->name(), isReader);
42}
43
Andreas Huber0fa9e392016-08-31 09:05:44 -070044status_t AST::generateJavaTypes(
Andreas Huberd29724f2016-09-14 09:33:13 -070045 const std::string &outputPath, const std::string &limitToType) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -070046 // Splits types.hal up into one java file per declared type.
47
Steven Morelandd537ab02016-09-12 10:32:01 -070048 for (const auto &type : mRootScope->getSubTypes()) {
49 std::string typeName = type->localName();
Andreas Huber85eabdb2016-08-25 11:24:49 -070050
51 if (type->isTypeDef()) {
52 continue;
53 }
54
Andreas Huberd29724f2016-09-14 09:33:13 -070055 if (!limitToType.empty() && typeName != limitToType) {
Andreas Huber0fa9e392016-08-31 09:05:44 -070056 continue;
57 }
58
Andreas Huber85eabdb2016-08-25 11:24:49 -070059 std::string path = outputPath;
60 path.append(mCoordinator->convertPackageRootToPath(mPackage));
61 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
62 path.append(typeName);
63 path.append(".java");
64
65 CHECK(Coordinator::MakeParentHierarchy(path));
66 FILE *file = fopen(path.c_str(), "w");
67
68 if (file == NULL) {
69 return -errno;
70 }
71
72 Formatter out(file);
73
74 std::vector<std::string> packageComponents;
75 getPackageAndVersionComponents(
76 &packageComponents, true /* cpp_compatible */);
77
78 out << "package " << mPackage.javaPackage() << ";\n\n";
79
80 out << "import android.os.HwBlob;\n";
81 out << "import android.os.HwParcel;\n\n";
82
Andreas Huberf630bc82016-09-09 14:52:25 -070083 out << "import java.util.Arrays;\n";
Andreas Huberf1abc2a2016-09-28 09:14:43 -070084 out << "import java.util.ArrayList;\n\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -070085
Iliyan Malchev800273d2016-09-02 15:25:07 -070086 for (const auto &item : mImportedNamesForJava) {
87 out << "import " << item.javaName() << ";\n";
88 }
89 out << "\n";
90
Andreas Huber85eabdb2016-08-25 11:24:49 -070091 status_t err =
92 type->emitJavaTypeDeclarations(out, true /* atTopLevel */);
93
94 if (err != OK) {
95 return err;
96 }
97 }
98
99 return OK;
100}
101
Andreas Huber0fa9e392016-08-31 09:05:44 -0700102status_t AST::generateJava(
Andreas Huberd29724f2016-09-14 09:33:13 -0700103 const std::string &outputPath, const std::string &limitToType) const {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700104 if (!isJavaCompatible()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700105 fprintf(stderr,
106 "ERROR: This interface is not Java compatible. The Java backend"
Andreas Huberf03332a2016-09-22 15:35:43 -0700107 " does NOT support union types nor native handles. "
108 "In addition, vectors of arrays are limited to at most "
Andreas Huber86a112b2016-10-19 14:25:16 -0700109 "one-dimensional arrays and vectors of {vectors,interfaces} are"
110 " not supported.\n");
Andreas Huber70a59e12016-08-16 12:57:01 -0700111
Andreas Huber2831d512016-08-15 09:33:47 -0700112 return UNKNOWN_ERROR;
113 }
114
Andreas Huber0fa9e392016-08-31 09:05:44 -0700115 std::string ifaceName;
116 if (!AST::isInterface(&ifaceName)) {
117 return generateJavaTypes(outputPath, limitToType);
118 }
119
120 const Interface *iface = mRootScope->getInterface();
121
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700122 const std::string baseName = iface->getBaseName();
Andreas Huber2831d512016-08-15 09:33:47 -0700123
124 std::string path = outputPath;
125 path.append(mCoordinator->convertPackageRootToPath(mPackage));
126 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
127 path.append(ifaceName);
128 path.append(".java");
129
130 CHECK(Coordinator::MakeParentHierarchy(path));
131 FILE *file = fopen(path.c_str(), "w");
132
133 if (file == NULL) {
134 return -errno;
135 }
136
137 Formatter out(file);
138
139 std::vector<std::string> packageComponents;
140 getPackageAndVersionComponents(
141 &packageComponents, true /* cpp_compatible */);
142
143 out << "package " << mPackage.javaPackage() << ";\n\n";
144
145 out << "import android.os.IHwBinder;\n";
146 out << "import android.os.IHwInterface;\n";
147 out << "import android.os.HwBinder;\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700148 out << "import android.os.HwBlob;\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700149 out << "import android.os.HwParcel;\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700150
151 out << "import java.util.Arrays;\n";
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700152 out << "import java.util.ArrayList;\n\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700153
Andreas Huber85eabdb2016-08-25 11:24:49 -0700154 for (const auto &item : mImportedNamesForJava) {
Andreas Huber2831d512016-08-15 09:33:47 -0700155 out << "import " << item.javaName() << ";\n";
156 }
157
Andreas Huber85eabdb2016-08-25 11:24:49 -0700158 if (!mImportedNamesForJava.empty()) {
Andreas Huber2831d512016-08-15 09:33:47 -0700159 out << "\n";
160 }
161
162 out.setNamespace(mPackage.javaPackage() + ".");
163
Andreas Huber2831d512016-08-15 09:33:47 -0700164 const Interface *superType = iface->superType();
165
166 out << "public interface " << ifaceName << " extends ";
167
168 if (superType != NULL) {
169 out << superType->fullJavaName();
170 } else {
171 out << "IHwInterface";
172 }
173
174 out << " {\n";
175 out.indent();
176
177 out << "public static final String kInterfaceName = \""
178 << mPackage.string()
179 << "::"
180 << ifaceName
181 << "\";\n\n";
182
183 out << "public static "
184 << ifaceName
185 << " asInterface(IHwBinder binder) {\n";
186
187 out.indent();
188
189 out << "if (binder == null) {\n";
190 out.indent();
191 out << "return null;\n";
192 out.unindent();
193 out << "}\n\n";
194
195 out << "IHwInterface iface =\n";
196 out.indent();
197 out.indent();
198 out << "binder.queryLocalInterface(kInterfaceName);\n\n";
199 out.unindent();
200 out.unindent();
201
202 out << "if ((iface != null) && (iface instanceof "
203 << ifaceName
204 << ")) {\n";
205
206 out.indent();
207 out << "return (" << ifaceName << ")iface;\n";
208 out.unindent();
209 out << "}\n\n";
210
211 out << "return new " << ifaceName << ".Proxy(binder);\n";
212
213 out.unindent();
214 out << "}\n\n";
215
216 out << "public IHwBinder asBinder();\n\n";
217
Andreas Huber2bb6e1e2016-10-25 13:26:43 -0700218 out << "public static "
219 << ifaceName
220 << " getService(String serviceName) {\n";
221
222 out.indent();
223
224 out << "return "
225 << ifaceName
226 << ".asInterface(HwBinder.getService(serviceName, "
227 << mPackage.getPackageMajorVersion()
228 << ", "
229 << mPackage.getPackageMinorVersion()
230 << "));\n";
231
232 out.unindent();
233
234 out << "}\n\n";
235
Andreas Huber2831d512016-08-15 09:33:47 -0700236 status_t err = emitJavaTypeDeclarations(out);
237
238 if (err != OK) {
239 return err;
240 }
241
Andreas Huber2831d512016-08-15 09:33:47 -0700242 for (const auto &method : iface->methods()) {
243 const bool returnsValue = !method->results().empty();
244 const bool needsCallback = method->results().size() > 1;
245
246 if (needsCallback) {
247 out << "\npublic abstract class "
248 << method->name()
249 << "Callback {\n";
250
251 out.indent();
252
253 out << "public abstract void onValues("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700254 << Method::GetJavaArgSignature(method->results())
Andreas Huber2831d512016-08-15 09:33:47 -0700255 << ");\n";
256
257 out.unindent();
258 out << "}\n\n";
259 }
260
261 if (returnsValue && !needsCallback) {
Yifan Hong4ed13472016-11-02 10:44:11 -0700262 out << method->results()[0]->type().getJavaType();
Andreas Huber2831d512016-08-15 09:33:47 -0700263 } else {
264 out << "void";
265 }
266
267 out << " "
268 << method->name()
269 << "("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700270 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700271
272 if (needsCallback) {
273 if (!method->args().empty()) {
274 out << ", ";
275 }
276
277 out << method->name()
278 << "Callback cb";
279 }
280
281 out << ");\n";
282 }
283
284 out << "\npublic static final class Proxy implements "
285 << ifaceName
286 << " {\n";
287
288 out.indent();
289
290 out << "private IHwBinder mRemote;\n\n";
291 out << "public Proxy(IHwBinder remote) {\n";
292 out.indent();
293 out << "mRemote = remote;\n";
294 out.unindent();
295 out << "}\n\n";
296
297 out << "public IHwBinder asBinder() {\n";
298 out.indent();
299 out << "return mRemote;\n";
300 out.unindent();
301 out << "}\n\n";
302
Yifan Hong10fe0b52016-10-19 14:20:17 -0700303 const Interface *prevInterface = nullptr;
304 for (const auto &tuple : iface->allMethodsFromRoot()) {
305 const Method *method = tuple.method();
306 const Interface *superInterface = tuple.interface();
307 if (prevInterface != superInterface) {
308 out << "// Methods from "
309 << superInterface->fullName()
310 << " follow.\n";
311 prevInterface = superInterface;
312 }
313 const bool returnsValue = !method->results().empty();
314 const bool needsCallback = method->results().size() > 1;
Andreas Huber2831d512016-08-15 09:33:47 -0700315
Yifan Hong10fe0b52016-10-19 14:20:17 -0700316 out << "public ";
317 if (returnsValue && !needsCallback) {
Yifan Hong4ed13472016-11-02 10:44:11 -0700318 out << method->results()[0]->type().getJavaType();
Yifan Hong10fe0b52016-10-19 14:20:17 -0700319 } else {
320 out << "void";
321 }
Andreas Huber2831d512016-08-15 09:33:47 -0700322
Yifan Hong10fe0b52016-10-19 14:20:17 -0700323 out << " "
324 << method->name()
325 << "("
326 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700327
Yifan Hong10fe0b52016-10-19 14:20:17 -0700328 if (needsCallback) {
329 if (!method->args().empty()) {
330 out << ", ";
Andreas Huber2831d512016-08-15 09:33:47 -0700331 }
332
Yifan Hong10fe0b52016-10-19 14:20:17 -0700333 out << method->name()
334 << "Callback cb";
335 }
Andreas Huber2831d512016-08-15 09:33:47 -0700336
Yifan Hong10fe0b52016-10-19 14:20:17 -0700337 out << ") {\n";
338 out.indent();
Andreas Huber2831d512016-08-15 09:33:47 -0700339
Yifan Hong10fe0b52016-10-19 14:20:17 -0700340 out << "HwParcel request = new HwParcel();\n";
341 out << "request.writeInterfaceToken("
342 << superInterface->fullJavaName()
343 << ".kInterfaceName);\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700344
Yifan Hong10fe0b52016-10-19 14:20:17 -0700345 for (const auto &arg : method->args()) {
346 emitJavaReaderWriter(
347 out,
348 "request",
349 arg,
350 false /* isReader */);
351 }
Andreas Huber2831d512016-08-15 09:33:47 -0700352
Yifan Hong10fe0b52016-10-19 14:20:17 -0700353 out << "\nHwParcel reply = new HwParcel();\n"
354 << "mRemote.transact("
355 << method->getSerialId()
356 << " /* "
357 << method->name()
358 << " */, request, reply, ";
Andreas Huber2831d512016-08-15 09:33:47 -0700359
Yifan Hong10fe0b52016-10-19 14:20:17 -0700360 if (method->isOneway()) {
361 out << "IHwBinder.FLAG_ONEWAY";
362 } else {
363 out << "0 /* flags */";
364 }
365
366 out << ");\n";
367
368 if (!method->isOneway()) {
369 out << "reply.verifySuccess();\n";
370 } else {
371 CHECK(!returnsValue);
372 }
373
374 out << "request.releaseTemporaryStorage();\n";
375
376 if (returnsValue) {
377 out << "\n";
378
379 for (const auto &arg : method->results()) {
Andreas Huber2831d512016-08-15 09:33:47 -0700380 emitJavaReaderWriter(
381 out,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700382 "reply",
Andreas Huber2831d512016-08-15 09:33:47 -0700383 arg,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700384 true /* isReader */);
Andreas Huber2831d512016-08-15 09:33:47 -0700385 }
386
Yifan Hong10fe0b52016-10-19 14:20:17 -0700387 if (needsCallback) {
388 out << "cb.onValues(";
Andreas Huber8b5da222016-08-18 14:28:18 -0700389
Yifan Hong10fe0b52016-10-19 14:20:17 -0700390 bool firstField = true;
Andreas Huber2831d512016-08-15 09:33:47 -0700391 for (const auto &arg : method->results()) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700392 if (!firstField) {
393 out << ", ";
Andreas Huber2831d512016-08-15 09:33:47 -0700394 }
395
Yifan Hong10fe0b52016-10-19 14:20:17 -0700396 out << arg->name();
397 firstField = false;
Andreas Huber2831d512016-08-15 09:33:47 -0700398 }
Andreas Huber2831d512016-08-15 09:33:47 -0700399
Yifan Hong10fe0b52016-10-19 14:20:17 -0700400 out << ");\n";
401 } else {
402 const std::string returnName = method->results()[0]->name();
403 out << "return " << returnName << ";\n";
404 }
Andreas Huber2831d512016-08-15 09:33:47 -0700405 }
Yifan Hong10fe0b52016-10-19 14:20:17 -0700406
407 out.unindent();
408 out << "}\n\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700409 }
410
411 out.unindent();
412 out << "}\n";
413
414 ////////////////////////////////////////////////////////////////////////////
415
416 out << "\npublic static abstract class Stub extends HwBinder "
417 << "implements "
418 << ifaceName << " {\n";
419
420 out.indent();
421
422 out << "public IHwBinder asBinder() {\n";
423 out.indent();
424 out << "return this;\n";
425 out.unindent();
426 out << "}\n\n";
427
Yifan Hong10fe0b52016-10-19 14:20:17 -0700428 // b/32383557 this is a hack. We need to change this if we have more reserved methods.
429 for (Method *method : iface->hidlReservedMethods()) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700430 out << "public final "
Yifan Hong4ed13472016-11-02 10:44:11 -0700431 << method->results()[0]->type().getJavaType()
Yifan Hong10fe0b52016-10-19 14:20:17 -0700432 << " "
433 << method->name()
434 << "() {\n";
435 out.indent();
436 method->javaImpl(out);
437 out.unindent();
438 out << "\n}\n\n";
439 }
440
Andreas Huber2831d512016-08-15 09:33:47 -0700441 out << "public IHwInterface queryLocalInterface(String descriptor) {\n";
442 out.indent();
443 // XXX what about potential superClasses?
444 out << "if (kInterfaceName.equals(descriptor)) {\n";
445 out.indent();
446 out << "return this;\n";
447 out.unindent();
448 out << "}\n";
449 out << "return null;\n";
450 out.unindent();
451 out << "}\n\n";
452
Andreas Huber2bb6e1e2016-10-25 13:26:43 -0700453 out << "public void registerAsService(String serviceName) {\n";
454 out.indent();
455
456 out << "registerService(serviceName, "
457 << mPackage.getPackageMajorVersion()
458 << ", "
459 << mPackage.getPackageMinorVersion()
460 << ");\n";
461
462 out.unindent();
463 out << "}\n\n";
464
Andreas Huber2831d512016-08-15 09:33:47 -0700465 out << "public void onTransact("
466 << "int code, HwParcel request, final HwParcel reply, "
467 << "int flags) {\n";
468
469 out.indent();
470
471 out << "switch (code) {\n";
472
473 out.indent();
474
Yifan Hong10fe0b52016-10-19 14:20:17 -0700475 for (const auto &tuple : iface->allMethodsFromRoot()) {
476 const Method *method = tuple.method();
477 const Interface *superInterface = tuple.interface();
478 const bool returnsValue = !method->results().empty();
479 const bool needsCallback = method->results().size() > 1;
Andreas Huber2831d512016-08-15 09:33:47 -0700480
Yifan Hong10fe0b52016-10-19 14:20:17 -0700481 out << "case "
482 << method->getSerialId()
483 << " /* "
484 << method->name()
485 << " */:\n{\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700486
Yifan Hong10fe0b52016-10-19 14:20:17 -0700487 out.indent();
Andreas Huber2831d512016-08-15 09:33:47 -0700488
Yifan Hong10fe0b52016-10-19 14:20:17 -0700489 out << "request.enforceInterface("
490 << superInterface->fullJavaName()
491 << ".kInterfaceName);\n\n";
492
493 for (const auto &arg : method->args()) {
494 emitJavaReaderWriter(
495 out,
496 "request",
497 arg,
498 true /* isReader */);
499 }
500
501 if (!needsCallback && returnsValue) {
502 const TypedVar *returnArg = method->results()[0];
Yifan Hong10fe0b52016-10-19 14:20:17 -0700503
Yifan Hong4ed13472016-11-02 10:44:11 -0700504 out << returnArg->type().getJavaType()
Yifan Hong10fe0b52016-10-19 14:20:17 -0700505 << " "
506 << returnArg->name()
507 << " = ";
508 }
509
510 out << method->name()
511 << "(";
512
513 bool firstField = true;
514 for (const auto &arg : method->args()) {
515 if (!firstField) {
516 out << ", ";
517 }
518
519 out << arg->name();
520
521 firstField = false;
522 }
523
524 if (needsCallback) {
525 if (!firstField) {
526 out << ", ";
527 }
528
529 out << "new " << method->name() << "Callback() {\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700530 out.indent();
531
Yifan Hong10fe0b52016-10-19 14:20:17 -0700532 out << "@Override\n"
533 << "public void onValues("
534 << Method::GetJavaArgSignature(method->results())
535 << ") {\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700536
Yifan Hong10fe0b52016-10-19 14:20:17 -0700537 out.indent();
538 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
539
540 for (const auto &arg : method->results()) {
Andreas Huber2831d512016-08-15 09:33:47 -0700541 emitJavaReaderWriter(
542 out,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700543 "reply",
Andreas Huber2831d512016-08-15 09:33:47 -0700544 arg,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700545 false /* isReader */);
Andreas Huber2831d512016-08-15 09:33:47 -0700546 }
547
Yifan Hong10fe0b52016-10-19 14:20:17 -0700548 out << "reply.send();\n"
549 << "}}";
Andreas Huber2831d512016-08-15 09:33:47 -0700550
Andreas Huber2831d512016-08-15 09:33:47 -0700551 out.unindent();
Yifan Hong10fe0b52016-10-19 14:20:17 -0700552 out.unindent();
Andreas Huber2831d512016-08-15 09:33:47 -0700553 }
Yifan Hong10fe0b52016-10-19 14:20:17 -0700554
555 out << ");\n";
556
557 if (!needsCallback) {
558 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
559
560 if (returnsValue) {
561 const TypedVar *returnArg = method->results()[0];
562
563 emitJavaReaderWriter(
564 out,
565 "reply",
566 returnArg,
567 false /* isReader */);
568 }
569
570 out << "reply.send();\n";
571 }
572
573 out << "break;\n";
574 out.unindent();
575 out << "}\n\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700576 }
577
578 out.unindent();
579 out << "}\n";
580
581 out.unindent();
582 out << "}\n";
583
584 out.unindent();
585 out << "}\n";
586
587 out.unindent();
588 out << "}\n";
589
590 return OK;
591}
592
593status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700594 return mRootScope->emitJavaTypeDeclarations(out, false /* atTopLevel */);
Andreas Huber2831d512016-08-15 09:33:47 -0700595}
596
597} // namespace android
598