Merge "Add acyclic check pass to hidl-gen"
diff --git a/Coordinator.cpp b/Coordinator.cpp
index 2211804..ffb76b1 100644
--- a/Coordinator.cpp
+++ b/Coordinator.cpp
@@ -559,8 +559,10 @@
             continue;
         }
 
-        // hash not define, interface not frozen
+        // hash not defined, interface not frozen
         if (frozen.size() == 0) {
+            // This ensures that it can be detected.
+            Hash::clearHash(ast->getFilename());
             continue;
         }
 
diff --git a/Hash.cpp b/Hash.cpp
index 032227f..e269a2c 100644
--- a/Hash.cpp
+++ b/Hash.cpp
@@ -16,6 +16,7 @@
 
 #include "Hash.h"
 
+#include <algorithm>
 #include <fstream>
 #include <iomanip>
 #include <map>
@@ -27,7 +28,9 @@
 
 namespace android {
 
-const Hash &Hash::getHash(const std::string &path) {
+const std::vector<uint8_t> Hash::kEmptyHash = std::vector<uint8_t>(SHA256_DIGEST_LENGTH, 0);
+
+Hash& Hash::getMutableHash(const std::string& path) {
     static std::map<std::string, Hash> hashes;
 
     auto it = hashes.find(path);
@@ -39,6 +42,14 @@
     return it->second;
 }
 
+const Hash& Hash::getHash(const std::string& path) {
+    return getMutableHash(path);
+}
+
+void Hash::clearHash(const std::string& path) {
+    getMutableHash(path).mHash = kEmptyHash;
+}
+
 static std::vector<uint8_t> sha256File(const std::string &path) {
     std::ifstream stream(path);
     std::stringstream fileStream;
diff --git a/include_hash/hidl-hash/Hash.h b/include_hash/hidl-hash/Hash.h
index 71a96e8..40cc5bf 100644
--- a/include_hash/hidl-hash/Hash.h
+++ b/include_hash/hidl-hash/Hash.h
@@ -23,8 +23,11 @@
 namespace android {
 
 struct Hash {
+    static const std::vector<uint8_t> kEmptyHash;
+
     // path to .hal file
     static const Hash &getHash(const std::string &path);
+    static void clearHash(const std::string& path);
 
     // returns matching hashes of interfaceName in path
     // path is something like hardware/interfaces/current.txt
@@ -42,8 +45,10 @@
 private:
     Hash(const std::string &path);
 
+    static Hash& getMutableHash(const std::string& path);
+
     const std::string mPath;
-    const std::vector<uint8_t> mHash;
+    std::vector<uint8_t> mHash;
 };
 
 }  // namespace android
diff --git a/test/hidl_test_client.cpp b/test/hidl_test_client.cpp
index 1b85c67..97747bd 100644
--- a/test/hidl_test_client.cpp
+++ b/test/hidl_test_client.cpp
@@ -560,17 +560,24 @@
 }
 
 TEST_F(HidlTest, HashTest) {
-    uint8_t ihash[32] = {74,38,204,105,102,117,11,15,207,7,238,198,29,35,30,62,100,
-            216,131,182,3,61,162,241,215,211,6,20,251,143,125,161};
+    static constexpr uint64_t kHashSize = 32u;
+    // unreleased interface has an empty hash
+    uint8_t ihash[kHashSize] = {0};
+    uint8_t ibase[kHashSize] = {189, 218, 182, 24,  77,  122, 52,  109, 166, 160, 125,
+                                192, 130, 140, 241, 154, 105, 111, 76,  170, 54,  17,
+                                197, 31,  46,  20,  86,  90,  20,  180, 15,  217};
     auto service = IHash::getService(mode == PASSTHROUGH /* getStub */);
-    EXPECT_OK(service->getHashChain([&] (const auto &chain) {
-        EXPECT_EQ(chain[0].size(), 32u);
-        EXPECT_ARRAYEQ(ihash, chain[0], 32);
-        EXPECT_OK(manager->getHashChain([&] (const auto &managerChain) {
-            EXPECT_EQ(chain[chain.size() - 1].size(), managerChain[managerChain.size() - 1].size());
-            EXPECT_ARRAYEQ(chain[chain.size() - 1], managerChain[managerChain.size() - 1],
-                    chain[chain.size() - 1].size()) << "Hash for IBase doesn't match!";
-        }));
+    EXPECT_OK(service->getHashChain([&](const auto& chain) {
+        ASSERT_EQ(chain.size(), 2u);
+        EXPECT_EQ(chain[0].size(), kHashSize);
+        EXPECT_ARRAYEQ(ihash, chain[0], kHashSize);
+        EXPECT_EQ(chain[1].size(), kHashSize);
+        EXPECT_ARRAYEQ(ibase, chain[1], kHashSize);
+    }));
+    EXPECT_OK(manager->getHashChain([&](const auto& managerChain) {
+        EXPECT_EQ(managerChain[managerChain.size() - 1].size(), kHashSize);
+        EXPECT_ARRAYEQ(ibase, managerChain[managerChain.size() - 1], kHashSize)
+            << "Hash for IBase doesn't match!";
     }));
 }