package jp.co.cyberagent.stf.monitor;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.util.Log;
import jp.co.cyberagent.stf.io.MessageWritable;
import jp.co.cyberagent.stf.proto.Wire;
public class BatteryMonitor extends AbstractMonitor {
private static final String TAG = "STFBatteryMonitor";
private BatteryState state = null;
public BatteryMonitor(Context context, MessageWritable writer) {
super(context, writer);
}
@Override
public void run() {
Log.i(TAG, "Monitor starting");
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
state = new BatteryState(intent);
report(writer, state);
}
};
context.registerReceiver(receiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
try {
synchronized (this) {
while (!isInterrupted()) {
wait();
}
}
}
catch (InterruptedException e) {
// Okay
}
catch (Exception e) {
e.printStackTrace();
}
finally {
Log.i(TAG, "Monitor stopping");
context.unregisterReceiver(receiver);
}
}
@Override
public void peek(MessageWritable writer) {
if (state != null) {
report(writer, state);
}
}
private void report(MessageWritable writer, BatteryState state) {
Log.i(TAG, String.format("Battery is %s (%s health); connected via %s; level at %d/%d; temp %.1fC@%.3fV",
statusLabel(state.status),
healthLabel(state.health),
sourceLabel(state.source),
state.level,
state.scale,
state.temp / 10.0,
state.voltage / 1000.0
));
writer.write(Wire.Envelope.newBuilder()
.setType(Wire.MessageType.EVENT_BATTERY)
.setMessage(Wire.BatteryEvent.newBuilder()
.setStatus(statusLabel(state.status))
.setHealth(healthLabel(state.health))
.setSource(sourceLabel(state.source))
.setLevel(state.level)
.setScale(state.scale)
.setTemp(state.temp / 10.0)
.setVoltage(state.voltage / 1000.0)
.build()
.toByteString())
.build());
}
private String healthLabel(int health) {
switch (health) {
case BatteryManager.BATTERY_HEALTH_COLD:
return "cold";
case BatteryManager.BATTERY_HEALTH_GOOD:
return "good";
case BatteryManager.BATTERY_HEALTH_DEAD:
return "dead";
case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
return "over_voltage";
case BatteryManager.BATTERY_HEALTH_OVERHEAT:
return "overheat";
case BatteryManager.BATTERY_HEALTH_UNKNOWN:
return "unknown";
case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
return "unspecified_failure";
default:
return "unknown_" + health;
}
}
private String sourceLabel(int source) {
switch (source) {
case BatteryManager.BATTERY_PLUGGED_AC:
return "ac";
case BatteryManager.BATTERY_PLUGGED_USB:
return "usb";
case BatteryManager.BATTERY_PLUGGED_WIRELESS:
return "wireless";
default:
return "unknown_" + source;
}
}
private String statusLabel(int status) {
switch (status) {
case BatteryManager.BATTERY_STATUS_CHARGING:
return "charging";
case BatteryManager.BATTERY_STATUS_DISCHARGING:
return "discharging";
case BatteryManager.BATTERY_STATUS_FULL:
return "full";
case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
return "not_charging";
case BatteryManager.BATTERY_STATUS_UNKNOWN:
return "unknown";
default:
return "unknown_" + status;
}
}
private static class BatteryState {
private int health;
private int level;
private int source;
private int scale;
private int status;
private String tech;
private int temp;
private int voltage;
public BatteryState(Intent intent) {
health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_UNKNOWN);
level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
source = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN);
tech = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY);
temp = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0);
voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0);
}
}
}