/*
This file is part of jpcsp.
Jpcsp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jpcsp 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jpcsp. If not, see <http://www.gnu.org/licenses/>.
*/
package jpcsp.hardware;
import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.win32.StdCallLibrary;
import jpcsp.util.OS;
import java.util.Arrays;
import java.util.List;
/**
* @author gid15
*/
public class BatteryUpdateThread extends Thread {
private static BatteryUpdateThread instance = null;
private long sleepMillis;
public static void initialize() {
if (instance == null) {
long secondsForOnePercentDrain = Battery.getLifeTime() * 60 / 100;
instance = new BatteryUpdateThread(secondsForOnePercentDrain * 1000);
instance.setDaemon(true);
instance.setName("Battery Drain");
instance.start();
}
}
public BatteryUpdateThread(long sleepMillis) {
this.sleepMillis = sleepMillis;
}
@Override
public void run() {
if (OS.isWindows) updateWindows();
else if (OS.isLinux) updateLinux();
else if (OS.isMac) updateMac();
else updateGeneric();
}
private void updateWindows() {
while (true) {
BatteryWindows.Kernel32.SYSTEM_POWER_STATUS status = BatteryWindows.status();
// getLifeTime
int batteryLifeTimeInSeconds = status.BatteryLifeTime;
if (batteryLifeTimeInSeconds < 0) batteryLifeTimeInSeconds = 5 * 3600; // Unknown lifetime
Battery.setLifeTime(batteryLifeTimeInSeconds / 60);
// isPluggedIn
Battery.setPluggedIn(status.ACLineStatus == 1);
// isPResent
Battery.setPresent((status.BatteryFlag & 128) != 0);
// currentPowerPercent
int percent = status.BatteryLifePercent;
if (percent >= 0 && percent <= 100) {
Battery.setCurrentPowerPercent(percent);
} else {
// Invalid value, not update it!
}
// isCharging
Battery.setCharging((status.BatteryFlag & 8) != 0);
sleepMillis(5 * 1000); // Wait five second between updates
}
}
static private void sleepMillis(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void updateLinux() {
updateGeneric();
}
private void updateMac() {
updateGeneric();
}
private void updateGeneric() {
while (true) {
sleepMillis(sleepMillis);
int powerPercent = Battery.getCurrentPowerPercent();
// Increase/decrease power by 1%
if (Battery.isCharging()) {
if (powerPercent < 100) {
powerPercent++;
}
} else {
if (powerPercent > 0) {
powerPercent--;
}
}
Battery.setCurrentPowerPercent(powerPercent);
}
}
static class BatteryWindows {
static private Kernel32.SYSTEM_POWER_STATUS result = new Kernel32.SYSTEM_POWER_STATUS();
static public Kernel32.SYSTEM_POWER_STATUS status() {
Kernel32.INSTANCE.GetSystemPowerStatus(result);
return result;
}
// http://stackoverflow.com/questions/3434719/how-to-get-the-remaining-battery-life-in-a-windows-system
// http://msdn2.microsoft.com/en-us/library/aa373232.aspx
public interface Kernel32 extends StdCallLibrary {
Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("Kernel32", Kernel32.class);
class SYSTEM_POWER_STATUS extends Structure {
public byte ACLineStatus; // 0 = Offline, 1 = Online, other = Unknown
public byte BatteryFlag; // 1 = High (more than 66%), 2 = Low (less than 33%), 4 = Critical (less than 5%), 8 = Charging, 128 = No system battery
public byte BatteryLifePercent; // 0-100 (-1 on desktop)
public byte Reserved1;
public int BatteryLifeTime; // Estimated Lifetime in seconds
public int BatteryFullLifeTime; // Estimated Lifetime in seconds on full charge
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("ACLineStatus", "BatteryFlag", "BatteryLifePercent", "Reserved1", "BatteryLifeTime", "BatteryFullLifeTime");
}
}
int GetSystemPowerStatus(SYSTEM_POWER_STATUS result);
}
}
// http://stackoverflow.com/questions/22128336/how-to-add-a-command-to-check-battery-level-in-linux-shell
static class BatteryLinux {
static private BatteryLinux INSTANCE = new BatteryLinux();
static private String FOLDER = "/sys/class/power_supply/BAT0";
static public BatteryLinux status() {
return INSTANCE;
}
public static void refresh() {
}
}
}