Fix resource mgmt bug in SubscriptionManager.

The subscription information map is not correctly cleared during
unsubscription.

Flag: EXEMPT HAL
Test: atest DefaultVehicleHalTest SubscriptionManagerTest
Bug: 38256329
Change-Id: I78968aec54eda291932a34e5ef6c3f3d0e194295
diff --git a/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h
index 42902fe..d360be0 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/current/vhal/include/DefaultVehicleHal.h
@@ -219,7 +219,7 @@
     // mBinderEvents.
     void onBinderDiedUnlinkedHandler();
 
-    size_t countSubscribeClients();
+    size_t countClients();
 
     // Handles the property change events in batch.
     void handleBatchedPropertyEvents(std::vector<aidlvhal::VehiclePropValue>&& batchedEvents);
diff --git a/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h b/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h
index fa438ec..f4e6ced 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h
+++ b/automotive/vehicle/aidl/impl/current/vhal/include/SubscriptionManager.h
@@ -146,6 +146,7 @@
   private:
     // Friend class for testing.
     friend class DefaultVehicleHalTest;
+    friend class SubscriptionManagerTest;
 
     IVehicleHardware* mVehicleHardware;
 
diff --git a/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp
index 050f88d..ea0c215 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/src/DefaultVehicleHal.cpp
@@ -1336,15 +1336,19 @@
         dprintf(fd, "Containing %zu property configs\n", configsByPropIdCopy.size());
         dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
         dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
-        dprintf(fd, "Currently have %zu subscribe clients\n", countSubscribeClients());
+        dprintf(fd, "Currently have %zu subscribe clients\n",
+                mSubscriptionManager->countPropertyChangeClients());
         dprintf(fd, "Currently have %zu supported values change subscribe clients\n",
                 mSubscriptionManager->countSupportedValueChangeClients());
     }
     return STATUS_OK;
 }
 
-size_t DefaultVehicleHal::countSubscribeClients() {
-    return mSubscriptionManager->countPropertyChangeClients();
+size_t DefaultVehicleHal::countClients() {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+    return mGetValuesClients.size() + mSetValuesClients.size() +
+           mSubscriptionManager->countPropertyChangeClients() +
+           mSubscriptionManager->countSupportedValueChangeClients();
 }
 
 }  // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp b/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp
index 946c217..64c46c9 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/src/SubscriptionManager.cpp
@@ -414,7 +414,6 @@
     std::scoped_lock<std::mutex> lockGuard(mLock);
 
     ClientIdType clientId = callback->asBinder().get();
-    ALOGE("ClientId: %p", clientId);
 
     // It is possible that some of the [propId, areaId]s are already subscribed, IVehicleHardware
     // will ignore them.
@@ -479,7 +478,7 @@
             mSupportedValueChangeClientsByPropIdAreaId.end()) {
             mSupportedValueChangeClientsByPropIdAreaId[propIdAreaId].erase(clientId);
         }
-        if (mSupportedValueChangeClientsByPropIdAreaId.empty()) {
+        if (mSupportedValueChangeClientsByPropIdAreaId[propIdAreaId].empty()) {
             mSupportedValueChangeClientsByPropIdAreaId.erase(propIdAreaId);
         }
         mSupportedValueChangePropIdAreaIdsByClient[clientId].erase(propIdAreaId);
diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp
index 90b34c4..ab5f667 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/DefaultVehicleHalTest.cpp
@@ -445,11 +445,7 @@
 
     size_t countPendingRequests() { return mVhal->mPendingRequestPool->countPendingRequests(); }
 
-    size_t countClients() {
-        std::scoped_lock<std::mutex> lockGuard(mVhal->mLock);
-        return mVhal->mGetValuesClients.size() + mVhal->mSetValuesClients.size() +
-               mVhal->countSubscribeClients();
-    }
+    size_t countClients() { return mVhal->countClients(); }
 
     std::shared_ptr<PendingRequestPool> getPool() { return mVhal->mPendingRequestPool; }
 
@@ -2575,8 +2571,10 @@
     ASSERT_TRUE(status.isOk()) << "Get non-okay status from unregisterSupportedValueChangeCallback"
                                << status.getMessage();
 
-    ASSERT_TRUE(getHardware()->getSubscribedSupportedValueChangePropIdAreaIds().empty())
+    EXPECT_TRUE(getHardware()->getSubscribedSupportedValueChangePropIdAreaIds().empty())
             << "All registered [propId, areaId]s must be unregistered";
+    EXPECT_EQ(countClients(), static_cast<size_t>(0)) << "subscribe clients must be cleared";
+    EXPECT_TRUE(hasNoSubscriptions()) << "subscribe clients must be cleared";
 }
 
 TEST_F(DefaultVehicleHalTest, testUnregisterSupportedValueChangeCallback_errorFromHardware) {
diff --git a/automotive/vehicle/aidl/impl/current/vhal/test/SubscriptionManagerTest.cpp b/automotive/vehicle/aidl/impl/current/vhal/test/SubscriptionManagerTest.cpp
index 6d0844a..d624cce 100644
--- a/automotive/vehicle/aidl/impl/current/vhal/test/SubscriptionManagerTest.cpp
+++ b/automotive/vehicle/aidl/impl/current/vhal/test/SubscriptionManagerTest.cpp
@@ -124,6 +124,8 @@
 
     std::shared_ptr<MockVehicleHardware> getHardware() { return mHardware; }
 
+    bool isEmpty() { return mManager->isEmpty(); }
+
   private:
     std::unique_ptr<SubscriptionManager> mManager;
     std::shared_ptr<PropertyCallback> mCallback;
@@ -946,6 +948,19 @@
             << "Incorrect supported value change events for client1";
     ASSERT_THAT(clients[client2], UnorderedElementsAre(propIdAreaId2))
             << "Incorrect supported value change events for client2";
+
+    result = getManager()->unsubscribeSupportedValueChange(binder2.get(), {propIdAreaId2});
+
+    ASSERT_TRUE(result.ok()) << "failed to call unsubscribeSupportedValueChange"
+                             << result.error().message();
+
+    result = getManager()->unsubscribeSupportedValueChange(binder1.get(), {propIdAreaId1});
+
+    ASSERT_TRUE(result.ok()) << "failed to call unsubscribeSupportedValueChange"
+                             << result.error().message();
+
+    EXPECT_EQ(getManager()->countSupportedValueChangeClients(), 0u) << "All clients cleared";
+    EXPECT_TRUE(isEmpty()) << "All clients cleared";
 }
 
 }  // namespace vehicle