blob: 63643e17eb6229185d6312cd3977fa822c5fa674 [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/Formatter.h>
Andreas Huber2831d512016-08-15 09:33:47 -070025#include <android-base/logging.h>
26
27namespace android {
28
Andreas Huber2831d512016-08-15 09:33:47 -070029void AST::emitJavaReaderWriter(
30 Formatter &out,
31 const std::string &parcelObj,
32 const TypedVar *arg,
33 bool isReader) const {
34 if (isReader) {
Andreas Huber4c865b72016-09-14 15:26:27 -070035 std::string extra;
36 out << arg->type().getJavaType(&extra)
37 << extra
Andreas Huber2831d512016-08-15 09:33:47 -070038 << " "
39 << arg->name()
40 << " = ";
41 }
42
43 arg->type().emitJavaReaderWriter(out, parcelObj, arg->name(), isReader);
44}
45
Andreas Huber0fa9e392016-08-31 09:05:44 -070046status_t AST::generateJavaTypes(
Andreas Huberd29724f2016-09-14 09:33:13 -070047 const std::string &outputPath, const std::string &limitToType) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -070048 // Splits types.hal up into one java file per declared type.
49
Steven Morelandd537ab02016-09-12 10:32:01 -070050 for (const auto &type : mRootScope->getSubTypes()) {
51 std::string typeName = type->localName();
Andreas Huber85eabdb2016-08-25 11:24:49 -070052
53 if (type->isTypeDef()) {
54 continue;
55 }
56
Andreas Huberd29724f2016-09-14 09:33:13 -070057 if (!limitToType.empty() && typeName != limitToType) {
Andreas Huber0fa9e392016-08-31 09:05:44 -070058 continue;
59 }
60
Andreas Huber85eabdb2016-08-25 11:24:49 -070061 std::string path = outputPath;
62 path.append(mCoordinator->convertPackageRootToPath(mPackage));
63 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
64 path.append(typeName);
65 path.append(".java");
66
67 CHECK(Coordinator::MakeParentHierarchy(path));
68 FILE *file = fopen(path.c_str(), "w");
69
70 if (file == NULL) {
71 return -errno;
72 }
73
74 Formatter out(file);
75
76 std::vector<std::string> packageComponents;
77 getPackageAndVersionComponents(
78 &packageComponents, true /* cpp_compatible */);
79
80 out << "package " << mPackage.javaPackage() << ";\n\n";
81
82 out << "import android.os.HwBlob;\n";
83 out << "import android.os.HwParcel;\n\n";
84
Andreas Huberf630bc82016-09-09 14:52:25 -070085 out << "import java.util.Arrays;\n";
Andreas Huberf1abc2a2016-09-28 09:14:43 -070086 out << "import java.util.ArrayList;\n\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -070087
Iliyan Malchev800273d2016-09-02 15:25:07 -070088 for (const auto &item : mImportedNamesForJava) {
89 out << "import " << item.javaName() << ";\n";
90 }
91 out << "\n";
92
Andreas Huber85eabdb2016-08-25 11:24:49 -070093 status_t err =
94 type->emitJavaTypeDeclarations(out, true /* atTopLevel */);
95
96 if (err != OK) {
97 return err;
98 }
99 }
100
101 return OK;
102}
103
Andreas Huber0fa9e392016-08-31 09:05:44 -0700104status_t AST::generateJava(
Andreas Huberd29724f2016-09-14 09:33:13 -0700105 const std::string &outputPath, const std::string &limitToType) const {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700106 if (!isJavaCompatible()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700107 fprintf(stderr,
108 "ERROR: This interface is not Java compatible. The Java backend"
Andreas Huberf03332a2016-09-22 15:35:43 -0700109 " does NOT support union types nor native handles. "
110 "In addition, vectors of arrays are limited to at most "
Andreas Huber86a112b2016-10-19 14:25:16 -0700111 "one-dimensional arrays and vectors of {vectors,interfaces} are"
112 " not supported.\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
Andreas Huber2bb6e1e2016-10-25 13:26:43 -0700220 out << "public static "
221 << ifaceName
222 << " getService(String serviceName) {\n";
223
224 out.indent();
225
226 out << "return "
227 << ifaceName
228 << ".asInterface(HwBinder.getService(serviceName, "
229 << mPackage.getPackageMajorVersion()
230 << ", "
231 << mPackage.getPackageMinorVersion()
232 << "));\n";
233
234 out.unindent();
235
236 out << "}\n\n";
237
Andreas Huber2831d512016-08-15 09:33:47 -0700238 status_t err = emitJavaTypeDeclarations(out);
239
240 if (err != OK) {
241 return err;
242 }
243
Andreas Huber2831d512016-08-15 09:33:47 -0700244 for (const auto &method : iface->methods()) {
245 const bool returnsValue = !method->results().empty();
246 const bool needsCallback = method->results().size() > 1;
247
248 if (needsCallback) {
249 out << "\npublic abstract class "
250 << method->name()
251 << "Callback {\n";
252
253 out.indent();
254
255 out << "public abstract void onValues("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700256 << Method::GetJavaArgSignature(method->results())
Andreas Huber2831d512016-08-15 09:33:47 -0700257 << ");\n";
258
259 out.unindent();
260 out << "}\n\n";
261 }
262
263 if (returnsValue && !needsCallback) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700264 std::string extra;
265 out << method->results()[0]->type().getJavaType(&extra)
266 << extra;
Andreas Huber2831d512016-08-15 09:33:47 -0700267 } else {
268 out << "void";
269 }
270
271 out << " "
272 << method->name()
273 << "("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700274 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700275
276 if (needsCallback) {
277 if (!method->args().empty()) {
278 out << ", ";
279 }
280
281 out << method->name()
282 << "Callback cb";
283 }
284
285 out << ");\n";
286 }
287
288 out << "\npublic static final class Proxy implements "
289 << ifaceName
290 << " {\n";
291
292 out.indent();
293
294 out << "private IHwBinder mRemote;\n\n";
295 out << "public Proxy(IHwBinder remote) {\n";
296 out.indent();
297 out << "mRemote = remote;\n";
298 out.unindent();
299 out << "}\n\n";
300
301 out << "public IHwBinder asBinder() {\n";
302 out.indent();
303 out << "return mRemote;\n";
304 out.unindent();
305 out << "}\n\n";
306
Yifan Hong10fe0b52016-10-19 14:20:17 -0700307 const Interface *prevInterface = nullptr;
308 for (const auto &tuple : iface->allMethodsFromRoot()) {
309 const Method *method = tuple.method();
310 const Interface *superInterface = tuple.interface();
311 if (prevInterface != superInterface) {
312 out << "// Methods from "
313 << superInterface->fullName()
314 << " follow.\n";
315 prevInterface = superInterface;
316 }
317 const bool returnsValue = !method->results().empty();
318 const bool needsCallback = method->results().size() > 1;
Andreas Huber2831d512016-08-15 09:33:47 -0700319
Yifan Hong10fe0b52016-10-19 14:20:17 -0700320 out << "public ";
321 if (returnsValue && !needsCallback) {
322 std::string extra;
323 out << method->results()[0]->type().getJavaType(&extra)
324 << extra;
325 } else {
326 out << "void";
327 }
Andreas Huber2831d512016-08-15 09:33:47 -0700328
Yifan Hong10fe0b52016-10-19 14:20:17 -0700329 out << " "
330 << method->name()
331 << "("
332 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700333
Yifan Hong10fe0b52016-10-19 14:20:17 -0700334 if (needsCallback) {
335 if (!method->args().empty()) {
336 out << ", ";
Andreas Huber2831d512016-08-15 09:33:47 -0700337 }
338
Yifan Hong10fe0b52016-10-19 14:20:17 -0700339 out << method->name()
340 << "Callback cb";
341 }
Andreas Huber2831d512016-08-15 09:33:47 -0700342
Yifan Hong10fe0b52016-10-19 14:20:17 -0700343 out << ") {\n";
344 out.indent();
Andreas Huber2831d512016-08-15 09:33:47 -0700345
Yifan Hong10fe0b52016-10-19 14:20:17 -0700346 out << "HwParcel request = new HwParcel();\n";
347 out << "request.writeInterfaceToken("
348 << superInterface->fullJavaName()
349 << ".kInterfaceName);\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700350
Yifan Hong10fe0b52016-10-19 14:20:17 -0700351 for (const auto &arg : method->args()) {
352 emitJavaReaderWriter(
353 out,
354 "request",
355 arg,
356 false /* isReader */);
357 }
Andreas Huber2831d512016-08-15 09:33:47 -0700358
Yifan Hong10fe0b52016-10-19 14:20:17 -0700359 out << "\nHwParcel reply = new HwParcel();\n"
360 << "mRemote.transact("
361 << method->getSerialId()
362 << " /* "
363 << method->name()
364 << " */, request, reply, ";
Andreas Huber2831d512016-08-15 09:33:47 -0700365
Yifan Hong10fe0b52016-10-19 14:20:17 -0700366 if (method->isOneway()) {
367 out << "IHwBinder.FLAG_ONEWAY";
368 } else {
369 out << "0 /* flags */";
370 }
371
372 out << ");\n";
373
374 if (!method->isOneway()) {
375 out << "reply.verifySuccess();\n";
376 } else {
377 CHECK(!returnsValue);
378 }
379
380 out << "request.releaseTemporaryStorage();\n";
381
382 if (returnsValue) {
383 out << "\n";
384
385 for (const auto &arg : method->results()) {
Andreas Huber2831d512016-08-15 09:33:47 -0700386 emitJavaReaderWriter(
387 out,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700388 "reply",
Andreas Huber2831d512016-08-15 09:33:47 -0700389 arg,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700390 true /* isReader */);
Andreas Huber2831d512016-08-15 09:33:47 -0700391 }
392
Yifan Hong10fe0b52016-10-19 14:20:17 -0700393 if (needsCallback) {
394 out << "cb.onValues(";
Andreas Huber8b5da222016-08-18 14:28:18 -0700395
Yifan Hong10fe0b52016-10-19 14:20:17 -0700396 bool firstField = true;
Andreas Huber2831d512016-08-15 09:33:47 -0700397 for (const auto &arg : method->results()) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700398 if (!firstField) {
399 out << ", ";
Andreas Huber2831d512016-08-15 09:33:47 -0700400 }
401
Yifan Hong10fe0b52016-10-19 14:20:17 -0700402 out << arg->name();
403 firstField = false;
Andreas Huber2831d512016-08-15 09:33:47 -0700404 }
Andreas Huber2831d512016-08-15 09:33:47 -0700405
Yifan Hong10fe0b52016-10-19 14:20:17 -0700406 out << ");\n";
407 } else {
408 const std::string returnName = method->results()[0]->name();
409 out << "return " << returnName << ";\n";
410 }
Andreas Huber2831d512016-08-15 09:33:47 -0700411 }
Yifan Hong10fe0b52016-10-19 14:20:17 -0700412
413 out.unindent();
414 out << "}\n\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700415 }
416
417 out.unindent();
418 out << "}\n";
419
420 ////////////////////////////////////////////////////////////////////////////
421
422 out << "\npublic static abstract class Stub extends HwBinder "
423 << "implements "
424 << ifaceName << " {\n";
425
426 out.indent();
427
428 out << "public IHwBinder asBinder() {\n";
429 out.indent();
430 out << "return this;\n";
431 out.unindent();
432 out << "}\n\n";
433
Yifan Hong10fe0b52016-10-19 14:20:17 -0700434 // b/32383557 this is a hack. We need to change this if we have more reserved methods.
435 for (Method *method : iface->hidlReservedMethods()) {
436 std::string extra;
437 out << "public final "
438 << method->results()[0]->type().getJavaType(&extra)
439 << extra
440 << " "
441 << method->name()
442 << "() {\n";
443 out.indent();
444 method->javaImpl(out);
445 out.unindent();
446 out << "\n}\n\n";
447 }
448
Andreas Huber2831d512016-08-15 09:33:47 -0700449 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
Andreas Huber2bb6e1e2016-10-25 13:26:43 -0700461 out << "public void registerAsService(String serviceName) {\n";
462 out.indent();
463
464 out << "registerService(serviceName, "
465 << mPackage.getPackageMajorVersion()
466 << ", "
467 << mPackage.getPackageMinorVersion()
468 << ");\n";
469
470 out.unindent();
471 out << "}\n\n";
472
Andreas Huber2831d512016-08-15 09:33:47 -0700473 out << "public void onTransact("
474 << "int code, HwParcel request, final HwParcel reply, "
475 << "int flags) {\n";
476
477 out.indent();
478
479 out << "switch (code) {\n";
480
481 out.indent();
482
Yifan Hong10fe0b52016-10-19 14:20:17 -0700483 for (const auto &tuple : iface->allMethodsFromRoot()) {
484 const Method *method = tuple.method();
485 const Interface *superInterface = tuple.interface();
486 const bool returnsValue = !method->results().empty();
487 const bool needsCallback = method->results().size() > 1;
Andreas Huber2831d512016-08-15 09:33:47 -0700488
Yifan Hong10fe0b52016-10-19 14:20:17 -0700489 out << "case "
490 << method->getSerialId()
491 << " /* "
492 << method->name()
493 << " */:\n{\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700494
Yifan Hong10fe0b52016-10-19 14:20:17 -0700495 out.indent();
Andreas Huber2831d512016-08-15 09:33:47 -0700496
Yifan Hong10fe0b52016-10-19 14:20:17 -0700497 out << "request.enforceInterface("
498 << superInterface->fullJavaName()
499 << ".kInterfaceName);\n\n";
500
501 for (const auto &arg : method->args()) {
502 emitJavaReaderWriter(
503 out,
504 "request",
505 arg,
506 true /* isReader */);
507 }
508
509 if (!needsCallback && returnsValue) {
510 const TypedVar *returnArg = method->results()[0];
511 std::string extra;
512
513 out << returnArg->type().getJavaType(&extra)
514 << extra
515 << " "
516 << returnArg->name()
517 << " = ";
518 }
519
520 out << method->name()
521 << "(";
522
523 bool firstField = true;
524 for (const auto &arg : method->args()) {
525 if (!firstField) {
526 out << ", ";
527 }
528
529 out << arg->name();
530
531 firstField = false;
532 }
533
534 if (needsCallback) {
535 if (!firstField) {
536 out << ", ";
537 }
538
539 out << "new " << method->name() << "Callback() {\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700540 out.indent();
541
Yifan Hong10fe0b52016-10-19 14:20:17 -0700542 out << "@Override\n"
543 << "public void onValues("
544 << Method::GetJavaArgSignature(method->results())
545 << ") {\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700546
Yifan Hong10fe0b52016-10-19 14:20:17 -0700547 out.indent();
548 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
549
550 for (const auto &arg : method->results()) {
Andreas Huber2831d512016-08-15 09:33:47 -0700551 emitJavaReaderWriter(
552 out,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700553 "reply",
Andreas Huber2831d512016-08-15 09:33:47 -0700554 arg,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700555 false /* isReader */);
Andreas Huber2831d512016-08-15 09:33:47 -0700556 }
557
Yifan Hong10fe0b52016-10-19 14:20:17 -0700558 out << "reply.send();\n"
559 << "}}";
Andreas Huber2831d512016-08-15 09:33:47 -0700560
Andreas Huber2831d512016-08-15 09:33:47 -0700561 out.unindent();
Yifan Hong10fe0b52016-10-19 14:20:17 -0700562 out.unindent();
Andreas Huber2831d512016-08-15 09:33:47 -0700563 }
Yifan Hong10fe0b52016-10-19 14:20:17 -0700564
565 out << ");\n";
566
567 if (!needsCallback) {
568 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
569
570 if (returnsValue) {
571 const TypedVar *returnArg = method->results()[0];
572
573 emitJavaReaderWriter(
574 out,
575 "reply",
576 returnArg,
577 false /* isReader */);
578 }
579
580 out << "reply.send();\n";
581 }
582
583 out << "break;\n";
584 out.unindent();
585 out << "}\n\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700586 }
587
588 out.unindent();
589 out << "}\n";
590
591 out.unindent();
592 out << "}\n";
593
594 out.unindent();
595 out << "}\n";
596
597 out.unindent();
598 out << "}\n";
599
600 return OK;
601}
602
603status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700604 return mRootScope->emitJavaTypeDeclarations(out, false /* atTopLevel */);
Andreas Huber2831d512016-08-15 09:33:47 -0700605}
606
607} // namespace android
608