blob: a5bdce662b6a56af9aca31df8db8ea5195e70e18 [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
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700122 const std::string baseName = iface->getBaseName();
Andreas Huber2831d512016-08-15 09:33:47 -0700123
124 std::string path = outputPath;
125 path.append(mCoordinator->convertPackageRootToPath(mPackage));
126 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
127 path.append(ifaceName);
128 path.append(".java");
129
130 CHECK(Coordinator::MakeParentHierarchy(path));
131 FILE *file = fopen(path.c_str(), "w");
132
133 if (file == NULL) {
134 return -errno;
135 }
136
137 Formatter out(file);
138
139 std::vector<std::string> packageComponents;
140 getPackageAndVersionComponents(
141 &packageComponents, true /* cpp_compatible */);
142
143 out << "package " << mPackage.javaPackage() << ";\n\n";
144
145 out << "import android.os.IHwBinder;\n";
146 out << "import android.os.IHwInterface;\n";
147 out << "import android.os.HwBinder;\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700148 out << "import android.os.HwBlob;\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700149 out << "import android.os.HwParcel;\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700150
151 out << "import java.util.Arrays;\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700152 out << "import java.util.Vector;\n\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700153
Andreas Huber85eabdb2016-08-25 11:24:49 -0700154 for (const auto &item : mImportedNamesForJava) {
Andreas Huber2831d512016-08-15 09:33:47 -0700155 out << "import " << item.javaName() << ";\n";
156 }
157
Andreas Huber85eabdb2016-08-25 11:24:49 -0700158 if (!mImportedNamesForJava.empty()) {
Andreas Huber2831d512016-08-15 09:33:47 -0700159 out << "\n";
160 }
161
162 out.setNamespace(mPackage.javaPackage() + ".");
163
Andreas Huber2831d512016-08-15 09:33:47 -0700164 const Interface *superType = iface->superType();
165
166 out << "public interface " << ifaceName << " extends ";
167
168 if (superType != NULL) {
169 out << superType->fullJavaName();
170 } else {
171 out << "IHwInterface";
172 }
173
174 out << " {\n";
175 out.indent();
176
177 out << "public static final String kInterfaceName = \""
178 << mPackage.string()
179 << "::"
180 << ifaceName
181 << "\";\n\n";
182
183 out << "public static "
184 << ifaceName
185 << " asInterface(IHwBinder binder) {\n";
186
187 out.indent();
188
189 out << "if (binder == null) {\n";
190 out.indent();
191 out << "return null;\n";
192 out.unindent();
193 out << "}\n\n";
194
195 out << "IHwInterface iface =\n";
196 out.indent();
197 out.indent();
198 out << "binder.queryLocalInterface(kInterfaceName);\n\n";
199 out.unindent();
200 out.unindent();
201
202 out << "if ((iface != null) && (iface instanceof "
203 << ifaceName
204 << ")) {\n";
205
206 out.indent();
207 out << "return (" << ifaceName << ")iface;\n";
208 out.unindent();
209 out << "}\n\n";
210
211 out << "return new " << ifaceName << ".Proxy(binder);\n";
212
213 out.unindent();
214 out << "}\n\n";
215
216 out << "public IHwBinder asBinder();\n\n";
217
218 status_t err = emitJavaTypeDeclarations(out);
219
220 if (err != OK) {
221 return err;
222 }
223
224 const std::string base = (superType != NULL)
225 ? (superType->fullJavaName() + ".kOpEnd")
226 : "IHwBinder.FIRST_CALL_TRANSACTION";
227
228 bool first = true;
229 size_t index = 0;
230 for (const auto &method : iface->methods()) {
231 out << "public static final int kOp_"
Steven Morelandaf440142016-09-07 10:09:11 -0700232 << StringHelper::Upcase(method->name())
Andreas Huber2831d512016-08-15 09:33:47 -0700233 << " = "
234 << base;
235
236 if (!first) {
237 out << " + " << index;
238 }
239
240 out << ";\n";
241
242 ++index;
243 first = false;
244 }
245
246 out << "public static final int kOpEnd = "
247 << base
248 << " + "
249 << index
250 << ";";
251
252 out << "\n\n";
253
254 for (const auto &method : iface->methods()) {
255 const bool returnsValue = !method->results().empty();
256 const bool needsCallback = method->results().size() > 1;
257
258 if (needsCallback) {
259 out << "\npublic abstract class "
260 << method->name()
261 << "Callback {\n";
262
263 out.indent();
264
265 out << "public abstract void onValues("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700266 << Method::GetJavaArgSignature(method->results())
Andreas Huber2831d512016-08-15 09:33:47 -0700267 << ");\n";
268
269 out.unindent();
270 out << "}\n\n";
271 }
272
273 if (returnsValue && !needsCallback) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700274 std::string extra;
275 out << method->results()[0]->type().getJavaType(&extra)
276 << extra;
Andreas Huber2831d512016-08-15 09:33:47 -0700277 } else {
278 out << "void";
279 }
280
281 out << " "
282 << method->name()
283 << "("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700284 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700285
286 if (needsCallback) {
287 if (!method->args().empty()) {
288 out << ", ";
289 }
290
291 out << method->name()
292 << "Callback cb";
293 }
294
295 out << ");\n";
296 }
297
298 out << "\npublic static final class Proxy implements "
299 << ifaceName
300 << " {\n";
301
302 out.indent();
303
304 out << "private IHwBinder mRemote;\n\n";
305 out << "public Proxy(IHwBinder remote) {\n";
306 out.indent();
307 out << "mRemote = remote;\n";
308 out.unindent();
309 out << "}\n\n";
310
311 out << "public IHwBinder asBinder() {\n";
312 out.indent();
313 out << "return mRemote;\n";
314 out.unindent();
315 out << "}\n\n";
316
317 std::vector<const Interface *> chain;
318 while (iface != NULL) {
319 chain.push_back(iface);
320 iface = iface->superType();
321 }
322
323 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
324 const Interface *superInterface = *it;
325
326 out << "// Methods from "
327 << superInterface->fullName()
328 << " follow.\n";
329
330 for (const auto &method : superInterface->methods()) {
331 const bool returnsValue = !method->results().empty();
332 const bool needsCallback = method->results().size() > 1;
333
334 out << "public ";
335 if (returnsValue && !needsCallback) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700336 std::string extra;
337 out << method->results()[0]->type().getJavaType(&extra)
338 << extra;
Andreas Huber2831d512016-08-15 09:33:47 -0700339 } else {
340 out << "void";
341 }
342
343 out << " "
344 << method->name()
345 << "("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700346 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700347
348 if (needsCallback) {
349 if (!method->args().empty()) {
350 out << ", ";
351 }
352
353 out << method->name()
354 << "Callback cb";
355 }
356
357 out << ") {\n";
358 out.indent();
359
360 out << "HwParcel request = new HwParcel();\n";
361 out << "request.writeInterfaceToken("
362 << superInterface->fullJavaName()
363 << ".kInterfaceName);\n";
364
365 for (const auto &arg : method->args()) {
366 emitJavaReaderWriter(
367 out,
368 "request",
369 arg,
370 false /* isReader */);
371 }
372
373 out << "\nHwParcel reply = new HwParcel();\n"
Andreas Huber8b5da222016-08-18 14:28:18 -0700374 << "mRemote.transact(kOp_"
Steven Morelandaf440142016-09-07 10:09:11 -0700375 << StringHelper::Upcase(method->name())
Andreas Huber8b5da222016-08-18 14:28:18 -0700376 << ", request, reply, ";
377
378 if (method->isOneway()) {
379 out << "IHwBinder.FLAG_ONEWAY";
380 } else {
381 out << "0 /* flags */";
382 }
383
384 out << ");\n";
385
386 if (!method->isOneway()) {
387 out << "reply.verifySuccess();\n";
388 } else {
389 CHECK(!returnsValue);
390 }
391
392 out << "request.releaseTemporaryStorage();\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700393
394 if (returnsValue) {
395 out << "\n";
396
397 for (const auto &arg : method->results()) {
398 emitJavaReaderWriter(
399 out,
400 "reply",
401 arg,
402 true /* isReader */);
403 }
404
405 if (needsCallback) {
406 out << "cb.onValues(";
407
408 bool firstField = true;
409 for (const auto &arg : method->results()) {
410 if (!firstField) {
411 out << ", ";
412 }
413
414 out << arg->name();
415 firstField = false;
416 }
417
418 out << ");\n";
419 } else {
420 const std::string returnName = method->results()[0]->name();
421 out << "return " << returnName << ";\n";
422 }
423 }
424
425 out.unindent();
426 out << "}\n\n";
427 }
428 }
429
430 out.unindent();
431 out << "}\n";
432
433 ////////////////////////////////////////////////////////////////////////////
434
435 out << "\npublic static abstract class Stub extends HwBinder "
436 << "implements "
437 << ifaceName << " {\n";
438
439 out.indent();
440
441 out << "public IHwBinder asBinder() {\n";
442 out.indent();
443 out << "return this;\n";
444 out.unindent();
445 out << "}\n\n";
446
447 out << "public IHwInterface queryLocalInterface(String descriptor) {\n";
448 out.indent();
449 // XXX what about potential superClasses?
450 out << "if (kInterfaceName.equals(descriptor)) {\n";
451 out.indent();
452 out << "return this;\n";
453 out.unindent();
454 out << "}\n";
455 out << "return null;\n";
456 out.unindent();
457 out << "}\n\n";
458
459 out << "public void onTransact("
460 << "int code, HwParcel request, final HwParcel reply, "
461 << "int flags) {\n";
462
463 out.indent();
464
465 out << "switch (code) {\n";
466
467 out.indent();
468
469 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
470 const Interface *superInterface = *it;
471
472 for (const auto &method : superInterface->methods()) {
473 const bool returnsValue = !method->results().empty();
474 const bool needsCallback = method->results().size() > 1;
475
476 out << "case "
477 << superInterface->fullJavaName()
478 << ".kOp_"
479 <<
Steven Morelandaf440142016-09-07 10:09:11 -0700480 StringHelper::Upcase(method->name())
Andreas Huber2831d512016-08-15 09:33:47 -0700481 << ":\n{\n";
482
483 out.indent();
484
485 out << "request.enforceInterface("
486 << superInterface->fullJavaName()
487 << ".kInterfaceName);\n\n";
488
489 for (const auto &arg : method->args()) {
490 emitJavaReaderWriter(
491 out,
492 "request",
493 arg,
494 true /* isReader */);
495 }
496
497 if (!needsCallback && returnsValue) {
498 const TypedVar *returnArg = method->results()[0];
Andreas Huber4c865b72016-09-14 15:26:27 -0700499 std::string extra;
Andreas Huber2831d512016-08-15 09:33:47 -0700500
Andreas Huber4c865b72016-09-14 15:26:27 -0700501 out << returnArg->type().getJavaType(&extra)
502 << extra
Andreas Huber2831d512016-08-15 09:33:47 -0700503 << " "
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