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 <functional>
23#include <map>
24#include <set>
25#include <string>
26#include <utils/Errors.h>
27#include <vector>
28
29namespace android {
30
31struct AST;
32struct FQName;
33struct Type;
34
35struct Coordinator {
36    Coordinator(
37            const std::vector<std::string> &packageRootPaths,
38            const std::vector<std::string> &packageRoots,
39            const std::string &rootPath);
40
41    ~Coordinator();
42
43    // adds path only if it doesn't exist
44    void addDefaultPackagePath(const std::string& root, const std::string& path);
45
46    enum class Enforce {
47        FULL,     // default
48        NO_HASH,  // only for use with -Lhash
49        NONE,     // only for use during enforcement
50    };
51
52    // Attempts to parse the interface/types referred to by fqName.
53    // Parsing an interface also parses the associated package's types.hal
54    // file if it exists.
55    // If "parsedASTs" is non-NULL, successfully parsed ASTs are inserted
56    // into the set.
57    // If !enforce, enforceRestrictionsOnPackage won't be run.
58    AST* parse(const FQName& fqName, std::set<AST*>* parsedASTs = nullptr,
59               Enforce enforcement = Enforce::FULL) const;
60
61    // Given package-root paths of ["hardware/interfaces",
62    // "vendor/<something>/interfaces"], package roots of
63    // ["android.hardware", "vendor.<something>.hardware"], and a
64    // FQName of "android.hardware.nfc@1.0::INfc, then getPackagePath()
65    // will return "hardware/interfaces/nfc/1.0" (if sanitized = false)
66    // or "hardware/interfaces/nfc/V1_0" (if sanitized = true).
67    std::string getPackagePath(
68            const FQName &fqName, bool relative = false,
69            bool sanitized = false) const;
70
71    // Given package roots of ["android.hardware",
72    // "vendor.<something>.hardware"] and a FQName of
73    // "android.hardware.nfc@1.0::INfc, then getPackageRoot() will
74    // return "android.hardware".
75    std::string getPackageRoot(const FQName &fqName) const;
76
77    // Given package-root paths of ["hardware/interfaces",
78    // "vendor/<something>/interfaces"], package roots of
79    // ["android.hardware", "vendor.<something>.hardware"], and a
80    // FQName of "android.hardware.nfc@1.0::INfc, then getPackageRootPath()
81    // will return "hardware/interfaces".
82    std::string getPackageRootPath(const FQName &fqName) const;
83
84    // return getPackageRoot + ":" + getPackageRootPath
85    std::string getPackageRootOption(const FQName &fqName) const;
86
87    // Given an FQName of "android.hardware.nfc@1.0::INfc", return
88    // "android/hardware/".
89    std::string convertPackageRootToPath(const FQName &fqName) const;
90
91    status_t getPackageInterfaceFiles(
92            const FQName &package,
93            std::vector<std::string> *fileNames) const;
94
95    status_t appendPackageInterfacesToVector(
96            const FQName &package,
97            std::vector<FQName> *packageInterfaces) const;
98
99    // Enforce a set of restrictions on a set of packages. These include:
100    //    - minor version upgrades
101    // "packages" contains names like "android.hardware.nfc@1.1".
102    //    - hashing restrictions
103    status_t enforceRestrictionsOnPackage(const FQName& fqName,
104                                          Enforce enforcement = Enforce::FULL) const;
105
106    static bool MakeParentHierarchy(const std::string &path);
107
108private:
109    // A list of top-level directories (mPackageRootPaths)
110    // corresponding to a list of package roots (mPackageRoots). For
111    // example, if mPackageRootPaths[0] == "hardware/interfaces" and
112    // mPackageRoots[0] == "android.hardware" this means that all
113    // packages starting with "android.hardware" will be looked up in
114    // "hardware/interfaces".
115    std::vector<std::string> mPackageRootPaths;
116    std::vector<std::string> mPackageRoots;
117
118    std::string mRootPath;
119
120    // cache to parse().
121    mutable std::map<FQName, AST *> mCache;
122
123    // cache to enforceRestrictionsOnPackage().
124    mutable std::set<FQName> mPackagesEnforced;
125
126    std::vector<std::string>::const_iterator findPackageRoot(
127            const FQName &fqName) const;
128
129    // Returns abs package path by prepending the root path if a package
130    // path is non-absolute.
131    // If root is '/android/master' and getPackagePath returns 'h/i/nfc/V1_0'
132    // this will return '/android/master/h/i/nfc/V1_0'.
133    // If root is '/android/master' and getPackagePath returns '/abs/path/to/nfc/V1_0'
134    // this will return '/abs/path/to/nfc/V1_0'
135    std::string getAbsolutePackagePath(const FQName& fqName) const;
136
137    // Rules of enforceRestrictionsOnPackage are listed below.
138    status_t enforceMinorVersionUprevs(const FQName &fqName) const;
139    status_t enforceHashes(const FQName &fqName) const;
140
141    DISALLOW_COPY_AND_ASSIGN(Coordinator);
142};
143
144}  // namespace android
145
146#endif  // COORDINATOR_H_
147