blob: 90fb101063890a440058e58d9ec2731abb72fca6 [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"
20#include "Formatter.h"
21#include "Interface.h"
22#include "Method.h"
23#include "Scope.h"
Steven Morelandaf440142016-09-07 10:09:11 -070024#include "StringHelper.h"
Andreas Huber2831d512016-08-15 09:33:47 -070025
26#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) {
36 out << arg->type().getJavaType()
37 << " "
38 << arg->name()
39 << " = ";
40 }
41
42 arg->type().emitJavaReaderWriter(out, parcelObj, arg->name(), isReader);
43}
44
Andreas Huber0fa9e392016-08-31 09:05:44 -070045status_t AST::generateJavaTypes(
46 const std::string &outputPath, const char *limitToType) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -070047 // Splits types.hal up into one java file per declared type.
48
49 for (size_t i = 0; i < mRootScope->countTypes(); ++i) {
50 std::string typeName;
51 const Type *type = mRootScope->typeAt(i, &typeName);
52
53 if (type->isTypeDef()) {
54 continue;
55 }
56
Andreas Huber0fa9e392016-08-31 09:05:44 -070057 if ((limitToType != nullptr) && typeName != limitToType) {
58 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
85 out << "import java.util.Vector;\n\n";
86
Iliyan Malchev800273d2016-09-02 15:25:07 -070087 for (const auto &item : mImportedNamesForJava) {
88 out << "import " << item.javaName() << ";\n";
89 }
90 out << "\n";
91
Andreas Huber85eabdb2016-08-25 11:24:49 -070092 status_t err =
93 type->emitJavaTypeDeclarations(out, true /* atTopLevel */);
94
95 if (err != OK) {
96 return err;
97 }
98 }
99
100 return OK;
101}
102
Andreas Huber0fa9e392016-08-31 09:05:44 -0700103status_t AST::generateJava(
104 const std::string &outputPath, const char *limitToType) const {
105 if (!isJavaCompatible()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700106 fprintf(stderr,
107 "ERROR: This interface is not Java compatible. The Java backend"
Andreas Huber85eabdb2016-08-25 11:24:49 -0700108 " does NOT support union types or native handles.\n");
Andreas Huber70a59e12016-08-16 12:57:01 -0700109
Andreas Huber2831d512016-08-15 09:33:47 -0700110 return UNKNOWN_ERROR;
111 }
112
Andreas Huber0fa9e392016-08-31 09:05:44 -0700113 std::string ifaceName;
114 if (!AST::isInterface(&ifaceName)) {
115 return generateJavaTypes(outputPath, limitToType);
116 }
117
118 const Interface *iface = mRootScope->getInterface();
119
Andreas Huber2831d512016-08-15 09:33:47 -0700120 // cut off the leading 'I'.
121 const std::string baseName = ifaceName.substr(1);
122
123 std::string path = outputPath;
124 path.append(mCoordinator->convertPackageRootToPath(mPackage));
125 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
126 path.append(ifaceName);
127 path.append(".java");
128
129 CHECK(Coordinator::MakeParentHierarchy(path));
130 FILE *file = fopen(path.c_str(), "w");
131
132 if (file == NULL) {
133 return -errno;
134 }
135
136 Formatter out(file);
137
138 std::vector<std::string> packageComponents;
139 getPackageAndVersionComponents(
140 &packageComponents, true /* cpp_compatible */);
141
142 out << "package " << mPackage.javaPackage() << ";\n\n";
143
144 out << "import android.os.IHwBinder;\n";
145 out << "import android.os.IHwInterface;\n";
146 out << "import android.os.HwBinder;\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700147 out << "import android.os.HwBlob;\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700148 out << "import android.os.HwParcel;\n\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700149 out << "import java.util.Vector;\n\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700150
Andreas Huber85eabdb2016-08-25 11:24:49 -0700151 for (const auto &item : mImportedNamesForJava) {
Andreas Huber2831d512016-08-15 09:33:47 -0700152 out << "import " << item.javaName() << ";\n";
153 }
154
Andreas Huber85eabdb2016-08-25 11:24:49 -0700155 if (!mImportedNamesForJava.empty()) {
Andreas Huber2831d512016-08-15 09:33:47 -0700156 out << "\n";
157 }
158
159 out.setNamespace(mPackage.javaPackage() + ".");
160
Andreas Huber2831d512016-08-15 09:33:47 -0700161 const Interface *superType = iface->superType();
162
163 out << "public interface " << ifaceName << " extends ";
164
165 if (superType != NULL) {
166 out << superType->fullJavaName();
167 } else {
168 out << "IHwInterface";
169 }
170
171 out << " {\n";
172 out.indent();
173
174 out << "public static final String kInterfaceName = \""
175 << mPackage.string()
176 << "::"
177 << ifaceName
178 << "\";\n\n";
179
180 out << "public static "
181 << ifaceName
182 << " asInterface(IHwBinder binder) {\n";
183
184 out.indent();
185
186 out << "if (binder == null) {\n";
187 out.indent();
188 out << "return null;\n";
189 out.unindent();
190 out << "}\n\n";
191
192 out << "IHwInterface iface =\n";
193 out.indent();
194 out.indent();
195 out << "binder.queryLocalInterface(kInterfaceName);\n\n";
196 out.unindent();
197 out.unindent();
198
199 out << "if ((iface != null) && (iface instanceof "
200 << ifaceName
201 << ")) {\n";
202
203 out.indent();
204 out << "return (" << ifaceName << ")iface;\n";
205 out.unindent();
206 out << "}\n\n";
207
208 out << "return new " << ifaceName << ".Proxy(binder);\n";
209
210 out.unindent();
211 out << "}\n\n";
212
213 out << "public IHwBinder asBinder();\n\n";
214
215 status_t err = emitJavaTypeDeclarations(out);
216
217 if (err != OK) {
218 return err;
219 }
220
221 const std::string base = (superType != NULL)
222 ? (superType->fullJavaName() + ".kOpEnd")
223 : "IHwBinder.FIRST_CALL_TRANSACTION";
224
225 bool first = true;
226 size_t index = 0;
227 for (const auto &method : iface->methods()) {
228 out << "public static final int kOp_"
Steven Morelandaf440142016-09-07 10:09:11 -0700229 << StringHelper::Upcase(method->name())
Andreas Huber2831d512016-08-15 09:33:47 -0700230 << " = "
231 << base;
232
233 if (!first) {
234 out << " + " << index;
235 }
236
237 out << ";\n";
238
239 ++index;
240 first = false;
241 }
242
243 out << "public static final int kOpEnd = "
244 << base
245 << " + "
246 << index
247 << ";";
248
249 out << "\n\n";
250
251 for (const auto &method : iface->methods()) {
252 const bool returnsValue = !method->results().empty();
253 const bool needsCallback = method->results().size() > 1;
254
255 if (needsCallback) {
256 out << "\npublic abstract class "
257 << method->name()
258 << "Callback {\n";
259
260 out.indent();
261
262 out << "public abstract void onValues("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700263 << Method::GetJavaArgSignature(method->results())
Andreas Huber2831d512016-08-15 09:33:47 -0700264 << ");\n";
265
266 out.unindent();
267 out << "}\n\n";
268 }
269
270 if (returnsValue && !needsCallback) {
271 out << method->results()[0]->type().getJavaType();
272 } else {
273 out << "void";
274 }
275
276 out << " "
277 << method->name()
278 << "("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700279 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700280
281 if (needsCallback) {
282 if (!method->args().empty()) {
283 out << ", ";
284 }
285
286 out << method->name()
287 << "Callback cb";
288 }
289
290 out << ");\n";
291 }
292
293 out << "\npublic static final class Proxy implements "
294 << ifaceName
295 << " {\n";
296
297 out.indent();
298
299 out << "private IHwBinder mRemote;\n\n";
300 out << "public Proxy(IHwBinder remote) {\n";
301 out.indent();
302 out << "mRemote = remote;\n";
303 out.unindent();
304 out << "}\n\n";
305
306 out << "public IHwBinder asBinder() {\n";
307 out.indent();
308 out << "return mRemote;\n";
309 out.unindent();
310 out << "}\n\n";
311
312 std::vector<const Interface *> chain;
313 while (iface != NULL) {
314 chain.push_back(iface);
315 iface = iface->superType();
316 }
317
318 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
319 const Interface *superInterface = *it;
320
321 out << "// Methods from "
322 << superInterface->fullName()
323 << " follow.\n";
324
325 for (const auto &method : superInterface->methods()) {
326 const bool returnsValue = !method->results().empty();
327 const bool needsCallback = method->results().size() > 1;
328
329 out << "public ";
330 if (returnsValue && !needsCallback) {
331 out << method->results()[0]->type().getJavaType();
332 } else {
333 out << "void";
334 }
335
336 out << " "
337 << method->name()
338 << "("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700339 << Method::GetJavaArgSignature(method->args());
Andreas Huber2831d512016-08-15 09:33:47 -0700340
341 if (needsCallback) {
342 if (!method->args().empty()) {
343 out << ", ";
344 }
345
346 out << method->name()
347 << "Callback cb";
348 }
349
350 out << ") {\n";
351 out.indent();
352
353 out << "HwParcel request = new HwParcel();\n";
354 out << "request.writeInterfaceToken("
355 << superInterface->fullJavaName()
356 << ".kInterfaceName);\n";
357
358 for (const auto &arg : method->args()) {
359 emitJavaReaderWriter(
360 out,
361 "request",
362 arg,
363 false /* isReader */);
364 }
365
366 out << "\nHwParcel reply = new HwParcel();\n"
Andreas Huber8b5da222016-08-18 14:28:18 -0700367 << "mRemote.transact(kOp_"
Steven Morelandaf440142016-09-07 10:09:11 -0700368 << StringHelper::Upcase(method->name())
Andreas Huber8b5da222016-08-18 14:28:18 -0700369 << ", request, reply, ";
370
371 if (method->isOneway()) {
372 out << "IHwBinder.FLAG_ONEWAY";
373 } else {
374 out << "0 /* flags */";
375 }
376
377 out << ");\n";
378
379 if (!method->isOneway()) {
380 out << "reply.verifySuccess();\n";
381 } else {
382 CHECK(!returnsValue);
383 }
384
385 out << "request.releaseTemporaryStorage();\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700386
387 if (returnsValue) {
388 out << "\n";
389
390 for (const auto &arg : method->results()) {
391 emitJavaReaderWriter(
392 out,
393 "reply",
394 arg,
395 true /* isReader */);
396 }
397
398 if (needsCallback) {
399 out << "cb.onValues(";
400
401 bool firstField = true;
402 for (const auto &arg : method->results()) {
403 if (!firstField) {
404 out << ", ";
405 }
406
407 out << arg->name();
408 firstField = false;
409 }
410
411 out << ");\n";
412 } else {
413 const std::string returnName = method->results()[0]->name();
414 out << "return " << returnName << ";\n";
415 }
416 }
417
418 out.unindent();
419 out << "}\n\n";
420 }
421 }
422
423 out.unindent();
424 out << "}\n";
425
426 ////////////////////////////////////////////////////////////////////////////
427
428 out << "\npublic static abstract class Stub extends HwBinder "
429 << "implements "
430 << ifaceName << " {\n";
431
432 out.indent();
433
434 out << "public IHwBinder asBinder() {\n";
435 out.indent();
436 out << "return this;\n";
437 out.unindent();
438 out << "}\n\n";
439
440 out << "public IHwInterface queryLocalInterface(String descriptor) {\n";
441 out.indent();
442 // XXX what about potential superClasses?
443 out << "if (kInterfaceName.equals(descriptor)) {\n";
444 out.indent();
445 out << "return this;\n";
446 out.unindent();
447 out << "}\n";
448 out << "return null;\n";
449 out.unindent();
450 out << "}\n\n";
451
452 out << "public void onTransact("
453 << "int code, HwParcel request, final HwParcel reply, "
454 << "int flags) {\n";
455
456 out.indent();
457
458 out << "switch (code) {\n";
459
460 out.indent();
461
462 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
463 const Interface *superInterface = *it;
464
465 for (const auto &method : superInterface->methods()) {
466 const bool returnsValue = !method->results().empty();
467 const bool needsCallback = method->results().size() > 1;
468
469 out << "case "
470 << superInterface->fullJavaName()
471 << ".kOp_"
472 <<
Steven Morelandaf440142016-09-07 10:09:11 -0700473 StringHelper::Upcase(method->name())
Andreas Huber2831d512016-08-15 09:33:47 -0700474 << ":\n{\n";
475
476 out.indent();
477
478 out << "request.enforceInterface("
479 << superInterface->fullJavaName()
480 << ".kInterfaceName);\n\n";
481
482 for (const auto &arg : method->args()) {
483 emitJavaReaderWriter(
484 out,
485 "request",
486 arg,
487 true /* isReader */);
488 }
489
490 if (!needsCallback && returnsValue) {
491 const TypedVar *returnArg = method->results()[0];
492
493 out << returnArg->type().getJavaType()
494 << " "
495 << returnArg->name()
496 << " = ";
497 }
498
499 out << method->name()
500 << "(";
501
502 bool firstField = true;
503 for (const auto &arg : method->args()) {
504 if (!firstField) {
505 out << ", ";
506 }
507
508 out << arg->name();
509
510 firstField = false;
511 }
512
513 if (needsCallback) {
514 if (!firstField) {
515 out << ", ";
516 }
517
518 out << "new " << method->name() << "Callback() {\n";
519 out.indent();
520
521 out << "@Override\n"
522 << "public void onValues("
Steven Morelanda7a421a2016-09-07 08:35:18 -0700523 << Method::GetJavaArgSignature(method->results())
Andreas Huber2831d512016-08-15 09:33:47 -0700524 << ") {\n";
525
526 out.indent();
527 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
528
529 for (const auto &arg : method->results()) {
530 emitJavaReaderWriter(
531 out,
532 "reply",
533 arg,
534 false /* isReader */);
535 }
536
537 out << "reply.send();\n"
538 << "}}";
539
540 out.unindent();
541 out.unindent();
542 }
543
544 out << ");\n";
545
546 if (!needsCallback) {
547 out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
548
549 if (returnsValue) {
550 const TypedVar *returnArg = method->results()[0];
551
552 emitJavaReaderWriter(
553 out,
554 "reply",
555 returnArg,
556 false /* isReader */);
557 }
558
559 out << "reply.send();\n";
560 }
561
562 out << "break;\n";
563 out.unindent();
564 out << "}\n\n";
565 }
566 }
567
568 out.unindent();
569 out << "}\n";
570
571 out.unindent();
572 out << "}\n";
573
574 out.unindent();
575 out << "}\n";
576
577 out.unindent();
578 out << "}\n";
579
580 return OK;
581}
582
583status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700584 return mRootScope->emitJavaTypeDeclarations(out, false /* atTopLevel */);
Andreas Huber2831d512016-08-15 09:33:47 -0700585}
586
587} // namespace android
588