Add VintfObjectRecovery
A special VintfObject for recovery. CheckCompatibility
knows how to mount /system and /vendor if necessary.
Test: testing with a test CL that replaces graphics test
into calling android::vintf::details::mountSystem
/ mountVendor, and the partitions are actually
mounted.
Bug: 36814503
Change-Id: Ie6a8e533841a128a411134973006ac4afb17a78e
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..b7b2ec0
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,27 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libvintf_recovery
+LOCAL_SRC_FILES := VintfObjectRecovery.cpp
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/vintf
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_CFLAGS := -Wall -Werror
+LOCAL_STATIC_LIBRARIES := \
+ libbase \
+ libvintf \
+ libfs_mgr
+include $(BUILD_STATIC_LIBRARY)
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 00e02dd..674031a 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -73,13 +73,7 @@
namespace details {
-static status_t mountSystem() {
- // TODO(b/36814503): mount system partition here for recovery mode.
- return OK;
-}
-
-static status_t mountVendor() {
- // TODO(b/36814503): mount vendor partition here for recovery mode.
+static status_t fakeMountUmount() {
return OK;
}
@@ -90,7 +84,7 @@
DUPLICATED_DEV_ENTRY,
};
-std::string toString(ParseStatus status) {
+static std::string toString(ParseStatus status) {
switch(status) {
case ParseStatus::OK: return "OK";
case ParseStatus::PARSE_ERROR: return "parse error";
@@ -101,7 +95,7 @@
}
template<typename T>
-ParseStatus tryParse(const std::string &xml, const XmlConverter<T> &parse,
+static ParseStatus tryParse(const std::string &xml, const XmlConverter<T> &parse,
std::unique_ptr<T> *fwk, std::unique_ptr<T> *dev) {
std::unique_ptr<T> ret = std::make_unique<T>();
if (!parse(ret.get(), xml)) {
@@ -124,6 +118,7 @@
template<typename T, typename GetFunction>
static status_t getMissing(const T *pkg, bool mount,
std::function<status_t(void)> mountFunction,
+ std::function<status_t(void)> umountFunction,
const T **updated,
GetFunction getFunction) {
if (pkg != nullptr) {
@@ -133,6 +128,9 @@
(void)mountFunction(); // ignore mount errors
}
*updated = getFunction();
+ if (mount) {
+ (void)umountFunction(); // ignore umount errors
+ }
}
return OK;
}
@@ -166,7 +164,9 @@
// Do compatibility check.
int32_t checkCompatibility(const std::vector<std::string> &xmls, bool mount,
std::function<status_t(void)> mountSystem,
+ std::function<status_t(void)> umountSystem,
std::function<status_t(void)> mountVendor,
+ std::function<status_t(void)> umountVendor,
std::function<const HalManifest *(bool)> GetFrameworkHalManifest,
std::function<const HalManifest *(bool)> GetDeviceHalManifest,
std::function<const RuntimeInfo *(bool)> GetRuntimeInfo,
@@ -205,11 +205,13 @@
}
// get missing info from device
- if ((status = getMissing(pkg.fwk.manifest.get(), mount, mountSystem, &updated.fwk.manifest,
+ if ((status = getMissing(pkg.fwk.manifest.get(), mount, mountSystem, umountSystem,
+ &updated.fwk.manifest,
std::bind(GetFrameworkHalManifest, true /* skipCache */))) != OK) {
return status;
}
- if ((status = getMissing(pkg.dev.manifest.get(), mount, mountVendor, &updated.dev.manifest,
+ if ((status = getMissing(pkg.dev.manifest.get(), mount, mountVendor, umountVendor,
+ &updated.dev.manifest,
std::bind(GetDeviceHalManifest, true /* skipCache */))) != OK) {
return status;
}
@@ -272,10 +274,10 @@
// static
int32_t VintfObject::CheckCompatibility(
- const std::vector<std::string> &xmls,
- bool mount, std::string *error) {
- return details::checkCompatibility(xmls, mount,
- &details::mountSystem, &details::mountVendor,
+ const std::vector<std::string> &xmls, std::string *error) {
+ return details::checkCompatibility(xmls, false /* mount */,
+ &details::fakeMountUmount, &details::fakeMountUmount,
+ &details::fakeMountUmount, &details::fakeMountUmount,
&VintfObject::GetFrameworkHalManifest,
&VintfObject::GetDeviceHalManifest,
&VintfObject::GetRuntimeInfo,
diff --git a/VintfObjectRecovery.cpp b/VintfObjectRecovery.cpp
new file mode 100644
index 0000000..ccae798
--- /dev/null
+++ b/VintfObjectRecovery.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VintfObjectRecovery.h"
+
+#include <android-base/properties.h>
+#include <sys/mount.h>
+
+#include "fs_mgr.h"
+
+namespace android {
+namespace vintf {
+
+namespace details {
+using FstabMgr = std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)>;
+
+static status_t mountAt(const FstabMgr &fstab, const char* path, const char* mount_point) {
+ fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab.get(), path);
+ if (rec == nullptr) {
+ return UNKNOWN_ERROR;
+ }
+ int result = mount(rec->blk_device, mount_point, rec->fs_type, rec->flags, rec->fs_options);
+ return result == 0 ? OK : -errno;
+}
+
+FstabMgr defaultFstabMgr() {
+ return FstabMgr{fs_mgr_read_fstab_default(), &fs_mgr_free_fstab};
+}
+
+status_t mountSystem() {
+ FstabMgr fstab = defaultFstabMgr();
+ if (fstab == NULL) {
+ return UNKNOWN_ERROR;
+ }
+ if (android::base::GetBoolProperty("ro.build.system_root_image", false)) {
+ return mountAt(fstab, "/", "/system_root");
+ } else {
+ return mountAt(fstab, "/system", "/system");
+ }
+}
+
+status_t mountVendor() {
+ FstabMgr fstab = defaultFstabMgr();
+ if (fstab == NULL) {
+ return UNKNOWN_ERROR;
+ }
+ return mountAt(fstab, "/vendor", "/vendor");
+}
+
+status_t umountSystem() {
+ if (android::base::GetBoolProperty("ro.build.system_root_image", false)) {
+ return umount("/system_root");
+ } else {
+ return umount("/system");
+ }
+}
+
+status_t umountVendor() {
+ return umount("/vendor");
+}
+
+} // namespace details
+
+// static
+int32_t VintfObjectRecovery::CheckCompatibility(
+ const std::vector<std::string> &xmls, std::string *error) {
+ return details::checkCompatibility(xmls, true /* mount */,
+ &details::mountSystem, &details::umountSystem,
+ &details::mountVendor, &details::umountVendor,
+ &VintfObject::GetFrameworkHalManifest,
+ &VintfObject::GetDeviceHalManifest,
+ &VintfObject::GetRuntimeInfo,
+ error);
+}
+
+
+} // namespace vintf
+} // namespace android
diff --git a/include/vintf/VintfObject.h b/include/vintf/VintfObject.h
index 4f38735..157d00b 100644
--- a/include/vintf/VintfObject.h
+++ b/include/vintf/VintfObject.h
@@ -68,11 +68,9 @@
/**
* Check compatibility, given a set of manifests / matrices in packageInfo.
* They will be checked against the manifests / matrices on the device.
- * Partitions (/system, /vendor) are mounted if necessary.
*
* @param packageInfo a list of XMLs of HalManifest /
* CompatibilityMatrix objects.
- * @param mount whether partitions should be mounted to do the check.
*
* @return = 0 if success (compatible)
* > 0 if incompatible
@@ -80,7 +78,6 @@
*/
static int32_t CheckCompatibility(
const std::vector<std::string> &packageInfo,
- bool mount = false,
std::string *error = nullptr);
};
@@ -89,6 +86,19 @@
INCOMPATIBLE = 1,
};
+// exposed for testing and VintfObjectRecovery.
+namespace details {
+int32_t checkCompatibility(const std::vector<std::string> &xmls, bool mount,
+ std::function<status_t(void)> mountSystem,
+ std::function<status_t(void)> umountSystem,
+ std::function<status_t(void)> mountVendor,
+ std::function<status_t(void)> umountVendor,
+ std::function<const HalManifest *(bool)> GetFrameworkHalManifest,
+ std::function<const HalManifest *(bool)> GetDeviceHalManifest,
+ std::function<const RuntimeInfo *(bool)> GetRuntimeInfo,
+ std::string *error);
+} // namespace details
+
} // namespace vintf
} // namespace android
diff --git a/include/vintf/VintfObjectRecovery.h b/include/vintf/VintfObjectRecovery.h
new file mode 100644
index 0000000..3b82bda
--- /dev/null
+++ b/include/vintf/VintfObjectRecovery.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VINTF_VINTF_OBJECT_RECOVERY_H_
+#define ANDROID_VINTF_VINTF_OBJECT_RECOVERY_H_
+
+#include "VintfObject.h"
+
+#include "utils/Errors.h"
+
+namespace android {
+namespace vintf {
+
+// Recovery version of VintfObject. It mount partitions if necessary. Partitions
+// are unmounted afterwards.
+
+class VintfObjectRecovery {
+ /**
+ * Check compatibility, given a set of manifests / matrices in packageInfo.
+ * They will be checked against the manifests / matrices on the device.
+ * Partitions (/system, /vendor) are mounted if necessary.
+ *
+ * @param packageInfo a list of XMLs of HalManifest /
+ * CompatibilityMatrix objects.
+ *
+ * @return = 0 if success (compatible)
+ * > 0 if incompatible
+ * < 0 if any error (mount partition fails, illformed XML, etc.)
+ */
+ static int32_t CheckCompatibility(
+ const std::vector<std::string> &packageInfo,
+ std::string *error = nullptr);
+
+};
+
+// exposed for testing purposes.
+namespace details {
+status_t mountSystem();
+status_t mountVendor();
+status_t umountSystem();
+status_t umountVendor();
+}
+
+} // namespace vintf
+} // namespace android
+
+#endif // ANDROID_VINTF_VINTF_OBJECT_RECOVERY_H_
diff --git a/test/main.cpp b/test/main.cpp
index da93b94..c7a243f 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -733,16 +733,6 @@
EXPECT_TRUE(manifest.checkCompatibility(matrix, &error)) << error;
}
-namespace details {
-int32_t checkCompatibility(const std::vector<std::string> &xmls, bool mount,
- std::function<status_t(void)> mountSystem,
- std::function<status_t(void)> mountVendor,
- std::function<const HalManifest *(bool)> GetFrameworkHalManifest,
- std::function<const HalManifest *(bool)> GetDeviceHalManifest,
- std::function<const RuntimeInfo *(bool)> GetRuntimeInfo,
- std::string *error);
-} // namespace details
-
TEST_F(LibVintfTest, Compat2) {
std::string deviceManifestXml =
"<manifest version=\"1.0\" type=\"device\">\n"
@@ -789,49 +779,61 @@
bool systemMounted = false;
bool vendorMounted = false;
- auto mountSystem = [&systemMounted] () { systemMounted = true; return OK; };
- auto mountVendor = [&vendorMounted] () { vendorMounted = true; return OK; };
+ bool systemUmounted = false;
+ bool vendorUmounted = false;
+ auto mountSystem = [&systemMounted] () { systemMounted = true; return OK; };
+ auto mountVendor = [&vendorMounted] () { vendorMounted = true; return OK; };
+ auto umountSystem = [&systemUmounted] () { systemUmounted = true; return OK; };
+ auto umountVendor = [&vendorUmounted] () { vendorUmounted = true; return OK; };
auto nullManifestFunc = [](bool) -> const HalManifest * { return nullptr; };
auto runtimeInfoFunc = [&](bool) { return &runtimeInfo; };
// full OTA
EXPECT_EQ(COMPATIBLE, details::checkCompatibility(
{deviceManifestXml, deviceMatrixXml, frameworkManifestXml, frameworkMatrixXml},
- false /* mount */, mountSystem, mountVendor,
+ false /* mount */, mountSystem, umountSystem, mountVendor, umountVendor,
nullManifestFunc,
nullManifestFunc,
runtimeInfoFunc,
&error)) << error;
EXPECT_FALSE(systemMounted);
EXPECT_FALSE(vendorMounted);
+ EXPECT_FALSE(systemUmounted);
+ EXPECT_FALSE(vendorUmounted);
EXPECT_EQ(COMPATIBLE, details::checkCompatibility(
{deviceManifestXml, deviceMatrixXml, frameworkManifestXml, frameworkMatrixXml},
- true /* mount */, mountSystem, mountVendor,
+ true /* mount */, mountSystem, umountSystem, mountVendor, umountVendor,
nullManifestFunc,
nullManifestFunc,
runtimeInfoFunc,
&error)) << error;
EXPECT_FALSE(systemMounted);
EXPECT_FALSE(vendorMounted);
+ EXPECT_FALSE(systemUmounted);
+ EXPECT_FALSE(vendorUmounted);
// framework only OTA
EXPECT_GT(0, details::checkCompatibility(
{frameworkManifestXml, frameworkMatrixXml},
- false /* mount */, mountSystem, mountVendor,
+ false /* mount */, mountSystem, umountSystem, mountVendor, umountVendor,
nullManifestFunc,
nullManifestFunc,
runtimeInfoFunc,
&error)) << "should not mount, thus info should be missing";
EXPECT_FALSE(systemMounted);
EXPECT_FALSE(vendorMounted);
+ EXPECT_FALSE(systemUmounted);
+ EXPECT_FALSE(vendorUmounted);
EXPECT_EQ(COMPATIBLE, details::checkCompatibility(
{frameworkManifestXml, frameworkMatrixXml},
- true /* mount */, mountSystem, mountVendor,
+ true /* mount */, mountSystem, umountSystem, mountVendor, umountVendor,
nullManifestFunc,
[&](auto) { return &devManifest; },
runtimeInfoFunc,
&error)) << error;
EXPECT_FALSE(systemMounted);
EXPECT_TRUE(vendorMounted);
+ EXPECT_FALSE(systemUmounted);
+ EXPECT_TRUE(vendorUmounted);
CompatibilityMatrix failedFwkMatrix;
std::string failedFrameworkMatrixXml;
@@ -856,13 +858,15 @@
EXPECT_FALSE(runtimeInfo.checkCompatibility(failedFwkMatrix, &error)) << error;
EXPECT_EQ(INCOMPATIBLE, details::checkCompatibility(
{frameworkManifestXml, failedFrameworkMatrixXml},
- true /* mount */, mountSystem, mountVendor,
+ true /* mount */, mountSystem, umountSystem, mountVendor, umountVendor,
nullManifestFunc,
[&](auto) { return &devManifest; },
runtimeInfoFunc,
&error)) << error;
EXPECT_FALSE(systemMounted);
EXPECT_TRUE(vendorMounted);
+ EXPECT_FALSE(systemUmounted);
+ EXPECT_TRUE(vendorUmounted);
// Failed framework only OTA example 2: unsupported HAL
failedFwkMatrix = {};
@@ -888,13 +892,15 @@
EXPECT_TRUE(runtimeInfo.checkCompatibility(failedFwkMatrix, &error)) << error;
EXPECT_EQ(INCOMPATIBLE, details::checkCompatibility(
{frameworkManifestXml, failedFrameworkMatrixXml},
- true /* mount */, mountSystem, mountVendor,
+ true /* mount */, mountSystem, umountSystem, mountVendor, umountVendor,
nullManifestFunc,
[&](auto) { return &devManifest; },
runtimeInfoFunc,
&error)) << error;
EXPECT_FALSE(systemMounted);
EXPECT_TRUE(vendorMounted);
+ EXPECT_FALSE(systemUmounted);
+ EXPECT_TRUE(vendorUmounted);
}
} // namespace vintf