vts_treble_vintf_test: <= O-MR1, less strict

In P, several new requirements were added universally across
devices. However, because old architectures were too dangerous
to change, we're opting to only add these requirements starting
on devices which launch with P. For instance, certain HAL
implementations were tightly coupled with the hardware they talk
to and could only start up when the device is in a specific state.
This means that devices launching with O/O-MR1 in P will not
be guaranteed to have an accurate vendor manifest. This is not
a regression from when they were launched.

For similar reasons, the hashes for interfaces in these old
architectures can not be updated, so they have also been exempted.

If a device has warnings, this means a side-band ABI is being
exposed which will need to be maintained in a backwards
compatible way.

Bug: 68662126 # for test failures
Bug: 77981855 # for getService not returning
Bug: 68661741 # for curren.txt issues
Test: vts_treble_vintf_test_all passes on Pixel 2
Test: vts_treble_vintf_test_all no change on device launching with P

Change-Id: Id7ddc88ed29589c203ea78a5f3cc30e3852c4727
diff --git a/treble/vintf/SingleManifestTest.cpp b/treble/vintf/SingleManifestTest.cpp
index f20bad9..4662d48 100644
--- a/treble/vintf/SingleManifestTest.cpp
+++ b/treble/vintf/SingleManifestTest.cpp
@@ -29,6 +29,38 @@
 using android::FqInstance;
 using android::vintf::toFQNameString;
 
+// For devices that launched <= Android O-MR1, systems/hals/implementations
+// were delivered to companies which either don't start up on device boot.
+bool LegacyAndExempt(const FQName &fq_name) {
+  return GetShippingApiLevel() <= 27 && !IsGoogleDefinedIface(fq_name);
+}
+
+void FailureHalMissing(const FQName &fq_name) {
+  if (LegacyAndExempt(fq_name)) {
+    cout << "[  WARNING ] " << fq_name.string()
+         << " not available but is exempted because it is legacy. It is still "
+            "recommended to fix this."
+         << endl;
+  } else {
+    ADD_FAILURE() << fq_name.string() << " not available.";
+  }
+}
+
+void FailureHashMissing(const FQName &fq_name) {
+  if (LegacyAndExempt(fq_name)) {
+    cout << "[  WARNING ] " << fq_name.string()
+         << " has an empty hash but is exempted because it is legacy. It is "
+            "still recommended to fix this. This is because it was compiled "
+            "without being frozen in a corresponding current.txt file."
+         << endl;
+  } else {
+    ADD_FAILURE()
+        << fq_name.string()
+        << " has an empty hash. This is because it was compiled "
+           "without being frozen in a corresponding current.txt file.";
+  }
+}
+
 // Tests that no HAL outside of the allowed set is specified as passthrough in
 // VINTF.
 TEST_P(SingleManifestTest, HalsAreBinderized) {
@@ -98,10 +130,10 @@
         hal_service = GetHalService(fq_name, instance_name, transport);
       }
 
-      EXPECT_NE(hal_service, nullptr)
-          << fq_name.string() << " not available." << endl;
-
-      if (hal_service == nullptr) return;
+      if (hal_service == nullptr) {
+        FailureHalMissing(fq_name);
+        return;
+      }
 
       EXPECT_EQ(transport == Transport::HWBINDER, hal_service->isRemote())
           << "transport is " << transport << "but HAL service is "
@@ -224,7 +256,7 @@
     sp<IBase> hal_service = GetHalService(fq_name, instance_name, transport);
 
     if (hal_service == nullptr) {
-      ADD_FAILURE() << fq_name.string() << " not available." << endl;
+      FailureHalMissing(fq_name);
       return;
     }
 
@@ -249,11 +281,10 @@
         return;
       }
       string hash = hash_chain[i];
-      // No interface is allowed to have an empty hash.
-      EXPECT_NE(hash, Hash::hexString(Hash::kEmptyHash))
-          << fq_iface_name.string()
-          << " has an empty hash. This is because it was compiled without"
-             " being frozen in a corresponding current.txt file.";
+
+      if (hash == Hash::hexString(Hash::kEmptyHash)) {
+        FailureHashMissing(fq_iface_name);
+      }
 
       if (IsGoogleDefinedIface(fq_iface_name)) {
         set<string> released_hashes = ReleasedHashes(fq_iface_name);