Home | History | Annotate | Download | only in default
      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 (at) 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 
     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.
     43 Return<Result> Health::registerCallback(const sp<IHealthInfoCallback>& callback) {
     44     if (callback == nullptr) {
     45         return Result::SUCCESS;
     46     }
     47 
     48     {
     49         std::lock_guard<std::mutex> _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 update();
     62 }
     63 
     64 bool Health::unregisterCallbackInternal(const sp<IBase>& callback) {
     65     if (callback == nullptr) return false;
     66 
     67     bool removed = false;
     68     std::lock_guard<std::mutex> _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 
     81 Return<Result> Health::unregisterCallback(const sp<IHealthInfoCallback>& callback) {
     82     return unregisterCallbackInternal(callback) ? Result::SUCCESS : Result::NOT_FOUND;
     83 }
     84 
     85 template <typename T>
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    142 Return<Result> Health::update() {
    143     if (!healthd_mode_ops || !healthd_mode_ops->battery_update) {
    144         LOG(WARNING) << "health (at) 2.0: update: not initialized. "
    145                      << "update() should not be called in charger / recovery.";
    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 
    159 void Health::notifyListeners(HealthInfo* healthInfo) {
    160     std::vector<StorageInfo> info;
    161     get_storage_info(info);
    162 
    163     std::vector<DiskStats> stats;
    164     get_disk_stats(stats);
    165 
    166     int32_t currentAvg = 0;
    167 
    168     struct BatteryProperty prop;
    169     status_t ret = battery_monitor_->getProperty(BATTERY_PROP_CURRENT_AVG, &prop);
    170     if (ret == OK) {
    171         currentAvg = static_cast<int32_t>(prop.valueInt64);
    172     }
    173 
    174     healthInfo->batteryCurrentAverage = currentAvg;
    175     healthInfo->diskStats = stats;
    176     healthInfo->storageInfos = info;
    177 
    178     std::lock_guard<std::mutex> _lock(callbacks_lock_);
    179     for (auto it = callbacks_.begin(); it != callbacks_.end();) {
    180         auto ret = (*it)->healthInfoChanged(*healthInfo);
    181         if (!ret.isOk() && ret.isDeadObject()) {
    182             it = callbacks_.erase(it);
    183         } else {
    184             ++it;
    185         }
    186     }
    187 }
    188 
    189 Return<void> Health::debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) {
    190     if (handle != nullptr && handle->numFds >= 1) {
    191         int fd = handle->data[0];
    192         battery_monitor_->dumpState(fd);
    193 
    194         getHealthInfo([fd](auto res, const auto& info) {
    195             android::base::WriteStringToFd("\ngetHealthInfo -> ", fd);
    196             if (res == Result::SUCCESS) {
    197                 android::base::WriteStringToFd(toString(info), fd);
    198             } else {
    199                 android::base::WriteStringToFd(toString(res), fd);
    200             }
    201             android::base::WriteStringToFd("\n", fd);
    202         });
    203 
    204         fsync(fd);
    205     }
    206     return Void();
    207 }
    208 
    209 Return<void> Health::getStorageInfo(getStorageInfo_cb _hidl_cb) {
    210     std::vector<struct StorageInfo> info;
    211     get_storage_info(info);
    212     hidl_vec<struct StorageInfo> info_vec(info);
    213     if (!info.size()) {
    214         _hidl_cb(Result::NOT_SUPPORTED, info_vec);
    215     } else {
    216         _hidl_cb(Result::SUCCESS, info_vec);
    217     }
    218     return Void();
    219 }
    220 
    221 Return<void> Health::getDiskStats(getDiskStats_cb _hidl_cb) {
    222     std::vector<struct DiskStats> stats;
    223     get_disk_stats(stats);
    224     hidl_vec<struct DiskStats> stats_vec(stats);
    225     if (!stats.size()) {
    226         _hidl_cb(Result::NOT_SUPPORTED, stats_vec);
    227     } else {
    228         _hidl_cb(Result::SUCCESS, stats_vec);
    229     }
    230     return Void();
    231 }
    232 
    233 Return<void> Health::getHealthInfo(getHealthInfo_cb _hidl_cb) {
    234     using android::hardware::health::V1_0::hal_conversion::convertToHealthInfo;
    235 
    236     update();
    237     struct android::BatteryProperties p = getBatteryProperties(battery_monitor_.get());
    238 
    239     V1_0::HealthInfo batteryInfo;
    240     convertToHealthInfo(&p, batteryInfo);
    241 
    242     std::vector<StorageInfo> info;
    243     get_storage_info(info);
    244 
    245     std::vector<DiskStats> stats;
    246     get_disk_stats(stats);
    247 
    248     int32_t currentAvg = 0;
    249 
    250     struct BatteryProperty prop;
    251     status_t ret = battery_monitor_->getProperty(BATTERY_PROP_CURRENT_AVG, &prop);
    252     if (ret == OK) {
    253         currentAvg = static_cast<int32_t>(prop.valueInt64);
    254     }
    255 
    256     V2_0::HealthInfo healthInfo = {};
    257     healthInfo.legacy = std::move(batteryInfo);
    258     healthInfo.batteryCurrentAverage = currentAvg;
    259     healthInfo.diskStats = stats;
    260     healthInfo.storageInfos = info;
    261 
    262     _hidl_cb(Result::SUCCESS, healthInfo);
    263     return Void();
    264 }
    265 
    266 void Health::serviceDied(uint64_t /* cookie */, const wp<IBase>& who) {
    267     (void)unregisterCallbackInternal(who.promote());
    268 }
    269 
    270 sp<IHealth> Health::initInstance(struct healthd_config* c) {
    271     if (instance_ == nullptr) {
    272         instance_ = new Health(c);
    273     }
    274     return instance_;
    275 }
    276 
    277 sp<Health> Health::getImplementation() {
    278     CHECK(instance_ != nullptr);
    279     return instance_;
    280 }
    281 
    282 }  // namespace implementation
    283 }  // namespace V2_0
    284 }  // namespace health
    285 }  // namespace hardware
    286 }  // namespace android
    287