1 /*
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 
17 #ifndef COORDINATOR_H_
18 
19 #define COORDINATOR_H_
20 
21 #include <android-base/macros.h>
22 #include <hidl-util/FQName.h>
23 #include <hidl-util/Formatter.h>
24 #include <utils/Errors.h>
25 #include <map>
26 #include <set>
27 #include <string>
28 #include <vector>
29 
30 namespace android {
31 
32 struct AST;
33 struct Type;
34 
35 struct Coordinator {
CoordinatorCoordinator36     Coordinator() {};
37 
38     const std::string& getRootPath() const;
39     void setRootPath(const std::string &rootPath);
40     void setOutputPath(const std::string& outputPath);
41 
42     void setVerbose(bool value);
43     bool isVerbose() const;
44 
45     void setRequireFrozen(bool requireFrozen);
46 
47     void setDepFile(const std::string& depFile);
48 
49     const std::string& getOwner() const;
50     void setOwner(const std::string& owner);
51 
52     // adds path only if it doesn't exist
53     status_t addPackagePath(const std::string& root, const std::string& path, std::string* error);
54     // adds path if it hasn't already been added
55     void addDefaultPackagePath(const std::string& root, const std::string& path);
56 
57     enum class Location {
58         STANDARD_OUT,
59         DIRECT,         // mOutputPath + file name
60         PACKAGE_ROOT,   // e.x. mRootPath + /nfc/1.0/Android.bp
61         GEN_OUTPUT,     // e.x. mOutputPath + /android/hardware/foo/1.0/*.cpp
62         GEN_SANITIZED,  // e.x. mOutputPath + /android/hardware/foo/V1_0/*.cpp
63     };
64 
65     status_t getFilepath(const FQName& fqName, Location location, const std::string& fileName,
66                          std::string* path) const;
67 
68     Formatter getFormatter(const FQName& fqName, Location location,
69                            const std::string& fileName) const;
70 
71     // must be called before file access
72     void onFileAccess(const std::string& path, const std::string& mode) const;
73 
74     status_t writeDepFile(const std::string& forFile) const;
75 
76     enum class Enforce {
77         FULL,     // default
78         NO_HASH,  // only for use with -Lhash
79         NONE,     // only for use during enforcement
80     };
81 
82     // Attempts to parse the interface/types referred to by fqName.
83     // Parsing an interface also parses the associated package's types.hal
84     // file if it exists.
85     // If "parsedASTs" is non-NULL, successfully parsed ASTs are inserted
86     // into the set.
87     // If !enforce, enforceRestrictionsOnPackage won't be run.
88     AST* parse(const FQName& fqName, std::set<AST*>* parsedASTs = nullptr,
89                Enforce enforcement = Enforce::FULL) const;
90 
91     // Same as parse, but it distinguishes between "missing file" and "could not parse AST"
92     // return OK, out *ast:
93     //    0xdeadbeef -> successfully parsed
94     //    nullptr    -> file not present
95     // return !OK
96     //    could not parse AST and file exists
97     status_t parseOptional(const FQName& fqName, AST** ast, std::set<AST*>* parsedASTs = nullptr,
98                            Enforce enforcement = Enforce::FULL) const;
99 
100     // Given package-root paths of ["hardware/interfaces",
101     // "vendor/<something>/interfaces"], package roots of
102     // ["android.hardware", "vendor.<something>.hardware"], and a
103     // FQName of "android.hardware.nfc@1.0::INfc, then getPackagePath()
104     // will return "hardware/interfaces/nfc/1.0" (if sanitized = false)
105     // or "hardware/interfaces/nfc/V1_0" (if sanitized = true).
106     status_t getPackagePath(const FQName& fqName, bool relative, bool sanitized,
107                             std::string* path) const;
108 
109     // Given package roots of ["android.hardware",
110     // "vendor.<something>.hardware"] and a FQName of
111     // "android.hardware.nfc@1.0::INfc, then getPackageRoot() will
112     // return "android.hardware".
113     status_t getPackageRoot(const FQName& fqName, std::string* root) const;
114 
115     status_t getPackageInterfaceFiles(
116             const FQName &package,
117             std::vector<std::string> *fileNames) const;
118 
119     // Returns true if the package points to a directory that exists
120     status_t packageExists(const FQName& package, bool* result) const;
121 
122     status_t appendPackageInterfacesToVector(
123             const FQName &package,
124             std::vector<FQName> *packageInterfaces) const;
125 
126     status_t isTypesOnlyPackage(const FQName& package, bool* result) const;
127 
128     // Returns types which are imported/defined but not referenced in code
129     status_t addUnreferencedTypes(const std::vector<FQName>& packageInterfaces,
130                                   std::set<FQName>* unreferencedDefinitions,
131                                   std::set<FQName>* unreferencedImports) const;
132 
133     // Enforce a set of restrictions on a set of packages. These include:
134     //    - minor version upgrades
135     // "packages" contains names like "android.hardware.nfc@1.1".
136     //    - hashing restrictions
137     status_t enforceRestrictionsOnPackage(const FQName& fqName,
138                                           Enforce enforcement = Enforce::FULL) const;
139 
140     // opt is the option that was parsed
141     // optarg contains the argument provided to opt
142     //     - optarg == NULL if opt is not expecting an argument
143     using HandleArg = std::function<void(int opt, char* optarg)>;
144 
145     // options is the same format as optstring for getopt
146     void parseOptions(int argc, char** argv, const std::string& options,
147                       const HandleArg& handleArg);
148 
149     static void emitOptionsUsageString(Formatter& out);
150     static void emitOptionsDetailString(Formatter& out);
151 
152     // Returns path relative to mRootPath
153     std::string makeRelative(const std::string& filename) const;
154 
155   private:
156     static bool MakeParentHierarchy(const std::string &path);
157 
158     enum class HashStatus {
159         ERROR,
160         UNFROZEN,
161         FROZEN,
162         CHANGED,  // frozen but changed
163     };
164     HashStatus checkHash(const FQName& fqName) const;
165     status_t getUnfrozenDependencies(const FQName& fqName, std::set<FQName>* result) const;
166 
167     // indicates that packages in "android.hardware" will be looked up in hardware/interfaces
168     struct PackageRoot {
169         std::string path; // e.x. hardware/interfaces
170         FQName root; // e.x. android.hardware@0.0
171     };
172 
173     // nullptr if it doesn't exist
174     const PackageRoot* findPackageRoot(const FQName& fqName) const;
175 
176     // Given package-root paths of ["hardware/interfaces",
177     // "vendor/<something>/interfaces"], package roots of
178     // ["android.hardware", "vendor.<something>.hardware"], and a
179     // FQName of "android.hardware.nfc@1.0::INfc, then getPackageRootPath()
180     // will return "hardware/interfaces".
181     status_t getPackageRootPath(const FQName& fqName, std::string* path) const;
182 
183     // Given an FQName of "android.hardware.nfc@1.0::INfc", return
184     // "android/hardware/".
185     status_t convertPackageRootToPath(const FQName& fqName, std::string* path) const;
186 
187     std::vector<PackageRoot> mPackageRoots;
188     std::string mRootPath;    // root of android source tree (to locate package roots)
189     std::string mOutputPath;  // root of output directory
190     std::string mDepFile;     // location to write depfile
191 
192     // hidl-gen options
193     bool mVerbose = false;
194     bool mRequireFrozen = false;
195     std::string mOwner;
196 
197     // cache to parse().
198     mutable std::map<FQName, AST *> mCache;
199 
200     // cache to enforceRestrictionsOnPackage().
201     mutable std::set<FQName> mPackagesEnforced;
202 
203     mutable std::set<std::string> mReadFiles;
204 
205     // Returns the given path if it is absolute, otherwise it returns
206     // the path relative to mRootPath
207     std::string makeAbsolute(const std::string& string) const;
208 
209     // Rules of enforceRestrictionsOnPackage are listed below.
210     status_t enforceMinorVersionUprevs(const FQName& fqName, Enforce enforcement) const;
211     status_t enforceHashes(const FQName &fqName) const;
212 
213     DISALLOW_COPY_AND_ASSIGN(Coordinator);
214 };
215 
216 }  // namespace android
217 
218 #endif  // COORDINATOR_H_
219