health: registerCallback() and getHealthInfo() does not notify all callbacks

registerCallback() and getHealthInfo() unintentionally broadcast
health info to all callbacks, which has a performance impact.

* registerCallback() still invokes the new callback immediately
* getHealthInfo() does not call any callbacks at all.

Test: VTS test call getHealthInfo does not invoke update()
Bug: 117167903
Change-Id: Ida99fdd73831e747fbf2d65089c7c0e7661fe7c4
diff --git a/health/2.0/default/Health.cpp b/health/2.0/default/Health.cpp
index 4a4bee0..a2b81d1 100644
--- a/health/2.0/default/Health.cpp
+++ b/health/2.0/default/Health.cpp
@@ -58,7 +58,7 @@
         // ignore the error
     }
 
-    return update();
+    return updateAndNotify(callback);
 }
 
 bool Health::unregisterCallbackInternal(const sp<IBase>& callback) {
@@ -156,6 +156,18 @@
     return Result::SUCCESS;
 }
 
+Return<Result> Health::updateAndNotify(const sp<IHealthInfoCallback>& callback) {
+    std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
+    std::vector<sp<IHealthInfoCallback>> storedCallbacks{std::move(callbacks_)};
+    callbacks_.clear();
+    if (callback != nullptr) {
+        callbacks_.push_back(callback);
+    }
+    Return<Result> result = update();
+    callbacks_ = std::move(storedCallbacks);
+    return result;
+}
+
 void Health::notifyListeners(HealthInfo* healthInfo) {
     std::vector<StorageInfo> info;
     get_storage_info(info);
@@ -233,7 +245,7 @@
 Return<void> Health::getHealthInfo(getHealthInfo_cb _hidl_cb) {
     using android::hardware::health::V1_0::hal_conversion::convertToHealthInfo;
 
-    update();
+    updateAndNotify(nullptr);
     struct android::BatteryProperties p = getBatteryProperties(battery_monitor_.get());
 
     V1_0::HealthInfo batteryInfo;
diff --git a/health/2.0/default/include/health2/Health.h b/health/2.0/default/include/health2/Health.h
index b960358..6410474 100644
--- a/health/2.0/default/include/health2/Health.h
+++ b/health/2.0/default/include/health2/Health.h
@@ -64,6 +64,10 @@
     std::unique_ptr<BatteryMonitor> battery_monitor_;
 
     bool unregisterCallbackInternal(const sp<IBase>& cb);
+
+    // update() and only notify the given callback, but none of the other callbacks.
+    // If cb is null, do not notify any callback at all.
+    Return<Result> updateAndNotify(const sp<IHealthInfoCallback>& cb);
 };
 
 }  // namespace implementation