blob: df239a2a8e67f1aa5d484c930e654a0f9e9f91f1 [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"
Andreas Huber2831d512016-08-15 09:33:47 -070020#include "Interface.h"
21#include "Method.h"
22#include "Scope.h"
23
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070024#include <hidl-util/StringHelper.h>
25#include <hidl-util/Formatter.h>
Andreas Huber2831d512016-08-15 09:33:47 -070026#include <android-base/logging.h>
27
28namespace android {
29
Andreas Huber2831d512016-08-15 09:33:47 -070030void AST::emitJavaReaderWriter(
31 Formatter &out,
32 const std::string &parcelObj,
33 const TypedVar *arg,
34 bool isReader) const {
35 if (isReader) {
Andreas Huber4c865b72016-09-14 15:26:27 -070036 std::string extra;
37 out << arg->type().getJavaType(&extra)
38 << extra
Andreas Huber2831d512016-08-15 09:33:47 -070039 << " "
40 << arg->name()
41 << " = ";
42 }
43
44 arg->type().emitJavaReaderWriter(out, parcelObj, arg->name(), isReader);
45}
46
Andreas Huber0fa9e392016-08-31 09:05:44 -070047status_t AST::generateJavaTypes(
Andreas Huberd29724f2016-09-14 09:33:13 -070048 const std::string &outputPath, const std::string &limitToType) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -070049 // Splits types.hal up into one java file per declared type.
50
Steven Morelandd537ab02016-09-12 10:32:01 -070051 for (const auto &type : mRootScope->getSubTypes()) {
52 std::string typeName = type->localName();
Andreas Huber85eabdb2016-08-25 11:24:49 -070053
54 if (type->isTypeDef()) {
55 continue;
56 }
57
Andreas Huberd29724f2016-09-14 09:33:13 -070058 if (!limitToType.empty() && typeName != limitToType) {
Andreas Huber0fa9e392016-08-31 09:05:44 -070059 continue;
60 }
61
Andreas Huber85eabdb2016-08-25 11:24:49 -070062 std::string path = outputPath;
63 path.append(mCoordinator->convertPackageRootToPath(mPackage));
64 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
65 path.append(typeName);
66 path.append(".java");
67
68 CHECK(Coordinator::MakeParentHierarchy(path));
69 FILE *file = fopen(path.c_str(), "w");
70
71 if (file == NULL) {
72 return -errno;
73 }
74
75 Formatter out(file);
76
77 std::vector<std::string> packageComponents;
78 getPackageAndVersionComponents(
79 &packageComponents, true /* cpp_compatible */);
80
81 out << "package " << mPackage.javaPackage() << ";\n\n";
82
83 out << "import android.os.HwBlob;\n";
84 out << "import android.os.HwParcel;\n\n";
85
Andreas Huberf630bc82016-09-09 14:52:25 -070086 out << "import java.util.Arrays;\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -070087 out << "import java.util.Vector;\n\n";
88
Iliyan Malchev800273d2016-09-02 15:25:07 -070089 for (const auto &item : mImportedNamesForJava) {
90 out << "import " << item.javaName() << ";\n";
91 }
92 out << "\n";
93
Andreas Huber85eabdb2016-08-25 11:24:49 -070094 status_t err =
95 type->emitJavaTypeDeclarations(out, true /* atTopLevel */);
96
97 if (err != OK) {
98 return err;
99 }
100 }
101
102 return OK;
103}
104
Andreas Huber0fa9e392016-08-31 09:05:44 -0700105status_t AST::generateJava(
Andreas Huberd29724f2016-09-14 09:33:13 -0700106 const std::string &outputPath, const std::string &limitToType) const {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700107 if (!isJavaCompatible()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700108 fprintf(stderr,
109 "ERROR: This interface is not Java compatible. The Java backend"
Andreas Huber85eabdb2016-08-25 11:24:49 -0700110 " does NOT support union types or native handles.\n");
Andreas Huber70a59e12016-08-16 12:57:01 -0700111
Andreas Huber2831d512016-08-15 09:33:47 -0700112 return UNKNOWN_ERROR;
113 }
114
Andreas Huber0fa9e392016-08-31 09:05:44 -0700115 std::string ifaceName;
116 if (!AST::isInterface(&ifaceName)) {
117 return generateJavaTypes(outputPath, limitToType);
118 }
119
120 const Interface *iface = mRootScope->getInterface();
121
Andreas Huber2831d512016-08-15 09:33:47 -0700122 // cut off the leading 'I'.
123 const std::string baseName = ifaceName.substr(1);
124
125 std::string path = outputPath;
126 path.append(mCoordinator->convertPackageRootToPath(mPackage));
127 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
128 path.append(ifaceName);
129 path.append(".java");
130
131 CHECK(Coordinator::MakeParentHierarchy(path));
132 FILE *file = fopen(path.c_str(), "w");
133
134 if (file == NULL) {
135 return -errno;
136 }
137
138 Formatter out(file);
139
140 std::vector<std::string> packageComponents;
141 getPackageAndVersionComponents(
142 &packageComponents, true /* cpp_compatible */);
143
144 out << "package " << mPackage.javaPackage() << ";\n\n";
145
146 out << "import android.os.IHwBinder;\n";
147 out << "import android.os.IHwInterface;\n";
148 out << "import android.os.HwBinder;\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700149 out << "import android.os.HwBlob;\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700150 out << "import android.os.HwParcel;\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700151
152 out << "import java.util.Arrays;\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_"
Steven Morelandaf440142016-09-07 10:09:11 -0700233 << StringHelper::Upcase(method->name())
Andreas Huber2831d512016-08-15 09:33:47 -0700234 << " = "
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("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700267 << Method::GetJavaArgSignature(method->results())
Andreas Huber2831d512016-08-15 09:33:47 -0700268 << ");\n";
269
270 out.unindent();
271 out << "}\n\n";
272 }
273
274 if (returnsValue && !needsCallback) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700275 std::string extra;
276 out << method->results()[0]->type().getJavaType(&extra)
277 << extra;
Andreas Huber2831d512016-08-15 09:33:47 -0700278 } else {
279 out << "void";
280 }
281
282 out << " "
283 << method->name()
284 << "("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700285 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700286
287 if (needsCallback) {
288 if (!method->args().empty()) {
289 out << ", ";
290 }
291
292 out << method->name()
293 << "Callback cb";
294 }
295
296 out << ");\n";
297 }
298
299 out << "\npublic static final class Proxy implements "
300 << ifaceName
301 << " {\n";
302
303 out.indent();
304
305 out << "private IHwBinder mRemote;\n\n";
306 out << "public Proxy(IHwBinder remote) {\n";
307 out.indent();
308 out << "mRemote = remote;\n";
309 out.unindent();
310 out << "}\n\n";
311
312 out << "public IHwBinder asBinder() {\n";
313 out.indent();
314 out << "return mRemote;\n";
315 out.unindent();
316 out << "}\n\n";
317
318 std::vector<const Interface *> chain;
319 while (iface != NULL) {
320 chain.push_back(iface);
321 iface = iface->superType();
322 }
323
324 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
325 const Interface *superInterface = *it;
326
327 out << "// Methods from "
328 << superInterface->fullName()
329 << " follow.\n";
330
331 for (const auto &method : superInterface->methods()) {
332 const bool returnsValue = !method->results().empty();
333 const bool needsCallback = method->results().size() > 1;
334
335 out << "public ";
336 if (returnsValue && !needsCallback) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700337 std::string extra;
338 out << method->results()[0]->type().getJavaType(&extra)
339 << extra;
Andreas Huber2831d512016-08-15 09:33:47 -0700340 } else {
341 out << "void";
342 }
343
344 out << " "
345 << method->name()
346 << "("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700347 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700348
349 if (needsCallback) {
350 if (!method->args().empty()) {
351 out << ", ";
352 }
353
354 out << method->name()
355 << "Callback cb";
356 }
357
358 out << ") {\n";
359 out.indent();
360
361 out << "HwParcel request = new HwParcel();\n";
362 out << "request.writeInterfaceToken("
363 << superInterface->fullJavaName()
364 << ".kInterfaceName);\n";
365
366 for (const auto &arg : method->args()) {
367 emitJavaReaderWriter(
368 out,
369 "request",
370 arg,
371 false /* isReader */);
372 }
373
374 out << "\nHwParcel reply = new HwParcel();\n"
Andreas Huber8b5da222016-08-18 14:28:18 -0700375 << "mRemote.transact(kOp_"
Steven Morelandaf440142016-09-07 10:09:11 -0700376 << StringHelper::Upcase(method->name())
Andreas Huber8b5da222016-08-18 14:28:18 -0700377 << ", request, reply, ";
378
379 if (method->isOneway()) {
380 out << "IHwBinder.FLAG_ONEWAY";
381 } else {
382 out << "0 /* flags */";
383 }
384
385 out << ");\n";
386
387 if (!method->isOneway()) {
388 out << "reply.verifySuccess();\n";
389 } else {
390 CHECK(!returnsValue);
391 }
392
393 out << "request.releaseTemporaryStorage();\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700394
395 if (returnsValue) {
396 out << "\n";
397
398 for (const auto &arg : method->results()) {
399 emitJavaReaderWriter(
400 out,
401 "reply",
402 arg,
403 true /* isReader */);
404 }
405
406 if (needsCallback) {
407 out << "cb.onValues(";
408
409 bool firstField = true;
410 for (const auto &arg : method->results()) {
411 if (!firstField) {
412 out << ", ";
413 }
414
415 out << arg->name();
416 firstField = false;
417 }
418
419 out << ");\n";
420 } else {
421 const std::string returnName = method->results()[0]->name();
422 out << "return " << returnName << ";\n";
423 }
424 }
425
426 out.unindent();
427 out << "}\n\n";
428 }
429 }
430
431 out.unindent();
432 out << "}\n";
433
434 ////////////////////////////////////////////////////////////////////////////
435
436 out << "\npublic static abstract class Stub extends HwBinder "
437 << "implements "
438 << ifaceName << " {\n";
439
440 out.indent();
441
442 out << "public IHwBinder asBinder() {\n";
443 out.indent();
444 out << "return this;\n";
445 out.unindent();
446 out << "}\n\n";
447
448 out << "public IHwInterface queryLocalInterface(String descriptor) {\n";
449 out.indent();
450 // XXX what about potential superClasses?
451 out << "if (kInterfaceName.equals(descriptor)) {\n";
452 out.indent();
453 out << "return this;\n";
454 out.unindent();
455 out << "}\n";
456 out << "return null;\n";
457 out.unindent();
458 out << "}\n\n";
459
460 out << "public void onTransact("
461 << "int code, HwParcel request, final HwParcel reply, "
462 << "int flags) {\n";
463
464 out.indent();
465
466 out << "switch (code) {\n";
467
468 out.indent();
469
470 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
471 const Interface *superInterface = *it;
472
473 for (const auto &method : superInterface->methods()) {
474 const bool returnsValue = !method->results().empty();
475 const bool needsCallback = method->results().size() > 1;
476
477 out << "case "
478 << superInterface->fullJavaName()
479 << ".kOp_"
480 <<
Steven Morelandaf440142016-09-07 10:09:11 -0700481 StringHelper::Upcase(method->name())
Andreas Huber2831d512016-08-15 09:33:47 -0700482 << ":\n{\n";
483
484 out.indent();
485
486 out << "request.enforceInterface("
487 << superInterface->fullJavaName()
488 << ".kInterfaceName);\n\n";
489
490 for (const auto &arg : method->args()) {
491 emitJavaReaderWriter(
492 out,
493 "request",
494 arg,
495 true /* isReader */);
496 }
497
498 if (!needsCallback && returnsValue) {
499 const TypedVar *returnArg = method->results()[0];
Andreas Huber4c865b72016-09-14 15:26:27 -0700500 std::string extra;
Andreas Huber2831d512016-08-15 09:33:47 -0700501
Andreas Huber4c865b72016-09-14 15:26:27 -0700502 out << returnArg->type().getJavaType(&extra)
503 << extra
Andreas Huber2831d512016-08-15 09:33:47 -0700504 << " "
505 << returnArg->name()
506 << " = ";
507 }
508
509 out << method->name()
510 << "(";
511
512 bool firstField = true;
513 for (const auto &arg : method->args()) {
514 if (!firstField) {
515 out << ", ";
516 }
517
518 out << arg->name();
519
520 firstField = false;
521 }
522
523 if (needsCallback) {
524 if (!firstField) {
525 out << ", ";
526 }
527
528 out << "new " << method->name() << "Callback() {\n";
529 out.indent();
530
531 out << "@Override\n"
532 << "public void onValues("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700533 << Method::GetJavaArgSignature(method->results())
Andreas Huber2831d512016-08-15 09:33:47 -0700534 << ") {\n";
535
536 out.indent();
537 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
538
539 for (const auto &arg : method->results()) {
540 emitJavaReaderWriter(
541 out,
542 "reply",
543 arg,
544 false /* isReader */);
545 }
546
547 out << "reply.send();\n"
548 << "}}";
549
550 out.unindent();
551 out.unindent();
552 }
553
554 out << ");\n";
555
556 if (!needsCallback) {
557 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
558
559 if (returnsValue) {
560 const TypedVar *returnArg = method->results()[0];
561
562 emitJavaReaderWriter(
563 out,
564 "reply",
565 returnArg,
566 false /* isReader */);
567 }
568
569 out << "reply.send();\n";
570 }
571
572 out << "break;\n";
573 out.unindent();
574 out << "}\n\n";
575 }
576 }
577
578 out.unindent();
579 out << "}\n";
580
581 out.unindent();
582 out << "}\n";
583
584 out.unindent();
585 out << "}\n";
586
587 out.unindent();
588 out << "}\n";
589
590 return OK;
591}
592
593status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700594 return mRootScope->emitJavaTypeDeclarations(out, false /* atTopLevel */);
Andreas Huber2831d512016-08-15 09:33:47 -0700595}
596
597} // namespace android
598