#include <sqlite3.h>
#include <time.h>
#include <glib.h>
+#include <device/battery.h>
#include <Types.h>
#include <Json.h>
#include "HeartDbReader.h"
#include "BatteryMonitor.h"
#define DEFAULT_ROW_ID_STR "1"
+#define HEART_DB_QUERY_INTERVAL 10 * 60 * 1000
using namespace ctx;
-static int __bootingTime = 0;
-static int __lastResetTime = 0;
-static int __lastPercent = -1;
-static int __lastPercentTime = 0;
-static int __lastBatteryTimeInfoDeleteTime = 0;
-static bool __isCharging = 0;
-static bool __timerRunning = false;
-static std::vector<Json> __batteryTimeInfoVec;
+BatteryMonitor* BatteryMonitor::__instance = NULL;
-#define HEART_DB_QUERY_DELAY 600000
-#define BATTERY_TIME_INFO_DELETE_DELAY 10 * 3600
+BatteryMonitor::BatteryMonitor() :
+ __bootingTime(0),
+ __lastFullTime(0),
+ __lastHeartAccessTime(0)
+{
+}
-#define UPDATE_BATTERY_LOGS_QUERY \
- "UPDATE " BATTERY_TEMP_TIME_INFO " SET " BATTERY_TO_BE_PROCESSED " = 0 WHERE " BATTERY_START_TIME " >= %d AND " BATTERY_END_TIME " <= %d"
+BatteryMonitor::~BatteryMonitor()
+{
+}
-BatteryMonitor::BatteryMonitor()
+BatteryMonitor* BatteryMonitor::getInstance()
{
- __initialize();
+ IF_FAIL_RETURN(!__instance, __instance);
+
+ __instance = new(std::nothrow) BatteryMonitor();
+ IF_FAIL_RETURN_TAG(__instance, NULL, _E, "Memory allocation failed");
+
+ return __instance;
}
-BatteryMonitor::~BatteryMonitor()
+void BatteryMonitor::destroy()
{
+ IF_FAIL_VOID(__instance);
+
+ delete __instance;
+ __instance = NULL;
}
-void BatteryMonitor::__initialize()
+void BatteryMonitor::initialize()
{
std::vector<Json> records;
__dbMgr.executeSync(
__dbMgr.executeSync(
"CREATE TABLE IF NOT EXISTS " BATTERY_LAST_CPU_USAGE_TABLE \
" (" BATTERY_LAST_CPU_USAGE_TABLE_COLUMNS ")", &records);
-
- __dbMgr.createTableSync(BATTERY_TEMP_TIME_INFO, BATTERY_TEMP_TIME_INFO_COLUMNS, NULL);
}
bool BatteryMonitor::__loadLastInfo()
{
__bootingTime = CURRENT_TIME;
- device_battery_is_charging(&__isCharging);
-
std::vector<Json> records;
bool ret = __dbMgr.executeSync(
"SELECT * FROM " BATTERY_LAST_INFO_TABLE \
IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to load last info");
if (records.size() == 1) {
- records[0].get(NULL, BATTERY_LAST_RESET_TIME, &__lastResetTime);
- records[0].get(NULL, BATTERY_LAST_PERCENT, &__lastPercent);
- records[0].get(NULL, BATTERY_LAST_PERCENT_TIME, &__lastPercentTime);
- records[0].get(NULL, BATTERY_TIME_INFO_LAST_DELETE_TIME, &__lastBatteryTimeInfoDeleteTime);
+ records[0].get(NULL, BATTERY_LAST_FULL_TIME, &__lastFullTime);
+ records[0].get(NULL, BATTERY_LAST_HEART_ACCESS_TIME, &__lastHeartAccessTime);
}
- records.clear();
- __batteryTimeInfoVec.clear();
- ret = __dbMgr.executeSync("SELECT * FROM " BATTERY_TEMP_TIME_INFO " WHERE " BATTERY_TO_BE_PROCESSED " = 1", &__batteryTimeInfoVec);
return true;
}
bool BatteryMonitor::__updateLastInfo()
{
char *query = sqlite3_mprintf("INSERT OR REPLACE INTO " BATTERY_LAST_INFO_TABLE " (" \
- BATTERY_ROW_ID ", " BATTERY_LAST_PERCENT ", " BATTERY_LAST_PERCENT_TIME \
- ", " BATTERY_TIME_INFO_LAST_DELETE_TIME ", " BATTERY_LAST_RESET_TIME ") VALUES (%s, %d, %d, %d, %d)",
- DEFAULT_ROW_ID_STR, __lastPercent, __lastPercentTime, __lastBatteryTimeInfoDeleteTime, __lastResetTime);
+ BATTERY_ROW_ID ", " BATTERY_LAST_FULL_TIME ", " BATTERY_LAST_HEART_ACCESS_TIME ") VALUES (%s, %d, %d)",
+ DEFAULT_ROW_ID_STR, __lastFullTime, __lastHeartAccessTime);
bool ret = __dbMgr.executeSync(query, NULL);
sqlite3_free(query);
return ret;
}
-void BatteryMonitor::__batteryChangeCb(device_callback_e type, void* value, void* userData)
-{
- IF_FAIL_VOID(type == DEVICE_CALLBACK_BATTERY_CAPACITY);
-
- int percent = intptr_t(value);
- int currentTime = CURRENT_TIME;
- BatteryMonitor* instance = static_cast<BatteryMonitor*>(userData);
-
- if (!__isCharging && percent == (__lastPercent - 1) && __lastPercentTime != 0) {
- _D("Battery capacity decreased: %d% -> %d%", __lastPercent, percent);
-
- Json battTimeInfo;
- battTimeInfo.set(NULL, BATTERY_AMOUNT, percent);
- battTimeInfo.set(NULL, BATTERY_START_TIME, __lastPercentTime);
- battTimeInfo.set(NULL, BATTERY_END_TIME, currentTime);
- battTimeInfo.set(NULL, BATTERY_TO_BE_PROCESSED, 1);
- __batteryTimeInfoVec.push_back(battTimeInfo);
-
- int64_t rowId;
- (instance->__dbMgr).insertSync(BATTERY_TEMP_TIME_INFO, battTimeInfo, &rowId);
-
- bool dataRemaining = instance->processBatteryUsage();
- if (dataRemaining && !__timerRunning) {
- __timerRunning = true;
- _D("Start timer to request HEART data");
- g_timeout_add(HEART_DB_QUERY_DELAY, __timeoutCb, instance);
- }
- }
-
- __lastPercentTime = currentTime;
- __lastPercent = percent;
-
- bool ret = instance->__updateLastInfo();
- IF_FAIL_VOID_TAG(ret, _E, "Failed to update last percent and last percent times");
-}
-
void BatteryMonitor::__chargerChangeCb(device_callback_e type, void* value, void* userData)
{
IF_FAIL_VOID(type == DEVICE_CALLBACK_BATTERY_CHARGING);
- __isCharging = intptr_t(value);
- IF_FAIL_VOID(!__isCharging);
+ bool isCharging = intptr_t(value);
+ IF_FAIL_VOID(!isCharging);
BatteryMonitor* instance = static_cast<BatteryMonitor*>(userData);
int percent;
- if (__lastPercent < 0) {
- int error = device_battery_get_percent(&percent);
- IF_FAIL_VOID_TAG(error == DEVICE_ERROR_NONE, _E, "Failed to get battery capacity");
- } else {
- percent = __lastPercent;
- }
+ int error = device_battery_get_percent(&percent);
+ IF_FAIL_VOID_TAG(error == DEVICE_ERROR_NONE, _E, "Failed to get battery capacity");
// If charger is disconnected after 100% charged
if (percent == 100) {
- __lastResetTime = CURRENT_TIME;
- __lastPercentTime = __lastResetTime;
- _D("Charger is disconnected after fully charged. ResetTime: %d", __lastResetTime);
+ instance->__lastFullTime = CURRENT_TIME;
+ _D("Charger is disconnected after fully charged. Last fully charged time: %d", instance->__lastFullTime);
bool ret = instance->__updateLastInfo();
IF_FAIL_VOID_TAG(ret, _E, "Failed to update last reset time and last percent time");
gboolean BatteryMonitor::__timeoutCb(gpointer data)
{
BatteryMonitor* instance = static_cast<BatteryMonitor*>(data);
+ instance->__processBatteryUsage();
- bool dataRemaining = instance->processBatteryUsage();
- if (!dataRemaining) {
- _D("Stop timer, no more data to process");
- __timerRunning = false;
- }
-
- return dataRemaining ? TRUE : FALSE;
+ return TRUE;
}
int BatteryMonitor::start()
{
__loadLastInfo();
- int error = device_add_callback(DEVICE_CALLBACK_BATTERY_CAPACITY, __batteryChangeCb, this);
- IF_FAIL_RETURN_TAG(error == DEVICE_ERROR_NONE, ERR_OPERATION_FAILED, _E, "Failed to set battery capacity change cb");
-
- error = device_add_callback(DEVICE_CALLBACK_BATTERY_CHARGING, __chargerChangeCb, NULL);
+ int error = device_add_callback(DEVICE_CALLBACK_BATTERY_CHARGING, __chargerChangeCb, this);
IF_FAIL_RETURN_TAG(error == DEVICE_ERROR_NONE, ERR_OPERATION_FAILED, _E, "Failed to set battery charging change cb");
- __timerRunning = true;
_D("Start timer to request HEART data");
- g_timeout_add(HEART_DB_QUERY_DELAY, __timeoutCb, this);
+ g_timeout_add(HEART_DB_QUERY_INTERVAL, __timeoutCb, this);
+
return ERR_NONE;
}
int BatteryMonitor::stop()
{
- int error = device_remove_callback(DEVICE_CALLBACK_BATTERY_CAPACITY, __batteryChangeCb);
- IF_FAIL_RETURN_TAG(error == DEVICE_ERROR_NONE, ERR_OPERATION_FAILED, _E, "Failed to remove callback for battery capacity");
-
- error = device_remove_callback(DEVICE_CALLBACK_BATTERY_CHARGING, __chargerChangeCb);
+ int error = device_remove_callback(DEVICE_CALLBACK_BATTERY_CHARGING, __chargerChangeCb);
IF_FAIL_RETURN_TAG(error == DEVICE_ERROR_NONE, ERR_OPERATION_FAILED, _E, "Failed to remove callback for charger status");
return ERR_NONE;
}
-bool BatteryMonitor::__getLastCpuUsageTable(CpuUsageMap* lastCpuUsage)
+bool BatteryMonitor::__getLastCpuUsageTable(CpuUsageMap* lastHeartCpuLog)
{
- std::vector<Json> lastCpuUsageLog;
- bool ret = __dbMgr.executeSync(
- "SELECT * FROM " BATTERY_LAST_CPU_USAGE_TABLE,
- &lastCpuUsageLog);
- IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to load last Cpu Times of Apps");
+ std::vector<Json> cpuLog;
+ bool ret = __dbMgr.executeSync("SELECT * FROM " BATTERY_LAST_CPU_USAGE_TABLE, &cpuLog);
+ IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to load last cpu times of apps");
unsigned int k = 0;
std::string appId;
int utime;
int pid;
- while (k < lastCpuUsageLog.size()) {
- lastCpuUsageLog[k].get(NULL, BATTERY_APP_ID, &appId);
- lastCpuUsageLog[k].get(NULL, BATTERY_TIMESTAMP, ×tamp);
- lastCpuUsageLog[k].get(NULL, BATTERY_UTIME, &utime);
- lastCpuUsageLog[k].get(NULL, BATTERY_STIME, &stime);
- lastCpuUsageLog[k].get(NULL, BATTERY_PID, &pid);
+ while (k < cpuLog.size()) {
+ cpuLog[k].get(NULL, BATTERY_APP_ID, &appId);
+ cpuLog[k].get(NULL, BATTERY_TIMESTAMP, ×tamp);
+ cpuLog[k].get(NULL, BATTERY_UTIME, &utime);
+ cpuLog[k].get(NULL, BATTERY_STIME, &stime);
+ cpuLog[k].get(NULL, BATTERY_PID, &pid);
k++;
- LastAppCpuUsageInfo lastAppCpuUsage;
- lastAppCpuUsage.timestamp = timestamp;
- lastAppCpuUsage.utime = utime;
- lastAppCpuUsage.stime = stime;
- lastAppCpuUsage.pid = pid;
- (*lastCpuUsage)[appId] = lastAppCpuUsage;
+ CpuLogInfo appInfo;
+ appInfo.timestamp = timestamp;
+ appInfo.utime = utime;
+ appInfo.stime = stime;
+ appInfo.pid = pid;
+ (*lastHeartCpuLog)[appId] = appInfo;
}
return true;
}
-//Return false if all is processed, true otherwise
-bool BatteryMonitor::processBatteryUsage()
+bool BatteryMonitor::__processBatteryUsage()
{
- IF_FAIL_RETURN_TAG(__batteryTimeInfoVec.size() > 0, false, _D, "All per-app battery usages are already calculated");
-
- int totalStartTime;
- int totalEndTime;
- __batteryTimeInfoVec.front().get(NULL, BATTERY_START_TIME, &totalStartTime);
- __batteryTimeInfoVec.back().get(NULL, BATTERY_END_TIME, &totalEndTime);
-
- // Read cpu table from heart db for time span of stacked in __batteryTimeInfoVec
+ // Read from heart cpu table
HeartDbReader heartReader;
bool ret = heartReader.open();
IF_FAIL_RETURN_TAG(ret, true, _E, "Failed to open heart db");
- std::vector<Json> cpuUsageLog;
- ret = heartReader.readCpuUsageLog(totalStartTime, totalEndTime, &cpuUsageLog);
+ std::vector<Json> heartCpuLog;
+ ret = heartReader.readCpuLog(__lastHeartAccessTime, &heartCpuLog);
heartReader.close();
+
IF_FAIL_RETURN_TAG(ret, true, _E, "Cannot read from heart cpu table");
- IF_FAIL_RETURN_TAG(cpuUsageLog.size() > 0, true, _W, "Heart cpu data is not prepared yet (%d ~ %d)", totalStartTime, totalEndTime);
- _D("Read %d rows from heart cpu table from %d to %d", cpuUsageLog.size(), totalStartTime, totalEndTime);
-
- // Get the last timestamp of HEART cpu data and maximum app times tables in cache
- int lastHeartTimestamp;
- cpuUsageLog.back().get(NULL, BATTERY_TIMESTAMP, &lastHeartTimestamp);
- CpuUsageMap lastCpuUsage;
- ret = __getLastCpuUsageTable(&lastCpuUsage);
-
- unsigned int i;
- for (i = 0; i < __batteryTimeInfoVec.size(); i++) {
- int startTime;
- int endTime;
-
- Json row = __batteryTimeInfoVec[i].str();
- row.get(NULL, BATTERY_START_TIME, &startTime);
- row.get(NULL, BATTERY_END_TIME, &endTime);
-
- if (endTime > lastHeartTimestamp) {
- _W("[%d] Heart cpu data is not prepared yet (%d ~ %d)", i, startTime, endTime);
- break;
- }
-
- // Calculate per app battery usage
- std::vector<Json> usage;
- ret = __analyzer.calculateBatteryUsage(startTime, endTime, cpuUsageLog, lastCpuUsage, &usage);
- if (!ret) {
- _E("[%d] Failed to calculate battery usage (%d ~ %d)", i, startTime, endTime);
- continue;
- }
- _D("[%d] Battery usage per app calculated (%d ~ %d)", i, startTime, endTime);
-
- // Insert battery usage
- ret = __insertBatteryUsageLog(usage);
- if (!ret) {
- _E("Failed to insert per app battery usage");
- }
- }
+ IF_FAIL_RETURN_TAG(heartCpuLog.size() > 0, true, _W, "Heart cpu data is not prepared");
+ _D("Read %d rows from heart cpu table from %d", heartCpuLog.size(), __lastHeartAccessTime);
- // Normalize the percentages data, insert log of last times of apps, and update battery infos ToBeProcessed field
- if (i != 0) {
- __analyzer.normalize();
-
- ret = __insertLastCpuUsageLog(lastCpuUsage);
- if (!ret) {
- _E("Failed to insert last Cpu Usage of apps");
- }
-
- int processedStartTime = totalStartTime;
- int processedEndTime;
- __batteryTimeInfoVec[i-1].get(NULL, BATTERY_END_TIME, &processedEndTime);
- char *sql = sqlite3_mprintf(UPDATE_BATTERY_LOGS_QUERY, processedStartTime, processedEndTime);
- __dbMgr.executeSync(sql, NULL);
- sqlite3_free(sql);
- }
+ heartCpuLog.back().get(NULL, BATTERY_TIMESTAMP, &__lastHeartAccessTime);
+ __updateLastInfo();
- // Remove completed time info
- _D("Total %d time intervals, %d intervals are calculated", __batteryTimeInfoVec.size(), i);
- __batteryTimeInfoVec.erase(__batteryTimeInfoVec.begin(), __batteryTimeInfoVec.begin() + i);
- __deleteBatteryTimeInfo();
+ // Get last heart cpu log
+ CpuUsageMap lastHeartCpuLog;;
+ ret = __getLastCpuUsageTable(&lastHeartCpuLog);
- if (__batteryTimeInfoVec.size() == 0) {
- return false;
- }
- else {
- return true;
- }
+ // Calculate per app battery usage
+ std::vector<Json> usage;
+ __analyzer.calculateBatteryUsage(heartCpuLog, lastHeartCpuLog, &usage);
+
+ // Insert battery usage
+ ret = __insertBatteryUsageLog(usage);
+ IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to insert per app battery usage");
+
+ // Update last cpu usage
+ ret = __updateLastCpuUsageLog(lastHeartCpuLog);
+ IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to update last cpu log");
+
+ return true;
}
bool BatteryMonitor::__insertBatteryUsageLog(std::vector<Json>& usage)
{
IF_FAIL_RETURN_TAG(usage.size(), true, _W, "No data");
std::string query("INSERT INTO " BATTERY_USAGE_TABLE \
- "(" BATTERY_APP_ID ", " BATTERY_START_TIME ", " \
- BATTERY_END_TIME ", " BATTERY_UTIME ", " \
- BATTERY_STIME ", " BATTERY_AMOUNT ") VALUES");
+ "(" BATTERY_APP_ID ", " BATTERY_START_TIME ", " BATTERY_END_TIME ", " \
+ BATTERY_UTIME ", " BATTERY_STIME "," BATTERY_TOTAL_TIME ") VALUES");
std::string appId;
- int startTime;
+ int startTime, endTime;
int stime, utime;
- int endTime;
- double amount;
for (unsigned int i = 0; i < usage.size(); i++) {
usage[i].get(NULL, BATTERY_APP_ID, &appId);
usage[i].get(NULL, BATTERY_END_TIME, &endTime);
usage[i].get(NULL, BATTERY_UTIME, &utime);
usage[i].get(NULL, BATTERY_STIME, &stime);
- usage[i].get(NULL, BATTERY_AMOUNT, &amount);
query += " ('" + appId + "', "
+ std::to_string(startTime) + ", "
+ std::to_string(endTime) + ", "
+ std::to_string(utime) + ", "
+ std::to_string(stime) + ", "
- + std::to_string((int) (amount * 10000)) + ")";
+ + std::to_string(utime + stime) + ")";
query += ", ";
}
return __dbMgr.executeSync(query.c_str(), NULL);
}
-bool BatteryMonitor::__insertLastCpuUsageLog(CpuUsageMap& usage)
+bool BatteryMonitor::__updateLastCpuUsageLog(CpuUsageMap& usage)
{
IF_FAIL_RETURN_TAG(usage.size(), true, _W, "No data");
- _D("Delete all rows from app last times table");
__dbMgr.executeSync("DELETE FROM " BATTERY_LAST_CPU_USAGE_TABLE, NULL);
std::string query("INSERT INTO " BATTERY_LAST_CPU_USAGE_TABLE "(" BATTERY_APP_ID ", " BATTERY_UTIME ", " BATTERY_STIME ", " BATTERY_TIMESTAMP ", " BATTERY_PID ") VALUES");
}
// Used for Recent Battery Usage
-int BatteryMonitor::getLastResetTime()
+int BatteryMonitor::getLastFullTime()
{
- if (__lastResetTime == 0) {
- _I("Device has not fully charged until now. Start time of recent battery usage will be booting time");
+ if (__lastFullTime == 0) {
+ _I("Device has not fully charged until now. Start time of recent battery usage will be booting time: %d", __bootingTime);
return __bootingTime;
}
- return __lastResetTime;
-}
-
-void BatteryMonitor::__deleteBatteryTimeInfo()
-{
- int batteryTimeInfoDeleteTime = CURRENT_TIME - BATTERY_TIME_INFO_DELETE_DELAY;
- if (__lastBatteryTimeInfoDeleteTime > batteryTimeInfoDeleteTime) {
- _D("Old battery time info already deleted");
- return;
- }
-
- std::string query("DELETE FROM " BATTERY_TEMP_TIME_INFO " WHERE StartTime <= ");
- query += std::to_string(batteryTimeInfoDeleteTime);
-
- __dbMgr.executeSync(query.c_str(), NULL);
- __lastBatteryTimeInfoDeleteTime = CURRENT_TIME;
-
- bool ret = __updateLastInfo();
- IF_FAIL_VOID_TAG(ret, _E, "Failed to update last battery time info deletion time");
- _D("Old battery time info deleted");
+ return __lastFullTime;
}
*/
#include <map>
-#include <sqlite3.h>
#include <Types.h>
#include "BatteryUsageAnalyzer.h"
using namespace ctx;
-static int __timestampToNormalizeFrom = INT_MAX;
-
-#define BATTERY_INTERVALS_QUERY \
- "SELECT " BATTERY_START_TIME " , " BATTERY_END_TIME " FROM " BATTERY_TEMP_TIME_INFO " WHERE " BATTERY_START_TIME " >= %d AND " BATTERY_END_TIME " <= %d"
-#define NORMALIZE_QUERY \
- "UPDATE " BATTERY_USAGE_TABLE " SET " BATTERY_AMOUNT " = 10000 * (" BATTERY_UTIME " + " BATTERY_STIME ") /((" \
- "SELECT SUM(" BATTERY_UTIME ") FROM " BATTERY_USAGE_TABLE " WHERE " BATTERY_START_TIME " >= %d AND " BATTERY_END_TIME " <= %d) + (" \
- "SELECT SUM(" BATTERY_STIME ") FROM " BATTERY_USAGE_TABLE " WHERE " BATTERY_START_TIME " >= %d AND " BATTERY_END_TIME " <= %d )) WHERE " BATTERY_START_TIME " >= %d AND " BATTERY_END_TIME " <= %d"
-
BatteryUsageAnalyzer::BatteryUsageAnalyzer()
{
}
{
}
-bool BatteryUsageAnalyzer::calculateBatteryUsage(int lastTime, int currTime, std::vector<Json>& cpuUsageLog, CpuUsageMap& lastCpuUsage, std::vector<Json>* usage)
+void BatteryUsageAnalyzer::calculateBatteryUsage(std::vector<Json>& cpuLog, CpuUsageMap& recentCpuUsageMap, std::vector<Json>* usage)
{
- int timeInterval = currTime - lastTime;
- IF_FAIL_RETURN(timeInterval > 0, false);
-
std::string appId;
int timestamp;
int stime;
int utime;
int idx;
int pid;
- int leastTimeLogInserted = __timestampToNormalizeFrom;
-
- for (unsigned int i = 0; i < cpuUsageLog.size(); i++) {
- cpuUsageLog[i].get(NULL, BATTERY_APP_ID, &appId);
- cpuUsageLog[i].get(NULL, BATTERY_TIMESTAMP, ×tamp);
- cpuUsageLog[i].get(NULL, BATTERY_UTIME, &utime);
- cpuUsageLog[i].get(NULL, BATTERY_STIME, &stime);
- cpuUsageLog[i].get(NULL, BATTERY_INDEX, &idx);
- cpuUsageLog[i].get(NULL, BATTERY_PID, &pid);
- if (timestamp < lastTime) {
- continue;
- }
- if (timestamp > currTime) {
- break;
- }
+ for (unsigned int i = 0; i < cpuLog.size(); i++) {
+ cpuLog[i].get(NULL, BATTERY_APP_ID, &appId);
+ cpuLog[i].get(NULL, BATTERY_TIMESTAMP, ×tamp);
+ cpuLog[i].get(NULL, BATTERY_UTIME, &utime);
+ cpuLog[i].get(NULL, BATTERY_STIME, &stime);
+ cpuLog[i].get(NULL, BATTERY_INDEX, &idx);
+ cpuLog[i].get(NULL, BATTERY_PID, &pid);
- //If CPU table is reset, clear last app times and make lastTime as the timestamp
+ //If CPU table is reset, clear last cpu usage
if (idx == 0) {
- lastCpuUsage.clear();
- lastTime = timestamp;
+ recentCpuUsageMap.clear();
}
- auto lastAppCpuUsage = lastCpuUsage.find(appId);
+ int prevTimestamp = timestamp;
int prevUtime = 0;
int prevStime = 0;
- int prevTimestamp = INT_MAX;
- int prevPid = 0;
-
- if (lastAppCpuUsage != lastCpuUsage.end()) {
- prevTimestamp = (lastAppCpuUsage->second).timestamp;
- prevUtime = (lastAppCpuUsage->second).utime;
- prevStime = (lastAppCpuUsage->second).stime;
- prevPid = (lastAppCpuUsage->second).pid;
- // If the app is killed and launched again
- if (pid != prevPid) {
- prevUtime = 0;
- prevStime = 0;
- prevTimestamp = lastTime;
+ auto lastAppCpuUsage = recentCpuUsageMap.find(appId);
+ if (lastAppCpuUsage != recentCpuUsageMap.end()) {
+ // If the last info of the app exists
+ if ((lastAppCpuUsage->second).pid == pid) {
+ prevTimestamp = (lastAppCpuUsage->second).timestamp;
+ prevUtime = (lastAppCpuUsage->second).utime;
+ prevStime = (lastAppCpuUsage->second).stime;
}
-
- double timeCurrPercent = (double)(timestamp - lastTime);
- double utimePerUnitTime = (((double)(utime - prevUtime)) / ((double)(timestamp - prevTimestamp)));
- double stimePerUnitTime = (((double)(stime - prevStime)) / ((double)(timestamp - prevTimestamp)));
- __addPreviousBatteryUsageLogs(prevTimestamp, lastTime, appId, utimePerUnitTime, stimePerUnitTime, usage);
-
- if (leastTimeLogInserted > prevTimestamp) {
- leastTimeLogInserted = prevTimestamp;
- }
-
- Json row;
- row.set(NULL, BATTERY_APP_ID, appId);
- row.set(NULL, BATTERY_START_TIME, lastTime);
- row.set(NULL, BATTERY_END_TIME, timestamp);
- row.set(NULL, BATTERY_AMOUNT, 0);
- row.set(NULL, BATTERY_UTIME, (int)(utimePerUnitTime * timeCurrPercent + 0.5));
- row.set(NULL, BATTERY_STIME, (int)(stimePerUnitTime * timeCurrPercent + 0.5));
-
- usage->push_back(row);
-
- } else {
- Json row;
- row.set(NULL, BATTERY_APP_ID, appId);
- row.set(NULL, BATTERY_START_TIME, lastTime);
- row.set(NULL, BATTERY_END_TIME, timestamp);
- row.set(NULL, BATTERY_AMOUNT, 0);
- row.set(NULL, BATTERY_UTIME, utime);
- row.set(NULL, BATTERY_STIME, stime);
-
- usage->push_back(row);
}
- LastAppCpuUsageInfo lastAppUsage;
- lastAppUsage.timestamp = timestamp;
- lastAppUsage.utime = utime;
- lastAppUsage.stime = stime;
- lastAppUsage.pid = pid;
- lastCpuUsage[appId] = lastAppUsage;
-
- __timestampToNormalizeFrom = leastTimeLogInserted;
- }
- return true;
-}
-
-// When an app is open across multiple percentage drops without any app event, this function is called on the next app event to distribute the battery drain among the percentages it was open
-bool BatteryUsageAnalyzer::__addPreviousBatteryUsageLogs(int startTime, int endTime, std::string appId, double utimePerUnitTime, double stimePerUnitTime, std::vector<Json>* usage)
-{
- std::vector<Json> batteryChanges;
- char *sql = sqlite3_mprintf(BATTERY_INTERVALS_QUERY, startTime, endTime);
- __dbMgr.executeSync(sql, &batteryChanges);
- sqlite3_free(sql);
-
- unsigned int k = 0;
- int batteryStartTime;
- int batteryEndTime;
- int batteryTimeDiff;
-
- while (k < batteryChanges.size()) {
- batteryChanges[k].get(NULL, BATTERY_START_TIME, &batteryStartTime);
- batteryChanges[k].get(NULL, BATTERY_END_TIME, &batteryEndTime);
- batteryTimeDiff = batteryEndTime - batteryStartTime;
- k++;
+ if (utime - prevUtime == 0 && stime - prevStime == 0) {
+ recentCpuUsageMap[appId].timestamp = timestamp;
+ continue;
+ }
Json row;
row.set(NULL, BATTERY_APP_ID, appId);
- row.set(NULL, BATTERY_START_TIME, batteryStartTime);
- row.set(NULL, BATTERY_END_TIME, batteryEndTime);
- row.set(NULL, BATTERY_AMOUNT, 0);
- row.set(NULL, BATTERY_UTIME, (int)(utimePerUnitTime * batteryTimeDiff + 0.5));
- row.set(NULL, BATTERY_STIME, (int)(stimePerUnitTime * batteryTimeDiff + 0.5));
- usage->push_back(row);
- }
- return true;
-}
-
-bool BatteryUsageAnalyzer::normalize()
-{
- _D("Normalizing battery usage data from time %d ", __timestampToNormalizeFrom);
- std::vector<Json> batteryChanges;
- char *sql = sqlite3_mprintf(BATTERY_INTERVALS_QUERY, __timestampToNormalizeFrom, CURRENT_TIME);
- __dbMgr.executeSync(sql, &batteryChanges);
-
- unsigned int k = 0;
- int batteryStartTime;
- int batteryEndTime;
+ row.set(NULL, BATTERY_START_TIME, prevTimestamp);
+ row.set(NULL, BATTERY_END_TIME, timestamp);
+ row.set(NULL, BATTERY_UTIME, utime - prevUtime);
+ row.set(NULL, BATTERY_STIME, stime - prevStime);
- while (k < batteryChanges.size()) {
- batteryChanges[k].get(NULL, BATTERY_START_TIME, &batteryStartTime);
- batteryChanges[k].get(NULL, BATTERY_END_TIME, &batteryEndTime);
- k++;
+ usage->push_back(row);
- sql = sqlite3_mprintf(NORMALIZE_QUERY, batteryStartTime, batteryEndTime, batteryStartTime, batteryEndTime, batteryStartTime, batteryEndTime);
- __dbMgr.executeSync(sql, NULL);
+ // Store recent cpu usage info of the app
+ CpuLogInfo currentAppInfo;
+ currentAppInfo.timestamp = timestamp;
+ currentAppInfo.utime = utime;
+ currentAppInfo.stime = stime;
+ currentAppInfo.pid = pid;
+ recentCpuUsageMap[appId] = currentAppInfo;
}
-
- __timestampToNormalizeFrom = INT_MAX;
- sqlite3_free(sql);
- return true;
}