/*
* Copyright (C) 2011 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.android.common.privateapiproxies;
import java.io.Serializable;
import java.util.Comparator;
import java.util.List;
import com.asksven.android.common.nameutils.UidInfo;
import com.asksven.android.common.nameutils.UidNameResolver;
import com.asksven.android.common.utils.StringUtils;
import com.google.gson.annotations.SerializedName;
//import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.util.Log;
/**
* @author sven
*
*/
public class PackageElement extends StatElement implements Comparable<PackageElement>, Serializable
{
/**
* the tag for logging
*/
private static transient final String TAG = "Package";
/**
* the package name of the wakelock holder
*/
@SerializedName("package_name")
private String m_packageName;
/**
* the name of the wakelock holder
*/
@SerializedName("name")
private String m_name;
/**
* the duration in ms
*/
@SerializedName("duration_ms")
private long m_duration;
/**
* the count
*/
@SerializedName("count")
private int m_count;
/**
* the number of wakeups
*/
@SerializedName("wakeups")
private long m_wakeups;
/**
* the total data transfer
*/
@SerializedName("rxtx")
private long m_rxtx;
/**
* Creates a package instance
* @param name the speaking name
* @param duration the duration the wakelock was held
* @param time the battery realtime
* @param count the number of time the wakelock was active
*/
public PackageElement(String packageName, String name, int uid, long duration, long time, int count, long wakeups, long rxtx)
{
m_packageName = packageName;
m_name = name;
m_duration = duration;
setTotal(time);
m_count = count;
m_wakeups = wakeups;
m_rxtx = rxtx;
super.setUid(uid);
}
public PackageElement clone()
{
PackageElement clone = new PackageElement(m_packageName, m_name, getuid(), m_duration, getTotal(), m_count, m_wakeups, m_rxtx);
// Overwrite name to avoid multiple hashes
clone.m_name = m_name;
clone.m_icon = m_icon;
clone.m_uidInfo = m_uidInfo;
clone.setUid(getuid());
return clone;
}
/**
* Substracts the values from a previous object
* found in myList from the current Process
* in order to obtain an object containing only the data since a referenc
* @param myList
*/
public void substractFromRef(List<StatElement> myList )
{
if (myList != null)
{
for (int i = 0; i < myList.size(); i++)
{
try
{
PackageElement myRef = (PackageElement) myList.get(i);
if ( (this.getName().equals(myRef.getName())) && (this.getuid() == myRef.getuid()) )
{
Log.i(TAG, "Substraction " + myRef.toString() + " from " + this.toString());
this.m_duration -= myRef.getDuration();
this.setTotal( getTotal() - myRef.getTotal());
this.m_count -= myRef.getCount();
this.m_wakeups -= myRef.m_wakeups;
this.m_rxtx -= myRef.m_rxtx;
Log.i(TAG, "Result: " + this.toString());
if ((m_count < 0) || (m_duration < 0) || (getTotal() < 0))
{
Log.e(TAG, "substractFromRef generated negative values (" + this.toString() + " - " + myRef.toString() + ")");
}
break;
}
}
catch (ClassCastException e)
{
// just log as it is no error not to change the process
// being substracted from to do nothing
Log.e(TAG, "substractFromRef was called with a wrong list type");
}
}
}
}
public void add(StatElement element)
{
if (element instanceof Wakelock)
{
m_duration += ((Wakelock) element).getDuration();
m_count += ((Wakelock) element).getCount();
}
else if (element instanceof Alarm)
{
m_wakeups += ((Alarm) element).getWakeups();
}
else if (element instanceof NetworkUsage)
{
m_rxtx += ((NetworkUsage) element).getTotalBytes();
}
else
{
Log.d(TAG, "element "+ element.toString() + " was not added.");
}
}
/**
* @return the name
*/
public String getName() {
return m_name;
}
/**
* @return the duration
*/
public long getDuration() {
return m_duration;
}
/**
* @return the number of wakeups
*/
public long getWakeups() {
return m_wakeups;
}
/**
* @return the data volume
*/
public long getDataVolume() {
return m_rxtx;
}
/**
* @return the count
*/
public int getCount() {
return m_count;
}
/**
* Compare a given Wakelock with this object.
* If the duration of this object is
* greater than the received object,
* then this object is greater than the other.
*/
public int compareTo(PackageElement o)
{
// we want to sort in descending order
return ((int)(o.getDuration() - this.getDuration()));
}
/**
* returns a string representation of the data
*/
public String getData(long totalTime)
{
return this.formatDuration(getDuration())
+ " Wakeups:" + m_wakeups
+ " Data:" + formatVolume(m_rxtx)
+ " " + this.formatRatio(getDuration(), totalTime);
}
/**
* Formats data volumes
* @param bytes
* @return the formated string
*/
public static String formatVolume(double bytes)
{
String ret = "";
double kB = Math.floor(bytes / 1024);
double mB = Math.floor(bytes / 1024 / 1024);
double gB = Math.floor(bytes / 1024 / 1024 / 1024);
double tB = Math.floor(bytes / 1024 / 1024 / 1024 / 1024);
if (tB > 0)
{
ret = tB + " TBytes";
}
else if ( gB > 0)
{
ret = gB + " GBytes";
}
else if ( mB > 0)
{
ret = mB + " MBytes";
}
else if ( kB > 0)
{
ret = kB + " KBytes";
}
else
{
ret = bytes + " Bytes";
}
return ret;
}
/**
* returns the values of the data
*/
public double[] getValues()
{
double[] retVal = new double[2];
retVal[0] = getDuration();
return retVal;
}
public static class WakelockCountComparator implements Comparator<PackageElement>
{
public int compare(PackageElement a, PackageElement b)
{
return ((int)(b.getCount() - a.getCount()));
}
}
public static class WakelockTimeComparator implements Comparator<PackageElement>
{
public int compare(PackageElement a, PackageElement b)
{
return ((int)(b.getDuration() - a.getDuration()));
}
}
public Drawable getIcon(UidNameResolver resolver)
{
if (m_icon == null)
{
// retrieve and store the icon for that package
String myPackage = m_packageName;
m_icon = resolver.getIcon(m_packageName);
}
return m_icon;
}
public String getPackageName()
{
if (m_uidInfo != null)
{
return m_uidInfo.getNamePackage();
}
else
{
return "";
}
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
return "PackageElement [m_name=" + m_name + ", m_packageName=" + m_packageName + ", m_uid=" + getuid() + ", m_duration=" + m_duration
+ ", m_count=" + m_count + ", m_rxtx=" + m_rxtx + ", m_wakeups=" + m_wakeups +"]";
}
}