blob: e9958b6e30a59575a87764e38e3b6fc7fa9e72f0 [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 Huberf1abc2a2016-09-28 09:14:43 -070087 out << "import java.util.ArrayList;\n\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -070088
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 Huberf03332a2016-09-22 15:35:43 -0700110 " does NOT support union types nor native handles. "
111 "In addition, vectors of arrays are limited to at most "
112 "one-dimensional arrays.\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
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700124 const std::string baseName = iface->getBaseName();
Andreas Huber2831d512016-08-15 09:33:47 -0700125
126 std::string path = outputPath;
127 path.append(mCoordinator->convertPackageRootToPath(mPackage));
128 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
129 path.append(ifaceName);
130 path.append(".java");
131
132 CHECK(Coordinator::MakeParentHierarchy(path));
133 FILE *file = fopen(path.c_str(), "w");
134
135 if (file == NULL) {
136 return -errno;
137 }
138
139 Formatter out(file);
140
141 std::vector<std::string> packageComponents;
142 getPackageAndVersionComponents(
143 &packageComponents, true /* cpp_compatible */);
144
145 out << "package " << mPackage.javaPackage() << ";\n\n";
146
147 out << "import android.os.IHwBinder;\n";
148 out << "import android.os.IHwInterface;\n";
149 out << "import android.os.HwBinder;\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700150 out << "import android.os.HwBlob;\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700151 out << "import android.os.HwParcel;\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700152
153 out << "import java.util.Arrays;\n";
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700154 out << "import java.util.ArrayList;\n\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700155
Andreas Huber85eabdb2016-08-25 11:24:49 -0700156 for (const auto &item : mImportedNamesForJava) {
Andreas Huber2831d512016-08-15 09:33:47 -0700157 out << "import " << item.javaName() << ";\n";
158 }
159
Andreas Huber85eabdb2016-08-25 11:24:49 -0700160 if (!mImportedNamesForJava.empty()) {
Andreas Huber2831d512016-08-15 09:33:47 -0700161 out << "\n";
162 }
163
164 out.setNamespace(mPackage.javaPackage() + ".");
165
Andreas Huber2831d512016-08-15 09:33:47 -0700166 const Interface *superType = iface->superType();
167
168 out << "public interface " << ifaceName << " extends ";
169
170 if (superType != NULL) {
171 out << superType->fullJavaName();
172 } else {
173 out << "IHwInterface";
174 }
175
176 out << " {\n";
177 out.indent();
178
179 out << "public static final String kInterfaceName = \""
180 << mPackage.string()
181 << "::"
182 << ifaceName
183 << "\";\n\n";
184
185 out << "public static "
186 << ifaceName
187 << " asInterface(IHwBinder binder) {\n";
188
189 out.indent();
190
191 out << "if (binder == null) {\n";
192 out.indent();
193 out << "return null;\n";
194 out.unindent();
195 out << "}\n\n";
196
197 out << "IHwInterface iface =\n";
198 out.indent();
199 out.indent();
200 out << "binder.queryLocalInterface(kInterfaceName);\n\n";
201 out.unindent();
202 out.unindent();
203
204 out << "if ((iface != null) && (iface instanceof "
205 << ifaceName
206 << ")) {\n";
207
208 out.indent();
209 out << "return (" << ifaceName << ")iface;\n";
210 out.unindent();
211 out << "}\n\n";
212
213 out << "return new " << ifaceName << ".Proxy(binder);\n";
214
215 out.unindent();
216 out << "}\n\n";
217
218 out << "public IHwBinder asBinder();\n\n";
219
220 status_t err = emitJavaTypeDeclarations(out);
221
222 if (err != OK) {
223 return err;
224 }
225
226 const std::string base = (superType != NULL)
227 ? (superType->fullJavaName() + ".kOpEnd")
228 : "IHwBinder.FIRST_CALL_TRANSACTION";
229
230 bool first = true;
231 size_t index = 0;
232 for (const auto &method : iface->methods()) {
233 out << "public static final int kOp_"
Yifan Hong42009032016-09-29 09:38:15 -0700234 << StringHelper::Uppercase(method->name())
Andreas Huber2831d512016-08-15 09:33:47 -0700235 << " = "
236 << base;
237
238 if (!first) {
239 out << " + " << index;
240 }
241
242 out << ";\n";
243
244 ++index;
245 first = false;
246 }
247
248 out << "public static final int kOpEnd = "
249 << base
250 << " + "
251 << index
252 << ";";
253
254 out << "\n\n";
255
256 for (const auto &method : iface->methods()) {
257 const bool returnsValue = !method->results().empty();
258 const bool needsCallback = method->results().size() > 1;
259
260 if (needsCallback) {
261 out << "\npublic abstract class "
262 << method->name()
263 << "Callback {\n";
264
265 out.indent();
266
267 out << "public abstract void onValues("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700268 << Method::GetJavaArgSignature(method->results())
Andreas Huber2831d512016-08-15 09:33:47 -0700269 << ");\n";
270
271 out.unindent();
272 out << "}\n\n";
273 }
274
275 if (returnsValue && !needsCallback) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700276 std::string extra;
277 out << method->results()[0]->type().getJavaType(&extra)
278 << extra;
Andreas Huber2831d512016-08-15 09:33:47 -0700279 } else {
280 out << "void";
281 }
282
283 out << " "
284 << method->name()
285 << "("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700286 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700287
288 if (needsCallback) {
289 if (!method->args().empty()) {
290 out << ", ";
291 }
292
293 out << method->name()
294 << "Callback cb";
295 }
296
297 out << ");\n";
298 }
299
300 out << "\npublic static final class Proxy implements "
301 << ifaceName
302 << " {\n";
303
304 out.indent();
305
306 out << "private IHwBinder mRemote;\n\n";
307 out << "public Proxy(IHwBinder remote) {\n";
308 out.indent();
309 out << "mRemote = remote;\n";
310 out.unindent();
311 out << "}\n\n";
312
313 out << "public IHwBinder asBinder() {\n";
314 out.indent();
315 out << "return mRemote;\n";
316 out.unindent();
317 out << "}\n\n";
318
319 std::vector<const Interface *> chain;
320 while (iface != NULL) {
321 chain.push_back(iface);
322 iface = iface->superType();
323 }
324
325 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
326 const Interface *superInterface = *it;
327
328 out << "// Methods from "
329 << superInterface->fullName()
330 << " follow.\n";
331
332 for (const auto &method : superInterface->methods()) {
333 const bool returnsValue = !method->results().empty();
334 const bool needsCallback = method->results().size() > 1;
335
336 out << "public ";
337 if (returnsValue && !needsCallback) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700338 std::string extra;
339 out << method->results()[0]->type().getJavaType(&extra)
340 << extra;
Andreas Huber2831d512016-08-15 09:33:47 -0700341 } 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_"
Yifan Hong42009032016-09-29 09:38:15 -0700377 << StringHelper::Uppercase(method->name())
Andreas Huber8b5da222016-08-18 14:28:18 -0700378 << ", 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 <<
Yifan Hong42009032016-09-29 09:38:15 -0700482 StringHelper::Uppercase(method->name())
Andreas Huber2831d512016-08-15 09:33:47 -0700483 << ":\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];
Andreas Huber4c865b72016-09-14 15:26:27 -0700501 std::string extra;
Andreas Huber2831d512016-08-15 09:33:47 -0700502
Andreas Huber4c865b72016-09-14 15:26:27 -0700503 out << returnArg->type().getJavaType(&extra)
504 << extra
Andreas Huber2831d512016-08-15 09:33:47 -0700505 << " "
506 << returnArg->name()
507 << " = ";
508 }
509
510 out << method->name()
511 << "(";
512
513 bool firstField = true;
514 for (const auto &arg : method->args()) {
515 if (!firstField) {
516 out << ", ";
517 }
518
519 out << arg->name();
520
521 firstField = false;
522 }
523
524 if (needsCallback) {
525 if (!firstField) {
526 out << ", ";
527 }
528
529 out << "new " << method->name() << "Callback() {\n";
530 out.indent();
531
532 out << "@Override\n"
533 << "public void onValues("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700534 << Method::GetJavaArgSignature(method->results())
Andreas Huber2831d512016-08-15 09:33:47 -0700535 << ") {\n";
536
537 out.indent();
538 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
539
540 for (const auto &arg : method->results()) {
541 emitJavaReaderWriter(
542 out,
543 "reply",
544 arg,
545 false /* isReader */);
546 }
547
548 out << "reply.send();\n"
549 << "}}";
550
551 out.unindent();
552 out.unindent();
553 }
554
555 out << ");\n";
556
557 if (!needsCallback) {
558 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
559
560 if (returnsValue) {
561 const TypedVar *returnArg = method->results()[0];
562
563 emitJavaReaderWriter(
564 out,
565 "reply",
566 returnArg,
567 false /* isReader */);
568 }
569
570 out << "reply.send();\n";
571 }
572
573 out << "break;\n";
574 out.unindent();
575 out << "}\n\n";
576 }
577 }
578
579 out.unindent();
580 out << "}\n";
581
582 out.unindent();
583 out << "}\n";
584
585 out.unindent();
586 out << "}\n";
587
588 out.unindent();
589 out << "}\n";
590
591 return OK;
592}
593
594status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700595 return mRootScope->emitJavaTypeDeclarations(out, false /* atTopLevel */);
Andreas Huber2831d512016-08-15 09:33:47 -0700596}
597
598} // namespace android
599