Fix problems with determining when to kill apps for wake usage.

Also improve debug printing of various times.

Change-Id: Ifcc288fd1bcbf44c069875ba97925b9e7ffe9a48
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index a0a3bdf..95f217f 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -23,6 +23,7 @@
 import android.util.Log;
 import android.util.Printer;
 import android.util.SparseArray;
+import android.util.TimeUtils;
 
 /**
  * A class providing access to battery usage statistics, including information on
@@ -1576,8 +1577,10 @@
                             Uid.Proc.ExcessiveWake ew = ps.getExcessiveWake(e);
                             if (ew != null) {
                                 pw.print(prefix); pw.print("      * Killed for wake lock use: ");
-                                        pw.print(ew.usedTime); pw.print("ms over ");
-                                        pw.print(ew.overTime); pw.print("ms (");
+                                        TimeUtils.formatDuration(ew.usedTime, pw);
+                                        pw.print(" over ");
+                                        TimeUtils.formatDuration(ew.overTime, pw);
+                                        pw.print(" (");
                                         pw.print((ew.usedTime*100)/ew.overTime);
                                         pw.println("%)");
                             }
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index a9d7342..d360140 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -192,10 +192,11 @@
         pw.println(prefix + "mQueue=" + ((mQueue != null) ? mQueue : "(null"));
         if (mQueue != null) {
             synchronized (mQueue) {
+                long now = SystemClock.uptimeMillis();
                 Message msg = mQueue.mMessages;
                 int n = 0;
                 while (msg != null) {
-                    pw.println(prefix + "  Message " + n + ": " + msg);
+                    pw.println(prefix + "  Message " + n + ": " + msg.toString(now));
                     n++;
                     msg = msg.next;
                 }
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 476da1d..49b72fe 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -19,6 +19,7 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.TimeUtils;
 
 /**
  * 
@@ -366,13 +367,17 @@
     }
 
     public String toString() {
+        return toString(SystemClock.uptimeMillis());
+    }
+
+    String toString(long now) {
         StringBuilder   b = new StringBuilder();
         
         b.append("{ what=");
         b.append(what);
 
         b.append(" when=");
-        b.append(when);
+        TimeUtils.formatDuration(when-now, b);
 
         if (arg1 != 0) {
             b.append(" arg1=");
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 0fc70d5..b01a71d 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -24,6 +24,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.io.PrintWriter;
 import java.util.TimeZone;
 import java.util.Date;
 
@@ -130,4 +131,128 @@
     public static String getTimeZoneDatabaseVersion() {
         return ZoneInfoDB.getVersion();
     }
+
+    private static final int SECONDS_PER_MINUTE = 60;
+    private static final int SECONDS_PER_HOUR = 60 * 60;
+    private static final int SECONDS_PER_DAY = 24 * 60 * 60;
+
+    /** @hide Just for debugging; not internationalized. */
+    public static void formatDuration(long duration, StringBuilder builder) {
+        if (duration == 0) {
+            builder.append("0");
+            return;
+        }
+        if (duration > 0) {
+            builder.append("+");
+        } else {
+            builder.append("-");
+            duration = -duration;
+        }
+
+        int millis = (int)(duration%1000);
+        int seconds = (int) Math.floor(duration / 1000);
+        int days = 0, hours = 0, minutes = 0;
+
+        if (seconds > SECONDS_PER_DAY) {
+            days = seconds / SECONDS_PER_DAY;
+            seconds -= days * SECONDS_PER_DAY;
+        }
+        if (seconds > SECONDS_PER_HOUR) {
+            hours = seconds / SECONDS_PER_HOUR;
+            seconds -= hours * SECONDS_PER_HOUR;
+        }
+        if (seconds > SECONDS_PER_MINUTE) {
+            minutes = seconds / SECONDS_PER_MINUTE;
+            seconds -= minutes * SECONDS_PER_MINUTE;
+        }
+
+        boolean doall = false;
+        if (days > 0) {
+            builder.append(days);
+            builder.append('d');
+            doall = true;
+        }
+        if (doall || hours > 0) {
+            builder.append(hours);
+            builder.append('h');
+            doall = true;
+        }
+        if (doall || minutes > 0) {
+            builder.append(minutes);
+            builder.append('m');
+            doall = true;
+        }
+        if (doall || seconds > 0) {
+            builder.append(seconds);
+            builder.append('s');
+            doall = true;
+        }
+        builder.append(millis);
+        builder.append("ms");
+    }
+
+    /** @hide Just for debugging; not internationalized. */
+    public static void formatDuration(long duration, PrintWriter pw) {
+        if (duration == 0) {
+            pw.print("0");
+            return;
+        }
+        if (duration > 0) {
+            pw.print("+");
+        } else {
+            pw.print("-");
+            duration = -duration;
+        }
+
+        int millis = (int)(duration%1000);
+        int seconds = (int) Math.floor(duration / 1000);
+        int days = 0, hours = 0, minutes = 0;
+
+        if (seconds > SECONDS_PER_DAY) {
+            days = seconds / SECONDS_PER_DAY;
+            seconds -= days * SECONDS_PER_DAY;
+        }
+        if (seconds > SECONDS_PER_HOUR) {
+            hours = seconds / SECONDS_PER_HOUR;
+            seconds -= hours * SECONDS_PER_HOUR;
+        }
+        if (seconds > SECONDS_PER_MINUTE) {
+            minutes = seconds / SECONDS_PER_MINUTE;
+            seconds -= minutes * SECONDS_PER_MINUTE;
+        }
+
+        boolean doall = false;
+        if (days > 0) {
+            pw.print(days);
+            pw.print('d');
+            doall = true;
+        }
+        if (doall || hours > 0) {
+            pw.print(hours);
+            pw.print('h');
+            doall = true;
+        }
+        if (doall || minutes > 0) {
+            pw.print(minutes);
+            pw.print('m');
+            doall = true;
+        }
+        if (doall || seconds > 0) {
+            pw.print(seconds);
+            pw.print('s');
+            doall = true;
+        }
+        pw.print(millis);
+        pw.print("ms");
+    }
+
+
+    /** @hide Just for debugging; not internationalized. */
+    public static void formatDuration(long time, long now, PrintWriter pw) {
+        if (time == 0) {
+            pw.print("--");
+            return;
+        }
+        formatDuration(time-now, pw);
+    }
 }
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index ce5959d..e1c5564 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -18,17 +18,31 @@
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.view.MotionEvent;
 import android.widget.ImageView;
