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