Fix issues #16655104 and #16875776 in battery stats.

Issue #16655104: Android system used 21% of battery

We weren't clearing the current process state when we now retain
process objects across resets.

Issue #16875776: abnormal outliers in screen-off battery life in go/batterystats

The checkin data since charged was using the since unplugged data
for the amount of drain with the screen on/off.

Also added a new version tag in the checkin output containing
the platform build number and internal version format number, to
start moving away from the wasteful version code on every line.

And fixed a bug in figuring out when things have changed over
discharge levels.

Change-Id: I89b89513a748016aacc848f14bbbc8b2400d92ca
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index ba79f91..7d086e1 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -159,7 +159,7 @@
     private static final long BYTES_PER_MB = 1048576; // 1024^2
     private static final long BYTES_PER_GB = 1073741824; //1024^3
     
-
+    private static final String VERSION_DATA = "vers";
     private static final String UID_DATA = "uid";
     private static final String APK_DATA = "apk";
     private static final String PROCESS_DATA = "pr";
@@ -1463,6 +1463,21 @@
     public abstract long getStartClockTime();
 
     /**
+     * Return platform version tag that we were running in when the battery stats started.
+     */
+    public abstract String getStartPlatformVersion();
+
+    /**
+     * Return platform version tag that we were running in when the battery stats ended.
+     */
+    public abstract String getEndPlatformVersion();
+
+    /**
+     * Return the internal version code of the parcelled format.
+     */
+    public abstract int getParcelVersion();
+
+    /**
      * Return whether we are currently running on battery.
      */
     public abstract boolean getIsOnBattery();
@@ -2008,7 +2023,8 @@
         } else {
             dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
                     getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
-                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
+                    getDischargeAmountScreenOnSinceCharge(),
+                    getDischargeAmountScreenOffSinceCharge());
         }
         
         if (reqUid < 0) {
@@ -3876,6 +3892,9 @@
             if (didPid) {
                 pw.println();
             }
+        }
+
+        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             if (dumpDurationSteps(pw, "Discharge step durations:", getDischargeStepDurationsArray(),
                     getNumDischargeStepDurations(), false)) {
                 long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
@@ -3896,9 +3915,6 @@
                 }
                 pw.println();
             }
-        }
-
-        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             pw.println("Statistics since last charge:");
             pw.println("  System starts: " + getStartCount()
                     + ", currently on battery: " + getIsOnBattery());
@@ -3915,7 +3931,10 @@
     public void dumpCheckinLocked(Context context, PrintWriter pw,
             List<ApplicationInfo> apps, int flags, long histStart) {
         prepareForDumpLocked();
-        
+
+        dumpLine(pw, 0 /* uid */, "i" /* category */, VERSION_DATA,
+                "10", getParcelVersion(), getStartPlatformVersion(), getEndPlatformVersion());
+
         long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
 
         final boolean filtering =
@@ -3976,7 +3995,7 @@
                 }
             }
         }
-        if (!filtering) {
+        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             dumpDurationSteps(pw, DISCHARGE_STEP_DATA, getDischargeStepDurationsArray(),
                     getNumDischargeStepDurations(), true);
             String[] lineArgs = new String[1];
@@ -3994,8 +4013,6 @@
                 dumpLine(pw, 0 /* uid */, "i" /* category */, CHARGE_TIME_REMAIN_DATA,
                         (Object[])lineArgs);
             }
-        }
-        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1);
         }
         if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 50b86d0..ee0d14b 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -29,6 +29,7 @@
 import android.os.BadParcelableException;
 import android.os.BatteryManager;
 import android.os.BatteryStats;
+import android.os.Build;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.Looper;
@@ -91,7 +92,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 112 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 113 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -233,6 +234,8 @@
     int mStartCount;
 
     long mStartClockTime;
+    String mStartPlatformVersion;
+    String mEndPlatformVersion;
 
     long mUptime;
     long mUptimeStart;
@@ -341,7 +344,7 @@
     int mDischargeAmountScreenOff;
     int mDischargeAmountScreenOffSinceCharge;
 
-    static final int MAX_LEVEL_STEPS = 100;
+    static final int MAX_LEVEL_STEPS = 200;
 
     int mInitStepMode = 0;
     int mCurStepMode = 0;
@@ -2840,8 +2843,6 @@
                 }
             }
 
-            mInitStepMode = mCurStepMode;
-            mModStepMode = 0;
             if (state == Display.STATE_ON) {
                 // Screen turning on.
                 final long elapsedRealtime = SystemClock.elapsedRealtime();
@@ -3928,6 +3929,18 @@
         return mStartClockTime;
     }
 
