• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #define LOG_TAG "android.hardware.health@2.0-impl"
17 #include <android-base/logging.h>
18 
19 #include <android-base/file.h>
20 #include <health2/Health.h>
21 
22 #include <hal_conversion.h>
23 #include <hidl/HidlTransportSupport.h>
24 
25 extern void healthd_battery_update_internal(bool);
26 
27 namespace android {
28 namespace hardware {
29 namespace health {
30 namespace V2_0 {
31 namespace implementation {
32 
33 sp<Health> Health::instance_;
34 
Health(struct healthd_config * c)35 Health::Health(struct healthd_config* c) {
36     // TODO(b/69268160): remove when libhealthd is removed.
37     healthd_board_init(c);
38     battery_monitor_ = std::make_unique<BatteryMonitor>();
39     battery_monitor_->init(c);
40 }
41 
42 // Methods from IHealth follow.
registerCallback(const sp<IHealthInfoCallback> & callback)43 Return<Result> Health::registerCallback(const sp<IHealthInfoCallback>& callback) {
44     if (callback == nullptr) {
45         return Result::SUCCESS;
46     }
47 
48     {
49         std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
50         callbacks_.push_back(callback);
51         // unlock
52     }
53 
54     auto linkRet = callback->linkToDeath(this, 0u /* cookie */);
55     if (!linkRet.withDefault(false)) {
56         LOG(WARNING) << __func__ << "Cannot link to death: "
57                      << (linkRet.isOk() ? "linkToDeath returns false" : linkRet.description());
58         // ignore the error
59     }
60 
61     return updateAndNotify(callback);
62 }
63 
unregisterCallbackInternal(const sp<IBase> & callback)64 bool Health::unregisterCallbackInternal(const sp<IBase>& callback) {
65     if (callback == nullptr) return false;
66 
67     bool removed = false;
68     std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
69     for (auto it = callbacks_.begin(); it != callbacks_.end();) {
70         if (interfacesEqual(*it, callback)) {
71             it = callbacks_.erase(it);
72             removed = true;
73         } else {
74             ++it;
75         }
76     }
77     (void)callback->unlinkToDeath(this).isOk();  // ignore errors
78     return removed;
79 }
80 
unregisterCallback(const sp<IHealthInfoCallback> & callback)81 Return<Result> Health::unregisterCallback(const sp<IHealthInfoCallback>& callback) {
82     return unregisterCallbackInternal(callback) ? Result::SUCCESS : Result::NOT_FOUND;
83 }
84 
85 template <typename T>
getProperty(const std::unique_ptr<BatteryMonitor> & monitor,int id,T defaultValue,const std::function<void (Result,T)> & callback)86 void getProperty(const std::unique_ptr<BatteryMonitor>& monitor, int id, T defaultValue,
87                  const std::function<void(Result, T)>& callback) {
88     struct BatteryProperty prop;
89     T ret = defaultValue;
90     Result result = Result::SUCCESS;
91     status_t err = monitor->getProperty(static_cast<int>(id), &prop);
92     if (err != OK) {
93         LOG(DEBUG) << "getProperty(" << id << ")"
94                    << " fails: (" << err << ") " << strerror(-err);
95     } else {
96         ret = static_cast<T>(prop.valueInt64);
97     }
98     switch (err) {
99         case OK:
100             result = Result::SUCCESS;
101             break;
102         case NAME_NOT_FOUND:
103             result = Result::NOT_SUPPORTED;
104             break;
105         default:
106             result = Result::UNKNOWN;
107             break;
108     }
109     callback(result, static_cast<T>(ret));
110 }
111 
getChargeCounter(getChargeCounter_cb _hidl_cb)112 Return<void> Health::getChargeCounter(getChargeCounter_cb _hidl_cb) {
113     getProperty<int32_t>(battery_monitor_, BATTERY_PROP_CHARGE_COUNTER, 0, _hidl_cb);
114     return Void();
115 }
116 
getCurrentNow(getCurrentNow_cb _hidl_cb)117 Return<void> Health::getCurrentNow(getCurrentNow_cb _hidl_cb) {
118     getProperty<int32_t>(battery_monitor_, BATTERY_PROP_CURRENT_NOW, 0, _hidl_cb);
119     return Void();
120 }
121 
getCurrentAverage(getCurrentAverage_cb _hidl_cb)122 Return<void> Health::getCurrentAverage(getCurrentAverage_cb _hidl_cb) {
123     getProperty<int32_t>(battery_monitor_, BATTERY_PROP_CURRENT_AVG, 0, _hidl_cb);
124     return Void();
125 }
126 
getCapacity(getCapacity_cb _hidl_cb)127 Return<void> Health::getCapacity(getCapacity_cb _hidl_cb) {
128     getProperty<int32_t>(battery_monitor_, BATTERY_PROP_CAPACITY, 0, _hidl_cb);
129     return Void();
130 }
131 
getEnergyCounter(getEnergyCounter_cb _hidl_cb)132 Return<void> Health::getEnergyCounter(getEnergyCounter_cb _hidl_cb) {
133     getProperty<int64_t>(battery_monitor_, BATTERY_PROP_ENERGY_COUNTER, 0, _hidl_cb);
134     return Void();
135 }
136 
getChargeStatus(getChargeStatus_cb _hidl_cb)137 Return<void> Health::getChargeStatus(getChargeStatus_cb _hidl_cb) {
138     getProperty(battery_monitor_, BATTERY_PROP_BATTERY_STATUS, BatteryStatus::UNKNOWN, _hidl_cb);
139     return Void();
140 }
141 
update()142 Return<Result> Health::update() {
143     if (!healthd_mode_ops || !healthd_mode_ops->battery_update) {
144         LOG(WARNING) << "health@2.0: update: not initialized. "
145                      << "update() should not be called in charger";
146         return Result::UNKNOWN;
147     }
148 
149     // Retrieve all information and call healthd_mode_ops->battery_update, which calls
150     // notifyListeners.
151     bool chargerOnline = battery_monitor_->update();
152 
153     // adjust uevent / wakealarm periods
154     healthd_battery_update_internal(chargerOnline);
155 
156     return Result::SUCCESS;
157 }
158 
updateAndNotify(const sp<IHealthInfoCallback> & callback)159 Return<Result> Health::updateAndNotify(const sp<IHealthInfoCallback>& callback) {
160     std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
161     std::vector<sp<IHealthInfoCallback>> storedCallbacks{std::move(callbacks_)};
162     callbacks_.clear();
163     if (callback != nullptr) {
164         callbacks_.push_back(callback);
165     }
166     Return<Result> result = update();
167     callbacks_ = std::move(storedCallbacks);
168     return result;
169 }
170 
notifyListeners(HealthInfo * healthInfo)171 void Health::notifyListeners(HealthInfo* healthInfo) {
172     std::vector<StorageInfo> info;
173     get_storage_info(info);
174 
175     std::vector<DiskStats> stats;
176     get_disk_stats(stats);
177 
178     int32_t currentAvg = 0;
179 
180     struct BatteryProperty prop;
181     status_t ret = battery_monitor_->getProperty(BATTERY_PROP_CURRENT_AVG, &prop);
182     if (ret == OK) {
183         currentAvg = static_cast<int32_t>(prop.valueInt64);
184     }
185 
186     healthInfo->batteryCurrentAverage = currentAvg;
187     healthInfo->diskStats = stats;
188     healthInfo->storageInfos = info;
189 
190     std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
191     for (auto it = callbacks_.begin(); it != callbacks_.end();) {
192         auto ret = (*it)->healthInfoChanged(*healthInfo);
193         if (!ret.isOk() && ret.isDeadObject()) {
194             it = callbacks_.erase(it);
195         } else {
196             ++it;
197         }
198     }
199 }
200 
debug(const hidl_handle & handle,const hidl_vec<hidl_string> &)201 Return<void> Health::debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) {
202     if (handle != nullptr && handle->numFds >= 1) {
203         int fd = handle->data[0];
204         battery_monitor_->dumpState(fd);
205 
206         getHealthInfo([fd](auto res, const auto& info) {
207             android::base::WriteStringToFd("\ngetHealthInfo -> ", fd);
208             if (res == Result::SUCCESS) {
209                 android::base::WriteStringToFd(toString(info), fd);
210             } else {
211                 android::base::WriteStringToFd(toString(res), fd);
212             }
213             android::base::WriteStringToFd("\n", fd);
214         });
215 
216         fsync(fd);
217     }
218     return Void();
219 }
220 
getStorageInfo(getStorageInfo_cb _hidl_cb)221 Return<void> Health::getStorageInfo(getStorageInfo_cb _hidl_cb) {
222     std::vector<struct StorageInfo> info;
223     get_storage_info(info);
224     hidl_vec<struct StorageInfo> info_vec(info);
225     if (!info.size()) {
226         _hidl_cb(Result::NOT_SUPPORTED, info_vec);
227     } else {
228         _hidl_cb(Result::SUCCESS, info_vec);
229     }
230     return Void();
231 }
232 
getDiskStats(getDiskStats_cb _hidl_cb)233 Return<void> Health::getDiskStats(getDiskStats_cb _hidl_cb) {
234     std::vector<struct DiskStats> stats;
235     get_disk_stats(stats);
236     hidl_vec<struct DiskStats> stats_vec(stats);
237     if (!stats.size()) {
238         _hidl_cb(Result::NOT_SUPPORTED, stats_vec);
239     } else {
240         _hidl_cb(Result::SUCCESS, stats_vec);
241     }
242     return Void();
243 }
244 
getHealthInfo(getHealthInfo_cb _hidl_cb)245 Return<void> Health::getHealthInfo(getHealthInfo_cb _hidl_cb) {
246     using android::hardware::health::V1_0::hal_conversion::convertToHealthInfo;
247 
248     updateAndNotify(nullptr);
249     struct android::BatteryProperties p = getBatteryProperties(battery_monitor_.get());
250 
251     V1_0::HealthInfo batteryInfo;
252     convertToHealthInfo(&p, batteryInfo);
253 
254     std::vector<StorageInfo> info;
255     get_storage_info(info);
256 
257     std::vector<DiskStats> stats;
258     get_disk_stats(stats);
259 
260     int32_t currentAvg = 0;
261 
262     struct BatteryProperty prop;
263     status_t ret = battery_monitor_->getProperty(BATTERY_PROP_CURRENT_AVG, &prop);
264     if (ret == OK) {
265         currentAvg = static_cast<int32_t>(prop.valueInt64);
266     }
267 
268     V2_0::HealthInfo healthInfo = {};
269     healthInfo.legacy = std::move(batteryInfo);
270     healthInfo.batteryCurrentAverage = currentAvg;
271     healthInfo.diskStats = stats;
272     healthInfo.storageInfos = info;
273 
274     _hidl_cb(Result::SUCCESS, healthInfo);
275     return Void();
276 }
277 
serviceDied(uint64_t,const wp<IBase> & who)278 void Health::serviceDied(uint64_t /* cookie */, const wp<IBase>& who) {
279     (void)unregisterCallbackInternal(who.promote());
280 }
281 
initInstance(struct healthd_config * c)282 sp<IHealth> Health::initInstance(struct healthd_config* c) {
283     if (instance_ == nullptr) {
284         instance_ = new Health(c);
285     }
286     return instance_;
287 }
288 
getImplementation()289 sp<Health> Health::getImplementation() {
290     CHECK(instance_ != nullptr);
291     return instance_;
292 }
293 
294 }  // namespace implementation
295 }  // namespace V2_0
296 }  // namespace health
297 }  // namespace hardware
298 }  // namespace android
299