Merge "Ensure Shipping FCM Version fulfills launch requirements"
diff --git a/treble/vintf/vts_treble_vintf_test.cpp b/treble/vintf/vts_treble_vintf_test.cpp
index c421006..880b29e 100644
--- a/treble/vintf/vts_treble_vintf_test.cpp
+++ b/treble/vintf/vts_treble_vintf_test.cpp
@@ -25,6 +25,7 @@
#include <thread>
#include <vector>
+#include <android-base/properties.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <gtest/gtest.h>
#include <hidl-hash/Hash.h>
@@ -35,12 +36,14 @@
using android::FQName;
using android::Hash;
+using android::sp;
+using android::base::GetUintProperty;
using android::hardware::hidl_array;
using android::hardware::hidl_string;
using android::hardware::hidl_vec;
using android::hidl::manager::V1_0::IServiceManager;
-using android::sp;
using android::vintf::HalManifest;
+using android::vintf::Level;
using android::vintf::ManifestHal;
using android::vintf::Transport;
using android::vintf::Version;
@@ -77,6 +80,34 @@
"android.hidl.memory",
};
+// kFcm2ApiLevelMap is associated with API level. There can be multiple
+// Framework Compatibility Matrix Version (FCM Version) per API level, or
+// multiple API levels per FCM version.
+// kFcm2ApiLevelMap is defined apart from android::vintf::Level. Level is an
+// integer designed to be irrelevant with API level; the O / O_MR1 values are
+// historic values for convenience, and should be removed (b/70628538). Hence
+// these values are not used here.
+// For example:
+// ...
+// // Assume devices launch with Android X must implement FCM version >= 9
+// X = 9,
+// // Assume devices launch with Android Y and Android Z must implement
+// // FCM version >= 11
+// Y = 11,
+// Z = 11
+static const map<size_t /* Shipping API Level */, Level /* FCM Version */>
+ kFcm2ApiLevelMap{{// N. The test runs on devices that launch with N and
+ // become a Treble device when upgrading to O.
+ {25, static_cast<Level>(1)},
+ // O
+ {26, static_cast<Level>(1)},
+ // O MR-1
+ {27, static_cast<Level>(2)},
+ // P
+ {28, static_cast<Level>(3)}}};
+
+static const string kShippingApiLevelProp = "ro.product.first_api_level";
+
// For a given interface returns package root if known. Returns empty string
// otherwise.
static const string PackageRoot(const FQName &fq_iface_name) {
@@ -379,6 +410,38 @@
<< error;
}
+// Tests that Shipping FCM Version in the device manifest is at least the
+// minimum Shipping FCM Version as required by Shipping API level.
+TEST(DeprecateTest, ShippingFcmVersion) {
+ uint64_t shipping_api_level =
+ GetUintProperty<uint64_t>(kShippingApiLevelProp, 0);
+
+ ASSERT_NE(shipping_api_level, 0u) << "sysprop " << kShippingApiLevelProp
+ << " is missing or cannot be parsed.";
+ Level shipping_fcm_version = VintfObject::GetDeviceHalManifest()->level();
+ if (shipping_fcm_version == Level::UNSPECIFIED) {
+ // O / O-MR1 vendor image doesn't have shipping FCM version declared and
+ // shipping FCM version is inferred from Shipping API level, hence it always
+ // meets the requirement.
+ return;
+ }
+
+ ASSERT_GE(shipping_api_level, kFcm2ApiLevelMap.begin()->first /* 25 */)
+ << "Pre-N devices should not run this test.";
+
+ auto it = kFcm2ApiLevelMap.find(shipping_api_level);
+ ASSERT_TRUE(it != kFcm2ApiLevelMap.end())
+ << "No launch requirement is set yet for Shipping API level "
+ << shipping_api_level << ". Please update the test.";
+
+ Level required_fcm_version = it->second;
+
+ ASSERT_GE(shipping_fcm_version, required_fcm_version)
+ << "Shipping API level == " << shipping_api_level
+ << " requires Shipping FCM Version >= " << required_fcm_version
+ << " (but is " << shipping_fcm_version << ")";
+}
+
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();