diff --git a/client/cs_prefs.cpp b/client/cs_prefs.cpp index e1c9d4bc7d..159ed18ccd 100644 --- a/client/cs_prefs.cpp +++ b/client/cs_prefs.cpp @@ -202,7 +202,9 @@ void CLIENT_STATE::get_disk_shares() { } } -// See if we should suspend processing +// See if we should suspend CPU and/or GPU processing; +// return the CPU suspend_reason, +// and if it's zero set gpu_suspend_reason // int CLIENT_STATE::check_suspend_processing() { if (are_cpu_benchmarks_running()) { @@ -265,6 +267,37 @@ int CLIENT_STATE::check_suspend_processing() { } } +#ifdef ANDROID + // on some devices, running jobs can drain the battery even + // while it's recharging. + // So use the following hysteresis policy: + // start computing when the batter is 95% charged. + // stop computing if it falls below 90%. + // Repeat. + // + static bool hyst_state = true; + host_info.get_battery_status(); + if (host_info.battery_state == BATTERY_STATE_OVERHEATED) { + return SUSPEND_REASON_BATTERY_OVERHEATED; + } + int cp = host_info.battery_charge_pct; + if (cp >= 0) { + if (cp < 90) { + hyst_state = true; + return SUSPEND_REASON_BATTERY_CHARGE; + } + if (cp < 95) { + if (hyst_state) { + return SUSPEND_REASON_BATTERY_CHARGE; + } + } else { + hyst_state = false; + } + } +#endif + + // CPU is not suspended. See if GPUs are + // if (!coprocs.none()) { int old_gpu_suspend_reason = gpu_suspend_reason; gpu_suspend_reason = 0; @@ -378,7 +411,7 @@ void CLIENT_STATE::check_suspend_network() { } #ifdef ANDROID - //verify that device is on wifi before making project transfers. + // use only WiFi // if (global_prefs.network_wifi_only && !host_info.host_wifi_online()) { file_xfers_suspended = true; diff --git a/client/hostinfo_network.cpp b/client/hostinfo_network.cpp index 692dd404d0..0ff7e1d474 100644 --- a/client/hostinfo_network.cpp +++ b/client/hostinfo_network.cpp @@ -64,30 +64,31 @@ // bool HOST_INFO::host_wifi_online() { char wifipath_pri[1024]; - snprintf(wifipath_pri, sizeof(wifipath_pri), "/sys/class/net/eth0/operstate"); //location in Android 2.3 + snprintf(wifipath_pri, sizeof(wifipath_pri), char wifipath_sec[1024]; - snprintf(wifipath_sec, sizeof(wifipath_sec), "/sys/class/net/wlan0/operstate"); //location in Android 4 + snprintf(wifipath_sec, sizeof(wifipath_sec), - FILE *fsyswifi = fopen(wifipath_pri, "r"); - if(!fsyswifi) { //primary location not available, try _sec - fsyswifi = fopen(wifipath_sec, "r"); + FILE *f = fopen("/sys/class/net/eth0/operstate", "r"); + // location in Android 2.3 + if (!fsyswifi) { + fsyswifi = fopen("/sys/class/net/wlan0/operstate", "r"); + // location in Android 4 } char wifi_state[64]; - bool wifi_online = false; - if (fsyswifi) { - (void) fscanf(fsyswifi, "%s", &wifi_state); - fclose(fsyswifi); + if (f) { + fgets(wifi_state, 64, f); + fclose(f); } else { LOGD("wifi adapter not found!"); + return false; } - if ((strcmp(wifi_state,"up")) == 0) { //operstate = up - wifi_online = true; + if (strstr(wifi_state,"up"))) { + return true; } - - return wifi_online; + return false; } #endif //ANDROID diff --git a/client/hostinfo_unix.cpp b/client/hostinfo_unix.cpp index f7aeee4b1d..e11dfb41a3 100644 --- a/client/hostinfo_unix.cpp +++ b/client/hostinfo_unix.cpp @@ -445,74 +445,58 @@ bool HOST_INFO::host_is_running_on_batteries() { #endif } -// Returns the percent of which the battery is charged +#ifdef ANDROID +// Get battery state and charge percentage // -int HOST_INFO::get_host_battery_charge() { - int capacity = 0; +void HOST_INFO::get_battery_status() { + char msg[1024]; + battery_charge_pct = -1; -#if defined(ANDROID) - - FILE *battery_capacity_file = fopen("/sys/class/power_supply/battery/capacity", "r"); - if(battery_capacity_file) { - fscanf(battery_capacity_file, "%d", &capacity); - fclose(battery_capacity_file); + FILE *f = fopen("/sys/class/power_supply/battery/capacity", "r"); + if (f) { + fscanf(f, "%d", &battery_charge_pct); + fclose(f); } - if (capacity) { - char msg[1024]; - snprintf(msg, sizeof(msg), - "battery capacity at: %d%% charge", - capacity - ); - LOGD(msg); - } - -#endif - - return capacity; -} - -// Returns the percent of which the battery is charged -// -int HOST_INFO::get_host_battery_state() { - int rc = BATTERY_STATE_UNKNOwN; - -#if defined(ANDROID) + snprintf(msg, sizeof(msg), + "battery capacity at: %d%% charge", + capacity + ); + LOGD(msg); char health[256]; char status[256]; + strcpy(health, ""); + strcpy(status, ""); - FILE *battery_health_file = fopen("/sys/class/power_supply/battery/health", "r"); - if(battery_health_file) { - fscanf(battery_health_file, "%s", &health); - fclose(battery_health_file); + f = fopen("/sys/class/power_supply/battery/health", "r"); + if (f) { + fgets(health, sizeof(health), f); + fclose(f); } - FILE *battery_status_file = fopen("/sys/class/power_supply/battery/status", "r"); - if(battery_status_file) { - fscanf(battery_status_file, "%s", &status); - fclose(battery_status_file); + f = fopen("/sys/class/power_supply/battery/status", "r"); + if (f) { + fgets(status, sizeof(status), f); + fclose(f); } - if (strlen(health) && (strcmp(health, "Overheat") == 0)) { - rc = BATTERY_STATE_OVERHEAT; - } else if (strlen(status) && (strcmp(status, "Not charging") == 0)) { - rc = BATTERY_STATE_DISCHARGING; - } else if (strlen(status) && (strcmp(status, "Charging") == 0)) { - rc = BATTERY_STATE_CHARGING; - } else if (strlen(status) && (strcmp(status, "Full") == 0)) { - rc = BATTERY_STATE_CHARGING; + battery_state = BATTERY_STATE_UNKNOWN; + if (strstr(health, "Overheat")) { + LOGD("battery is overheating"); + battery_state = BATTERY_STATE_OVERHEAT; + } else if (strstr(status, "Not charging")) { + LOGD("battery is discharging"); + battery_state = BATTERY_STATE_DISCHARGING; + } else if (strstr(status, "Charging")) { + LOGD("battery is charging"); + battery_state = BATTERY_STATE_CHARGING; + } else if (strstr(status, "Full")) { + LOGD("battery is charging"); + battery_state = BATTERY_STATE_CHARGING; } - - if (BATTERY_STATE_OVERHEAT == rc) LOGD("battery is overheating"); - if (BATTERY_STATE_DISCHARGING == rc) LOGD("battery is discharging"); - if (BATTERY_STATE_CHARGING == rc) LOGD("battery is charging"); - if (BATTERY_STATE_CHARGING == rc) LOGD("battery is full"); - -#endif - - return rc; } +#endif #if LINUX_LIKE_SYSTEM static void parse_meminfo_linux(HOST_INFO& host) { diff --git a/lib/common_defs.h b/lib/common_defs.h index ea82f8b16b..90474f7f16 100644 --- a/lib/common_defs.h +++ b/lib/common_defs.h @@ -106,17 +106,19 @@ enum SUSPEND_REASON { SUSPEND_REASON_CPU_USAGE = 1024, SUSPEND_REASON_NETWORK_QUOTA_EXCEEDED = 2048, SUSPEND_REASON_OS = 4096, - SUSPEND_REASON_WIFI_STATE = 8192 + SUSPEND_REASON_WIFI_STATE = 4097, + SUSPEND_REASON_BATTERY_CHARGING = 4098, + SUSPEND_REASON_BATTERY_OVERHEATED = 4099 }; -// bitmap defs for battery_state +// battery state (currently used only for Android) // enum BATTERY_STATE { - BATTERY_STATE_DISCHARGING = 1, - BATTERY_STATE_CHARGING = 2, - BATTERY_STATE_FULL = 4, - BATTERY_STATE_OVERHEAT = 8, - BATTERY_STATE_UNKNOwN = 16 + BATTERY_STATE_UNKNOWN=0, + BATTERY_STATE_DISCHARGING, + BATTERY_STATE_CHARGING, + BATTERY_STATE_FULL, + BATTERY_STATE_OVERHEAT }; // Values of RESULT::state in client. diff --git a/lib/hostinfo.h b/lib/hostinfo.h index fbc0efaef1..f1fdadc6a6 100644 --- a/lib/hostinfo.h +++ b/lib/hostinfo.h @@ -67,6 +67,12 @@ public: COPROCS coprocs; +#ifdef ANDROID + int battery_charge_pct; + int battery_state; + void get_battery_status(); +#endif + HOST_INFO(); int parse(XML_PARSER&, bool benchmarks_only = false); int write(MIOFILE&, bool include_net_info, bool include_coprocs); diff --git a/lib/str_util.cpp b/lib/str_util.cpp index a63b322104..b38426167f 100644 --- a/lib/str_util.cpp +++ b/lib/str_util.cpp @@ -578,6 +578,8 @@ const char* suspend_reason_string(int reason) { case SUSPEND_REASON_CPU_USAGE: return "CPU is busy"; case SUSPEND_REASON_NETWORK_QUOTA_EXCEEDED: return "network bandwidth limit exceeded"; case SUSPEND_REASON_OS: return "requested by operating system"; + case SUSPEND_REASON_WIFI_STATE: return "not connected to WiFi network"; + case SUSPEND_REASON_BATTERY_STATE: return "battery is recharging"; } return "unknown reason"; }