blob: b4976a451220aa7a1f84a6a570adfe7d0dc4e446 [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) {
Yifan Hong4ed13472016-11-02 10:44:11 -070035 out << arg->type().getJavaType()
Andreas Huber2831d512016-08-15 09:33:47 -070036 << " "
37 << arg->name()
38 << " = ";
39 }
40
41 arg->type().emitJavaReaderWriter(out, parcelObj, arg->name(), isReader);
42}
43
Andreas Huber0fa9e392016-08-31 09:05:44 -070044status_t AST::generateJavaTypes(
Andreas Huberd29724f2016-09-14 09:33:13 -070045 const std::string &outputPath, const std::string &limitToType) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -070046 // Splits types.hal up into one java file per declared type.
47
Steven Morelandd537ab02016-09-12 10:32:01 -070048 for (const auto &type : mRootScope->getSubTypes()) {
49 std::string typeName = type->localName();
Andreas Huber85eabdb2016-08-25 11:24:49 -070050
51 if (type->isTypeDef()) {
52 continue;
53 }
54
Andreas Huberd29724f2016-09-14 09:33:13 -070055 if (!limitToType.empty() && typeName != limitToType) {
Andreas Huber0fa9e392016-08-31 09:05:44 -070056 continue;
57 }
58
Andreas Huber85eabdb2016-08-25 11:24:49 -070059 std::string path = outputPath;
60 path.append(mCoordinator->convertPackageRootToPath(mPackage));
61 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
62 path.append(typeName);
63 path.append(".java");
64
65 CHECK(Coordinator::MakeParentHierarchy(path));
66 FILE *file = fopen(path.c_str(), "w");
67
68 if (file == NULL) {
69 return -errno;
70 }
71
72 Formatter out(file);
73
74 std::vector<std::string> packageComponents;
75 getPackageAndVersionComponents(
76 &packageComponents, true /* cpp_compatible */);
77
78 out << "package " << mPackage.javaPackage() << ";\n\n";
79
Iliyan Malchev800273d2016-09-02 15:25:07 -070080 for (const auto &item : mImportedNamesForJava) {
81 out << "import " << item.javaName() << ";\n";
82 }
83 out << "\n";
84
Andreas Huber85eabdb2016-08-25 11:24:49 -070085 status_t err =
86 type->emitJavaTypeDeclarations(out, true /* atTopLevel */);
87
88 if (err != OK) {
89 return err;
90 }
91 }
92
93 return OK;
94}
95
Andreas Huber0fa9e392016-08-31 09:05:44 -070096status_t AST::generateJava(
Andreas Huberd29724f2016-09-14 09:33:13 -070097 const std::string &outputPath, const std::string &limitToType) const {
Andreas Huber0fa9e392016-08-31 09:05:44 -070098 if (!isJavaCompatible()) {
Andreas Huber70a59e12016-08-16 12:57:01 -070099 fprintf(stderr,
100 "ERROR: This interface is not Java compatible. The Java backend"
Andreas Huberf03332a2016-09-22 15:35:43 -0700101 " does NOT support union types nor native handles. "
102 "In addition, vectors of arrays are limited to at most "
Andreas Huber86a112b2016-10-19 14:25:16 -0700103 "one-dimensional arrays and vectors of {vectors,interfaces} are"
104 " not supported.\n");
Andreas Huber70a59e12016-08-16 12:57:01 -0700105
Andreas Huber2831d512016-08-15 09:33:47 -0700106 return UNKNOWN_ERROR;
107 }
108
Andreas Huber0fa9e392016-08-31 09:05:44 -0700109 std::string ifaceName;
110 if (!AST::isInterface(&ifaceName)) {
111 return generateJavaTypes(outputPath, limitToType);
112 }
113
114 const Interface *iface = mRootScope->getInterface();
115
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700116 const std::string baseName = iface->getBaseName();
Andreas Huber2831d512016-08-15 09:33:47 -0700117
118 std::string path = outputPath;
119 path.append(mCoordinator->convertPackageRootToPath(mPackage));
120 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
121 path.append(ifaceName);
122 path.append(".java");
123
124 CHECK(Coordinator::MakeParentHierarchy(path));
125 FILE *file = fopen(path.c_str(), "w");
126
127 if (file == NULL) {
128 return -errno;
129 }
130
131 Formatter out(file);
132
133 std::vector<std::string> packageComponents;
134 getPackageAndVersionComponents(
135 &packageComponents, true /* cpp_compatible */);
136
137 out << "package " << mPackage.javaPackage() << ";\n\n";
138
Andreas Huber85eabdb2016-08-25 11:24:49 -0700139 for (const auto &item : mImportedNamesForJava) {
Andreas Huber2831d512016-08-15 09:33:47 -0700140 out << "import " << item.javaName() << ";\n";
141 }
142
Andreas Huber85eabdb2016-08-25 11:24:49 -0700143 if (!mImportedNamesForJava.empty()) {
Andreas Huber2831d512016-08-15 09:33:47 -0700144 out << "\n";
145 }
146
147 out.setNamespace(mPackage.javaPackage() + ".");
148
Andreas Huber2831d512016-08-15 09:33:47 -0700149 const Interface *superType = iface->superType();
150
151 out << "public interface " << ifaceName << " extends ";
152
153 if (superType != NULL) {
154 out << superType->fullJavaName();
155 } else {
Yifan Hong1af73532016-11-09 14:32:58 -0800156 out << "android.os.IHwInterface";
Andreas Huber2831d512016-08-15 09:33:47 -0700157 }
158
159 out << " {\n";
160 out.indent();
161
162 out << "public static final String kInterfaceName = \""
163 << mPackage.string()
164 << "::"
165 << ifaceName
166 << "\";\n\n";
167
168 out << "public static "
169 << ifaceName
Yifan Hong1af73532016-11-09 14:32:58 -0800170 << " asInterface(android.os.IHwBinder binder) {\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700171
172 out.indent();
173
174 out << "if (binder == null) {\n";
175 out.indent();
176 out << "return null;\n";
177 out.unindent();
178 out << "}\n\n";
179
Yifan Hong1af73532016-11-09 14:32:58 -0800180 out << "android.os.IHwInterface iface =\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700181 out.indent();
182 out.indent();
183 out << "binder.queryLocalInterface(kInterfaceName);\n\n";
184 out.unindent();
185 out.unindent();
186
187 out << "if ((iface != null) && (iface instanceof "
188 << ifaceName
189 << ")) {\n";
190
191 out.indent();
192 out << "return (" << ifaceName << ")iface;\n";
193 out.unindent();
194 out << "}\n\n";
195
196 out << "return new " << ifaceName << ".Proxy(binder);\n";
197
198 out.unindent();
199 out << "}\n\n";
200
Yifan Hong1af73532016-11-09 14:32:58 -0800201 out << "public android.os.IHwBinder asBinder();\n\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700202
Andreas Huber2bb6e1e2016-10-25 13:26:43 -0700203 out << "public static "
204 << ifaceName
205 << " getService(String serviceName) {\n";
206
207 out.indent();
208
209 out << "return "
210 << ifaceName
Yifan Hong1af73532016-11-09 14:32:58 -0800211 << ".asInterface(android.os.HwBinder.getService(\""
Steven Moreland7e367bf2016-11-04 11:31:41 -0700212 << iface->fqName().string()
213 << "\",serviceName));\n";
Andreas Huber2bb6e1e2016-10-25 13:26:43 -0700214
215 out.unindent();
216
217 out << "}\n\n";
218
Andreas Huber2831d512016-08-15 09:33:47 -0700219 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) {
Yifan Hong4ed13472016-11-02 10:44:11 -0700245 out << method->results()[0]->type().getJavaType();
Andreas Huber2831d512016-08-15 09:33:47 -0700246 } else {
247 out << "void";
248 }
249
250 out << " "
251 << method->name()
252 << "("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700253 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700254
255 if (needsCallback) {
256 if (!method->args().empty()) {
257 out << ", ";
258 }
259
260 out << method->name()
261 << "Callback cb";
262 }
263
264 out << ");\n";
265 }
266
267 out << "\npublic static final class Proxy implements "
268 << ifaceName
269 << " {\n";
270
271 out.indent();
272
Yifan Hong1af73532016-11-09 14:32:58 -0800273 out << "private android.os.IHwBinder mRemote;\n\n";
274 out << "public Proxy(android.os.IHwBinder remote) {\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700275 out.indent();
276 out << "mRemote = remote;\n";
277 out.unindent();
278 out << "}\n\n";
279
Yifan Hong1af73532016-11-09 14:32:58 -0800280 out << "public android.os.IHwBinder asBinder() {\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700281 out.indent();
282 out << "return mRemote;\n";
283 out.unindent();
284 out << "}\n\n";
285
Yifan Hong10fe0b52016-10-19 14:20:17 -0700286 const Interface *prevInterface = nullptr;
287 for (const auto &tuple : iface->allMethodsFromRoot()) {
288 const Method *method = tuple.method();
289 const Interface *superInterface = tuple.interface();
290 if (prevInterface != superInterface) {
291 out << "// Methods from "
292 << superInterface->fullName()
293 << " follow.\n";
294 prevInterface = superInterface;
295 }
296 const bool returnsValue = !method->results().empty();
297 const bool needsCallback = method->results().size() > 1;
Andreas Huber2831d512016-08-15 09:33:47 -0700298
Yifan Hong10fe0b52016-10-19 14:20:17 -0700299 out << "public ";
300 if (returnsValue && !needsCallback) {
Yifan Hong4ed13472016-11-02 10:44:11 -0700301 out << method->results()[0]->type().getJavaType();
Yifan Hong10fe0b52016-10-19 14:20:17 -0700302 } else {
303 out << "void";
304 }
Andreas Huber2831d512016-08-15 09:33:47 -0700305
Yifan Hong10fe0b52016-10-19 14:20:17 -0700306 out << " "
307 << method->name()
308 << "("
309 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700310
Yifan Hong10fe0b52016-10-19 14:20:17 -0700311 if (needsCallback) {
312 if (!method->args().empty()) {
313 out << ", ";
Andreas Huber2831d512016-08-15 09:33:47 -0700314 }
315
Yifan Hong10fe0b52016-10-19 14:20:17 -0700316 out << method->name()
317 << "Callback cb";
318 }
Andreas Huber2831d512016-08-15 09:33:47 -0700319
Yifan Hong10fe0b52016-10-19 14:20:17 -0700320 out << ") {\n";
321 out.indent();
Andreas Huber2831d512016-08-15 09:33:47 -0700322
Yifan Hong1af73532016-11-09 14:32:58 -0800323 out << "android.os.HwParcel request = new android.os.HwParcel();\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700324 out << "request.writeInterfaceToken("
325 << superInterface->fullJavaName()
326 << ".kInterfaceName);\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700327
Yifan Hong10fe0b52016-10-19 14:20:17 -0700328 for (const auto &arg : method->args()) {
329 emitJavaReaderWriter(
330 out,
331 "request",
332 arg,
333 false /* isReader */);
334 }
Andreas Huber2831d512016-08-15 09:33:47 -0700335
Yifan Hong1af73532016-11-09 14:32:58 -0800336 out << "\nandroid.os.HwParcel reply = new android.os.HwParcel();\n"
Yifan Hong10fe0b52016-10-19 14:20:17 -0700337 << "mRemote.transact("
338 << method->getSerialId()
339 << " /* "
340 << method->name()
341 << " */, request, reply, ";
Andreas Huber2831d512016-08-15 09:33:47 -0700342
Yifan Hong10fe0b52016-10-19 14:20:17 -0700343 if (method->isOneway()) {
Yifan Hong1af73532016-11-09 14:32:58 -0800344 out << "android.os.IHwBinder.FLAG_ONEWAY";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700345 } else {
346 out << "0 /* flags */";
347 }
348
349 out << ");\n";
350
351 if (!method->isOneway()) {
352 out << "reply.verifySuccess();\n";
353 } else {
354 CHECK(!returnsValue);
355 }
356
357 out << "request.releaseTemporaryStorage();\n";
358
359 if (returnsValue) {
360 out << "\n";
361
362 for (const auto &arg : method->results()) {
Andreas Huber2831d512016-08-15 09:33:47 -0700363 emitJavaReaderWriter(
364 out,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700365 "reply",
Andreas Huber2831d512016-08-15 09:33:47 -0700366 arg,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700367 true /* isReader */);
Andreas Huber2831d512016-08-15 09:33:47 -0700368 }
369
Yifan Hong10fe0b52016-10-19 14:20:17 -0700370 if (needsCallback) {
371 out << "cb.onValues(";
Andreas Huber8b5da222016-08-18 14:28:18 -0700372
Yifan Hong10fe0b52016-10-19 14:20:17 -0700373 bool firstField = true;
Andreas Huber2831d512016-08-15 09:33:47 -0700374 for (const auto &arg : method->results()) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700375 if (!firstField) {
376 out << ", ";
Andreas Huber2831d512016-08-15 09:33:47 -0700377 }
378
Yifan Hong10fe0b52016-10-19 14:20:17 -0700379 out << arg->name();
380 firstField = false;
Andreas Huber2831d512016-08-15 09:33:47 -0700381 }
Andreas Huber2831d512016-08-15 09:33:47 -0700382
Yifan Hong10fe0b52016-10-19 14:20:17 -0700383 out << ");\n";
384 } else {
385 const std::string returnName = method->results()[0]->name();
386 out << "return " << returnName << ";\n";
387 }
Andreas Huber2831d512016-08-15 09:33:47 -0700388 }
Yifan Hong10fe0b52016-10-19 14:20:17 -0700389
390 out.unindent();
391 out << "}\n\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700392 }
393
394 out.unindent();
395 out << "}\n";
396
397 ////////////////////////////////////////////////////////////////////////////
398
Yifan Hong1af73532016-11-09 14:32:58 -0800399 out << "\npublic static abstract class Stub extends android.os.HwBinder "
Andreas Huber2831d512016-08-15 09:33:47 -0700400 << "implements "
401 << ifaceName << " {\n";
402
403 out.indent();
404
Yifan Hong1af73532016-11-09 14:32:58 -0800405 out << "public android.os.IHwBinder asBinder() {\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700406 out.indent();
407 out << "return this;\n";
408 out.unindent();
409 out << "}\n\n";
410
Yifan Hong10fe0b52016-10-19 14:20:17 -0700411 // b/32383557 this is a hack. We need to change this if we have more reserved methods.
412 for (Method *method : iface->hidlReservedMethods()) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700413 out << "public final "
Yifan Hong4ed13472016-11-02 10:44:11 -0700414 << method->results()[0]->type().getJavaType()
Yifan Hong10fe0b52016-10-19 14:20:17 -0700415 << " "
416 << method->name()
417 << "() {\n";
418 out.indent();
419 method->javaImpl(out);
420 out.unindent();
421 out << "\n}\n\n";
422 }
423
Yifan Hong1af73532016-11-09 14:32:58 -0800424 out << "public android.os.IHwInterface queryLocalInterface(String descriptor) {\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700425 out.indent();
426 // XXX what about potential superClasses?
427 out << "if (kInterfaceName.equals(descriptor)) {\n";
428 out.indent();
429 out << "return this;\n";
430 out.unindent();
431 out << "}\n";
432 out << "return null;\n";
433 out.unindent();
434 out << "}\n\n";
435
Andreas Huber2bb6e1e2016-10-25 13:26:43 -0700436 out << "public void registerAsService(String serviceName) {\n";
437 out.indent();
438
Steven Moreland7e367bf2016-11-04 11:31:41 -0700439 out << "registerService(interfaceChain(), serviceName);\n";
Andreas Huber2bb6e1e2016-10-25 13:26:43 -0700440
441 out.unindent();
442 out << "}\n\n";
443
Andreas Huber2831d512016-08-15 09:33:47 -0700444 out << "public void onTransact("
Yifan Hong1af73532016-11-09 14:32:58 -0800445 << "int code, android.os.HwParcel request, final android.os.HwParcel reply, "
Andreas Huber2831d512016-08-15 09:33:47 -0700446 << "int flags) {\n";
447
448 out.indent();
449
450 out << "switch (code) {\n";
451
452 out.indent();
453
Yifan Hong10fe0b52016-10-19 14:20:17 -0700454 for (const auto &tuple : iface->allMethodsFromRoot()) {
455 const Method *method = tuple.method();
456 const Interface *superInterface = tuple.interface();
457 const bool returnsValue = !method->results().empty();
458 const bool needsCallback = method->results().size() > 1;
Andreas Huber2831d512016-08-15 09:33:47 -0700459
Yifan Hong10fe0b52016-10-19 14:20:17 -0700460 out << "case "
461 << method->getSerialId()
462 << " /* "
463 << method->name()
464 << " */:\n{\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700465
Yifan Hong10fe0b52016-10-19 14:20:17 -0700466 out.indent();
Andreas Huber2831d512016-08-15 09:33:47 -0700467
Yifan Hong10fe0b52016-10-19 14:20:17 -0700468 out << "request.enforceInterface("
469 << superInterface->fullJavaName()
470 << ".kInterfaceName);\n\n";
471
472 for (const auto &arg : method->args()) {
473 emitJavaReaderWriter(
474 out,
475 "request",
476 arg,
477 true /* isReader */);
478 }
479
480 if (!needsCallback && returnsValue) {
481 const TypedVar *returnArg = method->results()[0];
Yifan Hong10fe0b52016-10-19 14:20:17 -0700482
Yifan Hong4ed13472016-11-02 10:44:11 -0700483 out << returnArg->type().getJavaType()
Yifan Hong10fe0b52016-10-19 14:20:17 -0700484 << " "
485 << returnArg->name()
486 << " = ";
487 }
488
489 out << method->name()
490 << "(";
491
492 bool firstField = true;
493 for (const auto &arg : method->args()) {
494 if (!firstField) {
495 out << ", ";
496 }
497
498 out << arg->name();
499
500 firstField = false;
501 }
502
503 if (needsCallback) {
504 if (!firstField) {
505 out << ", ";
506 }
507
508 out << "new " << method->name() << "Callback() {\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700509 out.indent();
510
Yifan Hong10fe0b52016-10-19 14:20:17 -0700511 out << "@Override\n"
512 << "public void onValues("
513 << Method::GetJavaArgSignature(method->results())
514 << ") {\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700515
Yifan Hong10fe0b52016-10-19 14:20:17 -0700516 out.indent();
Yifan Hong1af73532016-11-09 14:32:58 -0800517 out << "reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700518
519 for (const auto &arg : method->results()) {
Andreas Huber2831d512016-08-15 09:33:47 -0700520 emitJavaReaderWriter(
521 out,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700522 "reply",
Andreas Huber2831d512016-08-15 09:33:47 -0700523 arg,
Yifan Hong10fe0b52016-10-19 14:20:17 -0700524 false /* isReader */);
Andreas Huber2831d512016-08-15 09:33:47 -0700525 }
526
Yifan Hong10fe0b52016-10-19 14:20:17 -0700527 out << "reply.send();\n"
528 << "}}";
Andreas Huber2831d512016-08-15 09:33:47 -0700529
Andreas Huber2831d512016-08-15 09:33:47 -0700530 out.unindent();
Yifan Hong10fe0b52016-10-19 14:20:17 -0700531 out.unindent();
Andreas Huber2831d512016-08-15 09:33:47 -0700532 }
Yifan Hong10fe0b52016-10-19 14:20:17 -0700533
534 out << ");\n";
535
536 if (!needsCallback) {
Yifan Hong1af73532016-11-09 14:32:58 -0800537 out << "reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700538
539 if (returnsValue) {
540 const TypedVar *returnArg = method->results()[0];
541
542 emitJavaReaderWriter(
543 out,
544 "reply",
545 returnArg,
546 false /* isReader */);
547 }
548
549 out << "reply.send();\n";
550 }
551
552 out << "break;\n";
553 out.unindent();
554 out << "}\n\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700555 }
556
557 out.unindent();
558 out << "}\n";
559
560 out.unindent();
561 out << "}\n";
562
563 out.unindent();
564 out << "}\n";
565
566 out.unindent();
567 out << "}\n";
568
569 return OK;
570}
571
572status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700573 return mRootScope->emitJavaTypeDeclarations(out, false /* atTopLevel */);
Andreas Huber2831d512016-08-15 09:33:47 -0700574}
575
576} // namespace android
577