/*
* Copyright (C) 2011-2014 asksven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.asksven.betterbatterystats.data;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.map.annotate.JsonDeserialize;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import android.os.SystemClock;
import android.util.Log;
import com.asksven.android.common.dto.AlarmDto;
import com.asksven.android.common.dto.MiscDto;
import com.asksven.android.common.dto.NativeKernelWakelockDto;
import com.asksven.android.common.dto.NetworkUsageDto;
import com.asksven.android.common.dto.ProcessDto;
import com.asksven.android.common.dto.SensorUsageDto;
import com.asksven.android.common.dto.StateDto;
import com.asksven.android.common.dto.WakelockDto;
import com.asksven.android.common.privateapiproxies.NativeKernelWakelock;
import com.asksven.android.common.kernelutils.State;
import com.asksven.android.common.privateapiproxies.Alarm;
import com.asksven.android.common.privateapiproxies.Misc;
import com.asksven.android.common.privateapiproxies.NetworkUsage;
import com.asksven.android.common.privateapiproxies.SensorUsage;
import com.asksven.android.common.privateapiproxies.StatElement;
import com.asksven.android.common.privateapiproxies.Process;
import com.asksven.android.common.utils.DateUtils;
import com.asksven.betterbatterystats.LogSettings;
import com.asksven.android.common.privateapiproxies.Wakelock;
/**
* A serializable value holder for stat references
* @author sven
*
*/
@JsonSerialize(include=JsonSerialize.Inclusion.ALWAYS)
@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY, getterVisibility=JsonAutoDetect.Visibility.NONE, setterVisibility=JsonAutoDetect.Visibility.NONE)
public class Reference implements Serializable
{
private static final long serialVersionUID = 3L;
private transient static final String TAG = "References";
public static final String EXTRA_REF_NAME = "com.asksven.betterbatterystats.REF_NAME";
public static final String CUSTOM_REF_FILENAME = "ref_custom";
public static final String TIMER_REF_FILENAME = "Timer ";
public static final String UNPLUGGED_REF_FILENAME = "ref_unplugged";
public static final String CHARGED_REF_FILENAME = "ref_charged";
public static final String SCREEN_OFF_REF_FILENAME = "ref_screen_off";
public static final String SCREEN_ON_REF_FILENAME = "ref_screen_on";
public static final String BOOT_REF_FILENAME = "ref_boot";
public static final String CURRENT_REF_FILENAME = "ref_current";
public static final int TYPE_CUSTOM = 1;
public static final int TYPE_EVENT = 2;
public static final int TYPE_CURRENT = 3;
public static final int TYPE_TIMER = 4;
protected static final String[] FILES = {CUSTOM_REF_FILENAME, CURRENT_REF_FILENAME, UNPLUGGED_REF_FILENAME, CHARGED_REF_FILENAME, SCREEN_OFF_REF_FILENAME, SCREEN_ON_REF_FILENAME, BOOT_REF_FILENAME};
protected static final String CUSTOM_REF_ERR = "No custom reference was set. Please use the menu to do so";
protected static final String UNPLUGGED_REF_ERR = "No reference unplugged was saved yet, plug/unplug you phone";
protected static final String CHARGED_REF_ERR = "No reference charged was saved yet, it will the next time you charge to 100%";
protected static final String SCREEN_OFF_REF_ERR = "Screen off event was not registered yet. Make sure to activate the watchdog.";
protected static final String SCREEN_ON_REF_ERR = "Screen on event was not registered yet. Make sure to activate the watchdog.";
protected static final String BOOT_REF_ERR = "Boot event was not registered yet, it will at next reboot";
protected static final String CUSTOM_REF_NAME = "Custom";
protected static final String CURRENT_REF_NAME = "Current";
protected static final String UNPLUGGED_REF_NAME = "Unplugged";
protected static final String CHARGED_REF_NAME = "Charged";
protected static final String SCREEN_OFF_REF_NAME = "Screen Off";
protected static final String SCREEN_ON_REF_NAME = "Screen On";
protected static final String BOOT_REF_NAME = "Boot";
protected static final String TIMER_REF_NAME = "Timer";
/** storage of custom references */
public String m_fileName = "";
protected long m_creationTime = 0;
protected int m_refType = 0;
protected String m_refLabel = "";
@JsonDeserialize(contentAs = Wakelock.class)
protected ArrayList<StatElement> m_refWakelocks = null;
@JsonDeserialize(contentAs = NativeKernelWakelock.class)
protected ArrayList<StatElement> m_refKernelWakelocks = null;
@JsonDeserialize(contentAs = NetworkUsage.class)
protected ArrayList<StatElement> m_refNetworkStats = null;
@JsonDeserialize(contentAs = Alarm.class)
protected ArrayList<StatElement> m_refAlarms = null;
@JsonDeserialize(contentAs = Process.class)
protected ArrayList<StatElement> m_refProcesses = null;
@JsonDeserialize(contentAs = Misc.class)
protected ArrayList<StatElement> m_refOther = null;
@JsonDeserialize(contentAs = State.class)
protected ArrayList<StatElement> m_refCpuStates = null;
@JsonDeserialize(contentAs = SensorUsage.class)
protected ArrayList<StatElement> m_refSensorUsage = null;
protected long m_refBatteryRealtime = 0;
protected int m_refBatteryLevel = 0;
protected int m_refBatteryVoltage = 0;
private Reference()
{
}
public Reference(ReferenceDto source)
{
if (source == null)
{
return;
}
this.m_creationTime = source.m_creationTime;
this.m_fileName = source.m_fileName;
this.m_refBatteryLevel = source.m_refBatteryLevel;
this.m_refBatteryRealtime = source.m_refBatteryRealtime;
this.m_refBatteryVoltage = source.m_refBatteryVoltage;
this.m_refLabel = source.m_refLabel;
this.m_refType = source.m_refType;
if (source.m_refAlarms != null)
{
this.m_refAlarms = new ArrayList<StatElement>();
for (int i=0; i < source.m_refAlarms.size(); i++)
{
this.m_refAlarms.add(new Alarm(source.m_refAlarms.get(i)));
}
}
if (source.m_refCpuStates != null)
{
this.m_refCpuStates = new ArrayList<StatElement>();
for (int i=0; i < source.m_refCpuStates.size(); i++)
{
this.m_refCpuStates.add(new State(source.m_refCpuStates.get(i)));
}
}
if (source.m_refKernelWakelocks != null)
{
this.m_refKernelWakelocks = new ArrayList<StatElement>();
for (int i=0; i < source.m_refKernelWakelocks.size(); i++)
{
this.m_refKernelWakelocks.add(new NativeKernelWakelock(source.m_refKernelWakelocks.get(i)));
}
}
if (source.m_refNetworkStats != null)
{
this.m_refNetworkStats = new ArrayList<StatElement>();
for (int i=0; i < source.m_refNetworkStats.size(); i++)
{
this.m_refNetworkStats.add(new NetworkUsage(source.m_refNetworkStats.get(i)));
}
}
if (source.m_refOther != null)
{
this.m_refOther = new ArrayList<StatElement>();
for (int i=0; i < source.m_refOther.size(); i++)
{
this.m_refOther.add(new Misc(source.m_refOther.get(i)));
}
}
if (source.m_refProcesses != null)
{
this.m_refProcesses = new ArrayList<StatElement>();
for (int i=0; i < source.m_refProcesses.size(); i++)
{
this.m_refProcesses.add(new Process(source.m_refProcesses.get(i)));
}
}
if (source.m_refWakelocks != null)
{
this.m_refWakelocks = new ArrayList<StatElement>();
for (int i=0; i < source.m_refWakelocks.size(); i++)
{
this.m_refWakelocks.add(new Wakelock(source.m_refWakelocks.get(i)));
}
}
if (source.m_refSensorUsage != null)
{
this.m_refSensorUsage = new ArrayList<StatElement>();
for (int i=0; i < source.m_refSensorUsage.size(); i++)
{
this.m_refSensorUsage.add(new SensorUsage(source.m_refSensorUsage.get(i)));
}
}
}
public Reference(String fileName, int type)
{
m_fileName = fileName;
m_creationTime = System.currentTimeMillis(); //SystemClock.elapsedRealtime();
m_refType = type;
m_refLabel = getLabel(fileName);
// + " " + DateUtils.format(m_creationTime);
if (LogSettings.DEBUG)
{
Log.i(TAG, "Create ref " + m_fileName + " at " + DateUtils.formatDuration(m_creationTime));
}
}
public ReferenceDto toReferenceDto()
{
ReferenceDto ret = new ReferenceDto();
ret.m_creationTime = this.m_creationTime;
ret.m_fileName = this.m_fileName;
ret.m_refBatteryLevel = this.m_refBatteryLevel;
ret.m_refBatteryRealtime = this.m_refBatteryRealtime;
ret.m_refBatteryVoltage = this.m_refBatteryVoltage;
ret.m_refLabel = this.m_refLabel;
ret.m_refType = this.m_refType;
if (this.m_refAlarms != null)
{
ret.m_refAlarms = new ArrayList<AlarmDto>();
for (int i=0; i < this.m_refAlarms.size(); i++)
{
ret.m_refAlarms.add(((Alarm) this.m_refAlarms.get(i)).toDto());
}
}
if (this.m_refCpuStates != null)
{
ret.m_refCpuStates = new ArrayList<StateDto>();
for (int i=0; i < this.m_refCpuStates.size(); i++)
{
ret.m_refCpuStates.add(((State) this.m_refCpuStates.get(i)).toDto());
}
}
if (this.m_refKernelWakelocks != null)
{
ret.m_refKernelWakelocks = new ArrayList<NativeKernelWakelockDto>();
for (int i=0; i < this.m_refKernelWakelocks.size(); i++)
{
ret.m_refKernelWakelocks.add(((NativeKernelWakelock) this.m_refKernelWakelocks.get(i)).toDto());
}
}
if (this.m_refNetworkStats != null)
{
ret.m_refNetworkStats = new ArrayList<NetworkUsageDto>();
for (int i=0; i < this.m_refNetworkStats.size(); i++)
{
ret.m_refNetworkStats.add(((NetworkUsage) this.m_refNetworkStats.get(i)).toDto());
}
}
if (this.m_refOther != null)
{
ret.m_refOther = new ArrayList<MiscDto>();
for (int i=0; i < this.m_refOther.size(); i++)
{
ret.m_refOther.add(((Misc) this.m_refOther.get(i)).toDto());
}
}
if (this.m_refProcesses != null)
{
ret.m_refProcesses = new ArrayList<ProcessDto>();
for (int i=0; i < this.m_refProcesses.size(); i++)
{
ret.m_refProcesses.add(((Process) this.m_refProcesses.get(i)).toDto());
}
}
if (this.m_refWakelocks != null)
{
ret.m_refWakelocks = new ArrayList<WakelockDto>();
for (int i=0; i < this.m_refWakelocks.size(); i++)
{
ret.m_refWakelocks.add(((Wakelock) this.m_refWakelocks.get(i)).toDto());
}
}
if (this.m_refSensorUsage != null)
{
ret.m_refSensorUsage = new ArrayList<SensorUsageDto>();
for (int i=0; i < this.m_refSensorUsage.size(); i++)
{
ret.m_refSensorUsage.add(((SensorUsage) this.m_refSensorUsage.get(i)).toDto());
}
}
return ret;
}
public void setEmpty()
{
m_creationTime = 0;
}
public void setTimestamp()
{
m_creationTime = SystemClock.elapsedRealtime();
}
public long getCreationTime()
{
return m_creationTime;
}
@JsonIgnore
public String getMissingRefError()
{
if (m_fileName.equals(CUSTOM_REF_FILENAME))
return CUSTOM_REF_ERR;
else if (m_fileName.equals(UNPLUGGED_REF_FILENAME))
return UNPLUGGED_REF_ERR;
else if (m_fileName.equals(CHARGED_REF_FILENAME))
return CHARGED_REF_ERR;
else if (m_fileName.equals(SCREEN_OFF_REF_FILENAME))
return SCREEN_OFF_REF_ERR;
else if (m_fileName.equals(SCREEN_ON_REF_FILENAME))
return SCREEN_ON_REF_ERR;
else if (m_fileName.equals(BOOT_REF_FILENAME))
return BOOT_REF_ERR;
else
return "No reference found";
}
public String whoAmI()
{
return "Reference " + m_fileName + " created " + DateUtils.formatDuration(m_creationTime) + " " + elements();
}
private String elements()
{
String wakelocks = (m_refWakelocks == null) ? "null" : m_refWakelocks.size() + " elements";
String kernelWakelocks = (m_refKernelWakelocks == null) ? "null" : m_refKernelWakelocks.size() + "elements";
String networkStats = (m_refNetworkStats == null) ? "null" : m_refNetworkStats.size() + " elements";
String alarms = (m_refAlarms == null) ? "null" : m_refAlarms.size() + " elements";
String processes = (m_refProcesses ==null) ? "null" : m_refProcesses.size() + " elements";
String other = (m_refOther == null) ? "null" : m_refOther.size() + " elements";
String cpuStates = (m_refCpuStates == null) ? "null" : m_refCpuStates.size() + " elements";
String sensorUsage = (m_refSensorUsage == null) ? "null" : m_refSensorUsage.size() + " elements";
wakelocks = "Wl: " + wakelocks;
kernelWakelocks = "KWl: " + kernelWakelocks;
networkStats = "NetS: " + networkStats;
alarms = "Alrm: " + alarms;
processes = "Proc: " + processes;
other = "Oth: " + other;
cpuStates = "CPU: " + cpuStates;
cpuStates = "Sensors: " + sensorUsage;
return "(" + wakelocks + "; " + kernelWakelocks + "; " + networkStats + "; " + alarms + "; "
+ processes + "; " + other + "; " + cpuStates + "; " + sensorUsage + ")";
}
@JsonIgnore
public static String getLabel(String refName)
{
String ret = "";
if (refName.equals(CUSTOM_REF_FILENAME))
ret = CUSTOM_REF_NAME;
else if (refName.equals(UNPLUGGED_REF_FILENAME))
ret = UNPLUGGED_REF_NAME;
else if (refName.equals(CHARGED_REF_FILENAME))
ret = CHARGED_REF_NAME;
else if (refName.equals(SCREEN_OFF_REF_FILENAME))
ret = SCREEN_OFF_REF_NAME;
else if (refName.equals(SCREEN_ON_REF_FILENAME))
ret = SCREEN_ON_REF_NAME;
else if (refName.equals(BOOT_REF_FILENAME))
ret = BOOT_REF_NAME;
else if (refName.equals(CURRENT_REF_FILENAME))
ret = CURRENT_REF_NAME;
else if (refName.startsWith(TIMER_REF_FILENAME))
ret = refName;
return ret;
}
@JsonIgnore
public String getLabel()
{
return Reference.getLabel(m_fileName);
}
}