blob: 4fa54d865ff462c8229c25f4153807e768fa0aa0 [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
Steven Moreland7e367bf2016-11-04 11:31:41 -0700226 << ".asInterface(HwBinder.getService(\""
227 << iface->fqName().string()
228 << "\",serviceName));\n";
Andreas Huber2bb6e1e2016-10-25 13:26:43 -0700229
230 out.unindent();
231
232 out << "}\n\n";
233
Andreas Huber2831d512016-08-15 09:33:47 -0700234 status_t err = emitJavaTypeDeclarations(out);
235
236 if (err != OK) {
237 return err;
238 }
239
Andreas Huber2831d512016-08-15 09:33:47 -0700240 for (const auto &method : iface->methods()) {
241 const bool returnsValue = !method->results().empty();
242 const bool needsCallback = method->results().size() > 1;
243
244 if (needsCallback) {
245 out << "\npublic abstract class "
246 << method->name()
247 << "Callback {\n";
248
249 out.indent();
250
251 out << "public abstract void onValues("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700252 << Method::GetJavaArgSignature(method->results())
Andreas Huber2831d512016-08-15 09:33:47 -0700253 << ");\n";
254
255 out.unindent();
256 out << "}\n\n";
257 }
258
259 if (returnsValue && !needsCallback) {
Yifan Hong4ed13472016-11-02 10:44:11 -0700260 out << method->results()[0]->type().getJavaType();
Andreas Huber2831d512016-08-15 09:33:47 -0700261 } else {
262 out << "void";
263 }
264
265 out << " "
266 << method->name()
267 << "("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700268 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700269
270 if (needsCallback) {
271 if (!method->args().empty()) {
272 out << ", ";
273 }
274
275 out << method->name()
276 << "Callback cb";
277 }
278
279 out << ");\n";
280 }
281
282 out << "\npublic static final class Proxy implements "
283 << ifaceName
284 << " {\n";
285
286 out.indent();
287
288 out << "private IHwBinder mRemote;\n\n";
289 out << "public Proxy(IHwBinder remote) {\n";
290 out.indent();
291 out << "mRemote = remote;\n";
292 out.unindent();
293 out << "}\n\n";
294
295 out << "public IHwBinder asBinder() {\n";
296 out.indent();
297 out << "return mRemote;\n";
298 out.unindent();
299 out << "}\n\n";
300
Yifan Hong10fe0b52016-10-19 14:20:17 -0700301 const Interface *prevInterface = nullptr;
302 for (const auto &tuple : iface->allMethodsFromRoot()) {
303 const Method *method = tuple.method();
304 const Interface *superInterface = tuple.interface();
305 if (prevInterface != superInterface) {
306 out << "// Methods from "
307 << superInterface->fullName()
308 << " follow.\n";
309 prevInterface = superInterface;
310 }
311 const bool returnsValue = !method->results().empty();
312 const bool needsCallback = method->results().size() > 1;
Andreas Huber2831d512016-08-15 09:33:47 -0700313
Yifan Hong10fe0b52016-10-19 14:20:17 -0700314 out << "public ";
315 if (returnsValue && !needsCallback) {
Yifan Hong4ed13472016-11-02 10:44:11 -0700316 out << method->results()[0]->type().getJavaType();
Yifan Hong10fe0b52016-10-19 14:20:17 -0700317 } else {
318 out << "void";
319 }
Andreas Huber2831d512016-08-15 09:33:47 -0700320
Yifan Hong10fe0b52016-10-19 14:20:17 -0700321 out << " "
322 << method->name()
323 << "("
324 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700325
Yifan Hong10fe0b52016-10-19 14:20:17 -0700326 if (needsCallback) {
327 if (!method->args().empty()) {
328 out << ", ";
Andreas Huber2831d512016-08-15 09:33:47 -0700329 }
330
Yifan Hong10fe0b52016-10-19 14:20:17 -0700331 out << method->name()
332 << "Callback cb";
333 }
Andreas Huber2831d512016-08-15 09:33:47 -0700334
Yifan Hong10fe0b52016-10-19 14:20:17 -0700335 out << ") {\n";
336 out.indent();
Andreas Huber2831d512016-08-15 09:33:47 -0700337
Yifan Hong10fe0b52016-10-19 14:20:17 -0700338 out << "HwParcel request = new HwParcel();\n";
339 out << "request.writeInterfaceToken("
340 << superInterface->fullJavaName()
341 << ".kInterfaceName);\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700342
Yifan Hong10fe0b52016-10-19 14:20:17 -0700343 for (const auto &arg : method->args()) {
344 emitJavaReaderWriter(
345 out,
346 "request",
347 arg,
348 false /* isReader */);
349 }
Andreas Huber2831d512016-08-15 09:33:47 -0700350
Yifan Hong10fe0b52016-10-19 14:20:17 -0700351 out << "\nHwParcel reply = new HwParcel();\n"
352 << "mRemote.transact("
353 << method->getSerialId()
354 << " /* "
355 << method->name()
356 << " */, request, reply, ";
Andreas Huber2831d512016-08-15 09:33:47 -0700357
Yifan Hong10fe0b52016-10-19 14:20:17 -0700358 if (method->isOneway()) {
359 out << "IHwBinder.FLAG_ONEWAY";
360 } else {
361 out << "0 /* flags */";
362 }
363
364 out << ");\n";
365
366 if (!method->isOneway()) {
367 out << "reply.verifySuccess();\n";
368 } else {
369 CHECK(!returnsValue);
370 }
371
372 out << "request.releaseTemporaryStorage();\n";
373
374 if (returnsValue) {
375 out << "\n";
376
377 for (const auto &arg : method->results()) {
Andreas Huber2831d512016-08-15 09:33:47 -0700378 emitJavaReaderWriter(
379 out,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700380 "reply",
Andreas Huber2831d512016-08-15 09:33:47 -0700381 arg,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700382 true /* isReader */);
Andreas Huber2831d512016-08-15 09:33:47 -0700383 }
384
Yifan Hong10fe0b52016-10-19 14:20:17 -0700385 if (needsCallback) {
386 out << "cb.onValues(";
Andreas Huber8b5da222016-08-18 14:28:18 -0700387
Yifan Hong10fe0b52016-10-19 14:20:17 -0700388 bool firstField = true;
Andreas Huber2831d512016-08-15 09:33:47 -0700389 for (const auto &arg : method->results()) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700390 if (!firstField) {
391 out << ", ";
Andreas Huber2831d512016-08-15 09:33:47 -0700392 }
393
Yifan Hong10fe0b52016-10-19 14:20:17 -0700394 out << arg->name();
395 firstField = false;
Andreas Huber2831d512016-08-15 09:33:47 -0700396 }
Andreas Huber2831d512016-08-15 09:33:47 -0700397
Yifan Hong10fe0b52016-10-19 14:20:17 -0700398 out << ");\n";
399 } else {
400 const std::string returnName = method->results()[0]->name();
401 out << "return " << returnName << ";\n";
402 }
Andreas Huber2831d512016-08-15 09:33:47 -0700403 }
Yifan Hong10fe0b52016-10-19 14:20:17 -0700404
405 out.unindent();
406 out << "}\n\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700407 }
408
409 out.unindent();
410 out << "}\n";
411
412 ////////////////////////////////////////////////////////////////////////////
413
414 out << "\npublic static abstract class Stub extends HwBinder "
415 << "implements "
416 << ifaceName << " {\n";
417
418 out.indent();
419
420 out << "public IHwBinder asBinder() {\n";
421 out.indent();
422 out << "return this;\n";
423 out.unindent();
424 out << "}\n\n";
425
Yifan Hong10fe0b52016-10-19 14:20:17 -0700426 // b/32383557 this is a hack. We need to change this if we have more reserved methods.
427 for (Method *method : iface->hidlReservedMethods()) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700428 out << "public final "
Yifan Hong4ed13472016-11-02 10:44:11 -0700429 << method->results()[0]->type().getJavaType()
Yifan Hong10fe0b52016-10-19 14:20:17 -0700430 << " "
431 << method->name()
432 << "() {\n";
433 out.indent();
434 method->javaImpl(out);
435 out.unindent();
436 out << "\n}\n\n";
437 }
438
Andreas Huber2831d512016-08-15 09:33:47 -0700439 out << "public IHwInterface queryLocalInterface(String descriptor) {\n";
440 out.indent();
441 // XXX what about potential superClasses?
442 out << "if (kInterfaceName.equals(descriptor)) {\n";
443 out.indent();
444 out << "return this;\n";
445 out.unindent();
446 out << "}\n";
447 out << "return null;\n";
448 out.unindent();
449 out << "}\n\n";
450
Andreas Huber2bb6e1e2016-10-25 13:26:43 -0700451 out << "public void registerAsService(String serviceName) {\n";
452 out.indent();
453
Steven Moreland7e367bf2016-11-04 11:31:41 -0700454 out << "registerService(interfaceChain(), serviceName);\n";
Andreas Huber2bb6e1e2016-10-25 13:26:43 -0700455
456 out.unindent();
457 out << "}\n\n";
458
Andreas Huber2831d512016-08-15 09:33:47 -0700459 out << "public void onTransact("
460 << "int code, HwParcel request, final HwParcel reply, "
461 << "int flags) {\n";
462
463 out.indent();
464
465 out << "switch (code) {\n";
466
467 out.indent();
468
Yifan Hong10fe0b52016-10-19 14:20:17 -0700469 for (const auto &tuple : iface->allMethodsFromRoot()) {
470 const Method *method = tuple.method();
471 const Interface *superInterface = tuple.interface();
472 const bool returnsValue = !method->results().empty();
473 const bool needsCallback = method->results().size() > 1;
Andreas Huber2831d512016-08-15 09:33:47 -0700474
Yifan Hong10fe0b52016-10-19 14:20:17 -0700475 out << "case "
476 << method->getSerialId()
477 << " /* "
478 << method->name()
479 << " */:\n{\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700480
Yifan Hong10fe0b52016-10-19 14:20:17 -0700481 out.indent();
Andreas Huber2831d512016-08-15 09:33:47 -0700482
Yifan Hong10fe0b52016-10-19 14:20:17 -0700483 out << "request.enforceInterface("
484 << superInterface->fullJavaName()
485 << ".kInterfaceName);\n\n";
486
487 for (const auto &arg : method->args()) {
488 emitJavaReaderWriter(
489 out,
490 "request",
491 arg,
492 true /* isReader */);
493 }
494
495 if (!needsCallback && returnsValue) {
496 const TypedVar *returnArg = method->results()[0];
Yifan Hong10fe0b52016-10-19 14:20:17 -0700497
Yifan Hong4ed13472016-11-02 10:44:11 -0700498 out << returnArg->type().getJavaType()
Yifan Hong10fe0b52016-10-19 14:20:17 -0700499 << " "
500 << returnArg->name()
501 << " = ";
502 }
503
504 out << method->name()
505 << "(";
506
507 bool firstField = true;
508 for (const auto &arg : method->args()) {
509 if (!firstField) {
510 out << ", ";
511 }
512
513 out << arg->name();
514
515 firstField = false;
516 }
517
518 if (needsCallback) {
519 if (!firstField) {
520 out << ", ";
521 }
522
523 out << "new " << method->name() << "Callback() {\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700524 out.indent();
525
Yifan Hong10fe0b52016-10-19 14:20:17 -0700526 out << "@Override\n"
527 << "public void onValues("
528 << Method::GetJavaArgSignature(method->results())
529 << ") {\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700530
Yifan Hong10fe0b52016-10-19 14:20:17 -0700531 out.indent();
532 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
533
534 for (const auto &arg : method->results()) {
Andreas Huber2831d512016-08-15 09:33:47 -0700535 emitJavaReaderWriter(
536 out,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700537 "reply",
Andreas Huber2831d512016-08-15 09:33:47 -0700538 arg,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700539 false /* isReader */);
Andreas Huber2831d512016-08-15 09:33:47 -0700540 }
541
Yifan Hong10fe0b52016-10-19 14:20:17 -0700542 out << "reply.send();\n"
543 << "}}";
Andreas Huber2831d512016-08-15 09:33:47 -0700544
Andreas Huber2831d512016-08-15 09:33:47 -0700545 out.unindent();
Yifan Hong10fe0b52016-10-19 14:20:17 -0700546 out.unindent();
Andreas Huber2831d512016-08-15 09:33:47 -0700547 }
Yifan Hong10fe0b52016-10-19 14:20:17 -0700548
549 out << ");\n";
550
551 if (!needsCallback) {
552 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
553
554 if (returnsValue) {
555 const TypedVar *returnArg = method->results()[0];
556
557 emitJavaReaderWriter(
558 out,
559 "reply",
560 returnArg,
561 false /* isReader */);
562 }
563
564 out << "reply.send();\n";
565 }
566
567 out << "break;\n";
568 out.unindent();
569 out << "}\n\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700570 }
571
572 out.unindent();
573 out << "}\n";
574
575 out.unindent();
576 out << "}\n";
577
578 out.unindent();
579 out << "}\n";
580
581 out.unindent();
582 out << "}\n";
583
584 return OK;
585}
586
587status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700588 return mRootScope->emitJavaTypeDeclarations(out, false /* atTopLevel */);
Andreas Huber2831d512016-08-15 09:33:47 -0700589}
590
591} // namespace android
592