• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 #include <optional>
18 #include <set>
19 
20 #include <android-base/logging.h>
21 #include <gflags/gflags.h>
22 #include <hidl-util/FqInstance.h>
23 #include <vintf/FileSystem.h>
24 #include <vintf/parse_string.h>
25 #include <vintf/parse_xml.h>
26 
27 namespace android {
28 namespace vintf {
29 
30 namespace {
31 
32 template <typename T>
readObject(const std::string & path)33 std::optional<T> readObject(const std::string& path) {
34     std::string xml;
35     std::string error;
36     status_t err = details::FileSystemImpl().fetch(path, &xml, &error);
37     if (err != OK) {
38         LOG(ERROR) << "Cannot read '" << path << "': " << error;
39         return std::nullopt;
40     }
41     auto ret = std::make_optional<T>();
42     if (!fromXml(&ret.value(), xml, &error)) {
43         LOG(ERROR) << "Cannot parse '" << path << "': " << error;
44         return std::nullopt;
45     }
46     return ret;
47 }
48 
49 template <typename F>
getDescription(const CompatibilityMatrix & mat,F descriptionFn,bool emitReq)50 std::set<std::string> getDescription(const CompatibilityMatrix& mat, F descriptionFn,
51                                      bool emitReq) {
52     std::set<std::string> set;
53     mat.forEachInstance([&set, descriptionFn, emitReq](const auto& matrixInstance) {
54         for (auto minorVer = matrixInstance.versionRange().minMinor;
55              minorVer >= matrixInstance.versionRange().minMinor &&
56              minorVer <= matrixInstance.versionRange().maxMinor;
57              ++minorVer) {
58             Version version{matrixInstance.versionRange().majorVer, minorVer};
59             std::string s = std::invoke(descriptionFn, matrixInstance, version);
60             if (emitReq) {
61                 s += (matrixInstance.optional() ? " optional" : " required");
62             }
63             set.insert(s);
64         }
65         return true;  // continue
66     });
67     return set;
68 }
69 
70 }  // namespace
71 
GetDescription(Level level)72 std::string GetDescription(Level level) {
73     switch (level) {
74         case Level::LEGACY:
75             return "Level legacy";
76         case Level::O:
77             return "Android 8.0 (O)";
78         case Level::O_MR1:
79             return "Android 8.1 (O-MR1)";
80         case Level::P:
81             return "Android 9 (P)";
82         case Level::Q:
83             return "Android 10 (Q)";
84         case Level::R:
85             return "Android 11 (R)";
86         case Level::S:
87             return "Android 12 (S)";
88         case Level::T:
89             return "Android 13 (T)";
90         case Level::UNSPECIFIED:
91             return "Level unspecified";
92         default:
93             return "Level " + std::to_string(level);
94     }
95 }
96 
97 }  // namespace vintf
98 }  // namespace android
99 
100 DEFINE_string(input, "", "Input compatibility matrix file");
ValidateInput(const char *,const std::string & value)101 static bool ValidateInput(const char* /* flagname */, const std::string& value) {
102     return !value.empty();
103 }
104 DEFINE_validator(input, &ValidateInput);
105 
106 DEFINE_bool(level, false, "Write level (FCM version) of the compatibility matrix.");
107 DEFINE_bool(level_name, false, "Write level name (FCM version) of the compatibility matrix.");
108 DEFINE_bool(interfaces, false, "Write strings like \"android.hardware.foo@1.0::IFoo\".");
109 DEFINE_bool(instances, false, "Write strings like \"android.hardware.foo@1.0::IFoo/default\".");
110 DEFINE_bool(requirement, false, "Append optional/required after each interface / instance.");
111 
main(int argc,char ** argv)112 int main(int argc, char** argv) {
113     using namespace android::vintf;
114 
115     gflags::ParseCommandLineFlags(&argc, &argv, true /* remove flags */);
116 
117     auto mat = readObject<CompatibilityMatrix>(FLAGS_input);
118     if (!mat) {
119         return 1;
120     }
121 
122     bool written = false;
123 
124     if (FLAGS_level) {
125         if (mat->level() == Level::UNSPECIFIED) {
126             LOG(WARNING) << "FCM version is unspecified.";
127         }
128         std::cout << mat->level() << std::endl;
129 
130         written = true;
131     }
132 
133     if (FLAGS_level_name) {
134         if (mat->level() == Level::UNSPECIFIED) {
135             LOG(WARNING) << "FCM version is unspecified.";
136         }
137         std::cout << GetDescription(mat->level()) << std::endl;
138 
139         written = true;
140     }
141 
142     if (FLAGS_interfaces) {
143         auto interfaces =
144             getDescription(*mat, &MatrixInstance::interfaceDescription, FLAGS_requirement);
145         if (interfaces.empty()) {
146             LOG(WARNING) << "No interfaces are found.";
147         }
148 
149         for (const auto& interface : interfaces) {
150             std::cout << interface << std::endl;
151         }
152 
153         written = true;
154     }
155 
156     if (FLAGS_instances) {
157         auto instances = getDescription(*mat, &MatrixInstance::description, FLAGS_requirement);
158         if (instances.empty()) {
159             LOG(WARNING) << "No instances are found.";
160         }
161 
162         for (const auto& instance : instances) {
163             std::cout << instance << std::endl;
164         }
165 
166         written = true;
167     }
168 
169     if (!written) {
170         LOG(ERROR) << "No output format is set.";
171         return 1;
172     }
173 
174     return 0;
175 }
176