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