summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYifan Hong2018-01-16 15:11:23 -0600
committerandroid-build-merger2018-01-16 15:11:23 -0600
commit9d2c77276bb4f77273f287efd7f4082384127ffc (patch)
tree12a9e88176075bc44cdc2fe98a1b396136de0131
parentb7008f8d49920594ce28dbeb36057394816d1c59 (diff)
parent85b1bde302c7dfc42c8a9b8dbb5db26c88c1f362 (diff)
downloadplatform-system-libvintf-9d2c77276bb4f77273f287efd7f4082384127ffc.tar.gz
platform-system-libvintf-9d2c77276bb4f77273f287efd7f4082384127ffc.tar.xz
platform-system-libvintf-9d2c77276bb4f77273f287efd7f4082384127ffc.zip
VintfObject::GetFwkMatrix combine matrices at runtime am: d52bf3e64c am: f1166a6a17
am: 85b1bde302 Change-Id: If17c173ce5d31ca63e6f22b42a57dbd682b749fe
-rw-r--r--VintfObject.cpp123
-rw-r--r--include/vintf/CompatibilityMatrix.h1
-rw-r--r--include/vintf/VintfObject.h8
-rw-r--r--test/Android.bp2
-rw-r--r--test/utils-fake.h5
-rw-r--r--test/vintf_object_tests.cpp38
-rw-r--r--utils.h21
7 files changed, 198 insertions, 0 deletions
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 8dd08ef..24694cd 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -20,6 +20,8 @@
20#include "parse_xml.h" 20#include "parse_xml.h"
21#include "utils.h" 21#include "utils.h"
22 22
23#include <dirent.h>
24
23#include <functional> 25#include <functional>
24#include <memory> 26#include <memory>
25#include <mutex> 27#include <mutex>
@@ -30,6 +32,8 @@
30 32
31#include <android-base/logging.h> 33#include <android-base/logging.h>
32 34
35#define FRAMEWORK_MATRIX_DIR "/system/etc/vintf/"
36
33using std::placeholders::_1; 37using std::placeholders::_1;
34using std::placeholders::_2; 38using std::placeholders::_2;
35 39
@@ -119,11 +123,130 @@ std::shared_ptr<const CompatibilityMatrix> VintfObject::GetDeviceCompatibilityMa
119// static 123// static
120std::shared_ptr<const CompatibilityMatrix> VintfObject::GetFrameworkCompatibilityMatrix(bool skipCache) { 124std::shared_ptr<const CompatibilityMatrix> VintfObject::GetFrameworkCompatibilityMatrix(bool skipCache) {
121 static LockedSharedPtr<CompatibilityMatrix> gFrameworkMatrix; 125 static LockedSharedPtr<CompatibilityMatrix> gFrameworkMatrix;
126 static LockedSharedPtr<CompatibilityMatrix> gCombinedFrameworkMatrix;
127 static std::mutex gFrameworkCompatibilityMatrixMutex;
128
129 // To avoid deadlock, get device manifest before any locks.
130 auto deviceManifest = GetDeviceHalManifest();
131
132 std::unique_lock<std::mutex> _lock(gFrameworkCompatibilityMatrixMutex);
133
134 auto combined =
135 Get(&gCombinedFrameworkMatrix, skipCache,
136 std::bind(&VintfObject::GetCombinedFrameworkMatrix, deviceManifest, _1, _2));
137 if (combined != nullptr) {
138 return combined;
139 }
140
122 return Get(&gFrameworkMatrix, skipCache, 141 return Get(&gFrameworkMatrix, skipCache,
123 std::bind(&CompatibilityMatrix::fetchAllInformation, _1, 142 std::bind(&CompatibilityMatrix::fetchAllInformation, _1,
124 "/system/compatibility_matrix.xml", _2)); 143 "/system/compatibility_matrix.xml", _2));
125} 144}
126 145
146status_t VintfObject::GetCombinedFrameworkMatrix(
147 const std::shared_ptr<const HalManifest>& deviceManifest, CompatibilityMatrix* out,
148 std::string* error) {
149 auto matrixFragments = GetAllFrameworkMatrixLevels(error);
150 if (matrixFragments.empty()) {
151 return NAME_NOT_FOUND;
152 }
153
154 Level deviceLevel = Level::UNSPECIFIED;
155
156 if (deviceManifest != nullptr) {
157 deviceLevel = deviceManifest->level();
158 }
159
160 // TODO(b/70628538): Do not infer from Shipping API level.
161#ifdef LIBVINTF_TARGET
162 if (deviceLevel == Level::UNSPECIFIED) {
163 auto shippingApi =
164 android::base::GetUintProperty<uint64_t>("ro.product.first_api_level", 0u);
165 if (shippingApi != 0u) {
166 deviceLevel = details::convertFromApiLevel(shippingApi);
167 }
168 }
169#endif
170
171 if (deviceLevel == Level::UNSPECIFIED) {
172 // Cannot infer FCM version. Combine all matrices by assuming
173 // Shipping FCM Version == min(all supported FCM Versions in the framework)
174 for (auto&& pair : matrixFragments) {
175 Level fragmentLevel = pair.object.level();
176 if (fragmentLevel != Level::UNSPECIFIED && deviceLevel > fragmentLevel) {
177 deviceLevel = fragmentLevel;
178 }
179 }
180 }
181
182 if (deviceLevel == Level::UNSPECIFIED) {
183 // None of the fragments specify any FCM version. Should never happen except
184 // for inconsistent builds.
185 if (error) {
186 *error = "No framework compatibility matrix files under " FRAMEWORK_MATRIX_DIR
187 " declare FCM version.";
188 }
189 return NAME_NOT_FOUND;
190 }
191
192 CompatibilityMatrix* combined =
193 CompatibilityMatrix::combine(deviceLevel, &matrixFragments, error);
194 if (combined == nullptr) {
195 return BAD_VALUE;
196 }
197 *out = std::move(*combined);
198 return OK;
199}
200
201std::vector<Named<CompatibilityMatrix>> VintfObject::GetAllFrameworkMatrixLevels(
202 std::string* error) {
203 std::vector<std::string> fileNames;
204 std::vector<Named<CompatibilityMatrix>> results;
205
206 if (details::gFetcher->listFiles(FRAMEWORK_MATRIX_DIR, &fileNames, error) != OK) {
207 return {};
208 }
209 for (const std::string& fileName : fileNames) {
210 std::string path = FRAMEWORK_MATRIX_DIR + fileName;
211
212 std::string content;
213 std::string fetchError;
214 status_t status = details::gFetcher->fetch(path, content, &fetchError);
215 if (status != OK) {
216 if (error) {
217 *error += "Ignore file " + path + ": " + fetchError + "\n";
218 }
219 continue;
220 }
221
222 auto it = results.emplace(results.end());
223 if (!gCompatibilityMatrixConverter(&it->object, content)) {
224 if (error) {
225 // TODO(b/71874788): do not use lastError() because it is not thread-safe.
226 *error +=
227 "Ignore file " + path + ": " + gCompatibilityMatrixConverter.lastError() + "\n";
228 }
229 results.erase(it);
230 continue;
231 }
232 }
233
234 if (results.empty()) {
235 if (error) {
236 *error = "No framework matrices under " FRAMEWORK_MATRIX_DIR
237 " can be fetched or parsed.\n" +
238 *error;
239 }
240 } else {
241 if (error && !error->empty()) {
242 LOG(WARNING) << *error;
243 *error = "";
244 }
245 }
246
247 return results;
248}
249
127// static 250// static
128std::shared_ptr<const RuntimeInfo> VintfObject::GetRuntimeInfo(bool skipCache, 251std::shared_ptr<const RuntimeInfo> VintfObject::GetRuntimeInfo(bool skipCache,
129 RuntimeInfo::FetchFlags flags) { 252 RuntimeInfo::FetchFlags flags) {
diff --git a/include/vintf/CompatibilityMatrix.h b/include/vintf/CompatibilityMatrix.h
index e3432a0..b7a5541 100644
--- a/include/vintf/CompatibilityMatrix.h
+++ b/include/vintf/CompatibilityMatrix.h
@@ -82,6 +82,7 @@ struct CompatibilityMatrix : public HalGroup<MatrixHal>, public XmlFileGroup<Mat
82 // - If level() == deviceLevel, all HAL versions and XML files are added as is 82 // - If level() == deviceLevel, all HAL versions and XML files are added as is
83 // (optionality is kept) 83 // (optionality is kept)
84 // - If level() > deviceLevel, all HAL versions and XML files are added as optional. 84 // - If level() > deviceLevel, all HAL versions and XML files are added as optional.
85 // Return a pointer into one of the elements in "matrices".
85 static CompatibilityMatrix* combine(Level deviceLevel, 86 static CompatibilityMatrix* combine(Level deviceLevel,
86 std::vector<Named<CompatibilityMatrix>>* matrices, 87 std::vector<Named<CompatibilityMatrix>>* matrices,
87 std::string* error); 88 std::string* error);
diff --git a/include/vintf/VintfObject.h b/include/vintf/VintfObject.h
index 5593da5..80df9ea 100644
--- a/include/vintf/VintfObject.h
+++ b/include/vintf/VintfObject.h
@@ -22,6 +22,7 @@
22#include "CompatibilityMatrix.h" 22#include "CompatibilityMatrix.h"
23#include "DisabledChecks.h" 23#include "DisabledChecks.h"
24#include "HalManifest.h" 24#include "HalManifest.h"
25#include "Named.h"
25#include "RuntimeInfo.h" 26#include "RuntimeInfo.h"
26 27
27namespace android { 28namespace android {
@@ -110,6 +111,13 @@ public:
110 static int32_t CheckCompatibility(const std::vector<std::string>& packageInfo, 111 static int32_t CheckCompatibility(const std::vector<std::string>& packageInfo,
111 std::string* error = nullptr, 112 std::string* error = nullptr,
112 DisabledChecks disabledChecks = ENABLE_ALL_CHECKS); 113 DisabledChecks disabledChecks = ENABLE_ALL_CHECKS);
114
115 private:
116 static status_t GetCombinedFrameworkMatrix(
117 const std::shared_ptr<const HalManifest>& deviceManifest, CompatibilityMatrix* out,
118 std::string* error = nullptr);
119 static std::vector<Named<CompatibilityMatrix>> GetAllFrameworkMatrixLevels(
120 std::string* error = nullptr);
113}; 121};
114 122
115enum : int32_t { 123enum : int32_t {
diff --git a/test/Android.bp b/test/Android.bp
index 607d452..540298a 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -68,6 +68,8 @@ cc_test {
68 cflags: [ 68 cflags: [
69 "-O0", 69 "-O0",
70 "-g", 70 "-g",
71 // Unexpected logging of string pointer warning from gmock
72 "-Wno-user-defined-warnings"
71 ], 73 ],
72 target: { 74 target: {
73 android: { 75 android: {
diff --git a/test/utils-fake.h b/test/utils-fake.h
index 7d7caf2..e2b2706 100644
--- a/test/utils-fake.h
+++ b/test/utils-fake.h
@@ -34,9 +34,14 @@ class MockFileFetcher : public FileFetcher {
34 ON_CALL(*this, fetch(_, _)).WillByDefault(Invoke([this](const auto& path, auto& fetched) { 34 ON_CALL(*this, fetch(_, _)).WillByDefault(Invoke([this](const auto& path, auto& fetched) {
35 return real_.fetchInternal(path, fetched, nullptr); 35 return real_.fetchInternal(path, fetched, nullptr);
36 })); 36 }));
37 ON_CALL(*this, listFiles(_, _, _))
38 .WillByDefault(
39 Invoke([this](const std::string& path, std::vector<std::string>* out,
40 std::string* error) { return real_.listFiles(path, out, error); }));
37 } 41 }
38 42
39 MOCK_METHOD2(fetch, status_t(const std::string& path, std::string& fetched)); 43 MOCK_METHOD2(fetch, status_t(const std::string& path, std::string& fetched));
44 MOCK_METHOD3(listFiles, status_t(const std::string&, std::vector<std::string>*, std::string*));
40 45
41 status_t fetch(const std::string& path, std::string& fetched, std::string*) override final { 46 status_t fetch(const std::string& path, std::string& fetched, std::string*) override final {
42 return fetch(path, fetched); 47 return fetch(path, fetched);
diff --git a/test/vintf_object_tests.cpp b/test/vintf_object_tests.cpp
index 61eb4df..2dc2d8a 100644
--- a/test/vintf_object_tests.cpp
+++ b/test/vintf_object_tests.cpp
@@ -204,6 +204,9 @@ void setupMockFetcher(const std::string& vendorManifestXml, const std::string& s
204 fetched = systemMatrixXml; 204 fetched = systemMatrixXml;
205 return 0; 205 return 0;
206 })); 206 }));
207 // Don't list /system/etc/vintf unless otherwise specified.
208 ON_CALL(*fetcher, listFiles(StrEq("/system/etc/vintf/"), _, _))
209 .WillByDefault(Return(::android::OK));
207} 210}
208 211
209static MockPartitionMounter &mounter() { 212static MockPartitionMounter &mounter() {
@@ -521,6 +524,41 @@ TEST_F(VintfObjectRuntimeInfoTest, GetRuntimeInfo) {
521 VintfObject::GetRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::ALL); 524 VintfObject::GetRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::ALL);
522} 525}
523 526
527// Test fixture that provides incompatible metadata from the mock device.
528class VintfObjectTest : public testing::Test {
529 protected:
530 virtual void SetUp() {}
531 virtual void TearDown() {
532 Mock::VerifyAndClear(&fetcher());
533 Mock::VerifyAndClear(&mounter());
534 }
535};
536
537// Test framework compatibility matrix is combined at runtime
538TEST_F(VintfObjectTest, FrameworkCompatibilityMatrixCombine) {
539 EXPECT_CALL(fetcher(), listFiles(StrEq("/system/etc/vintf/"), _, _))
540 .WillOnce(Invoke([](const auto&, auto* out, auto*) {
541 *out = {
542 "compatibility_matrix.1.xml",
543 "compatibility_matrix.empty.xml",
544 };
545 return ::android::OK;
546 }));
547 EXPECT_CALL(fetcher(), fetch(StrEq("/system/etc/vintf/compatibility_matrix.1.xml"), _))
548 .WillOnce(Invoke([](const auto&, auto& out) {
549 out = "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\"/>";
550 return ::android::OK;
551 }));
552 EXPECT_CALL(fetcher(), fetch(StrEq("/system/etc/vintf/compatibility_matrix.empty.xml"), _))
553 .WillOnce(Invoke([](const auto&, auto& out) {
554 out = "<compatibility-matrix version=\"1.0\" type=\"framework\"/>";
555 return ::android::OK;
556 }));
557 EXPECT_CALL(fetcher(), fetch(StrEq("/system/compatibility_matrix.xml"), _)).Times(0);
558
559 EXPECT_NE(nullptr, VintfObject::GetFrameworkCompatibilityMatrix(true /* skipCache */));
560}
561
524int main(int argc, char** argv) { 562int main(int argc, char** argv) {
525 ::testing::InitGoogleMock(&argc, argv); 563 ::testing::InitGoogleMock(&argc, argv);
526 564
diff --git a/utils.h b/utils.h
index 5f28b6d..c3dcd53 100644
--- a/utils.h
+++ b/utils.h
@@ -17,8 +17,11 @@
17#ifndef ANDROID_VINTF_UTILS_H 17#ifndef ANDROID_VINTF_UTILS_H
18#define ANDROID_VINTF_UTILS_H 18#define ANDROID_VINTF_UTILS_H
19 19
20#include <dirent.h>
21
20#include <fstream> 22#include <fstream>
21#include <iostream> 23#include <iostream>
24#include <memory>
22#include <sstream> 25#include <sstream>
23 26
24#include <utils/Errors.h> 27#include <utils/Errors.h>
@@ -58,6 +61,24 @@ class FileFetcher {
58 virtual status_t fetch(const std::string& path, std::string& fetched) { 61 virtual status_t fetch(const std::string& path, std::string& fetched) {
59 return fetchInternal(path, fetched, nullptr); 62 return fetchInternal(path, fetched, nullptr);
60 } 63 }
64 virtual status_t listFiles(const std::string& path, std::vector<std::string>* out,
65 std::string* error) {
66 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
67 if (!dir) {
68 if (error) {
69 *error = "Cannot open " + path;
70 }
71 return NAME_NOT_FOUND;
72 }
73
74 dirent* dp;
75 while ((dp = readdir(dir.get())) != nullptr) {
76 if (dp->d_type != DT_DIR) {
77 out->push_back(dp->d_name);
78 }
79 }
80 return OK;
81 }
61}; 82};
62 83
63extern FileFetcher* gFetcher; 84extern FileFetcher* gFetcher;