Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b6391d63 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 3857 into donut

* changes:
  Allow arrays of values for power profile data.
parents b3c5a878 3718aaab
Loading
Loading
Loading
Loading
+126 −9
Original line number Diff line number Diff line
@@ -30,9 +30,11 @@ import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.SparseArray;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -53,7 +55,7 @@ public final class BatteryStatsImpl extends BatteryStats {
    private static final int MAGIC = 0xBA757475; // 'BATSTATS' 

    // Current on-disk Parcel version
    private static final int VERSION = 38;
    private static final int VERSION = 39;

    private final File mFile;
    private final File mBackupFile;
@@ -149,6 +151,15 @@ public final class BatteryStatsImpl extends BatteryStats {

    long mLastWriteTime = 0; // Milliseconds

    // Mobile data transferred while on battery
    private long[] mMobileDataTx = new long[4];
    private long[] mMobileDataRx = new long[4];
    private long[] mTotalDataTx = new long[4];
    private long[] mTotalDataRx = new long[4];

    private long mRadioDataUptime;
    private long mRadioDataStart;

    /*
     * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
     */
@@ -894,6 +905,39 @@ public final class BatteryStatsImpl extends BatteryStats {
        return kwlt;
    }

    private void doDataPlug(long[] dataTransfer, long currentBytes) {
        dataTransfer[STATS_LAST] = dataTransfer[STATS_UNPLUGGED];
        dataTransfer[STATS_UNPLUGGED] = -1;
    }

    private void doDataUnplug(long[] dataTransfer, long currentBytes) {
        dataTransfer[STATS_UNPLUGGED] = currentBytes;
    }

    private long getCurrentRadioDataUptimeMs() {
        try {
            File awakeTimeFile = new File("/sys/devices/virtual/net/rmnet0/awake_time_ms");
            if (!awakeTimeFile.exists()) return 0;
            BufferedReader br = new BufferedReader(new FileReader(awakeTimeFile));
            String line = br.readLine();
            br.close();
            return Long.parseLong(line);
        } catch (NumberFormatException nfe) {
            // Nothing
        } catch (IOException ioe) {
            // Nothing
        }
        return 0;
    }

    public long getRadioDataUptimeMs() {
        if (mRadioDataStart == -1) {
            return mRadioDataUptime;
        } else {
            return getCurrentRadioDataUptimeMs() - mRadioDataStart;
        }
    }

    public void doUnplug(long batteryUptime, long batteryRealtime) {
        for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
            Uid u = mUidStats.valueAt(iu);
@@ -905,6 +949,14 @@ public final class BatteryStatsImpl extends BatteryStats {
        for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
            mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime);
        }
        // Track total mobile data
        doDataUnplug(mMobileDataRx, NetStat.getMobileRxBytes());
        doDataUnplug(mMobileDataTx, NetStat.getMobileTxBytes());
        doDataUnplug(mTotalDataRx, NetStat.getTotalRxBytes());
        doDataUnplug(mTotalDataTx, NetStat.getTotalTxBytes());
        // Track radio awake time
        mRadioDataStart = getCurrentRadioDataUptimeMs();
        mRadioDataUptime = 0;
    }

    public void doPlug(long batteryUptime, long batteryRealtime) {
@@ -922,6 +974,13 @@ public final class BatteryStatsImpl extends BatteryStats {
        for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
            mUnpluggables.get(i).plug(batteryUptime, batteryRealtime);
        }
        doDataPlug(mMobileDataRx, NetStat.getMobileRxBytes());
        doDataPlug(mMobileDataTx, NetStat.getMobileTxBytes());
        doDataPlug(mTotalDataRx, NetStat.getTotalRxBytes());
        doDataPlug(mTotalDataTx, NetStat.getTotalTxBytes());
        // Track radio awake time
        mRadioDataUptime = getRadioDataUptimeMs();
        mRadioDataStart = -1;
    }

    public void noteStartGps(int uid) {
@@ -1039,6 +1098,7 @@ public final class BatteryStatsImpl extends BatteryStats {
                    break;
            }
        }
        if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
        if (mPhoneDataConnectionType != bin) {
            if (mPhoneDataConnectionType >= 0) {
                mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this);
@@ -2702,6 +2762,43 @@ public final class BatteryStatsImpl extends BatteryStats {
        return getBatteryRealtimeLocked(curTime);
    }

    private long getTcpBytes(long current, long[] dataBytes, int which) {
        if (which == STATS_LAST) {
            return dataBytes[STATS_LAST];
        } else {
            if (which == STATS_UNPLUGGED) {
                if (dataBytes[STATS_UNPLUGGED] < 0) {
                    return dataBytes[STATS_LAST];
                } else {
                    return current - dataBytes[STATS_UNPLUGGED];
                }
            } else if (which == STATS_TOTAL) {
                return (current - dataBytes[STATS_CURRENT]) + dataBytes[STATS_TOTAL];
            }
            return current - dataBytes[STATS_CURRENT];
        }
    }

    /** Only STATS_UNPLUGGED works properly */
    public long getMobileTcpBytesSent(int which) {
        return getTcpBytes(NetStat.getMobileTxBytes(), mMobileDataTx, which);
    }

    /** Only STATS_UNPLUGGED works properly */
    public long getMobileTcpBytesReceived(int which) {
        return getTcpBytes(NetStat.getMobileRxBytes(), mMobileDataRx, which);
    }

    /** Only STATS_UNPLUGGED works properly */
    public long getTotalTcpBytesSent(int which) {
        return getTcpBytes(NetStat.getTotalTxBytes(), mTotalDataTx, which);
    }

    /** Only STATS_UNPLUGGED works properly */
    public long getTotalTcpBytesReceived(int which) {
        return getTcpBytes(NetStat.getTotalRxBytes(), mTotalDataRx, which);
    }

    @Override
    public int getDischargeStartLevel() {
        synchronized(this) {
@@ -3227,6 +3324,18 @@ public final class BatteryStatsImpl extends BatteryStats {
        mDischargeCurrentLevel = in.readInt();
        mLastWriteTime = in.readLong();

        mMobileDataRx[STATS_LAST] = in.readLong();
        mMobileDataRx[STATS_UNPLUGGED] = -1;
        mMobileDataTx[STATS_LAST] = in.readLong();
        mMobileDataTx[STATS_UNPLUGGED] = -1;
        mTotalDataRx[STATS_LAST] = in.readLong();
        mTotalDataRx[STATS_UNPLUGGED] = -1;
        mTotalDataTx[STATS_LAST] = in.readLong();
        mTotalDataTx[STATS_UNPLUGGED] = -1;

        mRadioDataUptime = in.readLong();
        mRadioDataStart = -1;

        mKernelWakelockStats.clear();
        int NKW = in.readInt();
        for (int ikw = 0; ikw < NKW; ikw++) {
@@ -3301,6 +3410,14 @@ public final class BatteryStatsImpl extends BatteryStats {
        out.writeInt(mDischargeCurrentLevel);
        out.writeLong(mLastWriteTime);

        out.writeLong(getMobileTcpBytesReceived(STATS_UNPLUGGED));
        out.writeLong(getMobileTcpBytesSent(STATS_UNPLUGGED));
        out.writeLong(getTotalTcpBytesReceived(STATS_UNPLUGGED));
        out.writeLong(getTotalTcpBytesSent(STATS_UNPLUGGED));

        // Write radio uptime for data
        out.writeLong(getRadioDataUptimeMs());

        out.writeInt(mKernelWakelockStats.size());
        for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
            SamplingTimer kwlt = ent.getValue();
+74 −21
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

/**
@@ -118,26 +119,28 @@ public class PowerProfile {
     */
    public static final String POWER_VIDEO = "dsp.video";

    static final HashMap<String, Double> sPowerMap = new HashMap<String, Double>();
    static final HashMap<String, Object> sPowerMap = new HashMap<String, Object>();

    private static final String TAG_DEVICE = "device";
    private static final String TAG_ITEM = "item";
    private static final String TAG_ARRAY = "array";
    private static final String TAG_ARRAYITEM = "value";
    private static final String ATTR_NAME = "name";

    public PowerProfile(Context context, CharSequence profile) {
    public PowerProfile(Context context) {
        // Read the XML file for the given profile (normally only one per
        // device)
        if (sPowerMap.size() == 0) {
            readPowerValuesFromXml(context, profile);
            readPowerValuesFromXml(context);
        }
    }

    private void readPowerValuesFromXml(Context context, CharSequence profile) {
        // FIXME
        //int id = context.getResources().getIdentifier(profile.toString(), "xml", 
        //        "com.android.internal");
        int id = com.android.internal.R.xml.power_profile_default;
    private void readPowerValuesFromXml(Context context) {
        int id = com.android.internal.R.xml.power_profile;
        XmlResourceParser parser = context.getResources().getXml(id);
        boolean parsingArray = false;
        ArrayList<Double> array = new ArrayList<Double>();
        String arrayName = null;

        try {
            XmlUtils.beginDocument(parser, TAG_DEVICE);
@@ -146,11 +149,20 @@ public class PowerProfile {
                XmlUtils.nextElement(parser);

                String element = parser.getName();
                if (element == null || !(element.equals(TAG_ITEM))) {
                    break;
                }
                if (element == null) break;
                
                String name = parser.getAttributeValue(null, ATTR_NAME);
                if (parsingArray && !element.equals(TAG_ARRAYITEM)) {
                    // Finish array
                    sPowerMap.put(arrayName, array.toArray(new Double[array.size()]));
                    parsingArray = false;
                }
                if (element.equals(TAG_ARRAY)) {
                    parsingArray = true;
                    array.clear();
                    arrayName = parser.getAttributeValue(null, ATTR_NAME);
                } else if (element.equals(TAG_ITEM) || element.equals(TAG_ARRAYITEM)) {
                    String name = null;
                    if (!parsingArray) name = parser.getAttributeValue(null, ATTR_NAME);
                    if (parser.next() == XmlPullParser.TEXT) {
                        String power = parser.getText();
                        double value = 0;
@@ -158,9 +170,17 @@ public class PowerProfile {
                            value = Double.valueOf(power);
                        } catch (NumberFormatException nfe) {
                        }
                        if (element.equals(TAG_ITEM)) {
                            sPowerMap.put(name, value);
                        } else if (parsingArray) {
                            array.add(value);
                        }
                    }
                }
            }
            if (parsingArray) {
                sPowerMap.put(arrayName, array.toArray(new Double[array.size()]));
            }
        } catch (XmlPullParserException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
@@ -177,7 +197,40 @@ public class PowerProfile {
     */
    public double getAveragePower(String type) {
        if (sPowerMap.containsKey(type)) {
            return sPowerMap.get(type);
            Object data = sPowerMap.get(type);
            if (data instanceof Double[]) {
                return ((Double[])data)[0];
            } else {
                return (Double) sPowerMap.get(type);
            }
        } else {
            return 0;
        }
    }
    
    /**
     * Returns the average current in mA consumed by the subsystem for the given level. 
     * @param type the subsystem type
     * @param level the level of power at which the subsystem is running. For instance, the
     *  signal strength of the cell network between 0 and 4 (if there are 4 bars max.).
     *  If there is no data for multiple levels, the level is ignored.
     * @return the average current in milliAmps.
     */
    public double getAveragePower(String type, int level) {
        if (sPowerMap.containsKey(type)) {
            Object data = sPowerMap.get(type);
            if (data instanceof double[]) {
                final double[] values = (double[]) data;
                if (values.length > level) {
                    return values[level];
                } else if (values.length < 0) {
                    return values[0];
                } else {
                    return values[values.length - 1];
                }
            } else {
                return (Double) data;
            }
        } else {
            return 0;
        }
+18 −15
Original line number Diff line number Diff line
@@ -19,19 +19,22 @@

<device name="Android">
  <item name="none">0</item>
  <item name="screen.on">30</item>
  <item name="bluetooth.active">103</item>
  <item name="bluetooth.on">5</item>
  <item name="screen.full">114</item>
  <item name="wifi.on">23</item>
  <item name="wifi.active">200</item>
  <item name="wifi.scan">200</item>
  <item name="cpu.idle">1.6</item>
  <item name="cpu.normal">100</item>
  <item name="cpu.full">140</item>
  <item name="dsp.audio">70</item>
  <item name="dsp.video">100</item>
  <item name="radio.on">3</item>
  <item name="radio.active">175</item>
  <item name="gps.on">120</item>
  <item name="screen.on">0.1</item>
  <item name="bluetooth.active">0.1</item>
  <item name="bluetooth.on">0.1</item>
  <item name="screen.full">0.1</item>
  <item name="wifi.on">0.1</item>
  <item name="wifi.active">0.1</item>
  <item name="wifi.scan">0.1</item>
  <item name="cpu.idle">0.1</item>
  <item name="cpu.normal">0.2</item>
  <item name="cpu.full">1</item>
  <item name="dsp.audio">0.1</item>
  <item name="dsp.video">0.1</item>
  <item name="radio.active">1</item>
  <item name="gps.on">1</item>
  <array name="radio.on"> <!-- Strength 0 to BINS-1 -->
      <value>1</value>
      <value>0.1</value>
  </array>
</device>