VintfObject::checkCompatibility loads XMLs from the device correctly.
Previously:
- When getFrameworkCompatibilityMatrix() is called, the Target FCM version
is always loaded from the device, but not from the update package.
This can potentially break a vendor-only OTA that updates the Target FCM
version, because the FCM from device isn't loaded with the correct Target FCM
version.
In this CL, I refactored checkCompatibility logic so that the
VintfObjectAfterUpdate object applies the updated VINTF metadata as an
overlay on top of the original VintfObject.
Test: vintf_object_test
Test: manual OTA
Bug: 118635062
Change-Id: Ib04ba09d4a07c8e5d1e4ac64194e956b37e1f76f
diff --git a/VintfObject.cpp b/VintfObject.cpp
index f39b933..a1d4a6c 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -16,11 +16,6 @@
#include "VintfObject.h"
-#include "CompatibilityMatrix.h"
-#include "parse_string.h"
-#include "parse_xml.h"
-#include "utils.h"
-
#include <dirent.h>
#include <functional>
@@ -29,6 +24,12 @@
#include <android-base/logging.h>
+#include "CompatibilityMatrix.h"
+#include "VintfObjectAfterUpdate.h"
+#include "parse_string.h"
+#include "parse_xml.h"
+#include "utils.h"
+
using std::placeholders::_1;
using std::placeholders::_2;
@@ -146,7 +147,7 @@
}
return Get(&mFrameworkMatrix, skipCache,
- std::bind(&CompatibilityMatrix::fetchAllInformation, _1, mFileSystem.get(),
+ std::bind(&CompatibilityMatrix::fetchAllInformation, _1, getFileSystem().get(),
kSystemLegacyMatrix, _2));
}
@@ -166,7 +167,7 @@
// TODO(b/70628538): Do not infer from Shipping API level.
if (deviceLevel == Level::UNSPECIFIED) {
- auto shippingApi = mPropertyFetcher->getUintProperty("ro.product.first_api_level", 0u);
+ auto shippingApi = getPropertyFetcher()->getUintProperty("ro.product.first_api_level", 0u);
if (shippingApi != 0u) {
deviceLevel = details::convertFromApiLevel(shippingApi);
}
@@ -205,7 +206,7 @@
status_t VintfObject::addDirectoryManifests(const std::string& directory, HalManifest* manifest,
std::string* error) {
std::vector<std::string> fileNames;
- status_t err = mFileSystem->listFiles(directory, &fileNames, error);
+ status_t err = getFileSystem()->listFiles(directory, &fileNames, error);
// if the directory isn't there, that's okay
if (err == NAME_NOT_FOUND) return OK;
if (err != OK) return err;
@@ -264,7 +265,7 @@
}
// Use legacy /vendor/manifest.xml
- return out->fetchAllInformation(mFileSystem.get(), kVendorLegacyManifest, error);
+ return out->fetchAllInformation(getFileSystem().get(), kVendorLegacyManifest, error);
}
// "out" is written to iff return status is OK.
@@ -279,7 +280,7 @@
status_t status;
std::string productModel;
- productModel = mPropertyFetcher->getProperty("ro.boot.product.hardware.sku", "");
+ productModel = getPropertyFetcher()->getProperty("ro.boot.product.hardware.sku", "");
if (!productModel.empty()) {
status =
@@ -315,7 +316,7 @@
status_t VintfObject::fetchOneHalManifest(const std::string& path, HalManifest* out,
std::string* error) {
HalManifest ret;
- status_t status = ret.fetchAllInformation(mFileSystem.get(), path, error);
+ status_t status = ret.fetchAllInformation(getFileSystem().get(), path, error);
if (status == OK) {
*out = std::move(ret);
}
@@ -324,20 +325,20 @@
status_t VintfObject::fetchDeviceMatrix(CompatibilityMatrix* out, std::string* error) {
CompatibilityMatrix etcMatrix;
- if (etcMatrix.fetchAllInformation(mFileSystem.get(), kVendorMatrix, error) == OK) {
+ if (etcMatrix.fetchAllInformation(getFileSystem().get(), kVendorMatrix, error) == OK) {
*out = std::move(etcMatrix);
return OK;
}
- return out->fetchAllInformation(mFileSystem.get(), kVendorLegacyMatrix, error);
+ return out->fetchAllInformation(getFileSystem().get(), kVendorLegacyMatrix, error);
}
status_t VintfObject::fetchFrameworkHalManifest(HalManifest* out, std::string* error) {
HalManifest etcManifest;
- if (etcManifest.fetchAllInformation(mFileSystem.get(), kSystemManifest, error) == OK) {
+ if (etcManifest.fetchAllInformation(getFileSystem().get(), kSystemManifest, error) == OK) {
*out = std::move(etcManifest);
return addDirectoryManifests(kSystemManifestFragmentDir, out, error);
}
- return out->fetchAllInformation(mFileSystem.get(), kSystemLegacyManifest, error);
+ return out->fetchAllInformation(getFileSystem().get(), kSystemLegacyManifest, error);
}
static void appendLine(std::string* error, const std::string& message) {
@@ -352,7 +353,7 @@
std::vector<std::string> fileNames;
std::vector<Named<CompatibilityMatrix>> results;
- if (mFileSystem->listFiles(kSystemVintfDir, &fileNames, error) != OK) {
+ if (getFileSystem()->listFiles(kSystemVintfDir, &fileNames, error) != OK) {
return {};
}
for (const std::string& fileName : fileNames) {
@@ -360,7 +361,7 @@
std::string content;
std::string fetchError;
- status_t status = mFileSystem->fetch(path, &content, &fetchError);
+ status_t status = getFileSystem()->fetch(path, &content, &fetchError);
if (status != OK) {
appendLine(error, "Framework Matrix: Ignore file " + path + ": " + fetchError);
continue;
@@ -403,7 +404,7 @@
}
if (mDeviceRuntimeInfo.object == nullptr) {
- mDeviceRuntimeInfo.object = mRuntimeInfoFactory->make_shared();
+ mDeviceRuntimeInfo.object = getRuntimeInfoFactory()->make_shared();
}
status_t status = mDeviceRuntimeInfo.object->fetchAllInformation(flags);
@@ -435,72 +436,36 @@
return "";
}
-template<typename T>
-static ParseStatus tryParse(const std::string &xml, const XmlConverter<T> &parse,
- std::shared_ptr<T> *fwk, std::shared_ptr<T> *dev) {
+template <typename T>
+static ParseStatus tryParse(const std::string& xml, const XmlConverter<T>& parse,
+ VintfObjectAfterUpdate* afterUpdate) {
std::shared_ptr<T> ret = std::make_shared<T>();
if (!parse(ret.get(), xml, nullptr /* error */)) {
return ParseStatus::PARSE_ERROR;
}
- if (ret->type() == SchemaType::FRAMEWORK) {
- if (fwk->get() != nullptr) {
+ if (!afterUpdate->set(ret)) {
+ if (ret->type() == SchemaType::FRAMEWORK) {
return ParseStatus::DUPLICATED_FWK_ENTRY;
- }
- *fwk = std::move(ret);
- } else if (ret->type() == SchemaType::DEVICE) {
- if (dev->get() != nullptr) {
+ } else if (ret->type() == SchemaType::DEVICE) {
return ParseStatus::DUPLICATED_DEV_ENTRY;
}
- *dev = std::move(ret);
+ LOG(FATAL) << "unknown SchemaType: "
+ << static_cast<std::underlying_type_t<SchemaType>>(ret->type());
}
return ParseStatus::OK;
}
-template <typename T, typename GetFunction>
-static status_t getMissing(const std::shared_ptr<T>& pkg, std::shared_ptr<const T>* updated,
- GetFunction getFunction) {
- if (pkg != nullptr) {
- *updated = pkg;
- } else {
- *updated = getFunction();
- }
- return OK;
-}
-
-struct PackageInfo {
- struct Pair {
- std::shared_ptr<HalManifest> manifest;
- std::shared_ptr<CompatibilityMatrix> matrix;
- };
- Pair dev;
- Pair fwk;
-};
-
-struct UpdatedInfo {
- struct Pair {
- std::shared_ptr<const HalManifest> manifest;
- std::shared_ptr<const CompatibilityMatrix> matrix;
- };
- Pair dev;
- Pair fwk;
- std::shared_ptr<const RuntimeInfo> runtimeInfo;
-};
-
} // namespace details
-// Checks given compatibility info against info on the device. If no
-// compatability info is given then the device info will be checked against
-// itself.
+// Simulate applying xmls to VintfObject, then checkCompatibility as usual.
int32_t VintfObject::checkCompatibility(const std::vector<std::string>& xmls, std::string* error,
CheckFlags::Type flags) {
- status_t status;
- ParseStatus parseStatus;
- PackageInfo pkg; // All information from package.
- UpdatedInfo updated; // All files and runtime info after the update.
+ VintfObjectAfterUpdate afterUpdate(this);
+ ParseStatus parseStatus = ParseStatus::OK;
// parse all information from package
for (const auto &xml : xmls) {
- parseStatus = tryParse(xml, gHalManifestConverter, &pkg.fwk.manifest, &pkg.dev.manifest);
+ parseStatus = tryParse(xml, gHalManifestConverter, &afterUpdate);
if (parseStatus == ParseStatus::OK) {
continue; // work on next one
}
@@ -508,7 +473,7 @@
appendLine(error, toString(parseStatus) + " manifest");
return ALREADY_EXISTS;
}
- parseStatus = tryParse(xml, gCompatibilityMatrixConverter, &pkg.fwk.matrix, &pkg.dev.matrix);
+ parseStatus = tryParse(xml, gCompatibilityMatrixConverter, &afterUpdate);
if (parseStatus == ParseStatus::OK) {
continue; // work on next one
}
@@ -520,52 +485,31 @@
return BAD_VALUE;
}
- // get missing info from device
- if ((status = getMissing(
- pkg.fwk.manifest, &updated.fwk.manifest,
- std::bind(&VintfObject::getFrameworkHalManifest, this, true /* skipCache */))) != OK) {
- return status;
- }
- if ((status = getMissing(
- pkg.dev.manifest, &updated.dev.manifest,
- std::bind(&VintfObject::getDeviceHalManifest, this, true /* skipCache */))) != OK) {
- return status;
- }
- if ((status = getMissing(pkg.fwk.matrix, &updated.fwk.matrix,
- std::bind(&VintfObject::getFrameworkCompatibilityMatrix, this,
- true /* skipCache */))) != OK) {
- return status;
- }
- if ((status = getMissing(pkg.dev.matrix, &updated.dev.matrix,
- std::bind(&VintfObject::getDeviceCompatibilityMatrix, this,
- true /* skipCache */))) != OK) {
- return status;
- }
+ return afterUpdate.checkCompatibility(error, flags);
+}
- if (flags.isRuntimeInfoEnabled()) {
- updated.runtimeInfo = getRuntimeInfo(true /* skipCache */);
- }
-
- // null checks for files and runtime info after the update
- if (updated.fwk.manifest == nullptr) {
+int32_t VintfObject::checkCompatibility(std::string* error, CheckFlags::Type flags) {
+ status_t status = OK;
+ // null checks for files and runtime info
+ if (getFrameworkHalManifest() == nullptr) {
appendLine(error, "No framework manifest file from device or from update package");
status = NO_INIT;
}
- if (updated.dev.manifest == nullptr) {
+ if (getDeviceHalManifest() == nullptr) {
appendLine(error, "No device manifest file from device or from update package");
status = NO_INIT;
}
- if (updated.fwk.matrix == nullptr) {
+ if (getFrameworkCompatibilityMatrix() == nullptr) {
appendLine(error, "No framework matrix file from device or from update package");
status = NO_INIT;
}
- if (updated.dev.matrix == nullptr) {
+ if (getDeviceCompatibilityMatrix() == nullptr) {
appendLine(error, "No device matrix file from device or from update package");
status = NO_INIT;
}
if (flags.isRuntimeInfoEnabled()) {
- if (updated.runtimeInfo == nullptr) {
+ if (getRuntimeInfo() == nullptr) {
appendLine(error, "No runtime info from device");
status = NO_INIT;
}
@@ -573,14 +517,14 @@
if (status != OK) return status;
// compatiblity check.
- if (!updated.dev.manifest->checkCompatibility(*updated.fwk.matrix, error)) {
+ if (!getDeviceHalManifest()->checkCompatibility(*getFrameworkCompatibilityMatrix(), error)) {
if (error) {
error->insert(0,
"Device manifest and framework compatibility matrix are incompatible: ");
}
return INCOMPATIBLE;
}
- if (!updated.fwk.manifest->checkCompatibility(*updated.dev.matrix, error)) {
+ if (!getFrameworkHalManifest()->checkCompatibility(*getDeviceCompatibilityMatrix(), error)) {
if (error) {
error->insert(0,
"Framework manifest and device compatibility matrix are incompatible: ");
@@ -589,7 +533,8 @@
}
if (flags.isRuntimeInfoEnabled()) {
- if (!updated.runtimeInfo->checkCompatibility(*updated.fwk.matrix, error, flags)) {
+ if (!getRuntimeInfo()->checkCompatibility(*getFrameworkCompatibilityMatrix(), error,
+ flags)) {
if (error) {
error->insert(0,
"Runtime info and framework compatibility matrix are incompatible: ");