android: implementation of <report_device_status>

This commit is contained in:
Joachim Fritzsch 2013-05-17 18:58:14 +02:00
parent 3bef989991
commit 8df34c4fbf
5 changed files with 194 additions and 0 deletions

View File

@ -25,6 +25,8 @@
<integer name="monitor_setup_connection_retry_rate_ms">1000</integer>
<integer name="monitor_setup_connection_retry_attempts">10</integer>
<integer name="autostart_notification_id">460</integer>
<!-- Device status -->
<integer name="minimum_device_status_refresh_rate_in_monitor_loops">10</integer>
<!-- configuration on tab layout -->
<bool name="tab_status">true</bool>
<bool name="tab_projects">true</bool>

View File

@ -46,6 +46,7 @@ import edu.berkeley.boinc.rpc.AccountIn;
import edu.berkeley.boinc.rpc.AccountOut;
import edu.berkeley.boinc.rpc.CcState;
import edu.berkeley.boinc.rpc.CcStatus;
import edu.berkeley.boinc.rpc.DeviceStatus;
import edu.berkeley.boinc.rpc.GlobalPreferences;
import edu.berkeley.boinc.rpc.Message;
import edu.berkeley.boinc.rpc.Project;
@ -919,6 +920,11 @@ public class Monitor extends Service {
// Frequency of which the monitor updates client status via RPC, to often can cause reduced performance!
private Integer refreshFrequency = getResources().getInteger(R.integer.monitor_refresh_rate_ms);
private Integer minimumDeviceStatusFrequency = getResources().getInteger(R.integer.minimum_device_status_refresh_rate_in_monitor_loops);
private Integer deviceStatusOmitCounter = 0;
// DeviceStatus wrapper class
private DeviceStatus deviceStatus = new DeviceStatus(getApplicationContext());
@Override
protected Boolean doInBackground(Integer... params) {
@ -933,6 +939,19 @@ public class Monitor extends Service {
clientSetup();
sleep = false;
} else {
// connection alive
// set devices status
try {
if(deviceStatus.update() || deviceStatusOmitCounter >= minimumDeviceStatusFrequency) {
if(showRpcCommands) Log.d(TAG, "reportDeviceStatus");
Boolean reportStatusSuccess = rpc.reportDeviceStatus(deviceStatus);
Log.d(TAG,"reportDeviceStatus returned: " + reportStatusSuccess);
if(reportStatusSuccess) deviceStatusOmitCounter = 0;
} else deviceStatusOmitCounter++;
} catch (Exception e) { Log.w(TAG, "device status update failed: " + e.getLocalizedMessage()); }
// retrieve client status
if(showRpcCommands) Log.d(TAG, "getCcStatus");
CcStatus status = rpc.getCcStatus();

View File

@ -0,0 +1,137 @@
/*******************************************************************************
* This file is part of BOINC.
* http://boinc.berkeley.edu
* Copyright (C) 2012 University of California
*
* BOINC is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* BOINC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with BOINC. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package edu.berkeley.boinc.rpc;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.BatteryManager;
import android.util.Log;
public class DeviceStatus{
private final String TAG = "Rpc.DeviceState";
// variables describing device status
private boolean on_ac_power;
private boolean on_usb_power; //not used
private int battery_charge_pct;
private int battery_state; //not used
private int battery_temperature_celcius;
private boolean wifi_online;
// android specifics
private Context ctx;// context required for reading device status
private ConnectivityManager connManager; // connManager contains current wifi status
private Intent batteryStatus; // sticky intent, extras of Intent contain status, see BatteryManager.
// constructor
public DeviceStatus(Context ctx) {
this.ctx = ctx;
this.connManager = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
batteryStatus = ctx.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}
// polls current device status
// returns true if data model has actually changed
// returns false if device status is unchanged -> avoid RPC call
public Boolean update() throws Exception {
if(ctx == null) {
Log.w(TAG,"context not set");
return false;
}
Boolean change = false;
// check battery
batteryStatus = ctx.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
if(batteryStatus != null){
// calculate charging level
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
int batteryPct = (int) ((level / (float) scale) * 100); // always rounds down
if(batteryPct <= 1 || batteryPct > 100) throw new Exception("battery level parsing error");
if(batteryPct != battery_charge_pct) {
battery_charge_pct = batteryPct;
change = true;
}
// temperature
int temperature = batteryStatus.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1) / 10; // always rounds down
if(temperature < 0) throw new Exception("temperature parsing error");
if(temperature != battery_temperature_celcius) {
battery_temperature_celcius = temperature;
change = true;
}
// plugged in
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
if(status != BatteryManager.BATTERY_STATUS_DISCHARGING){
// power supply online. not equivalent to BATTERY_STATUS_CHARGING which is not the case when full and plugged in
if(!on_ac_power) change = true; // if different from before, set flag
on_ac_power = true;
} else {
//power supply offline
if(on_ac_power) change = true; // if different from before, set flag
on_ac_power = false;
}
}
// check wifi status
if(connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected()){
//wifi is online
if(!wifi_online) change = true; // if different from before, set flag
wifi_online = true;
} else {
//wifi offline
if(wifi_online) change = true; // if different from before, set flag
wifi_online = false;
}
Log.d(TAG, "change: " + change + " - power supply: " + on_ac_power + " ; level: " + battery_charge_pct + " ; temperature: " + battery_temperature_celcius + " ; wifi: " + wifi_online);
return change;
}
// getter
public boolean isOn_ac_power() {
return on_ac_power;
}
public boolean isOn_usb_power() {
return on_usb_power;
}
public int getBattery_charge_pct() {
return battery_charge_pct;
}
public int getBattery_state() {
return battery_state;
}
public int getBattery_temperature_celcius() {
return battery_temperature_celcius;
}
public boolean isWifi_online() {
return wifi_online;
}
}

View File

@ -580,6 +580,41 @@ public class RpcClient {
}
}
/**
* Reports the current device state to the BOINC core client,
* if not called frequently, BOINC core client will suspend
* @return true for success, false for failure
*/
public synchronized boolean reportDeviceStatus(DeviceStatus deviceStatus) {
mLastErrorMessage = null;
mRequest.setLength(0);
mRequest.append("<report_device_status>\n <device_status>\n <on_ac_power>");
mRequest.append(deviceStatus.isOn_ac_power() ? 1 : 0);
mRequest.append("</on_ac_power>\n <on_usb_power>");
mRequest.append(deviceStatus.isOn_usb_power() ? 1 : 0);
mRequest.append("</on_usb_power>\n <battery_charge_pct>");
mRequest.append(deviceStatus.getBattery_charge_pct());
mRequest.append("</battery_charge_pct>\n <battery_state>");
mRequest.append(deviceStatus.getBattery_state());
mRequest.append("</battery_state>\n <battery_temperature_celsius>");
mRequest.append(deviceStatus.getBattery_temperature_celcius());
mRequest.append("</battery_temperature_celsius>\n <wifi_online>");
mRequest.append(deviceStatus.isWifi_online() ? 1 : 0);
mRequest.append("</wifi_online>\n </device_status>\n</report_device_status>\n");
try {
sendRequest(mRequest.toString());
SimpleReplyParser parser = SimpleReplyParser.parse(receiveReply());
if (parser == null)
return false;
mLastErrorMessage = parser.getErrorMessage();
return parser.result();
}
catch (IOException e) {
if (Logging.WARNING) Log.w(TAG, "error in networkAvailable()", e);
return false;
}
}
/**
* Tells the BOINC core client that a network connection is available,
* and that it should do as much network activity as it can.

View File

@ -105,6 +105,7 @@ public class BOINCDefs {
public static final int SUSPEND_REASON_WIFI_STATE = 4097;
public static final int SUSPEND_REASON_BATTERY_CHARGING = 4098;
public static final int SUSPEND_REASON_BATTERY_OVERHEATED = 4099;
public static final int SUSPEND_REASON_NO_GUI_KEEPALIVE = 4100;
// Values of RESULT::state
// THESE MUST BE IN NUMERICAL ORDER