Loading healthd/Android.mk +18 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,7 @@ ifneq ($(BOARD_PERIODIC_CHORES_INTERVAL_SLOW),) LOCAL_CFLAGS += -DBOARD_PERIODIC_CHORES_INTERVAL_SLOW=$(BOARD_PERIODIC_CHORES_INTERVAL_SLOW) endif LOCAL_STATIC_LIBRARIES := \ CHARGER_STATIC_LIBRARIES := \ android.hardware.health@2.0-impl \ android.hardware.health@2.0 \ android.hardware.health@1.0 \ Loading @@ -114,6 +114,8 @@ LOCAL_STATIC_LIBRARIES := \ libm \ libc \ LOCAL_STATIC_LIBRARIES := $(CHARGER_STATIC_LIBRARIES) ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true) LOCAL_STATIC_LIBRARIES += \ libminui \ Loading @@ -134,6 +136,21 @@ LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT) \ include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) LOCAL_MODULE := charger_test LOCAL_MODULE_TAGS := optional LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_C_INCLUDES := $(LOCAL_PATH)/include LOCAL_CFLAGS := -Wall -Werror -DCHARGER_TEST -DCHARGER_NO_UI LOCAL_STATIC_LIBRARIES := $(CHARGER_STATIC_LIBRARIES) LOCAL_SRC_FILES := \ charger.cpp \ charger_test.cpp \ include $(BUILD_EXECUTABLE) CHARGER_STATIC_LIBRARIES := ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true) define _add-charger-image include $$(CLEAR_VARS) Loading healthd/charger.cpp +7 −1 Original line number Diff line number Diff line Loading @@ -79,7 +79,7 @@ static void healthd_mode_nop_battery_update( struct android::BatteryProperties* /*props*/) { } int main(int argc, char **argv) { int healthd_charger_main(int argc, char** argv) { int ch; healthd_mode_ops = &charger_ops; Loading @@ -103,3 +103,9 @@ int main(int argc, char **argv) { return healthd_main(); } #ifndef CHARGER_TEST int main(int argc, char** argv) { return healthd_charger_main(argc, argv); } #endif healthd/charger_test.cpp 0 → 100644 +174 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "charger_test" #include <android/log.h> #include <chrono> #include <condition_variable> #include <fstream> #include <iostream> #include <mutex> #include <streambuf> #include <string> #include <thread> #include <vector> #include <healthd/healthd.h> #define LOG_THIS(fmt, ...) \ ALOGE(fmt, ##__VA_ARGS__); \ printf(fmt "\n", ##__VA_ARGS__); template <typename T> class Atomic { public: Atomic(T&& init) : mValue(std::move(init)) {} void set(T&& newVal) { { std::lock_guard<std::mutex> lock(mMutex); mValue = std::move(newVal); } mChanged.notify_all(); } bool waitFor(long ms, const T& expectVal) { std::unique_lock<std::mutex> lock(mMutex); return mChanged.wait_for(lock, std::chrono::milliseconds(ms), [this, &expectVal] { return mValue == expectVal; }); } private: std::mutex mMutex; std::condition_variable mChanged; T mValue; }; Atomic<bool>& getUpdateNotifier() { static Atomic<bool> val(false); return val; } int energyCounter(int64_t* counter) { *counter = 0xEC12345; return 0; } const char* createFile(const char* path, const char* content) { std::ofstream stream(path); if (!stream.is_open()) { LOG_THIS("Cannot create file %s", path); return NULL; } stream << content << std::endl; stream.close(); return path; } std::string openToString(const char* path) { std::ifstream stream(path); if (!stream.is_open()) { LOG_THIS("Cannot open file %s", path); return ""; } return std::string(std::istreambuf_iterator<char>(stream), std::istreambuf_iterator<char>()); } int expectContains(const std::string& content, const std::vector<std::string>& fields) { int status = 0; for (const auto& field : fields) { auto pos = content.find(field); if (pos == std::string::npos) { LOG_THIS("Cannot find substr '%s'", field.c_str()); status = 1; } } return status; } void healthd_board_init(struct healthd_config* config) { config->periodic_chores_interval_fast = 60; config->periodic_chores_interval_slow = 600; config->batteryStatusPath = createFile("/data/local/tmp/batteryStatus", "Not charging"); config->batteryHealthPath = createFile("/data/local/tmp/batteryHealth", "Unspecified failure"); config->batteryPresentPath = createFile("/data/local/tmp/batteryPresent", "1"); config->batteryCapacityPath = createFile("/data/local/tmp/batteryCapacity", "47"); config->batteryVoltagePath = createFile("/data/local/tmp/batteryVoltage", "45000"); config->batteryTemperaturePath = createFile("/data/local/tmp/batteryTemperature", "987"); config->batteryTechnologyPath = createFile("/data/local/tmp/batteryTechnology", "NiCd"); config->batteryCurrentNowPath = createFile("/data/local/tmp/batteryCurrentNow", "99000"); config->batteryCurrentAvgPath = createFile("/data/local/tmp/batteryCurrentAvg", "98000"); config->batteryChargeCounterPath = createFile("/data/local/tmp/batteryChargeCounter", "600"); config->batteryFullChargePath = createFile("/data/local/tmp/batteryFullCharge", "3515547"); config->batteryCycleCountPath = createFile("/data/local/tmp/batteryCycleCount", "77"); config->energyCounter = energyCounter; config->boot_min_cap = 50; config->screen_on = NULL; } int healthd_board_battery_update(struct android::BatteryProperties*) { getUpdateNotifier().set(true /* updated */); // return 0 to log periodic polled battery status to kernel log return 0; } extern int healthd_charger_main(int argc, char** argv); int main(int argc, char** argv) { const char* dumpFile = "/data/local/tmp/dump.txt"; std::thread bgThread([=] { healthd_charger_main(argc, argv); }); // wait for healthd_init to finish if (!getUpdateNotifier().waitFor(1000 /* wait ms */, true /* updated */)) { LOG_THIS("Time out."); exit(1); } int fd = creat(dumpFile, S_IRUSR | S_IWUSR); if (fd < 0) { exit(errno); } healthd_dump_battery_state(fd); close(fd); std::string content = openToString(dumpFile); int status = expectContains(content, { "status: 4", "health: 6", "present: 1", "level: 47", "voltage: 45", "temp: 987", "current now: 99000", "current avg: 98000", "charge counter: 600", "current now: 99", "cycle count: 77", "Full charge: 3515547" }); if (status == 0) { LOG_THIS("Test success."); } else { LOG_THIS("Actual dump:\n%s", content.c_str()); } exit(status); // force bgThread to exit } Loading
healthd/Android.mk +18 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,7 @@ ifneq ($(BOARD_PERIODIC_CHORES_INTERVAL_SLOW),) LOCAL_CFLAGS += -DBOARD_PERIODIC_CHORES_INTERVAL_SLOW=$(BOARD_PERIODIC_CHORES_INTERVAL_SLOW) endif LOCAL_STATIC_LIBRARIES := \ CHARGER_STATIC_LIBRARIES := \ android.hardware.health@2.0-impl \ android.hardware.health@2.0 \ android.hardware.health@1.0 \ Loading @@ -114,6 +114,8 @@ LOCAL_STATIC_LIBRARIES := \ libm \ libc \ LOCAL_STATIC_LIBRARIES := $(CHARGER_STATIC_LIBRARIES) ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true) LOCAL_STATIC_LIBRARIES += \ libminui \ Loading @@ -134,6 +136,21 @@ LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT) \ include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) LOCAL_MODULE := charger_test LOCAL_MODULE_TAGS := optional LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_C_INCLUDES := $(LOCAL_PATH)/include LOCAL_CFLAGS := -Wall -Werror -DCHARGER_TEST -DCHARGER_NO_UI LOCAL_STATIC_LIBRARIES := $(CHARGER_STATIC_LIBRARIES) LOCAL_SRC_FILES := \ charger.cpp \ charger_test.cpp \ include $(BUILD_EXECUTABLE) CHARGER_STATIC_LIBRARIES := ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true) define _add-charger-image include $$(CLEAR_VARS) Loading
healthd/charger.cpp +7 −1 Original line number Diff line number Diff line Loading @@ -79,7 +79,7 @@ static void healthd_mode_nop_battery_update( struct android::BatteryProperties* /*props*/) { } int main(int argc, char **argv) { int healthd_charger_main(int argc, char** argv) { int ch; healthd_mode_ops = &charger_ops; Loading @@ -103,3 +103,9 @@ int main(int argc, char **argv) { return healthd_main(); } #ifndef CHARGER_TEST int main(int argc, char** argv) { return healthd_charger_main(argc, argv); } #endif
healthd/charger_test.cpp 0 → 100644 +174 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "charger_test" #include <android/log.h> #include <chrono> #include <condition_variable> #include <fstream> #include <iostream> #include <mutex> #include <streambuf> #include <string> #include <thread> #include <vector> #include <healthd/healthd.h> #define LOG_THIS(fmt, ...) \ ALOGE(fmt, ##__VA_ARGS__); \ printf(fmt "\n", ##__VA_ARGS__); template <typename T> class Atomic { public: Atomic(T&& init) : mValue(std::move(init)) {} void set(T&& newVal) { { std::lock_guard<std::mutex> lock(mMutex); mValue = std::move(newVal); } mChanged.notify_all(); } bool waitFor(long ms, const T& expectVal) { std::unique_lock<std::mutex> lock(mMutex); return mChanged.wait_for(lock, std::chrono::milliseconds(ms), [this, &expectVal] { return mValue == expectVal; }); } private: std::mutex mMutex; std::condition_variable mChanged; T mValue; }; Atomic<bool>& getUpdateNotifier() { static Atomic<bool> val(false); return val; } int energyCounter(int64_t* counter) { *counter = 0xEC12345; return 0; } const char* createFile(const char* path, const char* content) { std::ofstream stream(path); if (!stream.is_open()) { LOG_THIS("Cannot create file %s", path); return NULL; } stream << content << std::endl; stream.close(); return path; } std::string openToString(const char* path) { std::ifstream stream(path); if (!stream.is_open()) { LOG_THIS("Cannot open file %s", path); return ""; } return std::string(std::istreambuf_iterator<char>(stream), std::istreambuf_iterator<char>()); } int expectContains(const std::string& content, const std::vector<std::string>& fields) { int status = 0; for (const auto& field : fields) { auto pos = content.find(field); if (pos == std::string::npos) { LOG_THIS("Cannot find substr '%s'", field.c_str()); status = 1; } } return status; } void healthd_board_init(struct healthd_config* config) { config->periodic_chores_interval_fast = 60; config->periodic_chores_interval_slow = 600; config->batteryStatusPath = createFile("/data/local/tmp/batteryStatus", "Not charging"); config->batteryHealthPath = createFile("/data/local/tmp/batteryHealth", "Unspecified failure"); config->batteryPresentPath = createFile("/data/local/tmp/batteryPresent", "1"); config->batteryCapacityPath = createFile("/data/local/tmp/batteryCapacity", "47"); config->batteryVoltagePath = createFile("/data/local/tmp/batteryVoltage", "45000"); config->batteryTemperaturePath = createFile("/data/local/tmp/batteryTemperature", "987"); config->batteryTechnologyPath = createFile("/data/local/tmp/batteryTechnology", "NiCd"); config->batteryCurrentNowPath = createFile("/data/local/tmp/batteryCurrentNow", "99000"); config->batteryCurrentAvgPath = createFile("/data/local/tmp/batteryCurrentAvg", "98000"); config->batteryChargeCounterPath = createFile("/data/local/tmp/batteryChargeCounter", "600"); config->batteryFullChargePath = createFile("/data/local/tmp/batteryFullCharge", "3515547"); config->batteryCycleCountPath = createFile("/data/local/tmp/batteryCycleCount", "77"); config->energyCounter = energyCounter; config->boot_min_cap = 50; config->screen_on = NULL; } int healthd_board_battery_update(struct android::BatteryProperties*) { getUpdateNotifier().set(true /* updated */); // return 0 to log periodic polled battery status to kernel log return 0; } extern int healthd_charger_main(int argc, char** argv); int main(int argc, char** argv) { const char* dumpFile = "/data/local/tmp/dump.txt"; std::thread bgThread([=] { healthd_charger_main(argc, argv); }); // wait for healthd_init to finish if (!getUpdateNotifier().waitFor(1000 /* wait ms */, true /* updated */)) { LOG_THIS("Time out."); exit(1); } int fd = creat(dumpFile, S_IRUSR | S_IWUSR); if (fd < 0) { exit(errno); } healthd_dump_battery_state(fd); close(fd); std::string content = openToString(dumpFile); int status = expectContains(content, { "status: 4", "health: 6", "present: 1", "level: 47", "voltage: 45", "temp: 987", "current now: 99000", "current avg: 98000", "charge counter: 600", "current now: 99", "cycle count: 77", "Full charge: 3515547" }); if (status == 0) { LOG_THIS("Test success."); } else { LOG_THIS("Actual dump:\n%s", content.c_str()); } exit(status); // force bgThread to exit }