blob: 38c7343d43a41327d4acadb6153fc721f0a44554 [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
38status_t AST::generateJava(const std::string &outputPath) const {
39 std::string ifaceName;
40 if (!AST::isInterface(&ifaceName)) {
Andreas Huber70a59e12016-08-16 12:57:01 -070041 fprintf(stderr,
42 "ERROR: Common types are unsupported in the Java backend.\n");
43
44 return UNKNOWN_ERROR;
45 }
46
47 const Interface *iface = mRootScope->getInterface();
48 if (!iface->isJavaCompatible()) {
49 fprintf(stderr,
50 "ERROR: This interface is not Java compatible. The Java backend"
51 " does NOT support struct/union types nor handles.\n");
52
Andreas Huber2831d512016-08-15 09:33:47 -070053 return UNKNOWN_ERROR;
54 }
55
56 // cut off the leading 'I'.
57 const std::string baseName = ifaceName.substr(1);
58
59 std::string path = outputPath;
60 path.append(mCoordinator->convertPackageRootToPath(mPackage));
61 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
62 path.append(ifaceName);
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.IHwBinder;\n";
81 out << "import android.os.IHwInterface;\n";
82 out << "import android.os.HwBinder;\n";
83 out << "import android.os.HwParcel;\n\n";
84
85 for (const auto &item : mImportedNames) {
86 out << "import " << item.javaName() << ";\n";
87 }
88
89 if (!mImportedNames.empty()) {
90 out << "\n";
91 }
92
93 out.setNamespace(mPackage.javaPackage() + ".");
94
Andreas Huber2831d512016-08-15 09:33:47 -070095 const Interface *superType = iface->superType();
96
97 out << "public interface " << ifaceName << " extends ";
98
99 if (superType != NULL) {
100 out << superType->fullJavaName();
101 } else {
102 out << "IHwInterface";
103 }
104
105 out << " {\n";
106 out.indent();
107
108 out << "public static final String kInterfaceName = \""
109 << mPackage.string()
110 << "::"
111 << ifaceName
112 << "\";\n\n";
113
114 out << "public static "
115 << ifaceName
116 << " asInterface(IHwBinder binder) {\n";
117
118 out.indent();
119
120 out << "if (binder == null) {\n";
121 out.indent();
122 out << "return null;\n";
123 out.unindent();
124 out << "}\n\n";
125
126 out << "IHwInterface iface =\n";
127 out.indent();
128 out.indent();
129 out << "binder.queryLocalInterface(kInterfaceName);\n\n";
130 out.unindent();
131 out.unindent();
132
133 out << "if ((iface != null) && (iface instanceof "
134 << ifaceName
135 << ")) {\n";
136
137 out.indent();
138 out << "return (" << ifaceName << ")iface;\n";
139 out.unindent();
140 out << "}\n\n";
141
142 out << "return new " << ifaceName << ".Proxy(binder);\n";
143
144 out.unindent();
145 out << "}\n\n";
146
147 out << "public IHwBinder asBinder();\n\n";
148
149 status_t err = emitJavaTypeDeclarations(out);
150
151 if (err != OK) {
152 return err;
153 }
154
155 const std::string base = (superType != NULL)
156 ? (superType->fullJavaName() + ".kOpEnd")
157 : "IHwBinder.FIRST_CALL_TRANSACTION";
158
159 bool first = true;
160 size_t index = 0;
161 for (const auto &method : iface->methods()) {
162 out << "public static final int kOp_"
163 << upcase(method->name())
164 << " = "
165 << base;
166
167 if (!first) {
168 out << " + " << index;
169 }
170
171 out << ";\n";
172
173 ++index;
174 first = false;
175 }
176
177 out << "public static final int kOpEnd = "
178 << base
179 << " + "
180 << index
181 << ";";
182
183 out << "\n\n";
184
185 for (const auto &method : iface->methods()) {
186 const bool returnsValue = !method->results().empty();
187 const bool needsCallback = method->results().size() > 1;
188
189 if (needsCallback) {
190 out << "\npublic abstract class "
191 << method->name()
192 << "Callback {\n";
193
194 out.indent();
195
196 out << "public abstract void onValues("
197 << Method::GetJavaSignature(method->results())
198 << ");\n";
199
200 out.unindent();
201 out << "}\n\n";
202 }
203
204 if (returnsValue && !needsCallback) {
205 out << method->results()[0]->type().getJavaType();
206 } else {
207 out << "void";
208 }
209
210 out << " "
211 << method->name()
212 << "("
213 << Method::GetJavaSignature(method->args());
214
215 if (needsCallback) {
216 if (!method->args().empty()) {
217 out << ", ";
218 }
219
220 out << method->name()
221 << "Callback cb";
222 }
223
224 out << ");\n";
225 }
226
227 out << "\npublic static final class Proxy implements "
228 << ifaceName
229 << " {\n";
230
231 out.indent();
232
233 out << "private IHwBinder mRemote;\n\n";
234 out << "public Proxy(IHwBinder remote) {\n";
235 out.indent();
236 out << "mRemote = remote;\n";
237 out.unindent();
238 out << "}\n\n";
239
240 out << "public IHwBinder asBinder() {\n";
241 out.indent();
242 out << "return mRemote;\n";
243 out.unindent();
244 out << "}\n\n";
245
246 std::vector<const Interface *> chain;
247 while (iface != NULL) {
248 chain.push_back(iface);
249 iface = iface->superType();
250 }
251
252 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
253 const Interface *superInterface = *it;
254
255 out << "// Methods from "
256 << superInterface->fullName()
257 << " follow.\n";
258
259 for (const auto &method : superInterface->methods()) {
260 const bool returnsValue = !method->results().empty();
261 const bool needsCallback = method->results().size() > 1;
262
263 out << "public ";
264 if (returnsValue && !needsCallback) {
265 out << method->results()[0]->type().getJavaType();
266 } else {
267 out << "void";
268 }
269
270 out << " "
271 << method->name()
272 << "("
273 << Method::GetJavaSignature(method->args());
274
275 if (needsCallback) {
276 if (!method->args().empty()) {
277 out << ", ";
278 }
279
280 out << method->name()
281 << "Callback cb";
282 }
283
284 out << ") {\n";
285 out.indent();
286
287 out << "HwParcel request = new HwParcel();\n";
288 out << "request.writeInterfaceToken("
289 << superInterface->fullJavaName()
290 << ".kInterfaceName);\n";
291
292 for (const auto &arg : method->args()) {
293 emitJavaReaderWriter(
294 out,
295 "request",
296 arg,
297 false /* isReader */);
298 }
299
300 out << "\nHwParcel reply = new HwParcel();\n"
Andreas Huber8b5da222016-08-18 14:28:18 -0700301 << "mRemote.transact(kOp_"
302 << upcase(method->name())
303 << ", request, reply, ";
304
305 if (method->isOneway()) {
306 out << "IHwBinder.FLAG_ONEWAY";
307 } else {
308 out << "0 /* flags */";
309 }
310
311 out << ");\n";
312
313 if (!method->isOneway()) {
314 out << "reply.verifySuccess();\n";
315 } else {
316 CHECK(!returnsValue);
317 }
318
319 out << "request.releaseTemporaryStorage();\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700320
321 if (returnsValue) {
322 out << "\n";
323
324 for (const auto &arg : method->results()) {
325 emitJavaReaderWriter(
326 out,
327 "reply",
328 arg,
329 true /* isReader */);
330 }
331
332 if (needsCallback) {
333 out << "cb.onValues(";
334
335 bool firstField = true;
336 for (const auto &arg : method->results()) {
337 if (!firstField) {
338 out << ", ";
339 }
340
341 out << arg->name();
342 firstField = false;
343 }
344
345 out << ");\n";
346 } else {
347 const std::string returnName = method->results()[0]->name();
348 out << "return " << returnName << ";\n";
349 }
350 }
351
352 out.unindent();
353 out << "}\n\n";
354 }
355 }
356
357 out.unindent();
358 out << "}\n";
359
360 ////////////////////////////////////////////////////////////////////////////
361
362 out << "\npublic static abstract class Stub extends HwBinder "
363 << "implements "
364 << ifaceName << " {\n";
365
366 out.indent();
367
368 out << "public IHwBinder asBinder() {\n";
369 out.indent();
370 out << "return this;\n";
371 out.unindent();
372 out << "}\n\n";
373
374 out << "public IHwInterface queryLocalInterface(String descriptor) {\n";
375 out.indent();
376 // XXX what about potential superClasses?
377 out << "if (kInterfaceName.equals(descriptor)) {\n";
378 out.indent();
379 out << "return this;\n";
380 out.unindent();
381 out << "}\n";
382 out << "return null;\n";
383 out.unindent();
384 out << "}\n\n";
385
386 out << "public void onTransact("
387 << "int code, HwParcel request, final HwParcel reply, "
388 << "int flags) {\n";
389
390 out.indent();
391
392 out << "switch (code) {\n";
393
394 out.indent();
395
396 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
397 const Interface *superInterface = *it;
398
399 for (const auto &method : superInterface->methods()) {
400 const bool returnsValue = !method->results().empty();
401 const bool needsCallback = method->results().size() > 1;
402
403 out << "case "
404 << superInterface->fullJavaName()
405 << ".kOp_"
406 <<
407 upcase(method->name())
408 << ":\n{\n";
409
410 out.indent();
411
412 out << "request.enforceInterface("
413 << superInterface->fullJavaName()
414 << ".kInterfaceName);\n\n";
415
416 for (const auto &arg : method->args()) {
417 emitJavaReaderWriter(
418 out,
419 "request",
420 arg,
421 true /* isReader */);
422 }
423
424 if (!needsCallback && returnsValue) {
425 const TypedVar *returnArg = method->results()[0];
426
427 out << returnArg->type().getJavaType()
428 << " "
429 << returnArg->name()
430 << " = ";
431 }
432
433 out << method->name()
434 << "(";
435
436 bool firstField = true;
437 for (const auto &arg : method->args()) {
438 if (!firstField) {
439 out << ", ";
440 }
441
442 out << arg->name();
443
444 firstField = false;
445 }
446
447 if (needsCallback) {
448 if (!firstField) {
449 out << ", ";
450 }
451
452 out << "new " << method->name() << "Callback() {\n";
453 out.indent();
454
455 out << "@Override\n"
456 << "public void onValues("
457 << Method::GetJavaSignature(method->results())
458 << ") {\n";
459
460 out.indent();
461 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
462
463 for (const auto &arg : method->results()) {
464 emitJavaReaderWriter(
465 out,
466 "reply",
467 arg,
468 false /* isReader */);
469 }
470
471 out << "reply.send();\n"
472 << "}}";
473
474 out.unindent();
475 out.unindent();
476 }
477
478 out << ");\n";
479
480 if (!needsCallback) {
481 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
482
483 if (returnsValue) {
484 const TypedVar *returnArg = method->results()[0];
485
486 emitJavaReaderWriter(
487 out,
488 "reply",
489 returnArg,
490 false /* isReader */);
491 }
492
493 out << "reply.send();\n";
494 }
495
496 out << "break;\n";
497 out.unindent();
498 out << "}\n\n";
499 }
500 }
501
502 out.unindent();
503 out << "}\n";
504
505 out.unindent();
506 out << "}\n";
507
508 out.unindent();
509 out << "}\n";
510
511 out.unindent();
512 out << "}\n";
513
514 return OK;
515}
516
517status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
518 return mRootScope->emitJavaTypeDeclarations(out);
519}
520
521} // namespace android
522