Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5291a67e authored by Yifan Hong's avatar Yifan Hong
Browse files

storaged: use health HAL

Test: storaged_test
Test: manual
Bug: 208543110

Change-Id: I60d42fc4f2e411f375fe98d1c8e145ce79c52f88
parent e8474c2a
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -24,8 +24,10 @@ cc_defaults {
    shared_libs: [
        "android.hardware.health@1.0",
        "android.hardware.health@2.0",
        "android.hardware.health-V1-ndk",
        "libbase",
        "libbinder",
        "libbinder_ndk",
        "libcutils",
        "libhidlbase",
        "liblog",
@@ -35,6 +37,12 @@ cc_defaults {
        "packagemanager_aidl-cpp",
    ],

    static_libs: [
        "android.hardware.health-translate-ndk",
        "libhealthhalutils",
        "libhealthshim",
    ],

    cflags: [
        "-Wall",
        "-Werror",
@@ -67,7 +75,6 @@ cc_library_static {
        ":storaged_aidl_private",
    ],

    static_libs: ["libhealthhalutils"],
    header_libs: ["libbatteryservice_headers"],

    logtags: ["EventLogTags.logtags"],
@@ -90,7 +97,6 @@ cc_binary {
    srcs: ["main.cpp"],

    static_libs: [
        "libhealthhalutils",
        "libstoraged",
    ],
}
@@ -107,7 +113,6 @@ cc_test {
    srcs: ["tests/storaged_test.cpp"],

    static_libs: [
        "libhealthhalutils",
        "libstoraged",
    ],
}
+24 −7
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@

#include <utils/Mutex.h>

#include <aidl/android/hardware/health/IHealth.h>
#include <android/hardware/health/2.0/IHealth.h>

#define FRIEND_TEST(test_case_name, test_name) \
@@ -67,6 +68,8 @@ using namespace android;
// UID IO threshold in bytes
#define DEFAULT_PERIODIC_CHORES_UID_IO_THRESHOLD ( 1024 * 1024 * 1024ULL )

class storaged_t;

struct storaged_config {
    int periodic_chores_interval_unit;
    int periodic_chores_interval_disk_stats_publish;
@@ -75,15 +78,33 @@ struct storaged_config {
    int event_time_check_usec;  // check how much cputime spent in event loop
};

class storaged_t : public android::hardware::health::V2_0::IHealthInfoCallback,
                   public android::hardware::hidl_death_recipient {
struct HealthServicePair {
    std::shared_ptr<aidl::android::hardware::health::IHealth> aidl_health;
    android::sp<android::hardware::health::V2_0::IHealth> hidl_health;
    static HealthServicePair get();
};

class hidl_health_death_recipient : public android::hardware::hidl_death_recipient {
  public:
    hidl_health_death_recipient(const android::sp<android::hardware::health::V2_0::IHealth>& health)
        : mHealth(health) {}
    void serviceDied(uint64_t cookie, const wp<::android::hidl::base::V1_0::IBase>& who);

  private:
    android::sp<android::hardware::health::V2_0::IHealth> mHealth;
};

class storaged_t : public RefBase {
  private:
    time_t mTimer;
    storaged_config mConfig;
    unique_ptr<disk_stats_monitor> mDsm;
    uid_monitor mUidm;
    time_t mStarttime;
    sp<android::hardware::health::V2_0::IHealth> health;
    std::shared_ptr<aidl::android::hardware::health::IHealth> health;
    sp<android::hardware::hidl_death_recipient> hidl_death_recp;
    ndk::ScopedAIBinder_DeathRecipient aidl_death_recp;
    shared_ptr<aidl::android::hardware::health::IHealthInfoCallback> aidl_health_callback;
    unique_ptr<storage_info_t> storage_info;
    static const uint32_t current_version;
    Mutex proto_lock;
@@ -135,10 +156,6 @@ class storaged_t : public android::hardware::health::V2_0::IHealthInfoCallback,
    void add_user_ce(userid_t user_id);
    void remove_user_ce(userid_t user_id);

    virtual ::android::hardware::Return<void> healthInfoChanged(
        const ::android::hardware::health::V2_0::HealthInfo& info);
    void serviceDied(uint64_t cookie, const wp<::android::hidl::base::V1_0::IBase>& who);

    void report_storage_info();

    void flush_protos(unordered_map<int, StoragedProto>* protos);
+9 −8
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@

#include <stdint.h>

#include <android/hardware/health/2.0/IHealth.h>
#include <aidl/android/hardware/health/IHealth.h>

// number of attributes diskstats has
#define DISK_STATS_SIZE ( 11 )
@@ -162,7 +162,7 @@ private:
    const double mSigma;
    struct disk_perf mMean;
    struct disk_perf mStd;
    android::sp<android::hardware::health::V2_0::IHealth> mHealth;
    std::shared_ptr<aidl::android::hardware::health::IHealth> mHealth;

    void update_mean();
    void update_std();
@@ -173,14 +173,15 @@ private:
    void update(struct disk_stats* stats);

public:
  disk_stats_monitor(const android::sp<android::hardware::health::V2_0::IHealth>& healthService,
  disk_stats_monitor(const std::shared_ptr<aidl::android::hardware::health::IHealth>& healthService,
                     uint32_t window_size = 5, double sigma = 1.0)
      : DISK_STATS_PATH(
                healthService != nullptr
                        ? nullptr
                        : (access(MMC_DISK_STATS_PATH, R_OK) == 0
                                   ? MMC_DISK_STATS_PATH
                       : (access(SDA_DISK_STATS_PATH, R_OK) == 0 ? SDA_DISK_STATS_PATH : nullptr))),
                                   : (access(SDA_DISK_STATS_PATH, R_OK) == 0 ? SDA_DISK_STATS_PATH
                                                                             : nullptr))),
        mPrevious(),
        mAccumulate(),
        mAccumulate_pub(),
+7 −7
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@

#include <chrono>

#include <android/hardware/health/2.0/IHealth.h>
#include <aidl/android/hardware/health/IHealth.h>
#include <utils/Mutex.h>

#include "storaged.h"
@@ -71,7 +71,7 @@ class storage_info_t {

  public:
    static storage_info_t* get_storage_info(
        const sp<android::hardware::health::V2_0::IHealth>& healthService);
            const shared_ptr<aidl::android::hardware::health::IHealth>& healthService);
    virtual ~storage_info_t(){};
    virtual void report() {};
    void load_perf_history_proto(const IOPerfHistory& perf_history);
@@ -105,14 +105,14 @@ public:

class health_storage_info_t : public storage_info_t {
  private:
    using IHealth = hardware::health::V2_0::IHealth;
    using StorageInfo = hardware::health::V2_0::StorageInfo;
    using IHealth = aidl::android::hardware::health::IHealth;
    using StorageInfo = aidl::android::hardware::health::StorageInfo;

    sp<IHealth> mHealth;
    shared_ptr<IHealth> mHealth;
    void set_values_from_hal_storage_info(const StorageInfo& halInfo);

  public:
    health_storage_info_t(const sp<IHealth>& service) : mHealth(service){};
    health_storage_info_t(const shared_ptr<IHealth>& service) : mHealth(service){};
    virtual ~health_storage_info_t() {}
    virtual void report();
};
+88 −34
Original line number Diff line number Diff line
@@ -28,12 +28,16 @@
#include <sstream>
#include <string>

#include <aidl/android/hardware/health/BnHealthInfoCallback.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <android/binder_ibinder.h>
#include <android/binder_manager.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <batteryservice/BatteryServiceConstants.h>
#include <cutils/properties.h>
#include <health-shim/shim.h>
#include <healthhalutils/HealthHalUtils.h>
#include <hidl/HidlTransportSupport.h>
#include <hwbinder/IPCThreadState.h>
@@ -64,69 +68,119 @@ constexpr ssize_t min_benchmark_size = 128 * 1024; // 128KB

const uint32_t storaged_t::current_version = 4;

using aidl::android::hardware::health::BatteryStatus;
using aidl::android::hardware::health::BnHealthInfoCallback;
using aidl::android::hardware::health::HealthInfo;
using aidl::android::hardware::health::IHealth;
using aidl::android::hardware::health::IHealthInfoCallback;
using android::hardware::interfacesEqual;
using android::hardware::Return;
using android::hardware::health::V1_0::BatteryStatus;
using android::hardware::health::V1_0::toString;
using android::hardware::health::V2_0::get_health_service;
using android::hardware::health::V2_0::HealthInfo;
using android::hardware::health::V2_0::IHealth;
using android::hardware::health::V2_0::Result;
using android::hidl::manager::V1_0::IServiceManager;
using HidlHealth = android::hardware::health::V2_0::IHealth;
using aidl::android::hardware::health::HealthShim;
using ndk::ScopedAIBinder_DeathRecipient;
using ndk::ScopedAStatus;

HealthServicePair HealthServicePair::get() {
    HealthServicePair ret;
    auto service_name = IHealth::descriptor + "/default"s;
    if (AServiceManager_isDeclared(service_name.c_str())) {
        ndk::SpAIBinder binder(AServiceManager_waitForService(service_name.c_str()));
        ret.aidl_health = IHealth::fromBinder(binder);
        if (ret.aidl_health == nullptr) {
            LOG(WARNING) << "AIDL health service is declared, but it cannot be retrieved.";
        }
    }
    if (ret.aidl_health == nullptr) {
        LOG(INFO) << "Unable to get AIDL health service, trying HIDL...";
        ret.hidl_health = get_health_service();
        if (ret.hidl_health != nullptr) {
            ret.aidl_health = ndk::SharedRefBase::make<HealthShim>(ret.hidl_health);
        }
    }
    if (ret.aidl_health == nullptr) {
        LOG(WARNING) << "health: failed to find IHealth service";
        return {};
    }
    return ret;
}

inline charger_stat_t is_charger_on(BatteryStatus prop) {
    return (prop == BatteryStatus::CHARGING || prop == BatteryStatus::FULL) ?
        CHARGER_ON : CHARGER_OFF;
}

Return<void> storaged_t::healthInfoChanged(const HealthInfo& props) {
    mUidm.set_charger_state(is_charger_on(props.legacy.batteryStatus));
    return android::hardware::Void();
class HealthInfoCallback : public BnHealthInfoCallback {
  public:
    HealthInfoCallback(uid_monitor* uidm) : mUidm(uidm) {}
    ScopedAStatus healthInfoChanged(const HealthInfo& info) override {
        mUidm->set_charger_state(is_charger_on(info.batteryStatus));
        return ScopedAStatus::ok();
    }

  private:
    uid_monitor* mUidm;
};

void storaged_t::init() {
    init_health_service();
    mDsm = std::make_unique<disk_stats_monitor>(health);
    storage_info.reset(storage_info_t::get_storage_info(health));
}

static void onHealthBinderDied(void*) {
    LOG(ERROR) << "health service died, exiting";
    android::hardware::IPCThreadState::self()->stopProcess();
    exit(1);
}

void storaged_t::init_health_service() {
    if (!mUidm.enabled())
        return;

    health = get_health_service();
    if (health == NULL) {
        LOG(WARNING) << "health: failed to find IHealth service";
        return;
    }
    auto [aidlHealth, hidlHealth] = HealthServicePair::get();
    health = aidlHealth;
    if (health == nullptr) return;

    BatteryStatus status = BatteryStatus::UNKNOWN;
    auto ret = health->getChargeStatus([&](Result r, BatteryStatus v) {
        if (r != Result::SUCCESS) {
            LOG(WARNING) << "health: cannot get battery status " << toString(r);
            return;
    auto ret = health->getChargeStatus(&status);
    if (!ret.isOk()) {
        LOG(WARNING) << "health: cannot get battery status: " << ret.getDescription();
    }
        if (v == BatteryStatus::UNKNOWN) {
    if (status == BatteryStatus::UNKNOWN) {
        LOG(WARNING) << "health: invalid battery status";
    }
        status = v;
    });
    if (!ret.isOk()) {
        LOG(WARNING) << "health: get charge status transaction error " << ret.description();
    }

    mUidm.init(is_charger_on(status));
    // register listener after init uid_monitor
    health->registerCallback(this);
    health->linkToDeath(this, 0 /* cookie */);
    aidl_health_callback = std::make_shared<HealthInfoCallback>(&mUidm);
    ret = health->registerCallback(aidl_health_callback);
    if (!ret.isOk()) {
        LOG(WARNING) << "health: failed to register callback: " << ret.getDescription();
    }

void storaged_t::serviceDied(uint64_t cookie, const wp<::android::hidl::base::V1_0::IBase>& who) {
    if (health != NULL && interfacesEqual(health, who.promote())) {
        LOG(ERROR) << "health service died, exiting";
        android::hardware::IPCThreadState::self()->stopProcess();
        exit(1);
    if (hidlHealth != nullptr) {
        hidl_death_recp = new hidl_health_death_recipient(hidlHealth);
        auto ret = hidlHealth->linkToDeath(hidl_death_recp, 0 /* cookie */);
        if (!ret.isOk()) {
            LOG(WARNING) << "Failed to link to death (HIDL): " << ret.description();
        }
    } else {
        aidl_death_recp =
                ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(onHealthBinderDied));
        auto ret = AIBinder_linkToDeath(health->asBinder().get(), aidl_death_recp.get(),
                                        nullptr /* cookie */);
        if (ret != STATUS_OK) {
            LOG(WARNING) << "Failed to link to death (AIDL): "
                         << ScopedAStatus(AStatus_fromStatus(ret)).getDescription();
        }
    }
}

void hidl_health_death_recipient::serviceDied(uint64_t cookie,
                                              const wp<::android::hidl::base::V1_0::IBase>& who) {
    if (mHealth != nullptr && interfacesEqual(mHealth, who.promote())) {
        onHealthBinderDied(reinterpret_cast<void*>(cookie));
    } else {
        LOG(ERROR) << "unknown service died";
    }
Loading