blob: bd0fa704792ac3c4d2665e509d9c4b2151fcd35d [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"
301 << "mRemote.transact(kOp_"
302 << upcase(method->name())
303 << ", request, reply, 0 /* flags */);\n"
304 << "reply.verifySuccess();\n"
305 << "request.releaseTemporaryStorage();\n";
306
307 if (returnsValue) {
308 out << "\n";
309
310 for (const auto &arg : method->results()) {
311 emitJavaReaderWriter(
312 out,
313 "reply",
314 arg,
315 true /* isReader */);
316 }
317
318 if (needsCallback) {
319 out << "cb.onValues(";
320
321 bool firstField = true;
322 for (const auto &arg : method->results()) {
323 if (!firstField) {
324 out << ", ";
325 }
326
327 out << arg->name();
328 firstField = false;
329 }
330
331 out << ");\n";
332 } else {
333 const std::string returnName = method->results()[0]->name();
334 out << "return " << returnName << ";\n";
335 }
336 }
337
338 out.unindent();
339 out << "}\n\n";
340 }
341 }
342
343 out.unindent();
344 out << "}\n";
345
346 ////////////////////////////////////////////////////////////////////////////
347
348 out << "\npublic static abstract class Stub extends HwBinder "
349 << "implements "
350 << ifaceName << " {\n";
351
352 out.indent();
353
354 out << "public IHwBinder asBinder() {\n";
355 out.indent();
356 out << "return this;\n";
357 out.unindent();
358 out << "}\n\n";
359
360 out << "public IHwInterface queryLocalInterface(String descriptor) {\n";
361 out.indent();
362 // XXX what about potential superClasses?
363 out << "if (kInterfaceName.equals(descriptor)) {\n";
364 out.indent();
365 out << "return this;\n";
366 out.unindent();
367 out << "}\n";
368 out << "return null;\n";
369 out.unindent();
370 out << "}\n\n";
371
372 out << "public void onTransact("
373 << "int code, HwParcel request, final HwParcel reply, "
374 << "int flags) {\n";
375
376 out.indent();
377
378 out << "switch (code) {\n";
379
380 out.indent();
381
382 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
383 const Interface *superInterface = *it;
384
385 for (const auto &method : superInterface->methods()) {
386 const bool returnsValue = !method->results().empty();
387 const bool needsCallback = method->results().size() > 1;
388
389 out << "case "
390 << superInterface->fullJavaName()
391 << ".kOp_"
392 <<
393 upcase(method->name())
394 << ":\n{\n";
395
396 out.indent();
397
398 out << "request.enforceInterface("
399 << superInterface->fullJavaName()
400 << ".kInterfaceName);\n\n";
401
402 for (const auto &arg : method->args()) {
403 emitJavaReaderWriter(
404 out,
405 "request",
406 arg,
407 true /* isReader */);
408 }
409
410 if (!needsCallback && returnsValue) {
411 const TypedVar *returnArg = method->results()[0];
412
413 out << returnArg->type().getJavaType()
414 << " "
415 << returnArg->name()
416 << " = ";
417 }
418
419 out << method->name()
420 << "(";
421
422 bool firstField = true;
423 for (const auto &arg : method->args()) {
424 if (!firstField) {
425 out << ", ";
426 }
427
428 out << arg->name();
429
430 firstField = false;
431 }
432
433 if (needsCallback) {
434 if (!firstField) {
435 out << ", ";
436 }
437
438 out << "new " << method->name() << "Callback() {\n";
439 out.indent();
440
441 out << "@Override\n"
442 << "public void onValues("
443 << Method::GetJavaSignature(method->results())
444 << ") {\n";
445
446 out.indent();
447 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
448
449 for (const auto &arg : method->results()) {
450 emitJavaReaderWriter(
451 out,
452 "reply",
453 arg,
454 false /* isReader */);
455 }
456
457 out << "reply.send();\n"
458 << "}}";
459
460 out.unindent();
461 out.unindent();
462 }
463
464 out << ");\n";
465
466 if (!needsCallback) {
467 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
468
469 if (returnsValue) {
470 const TypedVar *returnArg = method->results()[0];
471
472 emitJavaReaderWriter(
473 out,
474 "reply",
475 returnArg,
476 false /* isReader */);
477 }
478
479 out << "reply.send();\n";
480 }
481
482 out << "break;\n";
483 out.unindent();
484 out << "}\n\n";
485 }
486 }
487
488 out.unindent();
489 out << "}\n";
490
491 out.unindent();
492 out << "}\n";
493
494 out.unindent();
495 out << "}\n";
496
497 out.unindent();
498 out << "}\n";
499
500 return OK;
501}
502
503status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
504 return mRootScope->emitJavaTypeDeclarations(out);
505}
506
507} // namespace android
508