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