+import android.widget.Toast;
 
 public class PlatLogoActivity extends Activity {
+    Toast mToast;
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         
+        mToast = Toast.makeText(this, "Zombie art by Jack Larson", Toast.LENGTH_SHORT);
+
         ImageView content = new ImageView(this);
         content.setImageResource(com.android.internal.R.drawable.platlogo);
         content.setScaleType(ImageView.ScaleType.FIT_CENTER);
         
         setContentView(content);
     }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_UP) {
+            mToast.show();
+        }
+        return super.dispatchTouchEvent(ev);
+    }
 }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 2f26135..2a5b944 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -27,7 +27,6 @@
 import android.os.Parcelable;
 import android.os.Process;
 import android.os.SystemClock;
-import android.os.BatteryStats.Uid.Proc.ExcessiveWake;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
@@ -1241,25 +1240,31 @@
     int mWakeLockNesting;
 
     public void noteStartWakeLocked(int uid, int pid, String name, int type) {
-        if (mWakeLockNesting == 0) {
-            mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
-            if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
-                    + Integer.toHexString(mHistoryCur.states));
-            addHistoryRecordLocked(SystemClock.elapsedRealtime());
+        if (type == WAKE_TYPE_PARTIAL) {
+            // Only care about partial wake locks, since full wake locks
+            // will be canceled when the user puts the screen to sleep.
+            if (mWakeLockNesting == 0) {
+                mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
+                if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
+                        + Integer.toHexString(mHistoryCur.states));
+                addHistoryRecordLocked(SystemClock.elapsedRealtime());
+            }
+            mWakeLockNesting++;
         }
-        mWakeLockNesting++;
         if (uid >= 0) {
             getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type);
         }
     }
 
     public void noteStopWakeLocked(int uid, int pid, String name, int type) {
-        mWakeLockNesting--;
-        if (mWakeLockNesting == 0) {
-            mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
-            if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
-                    + Integer.toHexString(mHistoryCur.states));
-            addHistoryRecordLocked(SystemClock.elapsedRealtime());
+        if (type == WAKE_TYPE_PARTIAL) {
+            mWakeLockNesting--;
+            if (mWakeLockNesting == 0) {
+                mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
+                if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
+                        + Integer.toHexString(mHistoryCur.states));
+                addHistoryRecordLocked(SystemClock.elapsedRealtime());
+            }
         }
         if (uid >= 0) {
             getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type);
@@ -1353,7 +1358,7 @@
 
             // Fake a wake lock, so we consider the device waked as long
             // as the screen is on.
-            noteStartWakeLocked(-1, -1, "dummy", 0);
+            noteStartWakeLocked(-1, -1, "dummy", WAKE_TYPE_PARTIAL);
         }
     }
     
@@ -1369,7 +1374,7 @@
                 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this);
             }
 
-            noteStopWakeLocked(-1, -1, "dummy", 0);
+            noteStopWakeLocked(-1, -1, "dummy", WAKE_TYPE_PARTIAL);
         }
     }
     
@@ -3463,7 +3468,7 @@
             if (t != null) {
                 t.startRunningLocked(BatteryStatsImpl.this);
             }
-            if (pid >= 0) {
+            if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
                 Pid p = getPidStatsLocked(pid);
                 p.mWakeStart = SystemClock.elapsedRealtime();
             }
@@ -3474,7 +3479,7 @@
             if (t != null) {
                 t.stopRunningLocked(BatteryStatsImpl.this);
             }
-            if (pid >= 0) {
+            if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
                 Pid p = mPids.get(pid);
                 if (p != null) {
                     p.mWakeSum += SystemClock.elapsedRealtime() - p.mWakeStart;