lshal: add "Status" column and "Manifest HALs" section.

- Added "Status" column that has following values:
    - alive: running hwbinder service
    - registered;dead: registered, but service cannot accept calls
    - declared: only in VINTF, not in hwservicemanager
    - N/A: passthrough HALs

- Added a "Manifest HALs" section that lists all
  HALs (hwbinder or passthrough) in device / framework manifest

Test: lshal_test

Bug: 71555570

Change-Id: I202b562ee73bcd49506bb43cc9af27b86f32651c
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index 096b67d..b05946b 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -327,7 +327,7 @@
 
 class ListTest : public ::testing::Test {
 public:
-    void SetUp() override {
+    virtual void SetUp() override {
         initMockServiceManager();
         lshal = std::make_unique<Lshal>(out, err, serviceManager, passthruManager);
         initMockList();
@@ -351,13 +351,13 @@
         ON_CALL(*mockList, getPartition(_)).WillByDefault(Return(Partition::VENDOR));
 
         ON_CALL(*mockList, getDeviceManifest())
-                .WillByDefault(Return(VintfObject::GetDeviceHalManifest()));
+                .WillByDefault(Return(std::make_shared<HalManifest>()));
         ON_CALL(*mockList, getDeviceMatrix())
-                .WillByDefault(Return(VintfObject::GetDeviceCompatibilityMatrix()));
+                .WillByDefault(Return(std::make_shared<CompatibilityMatrix>()));
         ON_CALL(*mockList, getFrameworkManifest())
-                .WillByDefault(Return(VintfObject::GetFrameworkHalManifest()));
+                .WillByDefault(Return(std::make_shared<HalManifest>()));
         ON_CALL(*mockList, getFrameworkMatrix())
-                .WillByDefault(Return(VintfObject::GetFrameworkCompatibilityMatrix()));
+                .WillByDefault(Return(std::make_shared<CompatibilityMatrix>()));
     }
 
     void initMockServiceManager() {
@@ -411,16 +411,22 @@
 }
 
 TEST_F(ListTest, Fetch) {
-    EXPECT_EQ(0u, mockList->fetch());
+    optind = 1; // mimic Lshal::parseArg()
+    ASSERT_EQ(0u, mockList->parseArgs(createArg({"lshal"})));
+    ASSERT_EQ(0u, mockList->fetch());
     vintf::TransportArch hwbinder{Transport::HWBINDER, Arch::ARCH_64};
     vintf::TransportArch passthrough{Transport::PASSTHROUGH, Arch::ARCH_32};
     std::array<vintf::TransportArch, 6> transportArchs{{hwbinder, hwbinder, passthrough,
                                                         passthrough, passthrough, passthrough}};
-    int id = 1;
+    int i = 0;
     mockList->forEachTable([&](const Table& table) {
-        ASSERT_EQ(2u, table.size());
         for (const auto& entry : table) {
-            auto transport = transportArchs.at(id - 1).transport;
+            if (i >= transportArchs.size()) {
+                break;
+            }
+
+            int id = i + 1;
+            auto transport = transportArchs.at(i).transport;
             TableEntry expected{
                 .interfaceName = getFqInstanceName(id),
                 .transport = transport,
@@ -433,14 +439,16 @@
                 .serverObjectAddress = transport == Transport::HWBINDER ? getPtr(id) : NO_PTR,
                 .clientPids = getClients(id),
                 .clientCmdlines = {},
-                .arch = transportArchs.at(id - 1).arch,
+                .arch = transportArchs.at(i).arch,
             };
             EXPECT_EQ(expected, entry) << expected.to_string() << " vs. " << entry.to_string();
 
-            ++id;
+            ++i;
         }
     });
 
+    EXPECT_EQ(transportArchs.size(), i) << "Not all entries are tested.";
+
 }
 
 TEST_F(ListTest, DumpVintf) {
@@ -758,6 +766,45 @@
     EXPECT_EQ("", err.str());
 }
 
+class ListVintfTest : public ListTest {
+public:
+    virtual void SetUp() override {
+        ListTest::SetUp();
+        const std::string mockManifestXml =
+                "<manifest version=\"1.0\" type=\"device\">\n"
+                "    <hal format=\"hidl\">\n"
+                "        <name>a.h.foo1</name>\n"
+                "        <transport>hwbinder</transport>\n"
+                "        <fqname>@1.0::IFoo/1</fqname>\n"
+                "    </hal>\n"
+                "    <hal format=\"hidl\">\n"
+                "        <name>a.h.bar1</name>\n"
+                "        <transport>hwbinder</transport>\n"
+                "        <fqname>@1.0::IBar/1</fqname>\n"
+                "    </hal>\n"
+                "    <hal format=\"hidl\">\n"
+                "        <name>a.h.bar2</name>\n"
+                "        <transport arch=\"32+64\">passthrough</transport>\n"
+                "        <fqname>@2.0::IBar/2</fqname>\n"
+                "    </hal>\n"
+                "</manifest>";
+        auto manifest = std::make_shared<HalManifest>();
+        EXPECT_TRUE(gHalManifestConverter(manifest.get(), mockManifestXml));
+        EXPECT_CALL(*mockList, getDeviceManifest())
+            .Times(AnyNumber())
+            .WillRepeatedly(Return(manifest));
+    }
+};
+
+TEST_F(ListVintfTest, ManifestHals) {
+    optind = 1; // mimic Lshal::parseArg()
+    EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-iStr", "--types=v", "--neat"})));
+    EXPECT_THAT(out.str(), HasSubstr("a.h.bar1@1.0::IBar/1 declared hwbinder    ?"));
+    EXPECT_THAT(out.str(), HasSubstr("a.h.bar2@2.0::IBar/2 declared passthrough 32+64"));
+    EXPECT_THAT(out.str(), HasSubstr("a.h.foo1@1.0::IFoo/1 declared hwbinder    ?"));
+    EXPECT_EQ("", err.str());
+}
+
 class HelpTest : public ::testing::Test {
 public:
     void SetUp() override {