blob: bc7554757861a1f6f4caaaf9b2b226433e7c81b2 [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
Iliyan Malchev800273d2016-09-02 15:25:07 -070096 for (const auto &item : mImportedNamesForJava) {
97 out << "import " << item.javaName() << ";\n";
98 }
99 out << "\n";
100
Andreas Huber85eabdb2016-08-25 11:24:49 -0700101 status_t err =
102 type->emitJavaTypeDeclarations(out, true /* atTopLevel */);
103
104 if (err != OK) {
105 return err;
106 }
107 }
108
109 return OK;
110}
111
Andreas Huber0fa9e392016-08-31 09:05:44 -0700112status_t AST::generateJava(
113 const std::string &outputPath, const char *limitToType) const {
114 if (!isJavaCompatible()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700115 fprintf(stderr,
116 "ERROR: This interface is not Java compatible. The Java backend"
Andreas Huber85eabdb2016-08-25 11:24:49 -0700117 " does NOT support union types or native handles.\n");
Andreas Huber70a59e12016-08-16 12:57:01 -0700118
Andreas Huber2831d512016-08-15 09:33:47 -0700119 return UNKNOWN_ERROR;
120 }
121
Andreas Huber0fa9e392016-08-31 09:05:44 -0700122 std::string ifaceName;
123 if (!AST::isInterface(&ifaceName)) {
124 return generateJavaTypes(outputPath, limitToType);
125 }
126
127 const Interface *iface = mRootScope->getInterface();
128
Andreas Huber2831d512016-08-15 09:33:47 -0700129 // cut off the leading 'I'.
130 const std::string baseName = ifaceName.substr(1);
131
132 std::string path = outputPath;
133 path.append(mCoordinator->convertPackageRootToPath(mPackage));
134 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
135 path.append(ifaceName);
136 path.append(".java");
137
138 CHECK(Coordinator::MakeParentHierarchy(path));
139 FILE *file = fopen(path.c_str(), "w");
140
141 if (file == NULL) {
142 return -errno;
143 }
144
145 Formatter out(file);
146
147 std::vector<std::string> packageComponents;
148 getPackageAndVersionComponents(
149 &packageComponents, true /* cpp_compatible */);
150
151 out << "package " << mPackage.javaPackage() << ";\n\n";
152
153 out << "import android.os.IHwBinder;\n";
154 out << "import android.os.IHwInterface;\n";
155 out << "import android.os.HwBinder;\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700156 out << "import android.os.HwBlob;\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700157 out << "import android.os.HwParcel;\n\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700158 out << "import java.util.Vector;\n\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700159
Andreas Huber85eabdb2016-08-25 11:24:49 -0700160 for (const auto &item : mImportedNamesForJava) {
Andreas Huber2831d512016-08-15 09:33:47 -0700161 out << "import " << item.javaName() << ";\n";
162 }
163
Andreas Huber85eabdb2016-08-25 11:24:49 -0700164 if (!mImportedNamesForJava.empty()) {
Andreas Huber2831d512016-08-15 09:33:47 -0700165 out << "\n";
166 }
167
168 out.setNamespace(mPackage.javaPackage() + ".");
169
Andreas Huber2831d512016-08-15 09:33:47 -0700170 const Interface *superType = iface->superType();
171
172 out << "public interface " << ifaceName << " extends ";
173
174 if (superType != NULL) {
175 out << superType->fullJavaName();
176 } else {
177 out << "IHwInterface";
178 }
179
180 out << " {\n";
181 out.indent();
182
183 out << "public static final String kInterfaceName = \""
184 << mPackage.string()
185 << "::"
186 << ifaceName
187 << "\";\n\n";
188
189 out << "public static "
190 << ifaceName
191 << " asInterface(IHwBinder binder) {\n";
192
193 out.indent();
194
195 out << "if (binder == null) {\n";
196 out.indent();
197 out << "return null;\n";
198 out.unindent();
199 out << "}\n\n";
200
201 out << "IHwInterface iface =\n";
202 out.indent();
203 out.indent();
204 out << "binder.queryLocalInterface(kInterfaceName);\n\n";
205 out.unindent();
206 out.unindent();
207
208 out << "if ((iface != null) && (iface instanceof "
209 << ifaceName
210 << ")) {\n";
211
212 out.indent();
213 out << "return (" << ifaceName << ")iface;\n";
214 out.unindent();
215 out << "}\n\n";
216
217 out << "return new " << ifaceName << ".Proxy(binder);\n";
218
219 out.unindent();
220 out << "}\n\n";
221
222 out << "public IHwBinder asBinder();\n\n";
223
224 status_t err = emitJavaTypeDeclarations(out);
225
226 if (err != OK) {
227 return err;
228 }
229
230 const std::string base = (superType != NULL)
231 ? (superType->fullJavaName() + ".kOpEnd")
232 : "IHwBinder.FIRST_CALL_TRANSACTION";
233
234 bool first = true;
235 size_t index = 0;
236 for (const auto &method : iface->methods()) {
237 out << "public static final int kOp_"
238 << upcase(method->name())
239 << " = "
240 << base;
241
242 if (!first) {
243 out << " + " << index;
244 }
245
246 out << ";\n";
247
248 ++index;
249 first = false;
250 }
251
252 out << "public static final int kOpEnd = "
253 << base
254 << " + "
255 << index
256 << ";";
257
258 out << "\n\n";
259
260 for (const auto &method : iface->methods()) {
261 const bool returnsValue = !method->results().empty();
262 const bool needsCallback = method->results().size() > 1;
263
264 if (needsCallback) {
265 out << "\npublic abstract class "
266 << method->name()
267 << "Callback {\n";
268
269 out.indent();
270
271 out << "public abstract void onValues("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700272 << Method::GetJavaArgSignature(method->results())
Andreas Huber2831d512016-08-15 09:33:47 -0700273 << ");\n";
274
275 out.unindent();
276 out << "}\n\n";
277 }
278
279 if (returnsValue && !needsCallback) {
280 out << method->results()[0]->type().getJavaType();
281 } else {
282 out << "void";
283 }
284
285 out << " "
286 << method->name()
287 << "("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700288 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700289
290 if (needsCallback) {
291 if (!method->args().empty()) {
292 out << ", ";
293 }
294
295 out << method->name()
296 << "Callback cb";
297 }
298
299 out << ");\n";
300 }
301
302 out << "\npublic static final class Proxy implements "
303 << ifaceName
304 << " {\n";
305
306 out.indent();
307
308 out << "private IHwBinder mRemote;\n\n";
309 out << "public Proxy(IHwBinder remote) {\n";
310 out.indent();
311 out << "mRemote = remote;\n";
312 out.unindent();
313 out << "}\n\n";
314
315 out << "public IHwBinder asBinder() {\n";
316 out.indent();
317 out << "return mRemote;\n";
318 out.unindent();
319 out << "}\n\n";
320
321 std::vector<const Interface *> chain;
322 while (iface != NULL) {
323 chain.push_back(iface);
324 iface = iface->superType();
325 }
326
327 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
328 const Interface *superInterface = *it;
329
330 out << "// Methods from "
331 << superInterface->fullName()
332 << " follow.\n";
333
334 for (const auto &method : superInterface->methods()) {
335 const bool returnsValue = !method->results().empty();
336 const bool needsCallback = method->results().size() > 1;
337
338 out << "public ";
339 if (returnsValue && !needsCallback) {
340 out << method->results()[0]->type().getJavaType();
341 } else {
342 out << "void";
343 }
344
345 out << " "
346 << method->name()
347 << "("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700348 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700349
350 if (needsCallback) {
351 if (!method->args().empty()) {
352 out << ", ";
353 }
354
355 out << method->name()
356 << "Callback cb";
357 }
358
359 out << ") {\n";
360 out.indent();
361
362 out << "HwParcel request = new HwParcel();\n";
363 out << "request.writeInterfaceToken("
364 << superInterface->fullJavaName()
365 << ".kInterfaceName);\n";
366
367 for (const auto &arg : method->args()) {
368 emitJavaReaderWriter(
369 out,
370 "request",
371 arg,
372 false /* isReader */);
373 }
374
375 out << "\nHwParcel reply = new HwParcel();\n"
Andreas Huber8b5da222016-08-18 14:28:18 -0700376 << "mRemote.transact(kOp_"
377 << upcase(method->name())
378 << ", request, reply, ";
379
380 if (method->isOneway()) {
381 out << "IHwBinder.FLAG_ONEWAY";
382 } else {
383 out << "0 /* flags */";
384 }
385
386 out << ");\n";
387
388 if (!method->isOneway()) {
389 out << "reply.verifySuccess();\n";
390 } else {
391 CHECK(!returnsValue);
392 }
393
394 out << "request.releaseTemporaryStorage();\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700395
396 if (returnsValue) {
397 out << "\n";
398
399 for (const auto &arg : method->results()) {
400 emitJavaReaderWriter(
401 out,
402 "reply",
403 arg,
404 true /* isReader */);
405 }
406
407 if (needsCallback) {
408 out << "cb.onValues(";
409
410 bool firstField = true;
411 for (const auto &arg : method->results()) {
412 if (!firstField) {
413 out << ", ";
414 }
415
416 out << arg->name();
417 firstField = false;
418 }
419
420 out << ");\n";
421 } else {
422 const std::string returnName = method->results()[0]->name();
423 out << "return " << returnName << ";\n";
424 }
425 }
426
427 out.unindent();
428 out << "}\n\n";
429 }
430 }
431
432 out.unindent();
433 out << "}\n";
434
435 ////////////////////////////////////////////////////////////////////////////
436
437 out << "\npublic static abstract class Stub extends HwBinder "
438 << "implements "
439 << ifaceName << " {\n";
440
441 out.indent();
442
443 out << "public IHwBinder asBinder() {\n";
444 out.indent();
445 out << "return this;\n";
446 out.unindent();
447 out << "}\n\n";
448
449 out << "public IHwInterface queryLocalInterface(String descriptor) {\n";
450 out.indent();
451 // XXX what about potential superClasses?
452 out << "if (kInterfaceName.equals(descriptor)) {\n";
453 out.indent();
454 out << "return this;\n";
455 out.unindent();
456 out << "}\n";
457 out << "return null;\n";
458 out.unindent();
459 out << "}\n\n";
460
461 out << "public void onTransact("
462 << "int code, HwParcel request, final HwParcel reply, "
463 << "int flags) {\n";
464
465 out.indent();
466
467 out << "switch (code) {\n";
468
469 out.indent();
470
471 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
472 const Interface *superInterface = *it;
473
474 for (const auto &method : superInterface->methods()) {
475 const bool returnsValue = !method->results().empty();
476 const bool needsCallback = method->results().size() > 1;
477
478 out << "case "
479 << superInterface->fullJavaName()
480 << ".kOp_"
481 <<
482 upcase(method->name())
483 << ":\n{\n";
484
485 out.indent();
486
487 out << "request.enforceInterface("
488 << superInterface->fullJavaName()
489 << ".kInterfaceName);\n\n";
490
491 for (const auto &arg : method->args()) {
492 emitJavaReaderWriter(
493 out,
494 "request",
495 arg,
496 true /* isReader */);
497 }
498
499 if (!needsCallback && returnsValue) {
500 const TypedVar *returnArg = method->results()[0];
501
502 out << returnArg->type().getJavaType()
503 << " "
504 << returnArg->name()
505 << " = ";
506 }
507
508 out << method->name()
509 << "(";
510
511 bool firstField = true;
512 for (const auto &arg : method->args()) {
513 if (!firstField) {
514 out << ", ";
515 }
516
517 out << arg->name();
518
519 firstField = false;
520 }
521
522 if (needsCallback) {
523 if (!firstField) {
524 out << ", ";
525 }
526
527 out << "new " << method->name() << "Callback() {\n";
528 out.indent();
529
530 out << "@Override\n"
531 << "public void onValues("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700532 << Method::GetJavaArgSignature(method->results())
Andreas Huber2831d512016-08-15 09:33:47 -0700533 << ") {\n";
534
535 out.indent();
536 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
537
538 for (const auto &arg : method->results()) {
539 emitJavaReaderWriter(
540 out,
541 "reply",
542 arg,
543 false /* isReader */);
544 }
545
546 out << "reply.send();\n"
547 << "}}";
548
549 out.unindent();
550 out.unindent();
551 }
552
553 out << ");\n";
554
555 if (!needsCallback) {
556 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
557
558 if (returnsValue) {
559 const TypedVar *returnArg = method->results()[0];
560
561 emitJavaReaderWriter(
562 out,
563 "reply",
564 returnArg,
565 false /* isReader */);
566 }
567
568 out << "reply.send();\n";
569 }
570
571 out << "break;\n";
572 out.unindent();
573 out << "}\n\n";
574 }
575 }
576
577 out.unindent();
578 out << "}\n";
579
580 out.unindent();
581 out << "}\n";
582
583 out.unindent();
584 out << "}\n";
585
586 out.unindent();
587 out << "}\n";
588
589 return OK;
590}
591
592status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700593 return mRootScope->emitJavaTypeDeclarations(out, false /* atTopLevel */);
Andreas Huber2831d512016-08-15 09:33:47 -0700594}
595
596} // namespace android
597