+    @Override public String getStartPlatformVersion() {
+        return mStartPlatformVersion;
+    }
+
+    @Override public String getEndPlatformVersion() {
+        return mEndPlatformVersion;
+    }
+
+    @Override public int getParcelVersion() {
+        return VERSION;
+    }
+
     @Override public boolean getIsOnBattery() {
         return mOnBattery;
     }
@@ -4592,6 +4605,7 @@
                     proc.detach();
                     mProcessStats.removeAt(ip);
                 } else {
+                    proc.reset();
                     active = true;
                 }
             }
@@ -4848,7 +4862,7 @@
             mProcessStats.clear();
             for (int k = 0; k < numProcs; k++) {
                 String processName = in.readString();
-                Uid.Proc proc = new Proc();
+                Uid.Proc proc = new Proc(processName);
                 proc.readFromParcelLocked(in);
                 mProcessStats.put(processName, proc);
             }
@@ -5097,6 +5111,11 @@
          */
         public final class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
             /**
+             * The name of this process.
+             */
+            final String mName;
+
+            /**
              * Remains true until removed from the stats.
              */
             boolean mActive = true;
@@ -5190,7 +5209,8 @@
 
             ArrayList<ExcessivePower> mExcessivePower;
 
-            Proc() {
+            Proc(String name) {
+                mName = name;
                 mOnBatteryTimeBase.add(this);
                 mSpeedBins = new SamplingCounter[getCpuSpeedSteps()];
             }
@@ -5205,6 +5225,24 @@
             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
             }
 
+            void reset() {
+                mUserTime = mSystemTime = mForegroundTime = 0;
+                mStarts = 0;
+                mLoadedUserTime = mLoadedSystemTime = mLoadedForegroundTime = 0;
+                mLoadedStarts = 0;
+                mLastUserTime = mLastSystemTime = mLastForegroundTime = 0;
+                mLastStarts = 0;
+                mUnpluggedUserTime = mUnpluggedSystemTime = mUnpluggedForegroundTime = 0;
+                mUnpluggedStarts = 0;
+                for (int i = 0; i < mSpeedBins.length; i++) {
+                    SamplingCounter c = mSpeedBins[i];
+                    if (c != null) {
+                        c.reset(false);
+                    }
+                }
+                mExcessivePower = null;
+            }
+
             void detach() {
                 mActive = false;
                 mOnBatteryTimeBase.remove(this);
@@ -5793,7 +5831,7 @@
         public Proc getProcessStatsLocked(String name) {
             Proc ps = mProcessStats.get(name);
             if (ps == null) {
-                ps = new Proc();
+                ps = new Proc(name);
                 mProcessStats.put(name, ps);
             }
 
@@ -6147,6 +6185,7 @@
         long uptime = SystemClock.uptimeMillis() * 1000;
         long realtime = SystemClock.elapsedRealtime() * 1000;
         initTimes(uptime, realtime);
+        mStartPlatformVersion = mEndPlatformVersion = Build.ID;
         mDischargeStartLevel = 0;
         mDischargeUnplugLevel = 0;
         mDischargePlugLevel = -1;
@@ -7398,6 +7437,8 @@
             Slog.e("BatteryStats", "Error reading battery statistics", e);
         }
 
+        mEndPlatformVersion = Build.ID;
+
         if (mHistoryBuffer.dataPosition() > 0) {
             mRecordingHistory = true;
             final long elapsedRealtime = SystemClock.elapsedRealtime();
@@ -7554,6 +7595,8 @@
         mUptime = in.readLong();
         mRealtime = in.readLong();
         mStartClockTime = in.readLong();
+        mStartPlatformVersion = in.readString();
+        mEndPlatformVersion = in.readString();
         mOnBatteryTimeBase.readSummaryFromParcel(in);
         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
         mDischargeUnplugLevel = in.readInt();
@@ -7847,6 +7890,8 @@
         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
         out.writeLong(mStartClockTime);
+        out.writeString(mStartPlatformVersion);
+        out.writeString(mEndPlatformVersion);
         mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
         out.writeInt(mDischargeUnplugLevel);
@@ -8134,6 +8179,8 @@
 
         mStartCount = in.readInt();
         mStartClockTime = in.readLong();
+        mStartPlatformVersion = in.readString();
+        mEndPlatformVersion = in.readString();
         mUptime = in.readLong();
         mUptimeStart = in.readLong();
         mRealtime = in.readLong();
@@ -8289,6 +8336,8 @@
 
         out.writeInt(mStartCount);
         out.writeLong(mStartClockTime);
+        out.writeString(mStartPlatformVersion);
+        out.writeString(mEndPlatformVersion);
         out.writeLong(mUptime);
         out.writeLong(mUptimeStart);
         out.writeLong(mRealtime);