blob: 1e0c478d14c221118d0acf4725d91f2181da7f85 [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 "
111 "one-dimensional arrays.\n");
Andreas Huber70a59e12016-08-16 12:57:01 -0700112
Andreas Huber2831d512016-08-15 09:33:47 -0700113 return UNKNOWN_ERROR;
114 }
115
Andreas Huber0fa9e392016-08-31 09:05:44 -0700116 std::string ifaceName;
117 if (!AST::isInterface(&ifaceName)) {
118 return generateJavaTypes(outputPath, limitToType);
119 }
120
121 const Interface *iface = mRootScope->getInterface();
122
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700123 const std::string baseName = iface->getBaseName();
Andreas Huber2831d512016-08-15 09:33:47 -0700124
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 Huberf1abc2a2016-09-28 09:14:43 -0700153 out << "import java.util.ArrayList;\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
Andreas Huber2831d512016-08-15 09:33:47 -0700225 for (const auto &method : iface->methods()) {
226 const bool returnsValue = !method->results().empty();
227 const bool needsCallback = method->results().size() > 1;
228
229 if (needsCallback) {
230 out << "\npublic abstract class "
231 << method->name()
232 << "Callback {\n";
233
234 out.indent();
235
236 out << "public abstract void onValues("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700237 << Method::GetJavaArgSignature(method->results())
Andreas Huber2831d512016-08-15 09:33:47 -0700238 << ");\n";
239
240 out.unindent();
241 out << "}\n\n";
242 }
243
244 if (returnsValue && !needsCallback) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700245 std::string extra;
246 out << method->results()[0]->type().getJavaType(&extra)
247 << extra;
Andreas Huber2831d512016-08-15 09:33:47 -0700248 } else {
249 out << "void";
250 }
251
252 out << " "
253 << method->name()
254 << "("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700255 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700256
257 if (needsCallback) {
258 if (!method->args().empty()) {
259 out << ", ";
260 }
261
262 out << method->name()
263 << "Callback cb";
264 }
265
266 out << ");\n";
267 }
268
269 out << "\npublic static final class Proxy implements "
270 << ifaceName
271 << " {\n";
272
273 out.indent();
274
275 out << "private IHwBinder mRemote;\n\n";
276 out << "public Proxy(IHwBinder remote) {\n";
277 out.indent();
278 out << "mRemote = remote;\n";
279 out.unindent();
280 out << "}\n\n";
281
282 out << "public IHwBinder asBinder() {\n";
283 out.indent();
284 out << "return mRemote;\n";
285 out.unindent();
286 out << "}\n\n";
287
288 std::vector<const Interface *> chain;
289 while (iface != NULL) {
290 chain.push_back(iface);
291 iface = iface->superType();
292 }
293
294 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
295 const Interface *superInterface = *it;
296
297 out << "// Methods from "
298 << superInterface->fullName()
299 << " follow.\n";
300
301 for (const auto &method : superInterface->methods()) {
302 const bool returnsValue = !method->results().empty();
303 const bool needsCallback = method->results().size() > 1;
304
305 out << "public ";
306 if (returnsValue && !needsCallback) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700307 std::string extra;
308 out << method->results()[0]->type().getJavaType(&extra)
309 << extra;
Andreas Huber2831d512016-08-15 09:33:47 -0700310 } else {
311 out << "void";
312 }
313
314 out << " "
315 << method->name()
316 << "("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700317 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700318
319 if (needsCallback) {
320 if (!method->args().empty()) {
321 out << ", ";
322 }
323
324 out << method->name()
325 << "Callback cb";
326 }
327
328 out << ") {\n";
329 out.indent();
330
331 out << "HwParcel request = new HwParcel();\n";
332 out << "request.writeInterfaceToken("
333 << superInterface->fullJavaName()
334 << ".kInterfaceName);\n";
335
336 for (const auto &arg : method->args()) {
337 emitJavaReaderWriter(
338 out,
339 "request",
340 arg,
341 false /* isReader */);
342 }
343
344 out << "\nHwParcel reply = new HwParcel();\n"
Steven Morelandef1a9fe2016-10-06 17:19:09 -0700345 << "mRemote.transact("
346 << method->getSerialId()
347 << " /* "
348 << method->name()
349 << " */, request, reply, ";
Andreas Huber8b5da222016-08-18 14:28:18 -0700350
351 if (method->isOneway()) {
352 out << "IHwBinder.FLAG_ONEWAY";
353 } else {
354 out << "0 /* flags */";
355 }
356
357 out << ");\n";
358
359 if (!method->isOneway()) {
360 out << "reply.verifySuccess();\n";
361 } else {
362 CHECK(!returnsValue);
363 }
364
365 out << "request.releaseTemporaryStorage();\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700366
367 if (returnsValue) {
368 out << "\n";
369
370 for (const auto &arg : method->results()) {
371 emitJavaReaderWriter(
372 out,
373 "reply",
374 arg,
375 true /* isReader */);
376 }
377
378 if (needsCallback) {
379 out << "cb.onValues(";
380
381 bool firstField = true;
382 for (const auto &arg : method->results()) {
383 if (!firstField) {
384 out << ", ";
385 }
386
387 out << arg->name();
388 firstField = false;
389 }
390
391 out << ");\n";
392 } else {
393 const std::string returnName = method->results()[0]->name();
394 out << "return " << returnName << ";\n";
395 }
396 }
397
398 out.unindent();
399 out << "}\n\n";
400 }
401 }
402
403 out.unindent();
404 out << "}\n";
405
406 ////////////////////////////////////////////////////////////////////////////
407
408 out << "\npublic static abstract class Stub extends HwBinder "
409 << "implements "
410 << ifaceName << " {\n";
411
412 out.indent();
413
414 out << "public IHwBinder asBinder() {\n";
415 out.indent();
416 out << "return this;\n";
417 out.unindent();
418 out << "}\n\n";
419
420 out << "public IHwInterface queryLocalInterface(String descriptor) {\n";
421 out.indent();
422 // XXX what about potential superClasses?
423 out << "if (kInterfaceName.equals(descriptor)) {\n";
424 out.indent();
425 out << "return this;\n";
426 out.unindent();
427 out << "}\n";
428 out << "return null;\n";
429 out.unindent();
430 out << "}\n\n";
431
432 out << "public void onTransact("
433 << "int code, HwParcel request, final HwParcel reply, "
434 << "int flags) {\n";
435
436 out.indent();
437
438 out << "switch (code) {\n";
439
440 out.indent();
441
442 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
443 const Interface *superInterface = *it;
444
445 for (const auto &method : superInterface->methods()) {
446 const bool returnsValue = !method->results().empty();
447 const bool needsCallback = method->results().size() > 1;
448
449 out << "case "
Steven Morelandef1a9fe2016-10-06 17:19:09 -0700450 << method->getSerialId()
451 << " /* "
452 << method->name()
453 << " */:\n{\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700454
455 out.indent();
456
457 out << "request.enforceInterface("
458 << superInterface->fullJavaName()
459 << ".kInterfaceName);\n\n";
460
461 for (const auto &arg : method->args()) {
462 emitJavaReaderWriter(
463 out,
464 "request",
465 arg,
466 true /* isReader */);
467 }
468
469 if (!needsCallback && returnsValue) {
470 const TypedVar *returnArg = method->results()[0];
Andreas Huber4c865b72016-09-14 15:26:27 -0700471 std::string extra;
Andreas Huber2831d512016-08-15 09:33:47 -0700472
Andreas Huber4c865b72016-09-14 15:26:27 -0700473 out << returnArg->type().getJavaType(&extra)
474 << extra
Andreas Huber2831d512016-08-15 09:33:47 -0700475 << " "
476 << returnArg->name()
477 << " = ";
478 }
479
480 out << method->name()
481 << "(";
482
483 bool firstField = true;
484 for (const auto &arg : method->args()) {
485 if (!firstField) {
486 out << ", ";
487 }
488
489 out << arg->name();
490
491 firstField = false;
492 }
493
494 if (needsCallback) {
495 if (!firstField) {
496 out << ", ";
497 }
498
499 out << "new " << method->name() << "Callback() {\n";
500 out.indent();
501
502 out << "@Override\n"
503 << "public void onValues("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700504 << Method::GetJavaArgSignature(method->results())
Andreas Huber2831d512016-08-15 09:33:47 -0700505 << ") {\n";
506
507 out.indent();
508 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
509
510 for (const auto &arg : method->results()) {
511 emitJavaReaderWriter(
512 out,
513 "reply",
514 arg,
515 false /* isReader */);
516 }
517
518 out << "reply.send();\n"
519 << "}}";
520
521 out.unindent();
522 out.unindent();
523 }
524
525 out << ");\n";
526
527 if (!needsCallback) {
528 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
529
530 if (returnsValue) {
531 const TypedVar *returnArg = method->results()[0];
532
533 emitJavaReaderWriter(
534 out,
535 "reply",
536 returnArg,
537 false /* isReader */);
538 }
539
540 out << "reply.send();\n";
541 }
542
543 out << "break;\n";
544 out.unindent();
545 out << "}\n\n";
546 }
547 }
548
549 out.unindent();
550 out << "}\n";
551
552 out.unindent();
553 out << "}\n";
554
555 out.unindent();
556 out << "}\n";
557
558 out.unindent();
559 out << "}\n";
560
561 return OK;
562}
563
564status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700565 return mRootScope->emitJavaTypeDeclarations(out, false /* atTopLevel */);
Andreas Huber2831d512016-08-15 09:33:47 -0700566}
567
568} // namespace android
569