1*70a7ec85SAndroid Build Coastguard Worker /*
2*70a7ec85SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*70a7ec85SAndroid Build Coastguard Worker *
4*70a7ec85SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*70a7ec85SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*70a7ec85SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*70a7ec85SAndroid Build Coastguard Worker *
8*70a7ec85SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*70a7ec85SAndroid Build Coastguard Worker *
10*70a7ec85SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*70a7ec85SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*70a7ec85SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*70a7ec85SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*70a7ec85SAndroid Build Coastguard Worker * limitations under the License.
15*70a7ec85SAndroid Build Coastguard Worker */
16*70a7ec85SAndroid Build Coastguard Worker
17*70a7ec85SAndroid Build Coastguard Worker #include <optional>
18*70a7ec85SAndroid Build Coastguard Worker #include <set>
19*70a7ec85SAndroid Build Coastguard Worker
20*70a7ec85SAndroid Build Coastguard Worker #include <android-base/logging.h>
21*70a7ec85SAndroid Build Coastguard Worker #include <gflags/gflags.h>
22*70a7ec85SAndroid Build Coastguard Worker #include <vintf/FileSystem.h>
23*70a7ec85SAndroid Build Coastguard Worker #include <vintf/parse_string.h>
24*70a7ec85SAndroid Build Coastguard Worker #include <vintf/parse_xml.h>
25*70a7ec85SAndroid Build Coastguard Worker
26*70a7ec85SAndroid Build Coastguard Worker namespace android {
27*70a7ec85SAndroid Build Coastguard Worker namespace vintf {
28*70a7ec85SAndroid Build Coastguard Worker
29*70a7ec85SAndroid Build Coastguard Worker namespace {
30*70a7ec85SAndroid Build Coastguard Worker
31*70a7ec85SAndroid Build Coastguard Worker template <typename T>
readObject(const std::string & path)32*70a7ec85SAndroid Build Coastguard Worker std::optional<T> readObject(const std::string& path) {
33*70a7ec85SAndroid Build Coastguard Worker std::string xml;
34*70a7ec85SAndroid Build Coastguard Worker std::string error;
35*70a7ec85SAndroid Build Coastguard Worker status_t err = details::FileSystemImpl().fetch(path, &xml, &error);
36*70a7ec85SAndroid Build Coastguard Worker if (err != OK) {
37*70a7ec85SAndroid Build Coastguard Worker LOG(ERROR) << "Cannot read '" << path << "': " << error;
38*70a7ec85SAndroid Build Coastguard Worker return std::nullopt;
39*70a7ec85SAndroid Build Coastguard Worker }
40*70a7ec85SAndroid Build Coastguard Worker auto ret = std::make_optional<T>();
41*70a7ec85SAndroid Build Coastguard Worker if (!fromXml(&ret.value(), xml, &error)) {
42*70a7ec85SAndroid Build Coastguard Worker LOG(ERROR) << "Cannot parse '" << path << "': " << error;
43*70a7ec85SAndroid Build Coastguard Worker return std::nullopt;
44*70a7ec85SAndroid Build Coastguard Worker }
45*70a7ec85SAndroid Build Coastguard Worker return ret;
46*70a7ec85SAndroid Build Coastguard Worker }
47*70a7ec85SAndroid Build Coastguard Worker
48*70a7ec85SAndroid Build Coastguard Worker template <typename F>
getDescription(const CompatibilityMatrix & mat,F descriptionFn,bool emitReq)49*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> getDescription(const CompatibilityMatrix& mat, F descriptionFn,
50*70a7ec85SAndroid Build Coastguard Worker bool emitReq) {
51*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> set;
52*70a7ec85SAndroid Build Coastguard Worker mat.forEachInstance([&set, descriptionFn, emitReq](const auto& matrixInstance) {
53*70a7ec85SAndroid Build Coastguard Worker for (auto minorVer = matrixInstance.versionRange().minMinor;
54*70a7ec85SAndroid Build Coastguard Worker minorVer >= matrixInstance.versionRange().minMinor &&
55*70a7ec85SAndroid Build Coastguard Worker minorVer <= matrixInstance.versionRange().maxMinor;
56*70a7ec85SAndroid Build Coastguard Worker ++minorVer) {
57*70a7ec85SAndroid Build Coastguard Worker Version version{matrixInstance.versionRange().majorVer, minorVer};
58*70a7ec85SAndroid Build Coastguard Worker std::string s = std::invoke(descriptionFn, matrixInstance, version);
59*70a7ec85SAndroid Build Coastguard Worker if (emitReq) {
60*70a7ec85SAndroid Build Coastguard Worker s += (matrixInstance.optional() ? " optional" : " required");
61*70a7ec85SAndroid Build Coastguard Worker }
62*70a7ec85SAndroid Build Coastguard Worker set.insert(s);
63*70a7ec85SAndroid Build Coastguard Worker }
64*70a7ec85SAndroid Build Coastguard Worker return true; // continue
65*70a7ec85SAndroid Build Coastguard Worker });
66*70a7ec85SAndroid Build Coastguard Worker return set;
67*70a7ec85SAndroid Build Coastguard Worker }
68*70a7ec85SAndroid Build Coastguard Worker
69*70a7ec85SAndroid Build Coastguard Worker } // namespace
70*70a7ec85SAndroid Build Coastguard Worker
GetDescription(Level level)71*70a7ec85SAndroid Build Coastguard Worker std::string GetDescription(Level level) {
72*70a7ec85SAndroid Build Coastguard Worker switch (level) {
73*70a7ec85SAndroid Build Coastguard Worker case Level::LEGACY:
74*70a7ec85SAndroid Build Coastguard Worker return "Level legacy";
75*70a7ec85SAndroid Build Coastguard Worker case Level::O:
76*70a7ec85SAndroid Build Coastguard Worker return "Android 8.0 (O)";
77*70a7ec85SAndroid Build Coastguard Worker case Level::O_MR1:
78*70a7ec85SAndroid Build Coastguard Worker return "Android 8.1 (O-MR1)";
79*70a7ec85SAndroid Build Coastguard Worker case Level::P:
80*70a7ec85SAndroid Build Coastguard Worker return "Android 9 (P)";
81*70a7ec85SAndroid Build Coastguard Worker case Level::Q:
82*70a7ec85SAndroid Build Coastguard Worker return "Android 10 (Q)";
83*70a7ec85SAndroid Build Coastguard Worker case Level::R:
84*70a7ec85SAndroid Build Coastguard Worker return "Android 11 (R)";
85*70a7ec85SAndroid Build Coastguard Worker case Level::S:
86*70a7ec85SAndroid Build Coastguard Worker return "Android 12 (S)";
87*70a7ec85SAndroid Build Coastguard Worker case Level::T:
88*70a7ec85SAndroid Build Coastguard Worker return "Android 13 (T)";
89*70a7ec85SAndroid Build Coastguard Worker case Level::U:
90*70a7ec85SAndroid Build Coastguard Worker return "Android 14 (U)";
91*70a7ec85SAndroid Build Coastguard Worker case Level::V:
92*70a7ec85SAndroid Build Coastguard Worker return "Android 15 (V)";
93*70a7ec85SAndroid Build Coastguard Worker case Level::W:
94*70a7ec85SAndroid Build Coastguard Worker // TODO(b/346861728) verify name/number once decided
95*70a7ec85SAndroid Build Coastguard Worker return "Android 16 (W)";
96*70a7ec85SAndroid Build Coastguard Worker case Level::UNSPECIFIED:
97*70a7ec85SAndroid Build Coastguard Worker return "Level unspecified";
98*70a7ec85SAndroid Build Coastguard Worker default:
99*70a7ec85SAndroid Build Coastguard Worker return "Level " + to_string(level);
100*70a7ec85SAndroid Build Coastguard Worker }
101*70a7ec85SAndroid Build Coastguard Worker }
102*70a7ec85SAndroid Build Coastguard Worker
103*70a7ec85SAndroid Build Coastguard Worker } // namespace vintf
104*70a7ec85SAndroid Build Coastguard Worker } // namespace android
105*70a7ec85SAndroid Build Coastguard Worker
106*70a7ec85SAndroid Build Coastguard Worker DEFINE_string(input, "", "Input compatibility matrix file");
ValidateInput(const char *,const std::string & value)107*70a7ec85SAndroid Build Coastguard Worker static bool ValidateInput(const char* /* flagname */, const std::string& value) {
108*70a7ec85SAndroid Build Coastguard Worker return !value.empty();
109*70a7ec85SAndroid Build Coastguard Worker }
110*70a7ec85SAndroid Build Coastguard Worker DEFINE_validator(input, &ValidateInput);
111*70a7ec85SAndroid Build Coastguard Worker
112*70a7ec85SAndroid Build Coastguard Worker DEFINE_bool(level, false, "Write level (FCM version) of the compatibility matrix.");
113*70a7ec85SAndroid Build Coastguard Worker DEFINE_bool(level_name, false, "Write level name (FCM version) of the compatibility matrix.");
114*70a7ec85SAndroid Build Coastguard Worker DEFINE_bool(interfaces, false, "Write strings like \"[email protected]::IFoo\".");
115*70a7ec85SAndroid Build Coastguard Worker DEFINE_bool(instances, false, "Write strings like \"[email protected]::IFoo/default\".");
116*70a7ec85SAndroid Build Coastguard Worker DEFINE_bool(requirement, false, "Append optional/required after each interface / instance.");
117*70a7ec85SAndroid Build Coastguard Worker
main(int argc,char ** argv)118*70a7ec85SAndroid Build Coastguard Worker int main(int argc, char** argv) {
119*70a7ec85SAndroid Build Coastguard Worker using namespace android::vintf;
120*70a7ec85SAndroid Build Coastguard Worker
121*70a7ec85SAndroid Build Coastguard Worker gflags::ParseCommandLineFlags(&argc, &argv, true /* remove flags */);
122*70a7ec85SAndroid Build Coastguard Worker
123*70a7ec85SAndroid Build Coastguard Worker auto mat = readObject<CompatibilityMatrix>(FLAGS_input);
124*70a7ec85SAndroid Build Coastguard Worker if (!mat) {
125*70a7ec85SAndroid Build Coastguard Worker return 1;
126*70a7ec85SAndroid Build Coastguard Worker }
127*70a7ec85SAndroid Build Coastguard Worker
128*70a7ec85SAndroid Build Coastguard Worker bool written = false;
129*70a7ec85SAndroid Build Coastguard Worker
130*70a7ec85SAndroid Build Coastguard Worker if (FLAGS_level) {
131*70a7ec85SAndroid Build Coastguard Worker if (mat->level() == Level::UNSPECIFIED) {
132*70a7ec85SAndroid Build Coastguard Worker LOG(WARNING) << "FCM version is unspecified.";
133*70a7ec85SAndroid Build Coastguard Worker }
134*70a7ec85SAndroid Build Coastguard Worker std::cout << mat->level() << std::endl;
135*70a7ec85SAndroid Build Coastguard Worker
136*70a7ec85SAndroid Build Coastguard Worker written = true;
137*70a7ec85SAndroid Build Coastguard Worker }
138*70a7ec85SAndroid Build Coastguard Worker
139*70a7ec85SAndroid Build Coastguard Worker if (FLAGS_level_name) {
140*70a7ec85SAndroid Build Coastguard Worker if (mat->level() == Level::UNSPECIFIED) {
141*70a7ec85SAndroid Build Coastguard Worker LOG(WARNING) << "FCM version is unspecified.";
142*70a7ec85SAndroid Build Coastguard Worker }
143*70a7ec85SAndroid Build Coastguard Worker std::cout << GetDescription(mat->level()) << std::endl;
144*70a7ec85SAndroid Build Coastguard Worker
145*70a7ec85SAndroid Build Coastguard Worker written = true;
146*70a7ec85SAndroid Build Coastguard Worker }
147*70a7ec85SAndroid Build Coastguard Worker
148*70a7ec85SAndroid Build Coastguard Worker if (FLAGS_interfaces) {
149*70a7ec85SAndroid Build Coastguard Worker auto interfaces =
150*70a7ec85SAndroid Build Coastguard Worker getDescription(*mat, &MatrixInstance::interfaceDescription, FLAGS_requirement);
151*70a7ec85SAndroid Build Coastguard Worker if (interfaces.empty()) {
152*70a7ec85SAndroid Build Coastguard Worker LOG(WARNING) << "No interfaces are found.";
153*70a7ec85SAndroid Build Coastguard Worker }
154*70a7ec85SAndroid Build Coastguard Worker
155*70a7ec85SAndroid Build Coastguard Worker for (const auto& interface : interfaces) {
156*70a7ec85SAndroid Build Coastguard Worker std::cout << interface << std::endl;
157*70a7ec85SAndroid Build Coastguard Worker }
158*70a7ec85SAndroid Build Coastguard Worker
159*70a7ec85SAndroid Build Coastguard Worker written = true;
160*70a7ec85SAndroid Build Coastguard Worker }
161*70a7ec85SAndroid Build Coastguard Worker
162*70a7ec85SAndroid Build Coastguard Worker if (FLAGS_instances) {
163*70a7ec85SAndroid Build Coastguard Worker auto instances = getDescription(*mat, &MatrixInstance::description, FLAGS_requirement);
164*70a7ec85SAndroid Build Coastguard Worker if (instances.empty()) {
165*70a7ec85SAndroid Build Coastguard Worker LOG(WARNING) << "No instances are found.";
166*70a7ec85SAndroid Build Coastguard Worker }
167*70a7ec85SAndroid Build Coastguard Worker
168*70a7ec85SAndroid Build Coastguard Worker for (const auto& instance : instances) {
169*70a7ec85SAndroid Build Coastguard Worker std::cout << instance << std::endl;
170*70a7ec85SAndroid Build Coastguard Worker }
171*70a7ec85SAndroid Build Coastguard Worker
172*70a7ec85SAndroid Build Coastguard Worker written = true;
173*70a7ec85SAndroid Build Coastguard Worker }
174*70a7ec85SAndroid Build Coastguard Worker
175*70a7ec85SAndroid Build Coastguard Worker if (!written) {
176*70a7ec85SAndroid Build Coastguard Worker LOG(ERROR) << "No output format is set.";
177*70a7ec85SAndroid Build Coastguard Worker return 1;
178*70a7ec85SAndroid Build Coastguard Worker }
179*70a7ec85SAndroid Build Coastguard Worker
180*70a7ec85SAndroid Build Coastguard Worker return 0;
181*70a7ec85SAndroid Build Coastguard Worker }
182