blob: 098984e3501207cafd4a8e5413c1abb232866173 [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 Huberc9410c72016-07-28 12:18:40 -070017#include "AST.h"
Andreas Huber5345ec22016-07-29 13:33:27 -070018#include "Coordinator.h"
Steven Moreland55df0712019-01-16 14:37:11 -080019#include "Interface.h"
Andreas Huber0fa9e392016-08-31 09:05:44 -070020#include "Scope.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070021
Andreas Huber308d8a22017-11-06 14:46:52 -080022#include <android-base/logging.h>
Steven Moreland5bdfa702017-04-18 23:20:39 -070023#include <hidl-hash/Hash.h>
Steven Moreland7ae3d542017-01-18 16:46:01 -080024#include <hidl-util/FQName.h>
Steven Morelanda8153982017-11-28 15:22:28 -080025#include <hidl-util/Formatter.h>
Steven Morelandd177b122016-12-12 09:15:37 -080026#include <hidl-util/StringHelper.h>
Steven Morelanda8153982017-11-28 15:22:28 -080027#include <stdio.h>
28#include <sys/stat.h>
29#include <unistd.h>
Andreas Huber308d8a22017-11-06 14:46:52 -080030#include <iostream>
Iliyan Malchev5bb14022016-08-09 15:04:39 -070031#include <set>
Andreas Huberdca261f2016-08-04 13:47:51 -070032#include <string>
Andreas Huberdca261f2016-08-04 13:47:51 -070033#include <vector>
Andreas Huberc9410c72016-07-28 12:18:40 -070034
35using namespace android;
36
Steven Moreland5abcf012018-02-08 18:50:18 -080037enum class OutputMode {
38 NEEDS_DIR, // -o output option expects a directory
39 NEEDS_FILE, // -o output option expects a file
40 NEEDS_SRC, // for changes inside the source tree itself
41 NOT_NEEDED // does not create files
Iliyan Malchev5bb14022016-08-09 15:04:39 -070042};
Andreas Huberdca261f2016-08-04 13:47:51 -070043
Steven Moreland5abcf012018-02-08 18:50:18 -080044enum class GenerationGranularity {
45 PER_PACKAGE, // Files generated for each package
46 PER_FILE, // Files generated for each hal file
47 PER_TYPE, // Files generated for each hal file + each type in HAL files
48};
Iliyan Malchev5bb14022016-08-09 15:04:39 -070049
Steven Moreland5abcf012018-02-08 18:50:18 -080050// Represents a file that is generated by an -L option for an FQName
51struct FileGenerator {
52 using ShouldGenerateFunction = std::function<bool(const FQName& fqName)>;
53 using FileNameForFQName = std::function<std::string(const FQName& fqName)>;
54 using GenerationFunction = std::function<status_t(Formatter& out, const FQName& fqName,
55 const Coordinator* coordinator)>;
56
57 ShouldGenerateFunction mShouldGenerateForFqName; // If generate function applies to this target
58 FileNameForFQName mFileNameForFqName; // Target -> filename
59 GenerationFunction mGenerationFunction; // Function to generate output for file
60
Steven Moreland394af5c2018-02-09 14:41:46 -080061 std::string getFileName(const FQName& fqName) const {
62 return mFileNameForFqName ? mFileNameForFqName(fqName) : "";
63 }
64
Steven Moreland255c9a12018-02-26 13:10:27 -080065 status_t getOutputFile(const FQName& fqName, const Coordinator* coordinator,
66 Coordinator::Location location, std::string* file) const {
Steven Moreland394af5c2018-02-09 14:41:46 -080067 if (!mShouldGenerateForFqName(fqName)) {
Steven Moreland255c9a12018-02-26 13:10:27 -080068 return OK;
Steven Moreland394af5c2018-02-09 14:41:46 -080069 }
70
Steven Moreland255c9a12018-02-26 13:10:27 -080071 return coordinator->getFilepath(fqName, location, getFileName(fqName), file);
Steven Moreland394af5c2018-02-09 14:41:46 -080072 }
73
Steven Moreland255c9a12018-02-26 13:10:27 -080074 status_t appendOutputFiles(const FQName& fqName, const Coordinator* coordinator,
75 Coordinator::Location location,
76 std::vector<std::string>* outputFiles) const {
Steven Moreland394af5c2018-02-09 14:41:46 -080077 if (location == Coordinator::Location::STANDARD_OUT) {
Steven Moreland255c9a12018-02-26 13:10:27 -080078 return OK;
Steven Moreland394af5c2018-02-09 14:41:46 -080079 }
80
81 if (mShouldGenerateForFqName(fqName)) {
Steven Moreland255c9a12018-02-26 13:10:27 -080082 std::string fileName;
83 status_t err = getOutputFile(fqName, coordinator, location, &fileName);
84 if (err != OK) return err;
Steven Moreland394af5c2018-02-09 14:41:46 -080085
86 if (!fileName.empty()) {
87 outputFiles->push_back(fileName);
88 }
89 }
Steven Moreland255c9a12018-02-26 13:10:27 -080090 return OK;
Steven Moreland394af5c2018-02-09 14:41:46 -080091 }
92
Steven Moreland5abcf012018-02-08 18:50:18 -080093 status_t generate(const FQName& fqName, const Coordinator* coordinator,
94 Coordinator::Location location) const {
95 CHECK(mShouldGenerateForFqName != nullptr);
96 CHECK(mGenerationFunction != nullptr);
97
98 if (!mShouldGenerateForFqName(fqName)) {
99 return OK;
100 }
101
Steven Moreland394af5c2018-02-09 14:41:46 -0800102 Formatter out = coordinator->getFormatter(fqName, location, getFileName(fqName));
Steven Moreland255c9a12018-02-26 13:10:27 -0800103 if (!out.isValid()) {
104 return UNKNOWN_ERROR;
105 }
106
Steven Moreland5abcf012018-02-08 18:50:18 -0800107 return mGenerationFunction(out, fqName, coordinator);
108 }
109
110 // Helper methods for filling out this struct
111 static bool generateForTypes(const FQName& fqName) {
112 const auto names = fqName.names();
113 return names.size() > 0 && names[0] == "types";
114 }
115 static bool generateForInterfaces(const FQName& fqName) { return !generateForTypes(fqName); }
116 static bool alwaysGenerate(const FQName&) { return true; }
117};
118
119// Represents a -L option, takes a fqName and generates files
120struct OutputHandler {
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800121 using ValidationFunction = std::function<bool(
122 const FQName& fqName, const Coordinator* coordinator, const std::string& language)>;
Steven Moreland5abcf012018-02-08 18:50:18 -0800123
124 std::string mKey; // -L in Android.bp
125 std::string mDescription; // for display in help menu
126 OutputMode mOutputMode; // how this option interacts with -o
127 Coordinator::Location mLocation; // how to compute location relative to the output directory
Steven Moreland394af5c2018-02-09 14:41:46 -0800128 GenerationGranularity mGenerationGranularity; // what to run generate function on
Steven Moreland5abcf012018-02-08 18:50:18 -0800129 ValidationFunction mValidate; // if a given fqName is allowed for this option
130 std::vector<FileGenerator> mGenerateFunctions; // run for each target at this granularity
131
132 const std::string& name() const { return mKey; }
133 const std::string& description() const { return mDescription; }
134
135 status_t generate(const FQName& fqName, const Coordinator* coordinator) const;
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800136 status_t validate(const FQName& fqName, const Coordinator* coordinator,
137 const std::string& language) const {
138 return mValidate(fqName, coordinator, language);
Steven Moreland5abcf012018-02-08 18:50:18 -0800139 }
Steven Moreland394af5c2018-02-09 14:41:46 -0800140
141 status_t writeDepFile(const FQName& fqName, const Coordinator* coordinator) const;
142
143 private:
144 status_t appendTargets(const FQName& fqName, const Coordinator* coordinator,
145 std::vector<FQName>* targets) const;
146 status_t appendOutputFiles(const FQName& fqName, const Coordinator* coordinator,
147 std::vector<std::string>* outputFiles) const;
Steven Moreland5abcf012018-02-08 18:50:18 -0800148};
149
150// Helper method for GenerationGranularity::PER_TYPE
151// IFoo -> IFoo, types.hal (containing Bar, Baz) -> types.Bar, types.Baz
152static status_t appendPerTypeTargets(const FQName& fqName, const Coordinator* coordinator,
153 std::vector<FQName>* exportedPackageInterfaces) {
154 CHECK(fqName.isFullyQualified());
155 if (fqName.name() != "types") {
156 exportedPackageInterfaces->push_back(fqName);
157 return OK;
158 }
159
160 AST* typesAST = coordinator->parse(fqName);
161 if (typesAST == nullptr) {
162 fprintf(stderr, "ERROR: Could not parse %s. Aborting.\n", fqName.string().c_str());
163 return UNKNOWN_ERROR;
164 }
165
166 std::vector<NamedType*> rootTypes = typesAST->getRootScope()->getSubTypes();
167 for (const NamedType* rootType : rootTypes) {
168 if (rootType->isTypeDef()) continue;
169
170 FQName rootTypeName(fqName.package(), fqName.version(), "types." + rootType->localName());
171 exportedPackageInterfaces->push_back(rootTypeName);
172 }
173 return OK;
174}
175
Steven Moreland394af5c2018-02-09 14:41:46 -0800176status_t OutputHandler::appendTargets(const FQName& fqName, const Coordinator* coordinator,
177 std::vector<FQName>* targets) const {
Steven Moreland5abcf012018-02-08 18:50:18 -0800178 switch (mGenerationGranularity) {
179 case GenerationGranularity::PER_PACKAGE: {
Steven Moreland394af5c2018-02-09 14:41:46 -0800180 targets->push_back(fqName.getPackageAndVersion());
Steven Moreland5abcf012018-02-08 18:50:18 -0800181 } break;
182 case GenerationGranularity::PER_FILE: {
183 if (fqName.isFullyQualified()) {
Steven Moreland394af5c2018-02-09 14:41:46 -0800184 targets->push_back(fqName);
Steven Moreland5abcf012018-02-08 18:50:18 -0800185 break;
186 }
Steven Moreland394af5c2018-02-09 14:41:46 -0800187 status_t err = coordinator->appendPackageInterfacesToVector(fqName, targets);
Steven Moreland5abcf012018-02-08 18:50:18 -0800188 if (err != OK) return err;
189 } break;
190 case GenerationGranularity::PER_TYPE: {
191 if (fqName.isFullyQualified()) {
Steven Moreland394af5c2018-02-09 14:41:46 -0800192 status_t err = appendPerTypeTargets(fqName, coordinator, targets);
Steven Moreland5abcf012018-02-08 18:50:18 -0800193 if (err != OK) return err;
194 }
195
196 std::vector<FQName> packageInterfaces;
197 status_t err = coordinator->appendPackageInterfacesToVector(fqName, &packageInterfaces);
198 if (err != OK) return err;
199 for (const FQName& packageInterface : packageInterfaces) {
Steven Moreland394af5c2018-02-09 14:41:46 -0800200 err = appendPerTypeTargets(packageInterface, coordinator, targets);
Steven Moreland5abcf012018-02-08 18:50:18 -0800201 if (err != OK) return err;
202 }
203 } break;
204 default:
205 CHECK(!"Should be here");
206 }
207
Steven Moreland394af5c2018-02-09 14:41:46 -0800208 return OK;
209}
210
211status_t OutputHandler::generate(const FQName& fqName, const Coordinator* coordinator) const {
212 std::vector<FQName> targets;
213 status_t err = appendTargets(fqName, coordinator, &targets);
214 if (err != OK) return err;
215
Steven Moreland5abcf012018-02-08 18:50:18 -0800216 for (const FQName& fqName : targets) {
217 for (const FileGenerator& file : mGenerateFunctions) {
218 status_t err = file.generate(fqName, coordinator, mLocation);
219 if (err != OK) return err;
220 }
221 }
222
223 return OK;
224}
225
Steven Moreland394af5c2018-02-09 14:41:46 -0800226status_t OutputHandler::appendOutputFiles(const FQName& fqName, const Coordinator* coordinator,
227 std::vector<std::string>* outputFiles) const {
228 std::vector<FQName> targets;
229 status_t err = appendTargets(fqName, coordinator, &targets);
230 if (err != OK) return err;
231
232 for (const FQName& fqName : targets) {
233 for (const FileGenerator& file : mGenerateFunctions) {
Steven Moreland255c9a12018-02-26 13:10:27 -0800234 err = file.appendOutputFiles(fqName, coordinator, mLocation, outputFiles);
235 if (err != OK) return err;
Steven Moreland394af5c2018-02-09 14:41:46 -0800236 }
237 }
238
239 return OK;
240}
241
242status_t OutputHandler::writeDepFile(const FQName& fqName, const Coordinator* coordinator) const {
243 std::vector<std::string> outputFiles;
244 status_t err = appendOutputFiles(fqName, coordinator, &outputFiles);
245 if (err != OK) return err;
246
247 // No need for dep files
248 if (outputFiles.empty()) {
249 return OK;
250 }
251
252 // Depfiles in Android for genrules should be for the 'main file'. Because hidl-gen doesn't have
253 // a main file for most targets, we are just outputting a depfile for one single file only.
254 const std::string forFile = outputFiles[0];
255
256 return coordinator->writeDepFile(forFile);
257}
258
Steven Moreland5abcf012018-02-08 18:50:18 -0800259// Use an AST function as a OutputHandler GenerationFunction
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800260static FileGenerator::GenerationFunction astGenerationFunction(void (AST::*generate)(Formatter&)
Steven Moreland5abcf012018-02-08 18:50:18 -0800261 const = nullptr) {
262 return [generate](Formatter& out, const FQName& fqName,
263 const Coordinator* coordinator) -> status_t {
264 AST* ast = coordinator->parse(fqName);
265 if (ast == nullptr) {
266 fprintf(stderr, "ERROR: Could not parse %s. Aborting.\n", fqName.string().c_str());
267 return UNKNOWN_ERROR;
268 }
269
270 if (generate == nullptr) return OK; // just parsing AST
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800271 (ast->*generate)(out);
272
273 return OK;
Steven Moreland5abcf012018-02-08 18:50:18 -0800274 };
275}
276
277// Common pattern: single file for package or standard out
278static FileGenerator singleFileGenerator(
279 const std::string& fileName, const FileGenerator::GenerationFunction& generationFunction) {
280 return {
281 FileGenerator::alwaysGenerate, [fileName](const FQName&) { return fileName; },
282 generationFunction,
283 };
284}
285
286static status_t generateJavaForPackage(Formatter& out, const FQName& fqName,
287 const Coordinator* coordinator) {
288 AST* ast;
Andreas Huberd29724f2016-09-14 09:33:13 -0700289 std::string limitToType;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700290
Steven Moreland5abcf012018-02-08 18:50:18 -0800291 // Required for legacy -Lmakefile files
Andreas Huber0fa9e392016-08-31 09:05:44 -0700292 if (fqName.name().find("types.") == 0) {
Andreas Huberd29724f2016-09-14 09:33:13 -0700293 limitToType = fqName.name().substr(strlen("types."));
Andreas Huber0fa9e392016-08-31 09:05:44 -0700294
Yifan Hongfece6ec2017-01-12 17:04:04 -0800295 FQName typesName = fqName.getTypesForPackage();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700296 ast = coordinator->parse(typesName);
297 } else {
298 ast = coordinator->parse(fqName);
299 }
Steven Moreland5abcf012018-02-08 18:50:18 -0800300 if (ast == nullptr) {
301 fprintf(stderr, "ERROR: Could not parse %s. Aborting.\n", fqName.string().c_str());
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700302 return UNKNOWN_ERROR;
303 }
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800304 ast->generateJava(out, limitToType);
305 return OK;
Steven Moreland5abcf012018-02-08 18:50:18 -0800306};
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700307
Steven Morelandb65e5d92018-02-08 12:44:51 -0800308static status_t dumpDefinedButUnreferencedTypeNames(const FQName& packageFQName,
309 const Coordinator* coordinator) {
310 std::vector<FQName> packageInterfaces;
311 status_t err = coordinator->appendPackageInterfacesToVector(packageFQName, &packageInterfaces);
312 if (err != OK) return err;
313
Steven Moreland40b86352018-02-01 16:03:30 -0800314 std::set<FQName> unreferencedDefinitions;
315 std::set<FQName> unreferencedImports;
Steven Morelandb65e5d92018-02-08 12:44:51 -0800316 err = coordinator->addUnreferencedTypes(packageInterfaces, &unreferencedDefinitions,
317 &unreferencedImports);
318 if (err != OK) return err;
Andreas Huber308d8a22017-11-06 14:46:52 -0800319
Steven Moreland40b86352018-02-01 16:03:30 -0800320 for (const auto& fqName : unreferencedDefinitions) {
Andreas Huber308d8a22017-11-06 14:46:52 -0800321 std::cerr
322 << "VERBOSE: DEFINED-BUT-NOT-REFERENCED "
323 << fqName.string()
324 << std::endl;
325 }
326
Steven Moreland40b86352018-02-01 16:03:30 -0800327 for (const auto& fqName : unreferencedImports) {
Andreas Huber4f4b3822017-11-15 13:18:50 -0800328 std::cerr
329 << "VERBOSE: IMPORTED-BUT-NOT-REFERENCED "
330 << fqName.string()
331 << std::endl;
332 }
333
Andreas Huber308d8a22017-11-06 14:46:52 -0800334 return OK;
335}
336
Andreas Huberd2943e12016-08-05 11:59:31 -0700337static std::string makeLibraryName(const FQName &packageFQName) {
Iliyan Malcheve2c595a2016-08-07 21:20:04 -0700338 return packageFQName.string();
Andreas Huberd2943e12016-08-05 11:59:31 -0700339}
Steven Moreland5715fed2017-01-16 11:06:47 -0800340
Steven Morelande6d7f092018-02-08 13:25:45 -0800341static status_t isPackageJavaCompatible(const FQName& packageFQName, const Coordinator* coordinator,
342 bool* compatible) {
Andreas Huber75ae95d2016-10-12 16:08:26 -0700343 std::vector<FQName> todo;
344 status_t err =
345 coordinator->appendPackageInterfacesToVector(packageFQName, &todo);
346
347 if (err != OK) {
348 return err;
349 }
350
351 std::set<FQName> seen;
352 for (const auto &iface : todo) {
353 seen.insert(iface);
354 }
355
356 // Form the transitive closure of all imported interfaces (and types.hal-s)
357 // If any one of them is not java compatible, this package isn't either.
358 while (!todo.empty()) {
359 const FQName fqName = todo.back();
360 todo.pop_back();
361
362 AST *ast = coordinator->parse(fqName);
363
364 if (ast == nullptr) {
365 return UNKNOWN_ERROR;
366 }
367
368 if (!ast->isJavaCompatible()) {
369 *compatible = false;
370 return OK;
371 }
372
373 std::set<FQName> importedPackages;
374 ast->getImportedPackages(&importedPackages);
375
376 for (const auto &package : importedPackages) {
377 std::vector<FQName> packageInterfaces;
378 status_t err = coordinator->appendPackageInterfacesToVector(
379 package, &packageInterfaces);
380
381 if (err != OK) {
382 return err;
383 }
384
385 for (const auto &iface : packageInterfaces) {
386 if (seen.find(iface) != seen.end()) {
387 continue;
388 }
389
390 todo.push_back(iface);
391 seen.insert(iface);
392 }
393 }
394 }
395
396 *compatible = true;
397 return OK;
398}
399
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700400static bool packageNeedsJavaCode(
401 const std::vector<FQName> &packageInterfaces, AST *typesAST) {
Steven Morelandadc25022017-10-11 12:42:19 -0700402 if (packageInterfaces.size() == 0) {
403 return false;
404 }
405
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700406 // If there is more than just a types.hal file to this package we'll
407 // definitely need to generate Java code.
408 if (packageInterfaces.size() > 1
409 || packageInterfaces[0].name() != "types") {
410 return true;
411 }
412
413 CHECK(typesAST != nullptr);
414
415 // We'll have to generate Java code if types.hal contains any non-typedef
416 // type declarations.
417
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700418 Scope* rootScope = typesAST->getRootScope();
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700419 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
420
421 for (const auto &subType : subTypes) {
422 if (!subType->isTypeDef()) {
423 return true;
424 }
425 }
426
427 return false;
428}
429
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800430bool validateIsPackage(const FQName& fqName, const Coordinator*,
431 const std::string& /* language */) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700432 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700433 fprintf(stderr, "ERROR: Expecting package name\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700434 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700435 }
436
437 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700438 fprintf(stderr, "ERROR: Expecting package version\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700439 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700440 }
441
442 if (!fqName.name().empty()) {
443 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700444 "ERROR: Expecting only package name and version.\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700445 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700446 }
447
Steven Moreland05951b32017-05-12 17:22:22 -0700448 return true;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700449}
450
Steven Morelandf7f2a9a2017-07-21 18:05:38 -0700451bool isHidlTransportPackage(const FQName& fqName) {
Steven Morelande1b157e2018-03-06 14:18:32 -0800452 return fqName.package() == gIBaseFqName.package() ||
453 fqName.package() == gIManagerFqName.package();
Steven Moreland77cf7642017-06-15 14:49:39 -0700454}
455
Steven Morelandc7946c92017-08-08 14:48:32 -0700456bool isSystemProcessSupportedPackage(const FQName& fqName) {
457 // Technically, so is hidl IBase + IServiceManager, but
458 // these are part of libhidltransport.
Jiyong Park45ec8d12017-11-21 10:39:22 +0900459 return fqName.string() == "android.hardware.graphics.common@1.0" ||
Steven Moreland40f11352018-01-23 11:30:43 -0800460 fqName.string() == "android.hardware.graphics.common@1.1" ||
Steven Morelandc7946c92017-08-08 14:48:32 -0700461 fqName.string() == "android.hardware.graphics.mapper@2.0" ||
Chia-I Wu620cc392017-09-28 15:33:21 -0700462 fqName.string() == "android.hardware.graphics.mapper@2.1" ||
Marissa Wall1251dba2018-12-29 16:07:17 -0800463 fqName.string() == "android.hardware.graphics.mapper@3.0" ||
Steven Morelandc7946c92017-08-08 14:48:32 -0700464 fqName.string() == "android.hardware.renderscript@1.0" ||
Howard Chen01dfc6d2017-11-30 15:37:12 +0800465 fqName.string() == "android.hidl.memory.token@1.0" ||
Steven Moreland31aa2502018-11-26 12:23:43 -0800466 fqName.string() == "android.hidl.memory@1.0" ||
467 fqName.string() == "android.hidl.safe_union@1.0";
Steven Morelandc7946c92017-08-08 14:48:32 -0700468}
469
Steven Moreland14cf3112018-11-29 12:23:49 -0800470bool isCoreAndroidPackage(const FQName& package) {
Steven Moreland5edf5282017-07-20 12:56:58 -0700471 return package.inPackage("android.hidl") ||
472 package.inPackage("android.system") ||
473 package.inPackage("android.frameworks") ||
474 package.inPackage("android.hardware");
475}
476
Steven Morelanda8153982017-11-28 15:22:28 -0800477// TODO(b/69862859): remove special case
Steven Moreland255c9a12018-02-26 13:10:27 -0800478status_t isTestPackage(const FQName& fqName, const Coordinator* coordinator, bool* isTestPackage) {
Steven Morelanda8153982017-11-28 15:22:28 -0800479 const auto fileExists = [](const std::string& file) {
480 struct stat buf;
481 return stat(file.c_str(), &buf) == 0;
482 };
483
Steven Moreland255c9a12018-02-26 13:10:27 -0800484 std::string path;
485 status_t err = coordinator->getFilepath(fqName, Coordinator::Location::PACKAGE_ROOT,
486 ".hidl_for_test", &path);
487 if (err != OK) return err;
488
Steven Morelanda8153982017-11-28 15:22:28 -0800489 const bool exists = fileExists(path);
490
491 if (exists) {
492 coordinator->onFileAccess(path, "r");
493 }
494
Steven Moreland255c9a12018-02-26 13:10:27 -0800495 *isTestPackage = exists;
496 return OK;
Steven Morelanda8153982017-11-28 15:22:28 -0800497}
498
Steven Moreland5abcf012018-02-08 18:50:18 -0800499static status_t generateAdapterMainSource(Formatter& out, const FQName& packageFQName,
Steven Morelande6d7f092018-02-08 13:25:45 -0800500 const Coordinator* coordinator) {
Steven Moreland9a6da7a2017-09-15 16:21:24 -0700501 std::vector<FQName> packageInterfaces;
502 status_t err =
503 coordinator->appendPackageInterfacesToVector(packageFQName,
504 &packageInterfaces);
505 if (err != OK) {
506 return err;
507 }
508
509 out << "#include <hidladapter/HidlBinderAdapter.h>\n";
510
511 for (auto &interface : packageInterfaces) {
512 if (interface.name() == "types") {
513 continue;
514 }
515 AST::generateCppPackageInclude(out, interface, interface.getInterfaceAdapterName());
516 }
517
518 out << "int main(int argc, char** argv) ";
519 out.block([&] {
520 out << "return ::android::hardware::adapterMain<\n";
521 out.indent();
522 for (auto &interface : packageInterfaces) {
523 if (interface.name() == "types") {
524 continue;
525 }
526 out << interface.getInterfaceAdapterFqName().cppName();
527
528 if (&interface != &packageInterfaces.back()) {
529 out << ",\n";
530 }
531 }
532 out << ">(\"" << packageFQName.string() << "\", argc, argv);\n";
533 out.unindent();
534 }).endl();
535 return OK;
536}
537
Steven Moreland5abcf012018-02-08 18:50:18 -0800538static status_t generateAndroidBpForPackage(Formatter& out, const FQName& packageFQName,
Steven Morelande6d7f092018-02-08 13:25:45 -0800539 const Coordinator* coordinator) {
Steven Moreland77730892018-03-06 14:39:41 -0800540 CHECK(!packageFQName.isFullyQualified() && packageFQName.name().empty());
Steven Moreland40069d52017-10-03 09:36:51 -0700541
542 std::vector<FQName> packageInterfaces;
543
544 status_t err = coordinator->appendPackageInterfacesToVector(packageFQName, &packageInterfaces);
545
546 if (err != OK) {
547 return err;
548 }
549
550 std::set<FQName> importedPackagesHierarchy;
Steven Moreland887b84c2017-10-09 18:40:58 -0700551 std::vector<const Type *> exportedTypes;
Steven Moreland40069d52017-10-03 09:36:51 -0700552 AST* typesAST = nullptr;
553
554 for (const auto& fqName : packageInterfaces) {
555 AST* ast = coordinator->parse(fqName);
556
Yi Kong56758da2018-07-24 16:21:37 -0700557 if (ast == nullptr) {
Steven Moreland40069d52017-10-03 09:36:51 -0700558 fprintf(stderr, "ERROR: Could not parse %s. Aborting.\n", fqName.string().c_str());
559
560 return UNKNOWN_ERROR;
561 }
562
563 if (fqName.name() == "types") {
564 typesAST = ast;
565 }
566
567 ast->getImportedPackagesHierarchy(&importedPackagesHierarchy);
Steven Moreland887b84c2017-10-09 18:40:58 -0700568 ast->appendToExportedTypesVector(&exportedTypes);
Steven Moreland40069d52017-10-03 09:36:51 -0700569 }
570
Steven Moreland313a0132017-11-03 14:23:14 -0700571 bool needsJavaCode = packageNeedsJavaCode(packageInterfaces, typesAST);
572
573 bool genJavaConstants = needsJavaCode && !exportedTypes.empty();
Steven Moreland887b84c2017-10-09 18:40:58 -0700574
575 bool isJavaCompatible;
576 err = isPackageJavaCompatible(packageFQName, coordinator, &isJavaCompatible);
577 if (err != OK) return err;
Steven Moreland313a0132017-11-03 14:23:14 -0700578 bool genJavaLibrary = needsJavaCode && isJavaCompatible;
579
Steven Moreland255c9a12018-02-26 13:10:27 -0800580 bool generateForTest;
581 err = isTestPackage(packageFQName, coordinator, &generateForTest);
582 if (err != OK) return err;
583
Steven Moreland14cf3112018-11-29 12:23:49 -0800584 bool isCoreAndroid = isCoreAndroidPackage(packageFQName);
585
586 bool isVndk = !generateForTest && isCoreAndroid;
Steven Moreland313a0132017-11-03 14:23:14 -0700587 bool isVndkSp = isVndk && isSystemProcessSupportedPackage(packageFQName);
Steven Moreland887b84c2017-10-09 18:40:58 -0700588
Steven Moreland14cf3112018-11-29 12:23:49 -0800589 // Currently, all platform-provided interfaces are in the VNDK, so if it isn't in the VNDK, it
590 // is device specific and so should be put in the product partition.
591 bool isProduct = !isCoreAndroid;
592
Steven Moreland255c9a12018-02-26 13:10:27 -0800593 std::string packageRoot;
594 err = coordinator->getPackageRoot(packageFQName, &packageRoot);
595 if (err != OK) return err;
596
Steven Moreland313a0132017-11-03 14:23:14 -0700597 out << "// This file is autogenerated by hidl-gen -Landroidbp.\n\n";
Steven Moreland40069d52017-10-03 09:36:51 -0700598
Steven Moreland313a0132017-11-03 14:23:14 -0700599 out << "hidl_interface ";
Steven Moreland40069d52017-10-03 09:36:51 -0700600 out.block([&] {
Steven Moreland313a0132017-11-03 14:23:14 -0700601 out << "name: \"" << makeLibraryName(packageFQName) << "\",\n";
Steven Moreland89a9ebb2017-12-04 10:18:00 -0800602 if (!coordinator->getOwner().empty()) {
603 out << "owner: \"" << coordinator->getOwner() << "\",\n";
604 }
Steven Moreland255c9a12018-02-26 13:10:27 -0800605 out << "root: \"" << packageRoot << "\",\n";
Steven Moreland313a0132017-11-03 14:23:14 -0700606 if (isVndk) {
607 out << "vndk: ";
608 out.block([&]() {
609 out << "enabled: true,\n";
610 if (isVndkSp) {
611 out << "support_system_process: true,\n";
612 }
613 }) << ",\n";
614 }
Steven Moreland14cf3112018-11-29 12:23:49 -0800615 if (isProduct) {
616 out << "product_specific: true,\n";
617 }
Steven Moreland313a0132017-11-03 14:23:14 -0700618 (out << "srcs: [\n").indent([&] {
Steven Moreland40069d52017-10-03 09:36:51 -0700619 for (const auto& fqName : packageInterfaces) {
620 out << "\"" << fqName.name() << ".hal\",\n";
621 }
Steven Moreland313a0132017-11-03 14:23:14 -0700622 }) << "],\n";
623 if (!importedPackagesHierarchy.empty()) {
624 (out << "interfaces: [\n").indent([&] {
625 for (const auto& fqName : importedPackagesHierarchy) {
626 out << "\"" << fqName.string() << "\",\n";
627 }
628 }) << "],\n";
629 }
630 if (typesAST != nullptr) {
631 (out << "types: [\n").indent([&] {
632 std::vector<NamedType *> subTypes = typesAST->getRootScope()->getSubTypes();
633 std::sort(
634 subTypes.begin(),
635 subTypes.end(),
636 [](const NamedType *a, const NamedType *b) -> bool {
637 return a->fqName() < b->fqName();
638 });
639
640 for (const auto &type : subTypes) {
641 if (type->isTypeDef()) {
642 continue;
643 }
644
645 out << "\"" << type->localName() << "\",\n";
646 }
647 }) << "],\n";
648 }
649 // Explicity call this out for developers.
650 out << "gen_java: " << (genJavaLibrary ? "true" : "false") << ",\n";
651 if (genJavaConstants) {
652 out << "gen_java_constants: true,\n";
653 }
Steven Moreland40069d52017-10-03 09:36:51 -0700654 }).endl().endl();
655
Steven Moreland40069d52017-10-03 09:36:51 -0700656 return OK;
657}
658
Steven Moreland5abcf012018-02-08 18:50:18 -0800659static status_t generateAndroidBpImplForPackage(Formatter& out, const FQName& packageFQName,
Steven Morelande6d7f092018-02-08 13:25:45 -0800660 const Coordinator* coordinator) {
Iliyan Malchev4923f932016-09-09 13:04:59 -0700661 const std::string libraryName = makeLibraryName(packageFQName) + "-impl";
Steven Moreland197d56c2016-09-09 10:03:58 -0700662
663 std::vector<FQName> packageInterfaces;
664
665 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700666 coordinator->appendPackageInterfacesToVector(packageFQName,
667 &packageInterfaces);
Steven Moreland197d56c2016-09-09 10:03:58 -0700668
669 if (err != OK) {
670 return err;
671 }
672
673 std::set<FQName> importedPackages;
674
675 for (const auto &fqName : packageInterfaces) {
676 AST *ast = coordinator->parse(fqName);
677
Yi Kong56758da2018-07-24 16:21:37 -0700678 if (ast == nullptr) {
Steven Moreland197d56c2016-09-09 10:03:58 -0700679 fprintf(stderr,
680 "ERROR: Could not parse %s. Aborting.\n",
681 fqName.string().c_str());
682
683 return UNKNOWN_ERROR;
684 }
685
686 ast->getImportedPackages(&importedPackages);
687 }
688
Steven Moreland7fa84262018-09-26 17:12:14 -0700689 out << "// FIXME: your file license if you have one\n\n";
Yifan Hong958ee462016-12-06 17:09:51 -0800690 out << "cc_library_shared {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800691 out.indent([&] {
Steven Moreland92f1f452018-01-04 17:55:27 -0800692 out << "// FIXME: this should only be -impl for a passthrough hal.\n"
693 << "// In most cases, to convert this to a binderized implementation, you should:\n"
694 << "// - change '-impl' to '-service' here and make it a cc_binary instead of a\n"
695 << "// cc_library_shared.\n"
696 << "// - add a *.rc file for this module.\n"
697 << "// - delete HIDL_FETCH_I* functions.\n"
698 << "// - call configureRpcThreadpool and registerAsService on the instance.\n"
699 << "// You may also want to append '-impl/-service' with a specific identifier like\n"
700 << "// '-vendor' or '-<hardware identifier>' etc to distinguish it.\n";
Steven Moreland89a9ebb2017-12-04 10:18:00 -0800701 out << "name: \"" << libraryName << "\",\n";
702 if (!coordinator->getOwner().empty()) {
703 out << "owner: \"" << coordinator->getOwner() << "\",\n";
704 }
Steven Moreland92f1f452018-01-04 17:55:27 -0800705 out << "relative_install_path: \"hw\",\n";
706 if (coordinator->getOwner().empty()) {
707 out << "// FIXME: this should be 'vendor: true' for modules that will eventually be\n"
708 "// on AOSP.\n";
709 }
710 out << "proprietary: true,\n";
711 out << "srcs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800712 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800713 for (const auto &fqName : packageInterfaces) {
714 if (fqName.name() == "types") {
715 continue;
716 }
717 out << "\"" << fqName.getInterfaceBaseName() << ".cpp\",\n";
718 }
719 });
720 out << "],\n"
721 << "shared_libs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800722 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800723 out << "\"libhidlbase\",\n"
724 << "\"libhidltransport\",\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800725 << "\"libutils\",\n"
726 << "\"" << makeLibraryName(packageFQName) << "\",\n";
Yifan Honge0f7d692016-10-20 17:51:33 -0700727
Yifan Hong958ee462016-12-06 17:09:51 -0800728 for (const auto &importedPackage : importedPackages) {
Steven Morelanddadd1842017-05-09 13:24:54 -0700729 if (isHidlTransportPackage(importedPackage)) {
730 continue;
731 }
732
Yifan Hong958ee462016-12-06 17:09:51 -0800733 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
734 }
735 });
736 out << "],\n";
737 });
738 out << "}\n";
Steven Moreland197d56c2016-09-09 10:03:58 -0700739
740 return OK;
741}
742
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800743bool validateForSource(const FQName& fqName, const Coordinator* coordinator,
744 const std::string& language) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700745 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700746 fprintf(stderr, "ERROR: Expecting package name\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700747 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700748 }
749
750 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700751 fprintf(stderr, "ERROR: Expecting package version\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700752 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700753 }
754
Andreas Huber0fa9e392016-08-31 09:05:44 -0700755 const std::string &name = fqName.name();
756 if (!name.empty()) {
757 if (name.find('.') == std::string::npos) {
Steven Moreland05951b32017-05-12 17:22:22 -0700758 return true;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700759 }
760
761 if (language != "java" || name.find("types.") != 0) {
762 // When generating java sources for "types.hal", output can be
763 // constrained to just one of the top-level types declared
764 // by using the extended syntax
765 // android.hardware.Foo@1.0::types.TopLevelTypeName.
766 // In all other cases (different language, not 'types') the dot
767 // notation in the name is illegal in this context.
Steven Moreland05951b32017-05-12 17:22:22 -0700768 return false;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700769 }
770
Steven Moreland05951b32017-05-12 17:22:22 -0700771 return true;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700772 }
773
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800774 if (language == "java") {
775 bool isJavaCompatible;
776 status_t err = isPackageJavaCompatible(fqName, coordinator, &isJavaCompatible);
777 if (err != OK) return false;
778
779 if (!isJavaCompatible) {
780 fprintf(stderr,
781 "ERROR: %s is not Java compatible. The Java backend"
782 " does NOT support union types nor native handles. "
783 "In addition, vectors of arrays are limited to at most "
784 "one-dimensional arrays and vectors of {vectors,interfaces} are"
785 " not supported.\n",
786 fqName.string().c_str());
787 return false;
788 }
789 }
790
Steven Moreland05951b32017-05-12 17:22:22 -0700791 return true;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700792}
793
Steven Moreland5abcf012018-02-08 18:50:18 -0800794FileGenerator::GenerationFunction generateExportHeaderForPackage(bool forJava) {
795 return [forJava](Formatter& out, const FQName& packageFQName,
796 const Coordinator* coordinator) -> status_t {
Steven Moreland77730892018-03-06 14:39:41 -0800797 CHECK(!packageFQName.package().empty() && !packageFQName.version().empty() &&
798 packageFQName.name().empty());
Andreas Huber019d21d2016-10-03 12:59:47 -0700799
Steven Morelandf47912d2017-05-12 16:25:44 -0700800 std::vector<FQName> packageInterfaces;
Andreas Huber019d21d2016-10-03 12:59:47 -0700801
Steven Morelandf47912d2017-05-12 16:25:44 -0700802 status_t err = coordinator->appendPackageInterfacesToVector(
803 packageFQName, &packageInterfaces);
Andreas Huber019d21d2016-10-03 12:59:47 -0700804
Steven Morelandf47912d2017-05-12 16:25:44 -0700805 if (err != OK) {
806 return err;
Andreas Huber019d21d2016-10-03 12:59:47 -0700807 }
808
Steven Morelandf47912d2017-05-12 16:25:44 -0700809 std::vector<const Type *> exportedTypes;
Andreas Huber019d21d2016-10-03 12:59:47 -0700810
Steven Morelandf47912d2017-05-12 16:25:44 -0700811 for (const auto &fqName : packageInterfaces) {
812 AST *ast = coordinator->parse(fqName);
813
Yi Kong56758da2018-07-24 16:21:37 -0700814 if (ast == nullptr) {
Steven Morelandf47912d2017-05-12 16:25:44 -0700815 fprintf(stderr,
816 "ERROR: Could not parse %s. Aborting.\n",
817 fqName.string().c_str());
818
819 return UNKNOWN_ERROR;
820 }
821
822 ast->appendToExportedTypesVector(&exportedTypes);
823 }
824
825 if (exportedTypes.empty()) {
826 return OK;
827 }
828
Steven Morelanda885d252017-09-25 18:44:43 -0700829 if (!out.isValid()) {
830 return UNKNOWN_ERROR;
Steven Morelandf47912d2017-05-12 16:25:44 -0700831 }
832
Steven Moreland255c9a12018-02-26 13:10:27 -0800833 std::string packagePath;
834 err = coordinator->getPackagePath(packageFQName, false /* relative */,
835 false /* sanitized */, &packagePath);
836 if (err != OK) return err;
837
Steven Morelandf47912d2017-05-12 16:25:44 -0700838 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n"
839 << "// Source: " << packageFQName.string() << "\n"
Steven Moreland255c9a12018-02-26 13:10:27 -0800840 << "// Location: " << packagePath << "\n\n";
Steven Morelandf47912d2017-05-12 16:25:44 -0700841
842 std::string guard;
843 if (forJava) {
844 out << "package " << packageFQName.javaPackage() << ";\n\n";
845 out << "public class Constants {\n";
846 out.indent();
847 } else {
848 guard = "HIDL_GENERATED_";
849 guard += StringHelper::Uppercase(packageFQName.tokenName());
850 guard += "_";
851 guard += "EXPORTED_CONSTANTS_H_";
852
853 out << "#ifndef "
854 << guard
855 << "\n#define "
856 << guard
857 << "\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
858 }
859
860 for (const auto &type : exportedTypes) {
861 type->emitExportedHeader(out, forJava);
862 }
863
864 if (forJava) {
865 out.unindent();
866 out << "}\n";
867 } else {
868 out << "#ifdef __cplusplus\n}\n#endif\n\n#endif // "
869 << guard
870 << "\n";
871 }
872
Andreas Huber019d21d2016-10-03 12:59:47 -0700873 return OK;
Steven Morelandf47912d2017-05-12 16:25:44 -0700874 };
Andreas Huber019d21d2016-10-03 12:59:47 -0700875}
876
Steven Moreland5abcf012018-02-08 18:50:18 -0800877static status_t generateHashOutput(Formatter& out, const FQName& fqName,
878 const Coordinator* coordinator) {
879 CHECK(fqName.isFullyQualified());
Steven Morelandf2e44692017-04-18 20:19:09 -0700880
Steven Moreland5abcf012018-02-08 18:50:18 -0800881 AST* ast = coordinator->parse(fqName, {} /* parsed */,
882 Coordinator::Enforce::NO_HASH /* enforcement */);
883
Yi Kong56758da2018-07-24 16:21:37 -0700884 if (ast == nullptr) {
Steven Moreland5abcf012018-02-08 18:50:18 -0800885 fprintf(stderr, "ERROR: Could not parse %s. Aborting.\n", fqName.string().c_str());
886
887 return UNKNOWN_ERROR;
Steven Morelandf2e44692017-04-18 20:19:09 -0700888 }
889
Steven Moreland5abcf012018-02-08 18:50:18 -0800890 out << Hash::getHash(ast->getFilename()).hexString() << " " << fqName.string() << "\n";
Steven Morelandf2e44692017-04-18 20:19:09 -0700891
892 return OK;
893}
894
Steven Moreland55df0712019-01-16 14:37:11 -0800895static status_t generateFunctionCount(Formatter& out, const FQName& fqName,
896 const Coordinator* coordinator) {
897 CHECK(fqName.isFullyQualified());
898
899 AST* ast = coordinator->parse(fqName, {} /* parsed */,
900 Coordinator::Enforce::NO_HASH /* enforcement */);
901
902 if (ast == nullptr) {
903 fprintf(stderr, "ERROR: Could not parse %s. Aborting.\n", fqName.string().c_str());
904 return UNKNOWN_ERROR;
905 }
906
907 const Interface* interface = ast->getInterface();
908 if (interface == nullptr) {
909 fprintf(stderr, "ERROR: Function count requires interface: %s.\n", fqName.string().c_str());
910 return UNKNOWN_ERROR;
911 }
912
913 // This is wrong for android.hidl.base@1.0::IBase, but in that case, it doesn't matter.
914 // This is just the number of APIs that are added.
915 out << fqName.string() << " " << interface->userDefinedMethods().size() << "\n";
916
917 return OK;
918}
919
Steven Moreland5abcf012018-02-08 18:50:18 -0800920template <typename T>
921std::vector<T> operator+(const std::vector<T>& lhs, const std::vector<T>& rhs) {
922 std::vector<T> ret;
923 ret.reserve(lhs.size() + rhs.size());
924 ret.insert(ret.begin(), lhs.begin(), lhs.end());
925 ret.insert(ret.end(), rhs.begin(), rhs.end());
926 return ret;
927}
928
Steven Moreland0241a842017-10-06 10:26:07 -0700929// clang-format off
Steven Moreland5abcf012018-02-08 18:50:18 -0800930static const std::vector<FileGenerator> kCppHeaderFormats = {
931 {
932 FileGenerator::alwaysGenerate,
933 [](const FQName& fqName) { return fqName.name() + ".h"; },
934 astGenerationFunction(&AST::generateInterfaceHeader),
Steven Moreland3b1ce262017-04-21 14:19:59 -0700935 },
Steven Moreland5abcf012018-02-08 18:50:18 -0800936 {
937 FileGenerator::alwaysGenerate,
938 [](const FQName& fqName) {
939 return fqName.isInterfaceName() ? fqName.getInterfaceHwName() + ".h" : "hwtypes.h";
940 },
941 astGenerationFunction(&AST::generateHwBinderHeader),
942 },
943 {
944 FileGenerator::generateForInterfaces,
945 [](const FQName& fqName) { return fqName.getInterfaceStubName() + ".h"; },
946 astGenerationFunction(&AST::generateStubHeader),
947 },
948 {
949 FileGenerator::generateForInterfaces,
950 [](const FQName& fqName) { return fqName.getInterfaceProxyName() + ".h"; },
951 astGenerationFunction(&AST::generateProxyHeader),
952 },
953 {
954 FileGenerator::generateForInterfaces,
955 [](const FQName& fqName) { return fqName.getInterfacePassthroughName() + ".h"; },
956 astGenerationFunction(&AST::generatePassthroughHeader),
957 },
958};
Steven Moreland3b1ce262017-04-21 14:19:59 -0700959
Steven Moreland5abcf012018-02-08 18:50:18 -0800960static const std::vector<FileGenerator> kCppSourceFormats = {
961 {
962 FileGenerator::alwaysGenerate,
963 [](const FQName& fqName) {
964 return fqName.isInterfaceName() ? fqName.getInterfaceBaseName() + "All.cpp" : "types.cpp";
965 },
966 astGenerationFunction(&AST::generateCppSource),
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700967 },
Steven Moreland5abcf012018-02-08 18:50:18 -0800968};
Steven Moreland1cbf0362017-05-09 14:32:53 -0700969
Steven Moreland5abcf012018-02-08 18:50:18 -0800970static const std::vector<FileGenerator> kCppImplHeaderFormats = {
971 {
972 FileGenerator::generateForInterfaces,
973 [](const FQName& fqName) { return fqName.getInterfaceBaseName() + ".h"; },
974 astGenerationFunction(&AST::generateCppImplHeader),
Andreas Huber019d21d2016-10-03 12:59:47 -0700975 },
Steven Moreland5abcf012018-02-08 18:50:18 -0800976};
Andreas Huber019d21d2016-10-03 12:59:47 -0700977
Steven Moreland5abcf012018-02-08 18:50:18 -0800978static const std::vector<FileGenerator> kCppImplSourceFormats = {
979 {
980 FileGenerator::generateForInterfaces,
981 [](const FQName& fqName) { return fqName.getInterfaceBaseName() + ".cpp"; },
982 astGenerationFunction(&AST::generateCppImplSource),
Steven Moreland9c387612016-09-07 09:54:26 -0700983 },
Steven Moreland5abcf012018-02-08 18:50:18 -0800984};
Steven Moreland9c387612016-09-07 09:54:26 -0700985
Steven Moreland5abcf012018-02-08 18:50:18 -0800986static const std::vector<FileGenerator> kCppAdapterHeaderFormats = {
987 {
988 FileGenerator::alwaysGenerate,
989 [](const FQName& fqName) {
990 return fqName.isInterfaceName() ? fqName.getInterfaceAdapterName() + ".h" : "Atypes.h";
991 },
992 astGenerationFunction(&AST::generateCppAdapterHeader),
Steven Moreland9a6da7a2017-09-15 16:21:24 -0700993 },
Steven Moreland5abcf012018-02-08 18:50:18 -0800994};
Steven Moreland9a6da7a2017-09-15 16:21:24 -0700995
Steven Moreland5abcf012018-02-08 18:50:18 -0800996static const std::vector<FileGenerator> kCppAdapterSourceFormats = {
997 {
998 FileGenerator::alwaysGenerate,
999 [](const FQName& fqName) {
1000 return fqName.isInterfaceName() ? fqName.getInterfaceAdapterName() + ".cpp" : "Atypes.cpp";
1001 },
1002 astGenerationFunction(&AST::generateCppAdapterSource),
Andreas Huber2831d512016-08-15 09:33:47 -07001003 },
Steven Moreland5abcf012018-02-08 18:50:18 -08001004};
Andreas Huber2831d512016-08-15 09:33:47 -07001005
Steven Moreland5abcf012018-02-08 18:50:18 -08001006static const std::vector<OutputHandler> kFormats = {
1007 {
1008 "check",
1009 "Parses the interface to see if valid but doesn't write any files.",
1010 OutputMode::NOT_NEEDED,
1011 Coordinator::Location::STANDARD_OUT,
1012 GenerationGranularity::PER_FILE,
1013 validateForSource,
1014 {
1015 {
1016 FileGenerator::alwaysGenerate,
1017 nullptr /* filename for fqname */,
1018 astGenerationFunction(),
1019 },
1020 },
Andreas Huber1c507272016-10-05 14:33:21 -07001021 },
Steven Moreland5abcf012018-02-08 18:50:18 -08001022 {
1023 "c++",
1024 "(internal) (deprecated) Generates C++ interface files for talking to HIDL interfaces.",
1025 OutputMode::NEEDS_DIR,
1026 Coordinator::Location::GEN_OUTPUT,
1027 GenerationGranularity::PER_FILE,
1028 validateForSource,
1029 kCppHeaderFormats + kCppSourceFormats,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001030 },
Steven Moreland5abcf012018-02-08 18:50:18 -08001031 {
1032 "c++-headers",
1033 "(internal) Generates C++ headers for interface files for talking to HIDL interfaces.",
1034 OutputMode::NEEDS_DIR,
1035 Coordinator::Location::GEN_OUTPUT,
1036 GenerationGranularity::PER_FILE,
1037 validateForSource,
1038 kCppHeaderFormats,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001039 },
Steven Moreland5abcf012018-02-08 18:50:18 -08001040 {
1041 "c++-sources",
1042 "(internal) Generates C++ sources for interface files for talking to HIDL interfaces.",
1043 OutputMode::NEEDS_DIR,
1044 Coordinator::Location::GEN_OUTPUT,
1045 GenerationGranularity::PER_FILE,
1046 validateForSource,
1047 kCppSourceFormats,
Dan Willemsen676abdc2016-09-28 19:42:22 -07001048 },
Steven Moreland5abcf012018-02-08 18:50:18 -08001049 {
1050 "export-header",
1051 "Generates a header file from @export enumerations to help maintain legacy code.",
1052 OutputMode::NEEDS_FILE,
1053 Coordinator::Location::DIRECT,
1054 GenerationGranularity::PER_PACKAGE,
1055 validateIsPackage,
1056 {singleFileGenerator("", generateExportHeaderForPackage(false /* forJava */))}
Steven Morelandf2e44692017-04-18 20:19:09 -07001057 },
Steven Moreland5abcf012018-02-08 18:50:18 -08001058 {
1059 "c++-impl",
1060 "Generates boilerplate implementation of a hidl interface in C++ (for convenience).",
1061 OutputMode::NEEDS_DIR,
1062 Coordinator::Location::DIRECT,
1063 GenerationGranularity::PER_FILE,
1064 validateForSource,
1065 kCppImplHeaderFormats + kCppImplSourceFormats,
1066 },
1067 {
1068 "c++-impl-headers",
Alessio Balsini56a0c832019-01-10 12:53:01 +00001069 "c++-impl but headers only.",
Steven Moreland5abcf012018-02-08 18:50:18 -08001070 OutputMode::NEEDS_DIR,
1071 Coordinator::Location::DIRECT,
1072 GenerationGranularity::PER_FILE,
1073 validateForSource,
1074 kCppImplHeaderFormats,
1075 },
1076 {
1077 "c++-impl-sources",
Alessio Balsini56a0c832019-01-10 12:53:01 +00001078 "c++-impl but sources only.",
Steven Moreland5abcf012018-02-08 18:50:18 -08001079 OutputMode::NEEDS_DIR,
1080 Coordinator::Location::DIRECT,
1081 GenerationGranularity::PER_FILE,
1082 validateForSource,
1083 kCppImplSourceFormats,
1084 },
1085 {
1086 "c++-adapter",
1087 "Takes a x.(y+n) interface and mocks an x.y interface.",
1088 OutputMode::NEEDS_DIR,
1089 Coordinator::Location::GEN_OUTPUT,
1090 GenerationGranularity::PER_FILE,
1091 validateForSource,
1092 kCppAdapterHeaderFormats + kCppAdapterSourceFormats,
1093 },
1094 {
1095 "c++-adapter-headers",
Alessio Balsini56a0c832019-01-10 12:53:01 +00001096 "c++-adapter but helper headers only.",
Steven Moreland5abcf012018-02-08 18:50:18 -08001097 OutputMode::NEEDS_DIR,
1098 Coordinator::Location::GEN_OUTPUT,
1099 GenerationGranularity::PER_FILE,
1100 validateForSource,
1101 kCppAdapterHeaderFormats,
1102 },
1103 {
1104 "c++-adapter-sources",
Alessio Balsini56a0c832019-01-10 12:53:01 +00001105 "c++-adapter but helper sources only.",
Steven Moreland5abcf012018-02-08 18:50:18 -08001106 OutputMode::NEEDS_DIR,
1107 Coordinator::Location::GEN_OUTPUT,
1108 GenerationGranularity::PER_FILE,
1109 validateForSource,
1110 kCppAdapterSourceFormats,
1111 },
1112 {
1113 "c++-adapter-main",
Alessio Balsini56a0c832019-01-10 12:53:01 +00001114 "c++-adapter but the adapter binary source only.",
Steven Moreland5abcf012018-02-08 18:50:18 -08001115 OutputMode::NEEDS_DIR,
1116 Coordinator::Location::DIRECT,
1117 GenerationGranularity::PER_PACKAGE,
1118 validateIsPackage,
1119 {singleFileGenerator("main.cpp", generateAdapterMainSource)},
1120 },
1121 {
1122 "java",
1123 "(internal) Generates Java library for talking to HIDL interfaces in Java.",
1124 OutputMode::NEEDS_DIR,
1125 Coordinator::Location::GEN_SANITIZED,
1126 GenerationGranularity::PER_TYPE,
1127 validateForSource,
1128 {
1129 {
1130 FileGenerator::alwaysGenerate,
1131 [](const FQName& fqName) {
1132 return StringHelper::LTrim(fqName.name(), "types.") + ".java";
1133 },
1134 generateJavaForPackage,
1135 },
1136 }
1137 },
1138 {
1139 "java-constants",
1140 "(internal) Like export-header but for Java (always created by -Lmakefile if @export exists).",
1141 OutputMode::NEEDS_DIR,
1142 Coordinator::Location::GEN_SANITIZED,
1143 GenerationGranularity::PER_PACKAGE,
1144 validateIsPackage,
1145 {singleFileGenerator("Constants.java", generateExportHeaderForPackage(true /* forJava */))}
1146 },
1147 {
1148 "vts",
1149 "(internal) Generates vts proto files for use in vtsd.",
1150 OutputMode::NEEDS_DIR,
1151 Coordinator::Location::GEN_OUTPUT,
1152 GenerationGranularity::PER_FILE,
1153 validateForSource,
1154 {
1155 {
1156 FileGenerator::alwaysGenerate,
1157 [](const FQName& fqName) {
1158 return fqName.isInterfaceName() ? fqName.getInterfaceBaseName() + ".vts" : "types.vts";
1159 },
1160 astGenerationFunction(&AST::generateVts),
1161 },
1162 }
1163 },
1164 {
1165 "makefile",
1166 "(removed) Used to generate makefiles for -Ljava and -Ljava-constants.",
1167 OutputMode::NEEDS_SRC,
1168 Coordinator::Location::PACKAGE_ROOT,
1169 GenerationGranularity::PER_PACKAGE,
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001170 [](const FQName &, const Coordinator*, const std::string &) {
Steven Moreland5abcf012018-02-08 18:50:18 -08001171 fprintf(stderr, "ERROR: makefile output is not supported. Use -Landroidbp for all build file generation.\n");
1172 return false;
1173 },
1174 {},
1175 },
1176 {
1177 "androidbp",
1178 "(internal) Generates Soong bp files for -Lc++-headers, -Lc++-sources, -Ljava, -Ljava-constants, and -Lc++-adapter.",
1179 OutputMode::NEEDS_SRC,
1180 Coordinator::Location::PACKAGE_ROOT,
1181 GenerationGranularity::PER_PACKAGE,
1182 validateIsPackage,
1183 {singleFileGenerator("Android.bp", generateAndroidBpForPackage)},
1184 },
1185 {
1186 "androidbp-impl",
1187 "Generates boilerplate bp files for implementation created with -Lc++-impl.",
1188 OutputMode::NEEDS_DIR,
1189 Coordinator::Location::DIRECT,
1190 GenerationGranularity::PER_PACKAGE,
1191 validateIsPackage,
1192 {singleFileGenerator("Android.bp", generateAndroidBpImplForPackage)},
1193 },
1194 {
1195 "hash",
1196 "Prints hashes of interface in `current.txt` format to standard out.",
1197 OutputMode::NOT_NEEDED,
1198 Coordinator::Location::STANDARD_OUT,
1199 GenerationGranularity::PER_FILE,
1200 validateForSource,
1201 {
1202 {
1203 FileGenerator::alwaysGenerate,
1204 nullptr /* file name for fqName */,
1205 generateHashOutput,
1206 },
1207 }
Steven Morelandf2e44692017-04-18 20:19:09 -07001208 },
Yifan Honge4010112018-10-05 11:44:15 -07001209 {
Steven Moreland55df0712019-01-16 14:37:11 -08001210 "function-count",
1211 "Prints the total number of functions added by the package or interface.",
1212 OutputMode::NOT_NEEDED,
1213 Coordinator::Location::STANDARD_OUT,
1214 GenerationGranularity::PER_FILE,
1215 validateForSource,
1216 {
1217 {
1218 FileGenerator::generateForInterfaces,
1219 nullptr /* file name for fqName */,
1220 generateFunctionCount,
1221 },
1222 }
1223 },
1224 {
Yifan Honge4010112018-10-05 11:44:15 -07001225 "dependencies",
1226 "Prints all depended types.",
1227 OutputMode::NOT_NEEDED,
1228 Coordinator::Location::STANDARD_OUT,
1229 GenerationGranularity::PER_FILE,
1230 validateForSource,
1231 {
1232 {
1233 FileGenerator::alwaysGenerate,
1234 nullptr /* file name for fqName */,
1235 astGenerationFunction(&AST::generateDependencies),
1236 },
1237 },
1238 },
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001239};
Steven Moreland0241a842017-10-06 10:26:07 -07001240// clang-format on
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001241
1242static void usage(const char *me) {
1243 fprintf(stderr,
Steven Moreland89a9ebb2017-12-04 10:18:00 -08001244 "usage: %s [-p <root path>] -o <output path> -L <language> [-O <owner>] (-r <interface "
Yifan Hong5418c112018-10-09 17:30:22 -07001245 "root>)+ [-R] [-v] [-d <depfile>] FQNAME...\n\n",
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001246 me);
1247
Steven Morelanda12df112018-02-15 14:32:46 -08001248 fprintf(stderr,
1249 "Process FQNAME, PACKAGE(.SUBPACKAGE)*@[0-9]+.[0-9]+(::TYPE)?, to create output.\n\n");
1250
Steven Moreland97e52332017-05-12 16:47:19 -07001251 fprintf(stderr, " -h: Prints this menu.\n");
1252 fprintf(stderr, " -L <language>: The following options are available:\n");
Steven Moreland5abcf012018-02-08 18:50:18 -08001253 for (auto& e : kFormats) {
Steven Moreland97e52332017-05-12 16:47:19 -07001254 fprintf(stderr, " %-16s: %s\n", e.name().c_str(), e.description().c_str());
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001255 }
Steven Moreland89a9ebb2017-12-04 10:18:00 -08001256 fprintf(stderr, " -O <owner>: The owner of the module for -Landroidbp(-impl)?.\n");
Steven Moreland97e52332017-05-12 16:47:19 -07001257 fprintf(stderr, " -o <output path>: Location to output files.\n");
1258 fprintf(stderr, " -p <root path>: Android build root, defaults to $ANDROID_BUILD_TOP or pwd.\n");
Alessio Balsini56a0c832019-01-10 12:53:01 +00001259 fprintf(stderr, " -R: Do not add default package roots if not specified in -r.\n");
Steven Moreland97e52332017-05-12 16:47:19 -07001260 fprintf(stderr, " -r <package:path root>: E.g., android.hardware:hardware/interfaces.\n");
Steven Morelanda838ceb2018-02-06 13:19:23 -08001261 fprintf(stderr, " -v: verbose output.\n");
Steven Moreland394af5c2018-02-09 14:41:46 -08001262 fprintf(stderr, " -d <depfile>: location of depfile to write to.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001263}
1264
Andreas Gampec4ce9262017-04-27 21:03:20 -07001265// hidl is intentionally leaky. Turn off LeakSanitizer by default.
1266extern "C" const char *__asan_default_options() {
Evgenii Stepanova3ee97c2017-08-16 14:59:29 -07001267 return "detect_leaks=0";
Andreas Gampec4ce9262017-04-27 21:03:20 -07001268}
1269
Andreas Huberb82318c2016-08-02 14:45:54 -07001270int main(int argc, char **argv) {
Andreas Huber737080b2016-08-02 15:38:04 -07001271 const char *me = argv[0];
Steven Moreland3db99f22017-05-11 16:21:46 -07001272 if (argc == 1) {
1273 usage(me);
1274 exit(1);
1275 }
1276
Steven Moreland5abcf012018-02-08 18:50:18 -08001277 const OutputHandler* outputFormat = nullptr;
Steven Moreland47792c42017-09-20 10:03:20 -07001278 Coordinator coordinator;
1279 std::string outputPath;
Yifan Hong5418c112018-10-09 17:30:22 -07001280 bool suppressDefaultPackagePaths = false;
Steven Moreland47792c42017-09-20 10:03:20 -07001281
Andreas Huberb82318c2016-08-02 14:45:54 -07001282 int res;
Yifan Hong5418c112018-10-09 17:30:22 -07001283 while ((res = getopt(argc, argv, "hp:o:O:r:L:vd:R")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -07001284 switch (res) {
Steven Moreland394af5c2018-02-09 14:41:46 -08001285 case 'p': {
Steven Moreland0d93b142018-01-04 17:26:30 -08001286 if (!coordinator.getRootPath().empty()) {
1287 fprintf(stderr, "ERROR: -p <root path> can only be specified once.\n");
1288 exit(1);
1289 }
Steven Moreland47792c42017-09-20 10:03:20 -07001290 coordinator.setRootPath(optarg);
Steven Morelandf7fa0682017-05-11 16:14:55 -07001291 break;
1292 }
1293
Steven Moreland394af5c2018-02-09 14:41:46 -08001294 case 'v': {
Steven Moreland37c57ee2017-09-25 19:08:56 -07001295 coordinator.setVerbose(true);
1296 break;
1297 }
1298
Steven Moreland394af5c2018-02-09 14:41:46 -08001299 case 'd': {
1300 coordinator.setDepFile(optarg);
1301 break;
1302 }
1303
1304 case 'o': {
Steven Moreland0d93b142018-01-04 17:26:30 -08001305 if (!outputPath.empty()) {
1306 fprintf(stderr, "ERROR: -o <output path> can only be specified once.\n");
1307 exit(1);
1308 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001309 outputPath = optarg;
Andreas Huberb82318c2016-08-02 14:45:54 -07001310 break;
1311 }
1312
Steven Moreland89a9ebb2017-12-04 10:18:00 -08001313 case 'O': {
1314 if (!coordinator.getOwner().empty()) {
1315 fprintf(stderr, "ERROR: -O <owner> can only be specified once.\n");
1316 exit(1);
1317 }
1318 coordinator.setOwner(optarg);
1319 break;
1320 }
1321
Steven Moreland394af5c2018-02-09 14:41:46 -08001322 case 'r': {
Andreas Huberdca261f2016-08-04 13:47:51 -07001323 std::string val(optarg);
1324 auto index = val.find_first_of(':');
Steven Moreland4ff74202017-04-21 14:24:47 -07001325 if (index == std::string::npos) {
1326 fprintf(stderr, "ERROR: -r option must contain ':': %s\n", val.c_str());
1327 exit(1);
1328 }
Andreas Huberdca261f2016-08-04 13:47:51 -07001329
Steven Moreland13594d12017-09-28 23:27:50 +00001330 auto root = val.substr(0, index);
1331 auto path = val.substr(index + 1);
Steven Moreland47792c42017-09-20 10:03:20 -07001332
1333 std::string error;
1334 status_t err = coordinator.addPackagePath(root, path, &error);
1335 if (err != OK) {
1336 fprintf(stderr, "%s\n", error.c_str());
1337 exit(1);
1338 }
1339
Andreas Huberdca261f2016-08-04 13:47:51 -07001340 break;
1341 }
1342
Yifan Hong5418c112018-10-09 17:30:22 -07001343 case 'R': {
1344 suppressDefaultPackagePaths = true;
1345 break;
1346 }
1347
Steven Moreland394af5c2018-02-09 14:41:46 -08001348 case 'L': {
Steven Morelanddd583842017-04-19 13:09:57 -07001349 if (outputFormat != nullptr) {
1350 fprintf(stderr,
1351 "ERROR: only one -L option allowed. \"%s\" already specified.\n",
1352 outputFormat->name().c_str());
1353 exit(1);
1354 }
Steven Moreland5abcf012018-02-08 18:50:18 -08001355 for (auto& e : kFormats) {
Steven Morelanddd583842017-04-19 13:09:57 -07001356 if (e.name() == optarg) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001357 outputFormat = &e;
1358 break;
1359 }
1360 }
Steven Morelanddd583842017-04-19 13:09:57 -07001361 if (outputFormat == nullptr) {
1362 fprintf(stderr,
1363 "ERROR: unrecognized -L option: \"%s\".\n",
1364 optarg);
1365 exit(1);
1366 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001367 break;
1368 }
1369
Andreas Huberb82318c2016-08-02 14:45:54 -07001370 case '?':
1371 case 'h':
Steven Moreland394af5c2018-02-09 14:41:46 -08001372 default: {
Andreas Huber737080b2016-08-02 15:38:04 -07001373 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -07001374 exit(1);
1375 break;
1376 }
1377 }
1378 }
1379
Steven Moreland0d93b142018-01-04 17:26:30 -08001380 if (coordinator.getRootPath().empty()) {
1381 const char* ANDROID_BUILD_TOP = getenv("ANDROID_BUILD_TOP");
1382 if (ANDROID_BUILD_TOP != nullptr) {
1383 coordinator.setRootPath(ANDROID_BUILD_TOP);
1384 }
1385 }
1386
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001387 if (outputFormat == nullptr) {
Steven Morelanddd583842017-04-19 13:09:57 -07001388 fprintf(stderr,
1389 "ERROR: no -L option provided.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001390 exit(1);
1391 }
1392
Andreas Huberb82318c2016-08-02 14:45:54 -07001393 argc -= optind;
1394 argv += optind;
1395
Steven Moreland3effa832017-06-16 16:17:41 -07001396 if (argc == 0) {
1397 fprintf(stderr, "ERROR: no fqname specified.\n");
1398 usage(me);
1399 exit(1);
1400 }
1401
Andreas Huber737080b2016-08-02 15:38:04 -07001402 // Valid options are now in argv[0] .. argv[argc - 1].
1403
Andreas Huber019d21d2016-10-03 12:59:47 -07001404 switch (outputFormat->mOutputMode) {
Steven Moreland5abcf012018-02-08 18:50:18 -08001405 case OutputMode::NEEDS_DIR:
1406 case OutputMode::NEEDS_FILE: {
Andreas Huber019d21d2016-10-03 12:59:47 -07001407 if (outputPath.empty()) {
1408 usage(me);
1409 exit(1);
1410 }
1411
Steven Moreland5abcf012018-02-08 18:50:18 -08001412 if (outputFormat->mOutputMode == OutputMode::NEEDS_DIR) {
Howard Chen30f6b492017-08-24 16:50:12 +08001413 if (outputPath.back() != '/') {
Andreas Huber019d21d2016-10-03 12:59:47 -07001414 outputPath += "/";
1415 }
1416 }
1417 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001418 }
Steven Moreland5abcf012018-02-08 18:50:18 -08001419 case OutputMode::NEEDS_SRC: {
Steven Morelanda171b562017-05-12 15:18:03 -07001420 if (outputPath.empty()) {
Steven Moreland47792c42017-09-20 10:03:20 -07001421 outputPath = coordinator.getRootPath();
Steven Morelanda171b562017-05-12 15:18:03 -07001422 }
Howard Chen30f6b492017-08-24 16:50:12 +08001423 if (outputPath.back() != '/') {
1424 outputPath += "/";
1425 }
Steven Morelanda171b562017-05-12 15:18:03 -07001426
1427 break;
1428 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001429
1430 default:
1431 outputPath.clear(); // Unused.
1432 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001433 }
1434
Steven Moreland6d3d3c82018-02-08 11:49:34 -08001435 coordinator.setOutputPath(outputPath);
1436
Yifan Hong5418c112018-10-09 17:30:22 -07001437 if (!suppressDefaultPackagePaths) {
1438 coordinator.addDefaultPackagePath("android.hardware", "hardware/interfaces");
1439 coordinator.addDefaultPackagePath("android.hidl", "system/libhidl/transport");
1440 coordinator.addDefaultPackagePath("android.frameworks", "frameworks/hardware/interfaces");
1441 coordinator.addDefaultPackagePath("android.system", "system/hardware/interfaces");
1442 }
Andreas Huber5345ec22016-07-29 13:33:27 -07001443
Andreas Huber737080b2016-08-02 15:38:04 -07001444 for (int i = 0; i < argc; ++i) {
Steven Morelande7d32102018-12-03 17:03:36 -08001445 const char* arg = argv[i];
1446
Steven Morelande1b157e2018-03-06 14:18:32 -08001447 FQName fqName;
Steven Morelande7d32102018-12-03 17:03:36 -08001448 if (!FQName::parse(arg, &fqName)) {
1449 fprintf(stderr, "ERROR: Invalid fully-qualified name as argument: %s.\n", arg);
1450 exit(1);
1451 }
1452
1453 if (coordinator.getPackageInterfaceFiles(fqName, nullptr /*fileNames*/) != OK) {
1454 fprintf(stderr, "ERROR: Could not get sources for %s.\n", arg);
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001455 exit(1);
1456 }
Andreas Huber881227d2016-08-02 14:20:21 -07001457
Steven Morelandb65e5d92018-02-08 12:44:51 -08001458 // Dump extra verbose output
1459 if (coordinator.isVerbose()) {
1460 status_t err =
1461 dumpDefinedButUnreferencedTypeNames(fqName.getPackageAndVersion(), &coordinator);
1462 if (err != OK) return err;
1463 }
1464
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001465 if (!outputFormat->validate(fqName, &coordinator, outputFormat->name())) {
Steven Morelandf2e44692017-04-18 20:19:09 -07001466 fprintf(stderr,
1467 "ERROR: output handler failed.\n");
Andreas Hubere61e3f72016-08-03 10:22:03 -07001468 exit(1);
1469 }
Andreas Huberd2943e12016-08-05 11:59:31 -07001470
Steven Moreland1125cf32018-02-08 13:15:27 -08001471 status_t err = outputFormat->generate(fqName, &coordinator);
Steven Moreland394af5c2018-02-09 14:41:46 -08001472 if (err != OK) exit(1);
Andreas Huberd2943e12016-08-05 11:59:31 -07001473
Steven Moreland394af5c2018-02-09 14:41:46 -08001474 err = outputFormat->writeDepFile(fqName, &coordinator);
1475 if (err != OK) exit(1);
Andreas Hubereb1081f2016-07-28 13:13:24 -07001476 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001477
Andreas Huberd2943e12016-08-05 11:59:31 -07001478 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -07001479}