blob: aa7c05a2c61ee45f0fc43d02d5f765cfd2543469 [file] [log] [blame]
Andreas Huber2831d512016-08-15 09:33:47 -07001#include "AST.h"
2
3#include "Coordinator.h"
4#include "Formatter.h"
5#include "Interface.h"
6#include "Method.h"
7#include "Scope.h"
8
9#include <android-base/logging.h>
10
11namespace android {
12
13static std::string upcase(const std::string in) {
14 std::string out{in};
15
16 for (auto &ch : out) {
17 ch = toupper(ch);
18 }
19
20 return out;
21}
22
23void AST::emitJavaReaderWriter(
24 Formatter &out,
25 const std::string &parcelObj,
26 const TypedVar *arg,
27 bool isReader) const {
28 if (isReader) {
29 out << arg->type().getJavaType()
30 << " "
31 << arg->name()
32 << " = ";
33 }
34
35 arg->type().emitJavaReaderWriter(out, parcelObj, arg->name(), isReader);
36}
37
Andreas Huber85eabdb2016-08-25 11:24:49 -070038status_t AST::generateJavaTypes(const std::string &outputPath) const {
39 // Splits types.hal up into one java file per declared type.
40
41 for (size_t i = 0; i < mRootScope->countTypes(); ++i) {
42 std::string typeName;
43 const Type *type = mRootScope->typeAt(i, &typeName);
44
45 if (type->isTypeDef()) {
46 continue;
47 }
48
49 std::string path = outputPath;
50 path.append(mCoordinator->convertPackageRootToPath(mPackage));
51 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
52 path.append(typeName);
53 path.append(".java");
54
55 CHECK(Coordinator::MakeParentHierarchy(path));
56 FILE *file = fopen(path.c_str(), "w");
57
58 if (file == NULL) {
59 return -errno;
60 }
61
62 Formatter out(file);
63
64 std::vector<std::string> packageComponents;
65 getPackageAndVersionComponents(
66 &packageComponents, true /* cpp_compatible */);
67
68 out << "package " << mPackage.javaPackage() << ";\n\n";
69
70 out << "import android.os.HwBlob;\n";
71 out << "import android.os.HwParcel;\n\n";
72
73 out << "import java.util.Vector;\n\n";
74
75 status_t err =
76 type->emitJavaTypeDeclarations(out, true /* atTopLevel */);
77
78 if (err != OK) {
79 return err;
80 }
81 }
82
83 return OK;
84}
85
Andreas Huber2831d512016-08-15 09:33:47 -070086status_t AST::generateJava(const std::string &outputPath) const {
87 std::string ifaceName;
88 if (!AST::isInterface(&ifaceName)) {
Andreas Huber85eabdb2016-08-25 11:24:49 -070089 return generateJavaTypes(outputPath);
Andreas Huber70a59e12016-08-16 12:57:01 -070090 }
91
92 const Interface *iface = mRootScope->getInterface();
93 if (!iface->isJavaCompatible()) {
94 fprintf(stderr,
95 "ERROR: This interface is not Java compatible. The Java backend"
Andreas Huber85eabdb2016-08-25 11:24:49 -070096 " does NOT support union types or native handles.\n");
Andreas Huber70a59e12016-08-16 12:57:01 -070097
Andreas Huber2831d512016-08-15 09:33:47 -070098 return UNKNOWN_ERROR;
99 }
100
101 // cut off the leading 'I'.
102 const std::string baseName = ifaceName.substr(1);
103
104 std::string path = outputPath;
105 path.append(mCoordinator->convertPackageRootToPath(mPackage));
106 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
107 path.append(ifaceName);
108 path.append(".java");
109
110 CHECK(Coordinator::MakeParentHierarchy(path));
111 FILE *file = fopen(path.c_str(), "w");
112
113 if (file == NULL) {
114 return -errno;
115 }
116
117 Formatter out(file);
118
119 std::vector<std::string> packageComponents;
120 getPackageAndVersionComponents(
121 &packageComponents, true /* cpp_compatible */);
122
123 out << "package " << mPackage.javaPackage() << ";\n\n";
124
125 out << "import android.os.IHwBinder;\n";
126 out << "import android.os.IHwInterface;\n";
127 out << "import android.os.HwBinder;\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700128 out << "import android.os.HwBlob;\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700129 out << "import android.os.HwParcel;\n\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700130 out << "import java.util.Vector;\n\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700131
Andreas Huber85eabdb2016-08-25 11:24:49 -0700132 for (const auto &item : mImportedNamesForJava) {
Andreas Huber2831d512016-08-15 09:33:47 -0700133 out << "import " << item.javaName() << ";\n";
134 }
135
Andreas Huber85eabdb2016-08-25 11:24:49 -0700136 if (!mImportedNamesForJava.empty()) {
Andreas Huber2831d512016-08-15 09:33:47 -0700137 out << "\n";
138 }
139
140 out.setNamespace(mPackage.javaPackage() + ".");
141
Andreas Huber2831d512016-08-15 09:33:47 -0700142 const Interface *superType = iface->superType();
143
144 out << "public interface " << ifaceName << " extends ";
145
146 if (superType != NULL) {
147 out << superType->fullJavaName();
148 } else {
149 out << "IHwInterface";
150 }
151
152 out << " {\n";
153 out.indent();
154
155 out << "public static final String kInterfaceName = \""
156 << mPackage.string()
157 << "::"
158 << ifaceName
159 << "\";\n\n";
160
161 out << "public static "
162 << ifaceName
163 << " asInterface(IHwBinder binder) {\n";
164
165 out.indent();
166
167 out << "if (binder == null) {\n";
168 out.indent();
169 out << "return null;\n";
170 out.unindent();
171 out << "}\n\n";
172
173 out << "IHwInterface iface =\n";
174 out.indent();
175 out.indent();
176 out << "binder.queryLocalInterface(kInterfaceName);\n\n";
177 out.unindent();
178 out.unindent();
179
180 out << "if ((iface != null) && (iface instanceof "
181 << ifaceName
182 << ")) {\n";
183
184 out.indent();
185 out << "return (" << ifaceName << ")iface;\n";
186 out.unindent();
187 out << "}\n\n";
188
189 out << "return new " << ifaceName << ".Proxy(binder);\n";
190
191 out.unindent();
192 out << "}\n\n";
193
194 out << "public IHwBinder asBinder();\n\n";
195
196 status_t err = emitJavaTypeDeclarations(out);
197
198 if (err != OK) {
199 return err;
200 }
201
202 const std::string base = (superType != NULL)
203 ? (superType->fullJavaName() + ".kOpEnd")
204 : "IHwBinder.FIRST_CALL_TRANSACTION";
205
206 bool first = true;
207 size_t index = 0;
208 for (const auto &method : iface->methods()) {
209 out << "public static final int kOp_"
210 << upcase(method->name())
211 << " = "
212 << base;
213
214 if (!first) {
215 out << " + " << index;
216 }
217
218 out << ";\n";
219
220 ++index;
221 first = false;
222 }
223
224 out << "public static final int kOpEnd = "
225 << base
226 << " + "
227 << index
228 << ";";
229
230 out << "\n\n";
231
232 for (const auto &method : iface->methods()) {
233 const bool returnsValue = !method->results().empty();
234 const bool needsCallback = method->results().size() > 1;
235
236 if (needsCallback) {
237 out << "\npublic abstract class "
238 << method->name()
239 << "Callback {\n";
240
241 out.indent();
242
243 out << "public abstract void onValues("
244 << Method::GetJavaSignature(method->results())
245 << ");\n";
246
247 out.unindent();
248 out << "}\n\n";
249 }
250
251 if (returnsValue && !needsCallback) {
252 out << method->results()[0]->type().getJavaType();
253 } else {
254 out << "void";
255 }
256
257 out << " "
258 << method->name()
259 << "("
260 << Method::GetJavaSignature(method->args());
261
262 if (needsCallback) {
263 if (!method->args().empty()) {
264 out << ", ";
265 }
266
267 out << method->name()
268 << "Callback cb";
269 }
270
271 out << ");\n";
272 }
273
274 out << "\npublic static final class Proxy implements "
275 << ifaceName
276 << " {\n";
277
278 out.indent();
279
280 out << "private IHwBinder mRemote;\n\n";
281 out << "public Proxy(IHwBinder remote) {\n";
282 out.indent();
283 out << "mRemote = remote;\n";
284 out.unindent();
285 out << "}\n\n";
286
287 out << "public IHwBinder asBinder() {\n";
288 out.indent();
289 out << "return mRemote;\n";
290 out.unindent();
291 out << "}\n\n";
292
293 std::vector<const Interface *> chain;
294 while (iface != NULL) {
295 chain.push_back(iface);
296 iface = iface->superType();
297 }
298
299 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
300 const Interface *superInterface = *it;
301
302 out << "// Methods from "
303 << superInterface->fullName()
304 << " follow.\n";
305
306 for (const auto &method : superInterface->methods()) {
307 const bool returnsValue = !method->results().empty();
308 const bool needsCallback = method->results().size() > 1;
309
310 out << "public ";
311 if (returnsValue && !needsCallback) {
312 out << method->results()[0]->type().getJavaType();
313 } else {
314 out << "void";
315 }
316
317 out << " "
318 << method->name()
319 << "("
320 << Method::GetJavaSignature(method->args());
321
322 if (needsCallback) {
323 if (!method->args().empty()) {
324 out << ", ";
325 }
326
327 out << method->name()
328 << "Callback cb";
329 }
330
331 out << ") {\n";
332 out.indent();
333
334 out << "HwParcel request = new HwParcel();\n";
335 out << "request.writeInterfaceToken("
336 << superInterface->fullJavaName()
337 << ".kInterfaceName);\n";
338
339 for (const auto &arg : method->args()) {
340 emitJavaReaderWriter(
341 out,
342 "request",
343 arg,
344 false /* isReader */);
345 }
346
347 out << "\nHwParcel reply = new HwParcel();\n"
Andreas Huber8b5da222016-08-18 14:28:18 -0700348 << "mRemote.transact(kOp_"
349 << upcase(method->name())
350 << ", request, reply, ";
351
352 if (method->isOneway()) {
353 out << "IHwBinder.FLAG_ONEWAY";
354 } else {
355 out << "0 /* flags */";
356 }
357
358 out << ");\n";
359
360 if (!method->isOneway()) {
361 out << "reply.verifySuccess();\n";
362 } else {
363 CHECK(!returnsValue);
364 }
365
366 out << "request.releaseTemporaryStorage();\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700367
368 if (returnsValue) {
369 out << "\n";
370
371 for (const auto &arg : method->results()) {
372 emitJavaReaderWriter(
373 out,
374 "reply",
375 arg,
376 true /* isReader */);
377 }
378
379 if (needsCallback) {
380 out << "cb.onValues(";
381
382 bool firstField = true;
383 for (const auto &arg : method->results()) {
384 if (!firstField) {
385 out << ", ";
386 }
387
388 out << arg->name();
389 firstField = false;
390 }
391
392 out << ");\n";
393 } else {
394 const std::string returnName = method->results()[0]->name();
395 out << "return " << returnName << ";\n";
396 }
397 }
398
399 out.unindent();
400 out << "}\n\n";
401 }
402 }
403
404 out.unindent();
405 out << "}\n";
406
407 ////////////////////////////////////////////////////////////////////////////
408
409 out << "\npublic static abstract class Stub extends HwBinder "
410 << "implements "
411 << ifaceName << " {\n";
412
413 out.indent();
414
415 out << "public IHwBinder asBinder() {\n";
416 out.indent();
417 out << "return this;\n";
418 out.unindent();
419 out << "}\n\n";
420
421 out << "public IHwInterface queryLocalInterface(String descriptor) {\n";
422 out.indent();
423 // XXX what about potential superClasses?
424 out << "if (kInterfaceName.equals(descriptor)) {\n";
425 out.indent();
426 out << "return this;\n";
427 out.unindent();
428 out << "}\n";
429 out << "return null;\n";
430 out.unindent();
431 out << "}\n\n";
432
433 out << "public void onTransact("
434 << "int code, HwParcel request, final HwParcel reply, "
435 << "int flags) {\n";
436
437 out.indent();
438
439 out << "switch (code) {\n";
440
441 out.indent();
442
443 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
444 const Interface *superInterface = *it;
445
446 for (const auto &method : superInterface->methods()) {
447 const bool returnsValue = !method->results().empty();
448 const bool needsCallback = method->results().size() > 1;
449
450 out << "case "
451 << superInterface->fullJavaName()
452 << ".kOp_"
453 <<
454 upcase(method->name())
455 << ":\n{\n";
456
457 out.indent();
458
459 out << "request.enforceInterface("
460 << superInterface->fullJavaName()
461 << ".kInterfaceName);\n\n";
462
463 for (const auto &arg : method->args()) {
464 emitJavaReaderWriter(
465 out,
466 "request",
467 arg,
468 true /* isReader */);
469 }
470
471 if (!needsCallback && returnsValue) {
472 const TypedVar *returnArg = method->results()[0];
473
474 out << returnArg->type().getJavaType()
475 << " "
476 << returnArg->name()
477 << " = ";
478 }
479
480 out << method->name()
481 << "(";
482
483 bool firstField = true;
484 for (const auto &arg : method->args()) {
485 if (!firstField) {
486 out << ", ";
487 }
488
489 out << arg->name();
490
491 firstField = false;
492 }
493
494 if (needsCallback) {
495 if (!firstField) {
496 out << ", ";
497 }
498
499 out << "new " << method->name() << "Callback() {\n";
500 out.indent();
501
502 out << "@Override\n"
503 << "public void onValues("
504 << Method::GetJavaSignature(method->results())
505 << ") {\n";
506
507 out.indent();
508 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
509
510 for (const auto &arg : method->results()) {
511 emitJavaReaderWriter(
512 out,
513 "reply",
514 arg,
515 false /* isReader */);
516 }
517
518 out << "reply.send();\n"
519 << "}}";
520
521 out.unindent();
522 out.unindent();
523 }
524
525 out << ");\n";
526
527 if (!needsCallback) {
528 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
529
530 if (returnsValue) {
531 const TypedVar *returnArg = method->results()[0];
532
533 emitJavaReaderWriter(
534 out,
535 "reply",
536 returnArg,
537 false /* isReader */);
538 }
539
540 out << "reply.send();\n";
541 }
542
543 out << "break;\n";
544 out.unindent();
545 out << "}\n\n";
546 }
547 }
548
549 out.unindent();
550 out << "}\n";
551
552 out.unindent();
553 out << "}\n";
554
555 out.unindent();
556 out << "}\n";
557
558 out.unindent();
559 out << "}\n";
560
561 return OK;
562}
563
564status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700565 return mRootScope->emitJavaTypeDeclarations(out, false /* atTopLevel */);
Andreas Huber2831d512016-08-15 09:33:47 -0700566}
567
568} // namespace android
569