Merge "Import translations. DO NOT MERGE"
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 62ed697..d65a6a2 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -21,6 +21,7 @@
 import com.android.internal.app.IUsageStats;
 import com.android.internal.os.PkgUsageStats;
 import com.android.internal.os.TransferPipe;
+import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.MemInfoReader;
 
 import android.content.ComponentName;
@@ -2206,12 +2207,14 @@
      */
     public static void dumpPackageStateStatic(FileDescriptor fd, String packageName) {
         FileOutputStream fout = new FileOutputStream(fd);
-        PrintWriter pw = new PrintWriter(fout);
-        dumpService(pw, fd, Context.ACTIVITY_SERVICE, new String[] { "package", packageName});
+        PrintWriter pw = new FastPrintWriter(fout);
+        dumpService(pw, fd, Context.ACTIVITY_SERVICE, new String[] { "package", packageName });
         pw.println();
-        dumpService(pw, fd, "package", new String[] { packageName});
+        dumpService(pw, fd, "procstats", new String[] { packageName });
         pw.println();
-        dumpService(pw, fd, BatteryStats.SERVICE_NAME, new String[] { packageName});
+        dumpService(pw, fd, "package", new String[] { packageName });
+        pw.println();
+        dumpService(pw, fd, BatteryStats.SERVICE_NAME, new String[] { packageName });
         pw.flush();
     }
 
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 066775d..bf89fa6 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -93,6 +93,7 @@
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.RuntimeInit;
 import com.android.internal.os.SamplingProfilerIntegration;
+import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.Objects;
 import com.android.org.conscrypt.OpenSSLSocketImpl;
 
@@ -899,7 +900,7 @@
         public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, boolean checkin,
                 boolean dumpInfo, boolean dumpDalvik, String[] args) {
             FileOutputStream fout = new FileOutputStream(fd);
-            PrintWriter pw = new PrintWriter(fout);
+            PrintWriter pw = new FastPrintWriter(fout);
             try {
                 return dumpMemInfo(pw, checkin, dumpInfo, dumpDalvik);
             } finally {
@@ -1176,7 +1177,7 @@
 
         @Override
         public void dumpDbInfo(FileDescriptor fd, String[] args) {
-            PrintWriter pw = new PrintWriter(new FileOutputStream(fd));
+            PrintWriter pw = new FastPrintWriter(new FileOutputStream(fd));
             PrintWriterPrinter printer = new PrintWriterPrinter(pw);
             SQLiteDebug.dump(printer, args);
             pw.flush();
@@ -2730,7 +2731,8 @@
         try {
             Service s = mServices.get(info.token);
             if (s != null) {
-                PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
+                PrintWriter pw = new FastPrintWriter(new FileOutputStream(
+                        info.fd.getFileDescriptor()));
                 s.dump(info.fd.getFileDescriptor(), pw, info.args);
                 pw.flush();
             }
@@ -2745,7 +2747,8 @@
         try {
             ActivityClientRecord r = mActivities.get(info.token);
             if (r != null && r.activity != null) {
-                PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
+                PrintWriter pw = new FastPrintWriter(new FileOutputStream(
+                        info.fd.getFileDescriptor()));
                 r.activity.dump(info.prefix, info.fd.getFileDescriptor(), pw, info.args);
                 pw.flush();
             }
@@ -2760,7 +2763,8 @@
         try {
             ProviderClientRecord r = mLocalProviders.get(info.token);
             if (r != null && r.mLocalProvider != null) {
-                PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
+                PrintWriter pw = new FastPrintWriter(new FileOutputStream(
+                        info.fd.getFileDescriptor()));
                 r.mLocalProvider.dump(info.fd.getFileDescriptor(), pw, info.args);
                 pw.flush();
             }
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 954476d..c117486 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -28,6 +28,7 @@
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.util.Printer;
+import com.android.internal.util.FastPrintWriter;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -327,7 +328,9 @@
          */
         public CrashInfo(Throwable tr) {
             StringWriter sw = new StringWriter();
-            tr.printStackTrace(new PrintWriter(sw));
+            PrintWriter pw = new FastPrintWriter(sw, false, 256);
+            tr.printStackTrace(pw);
+            pw.flush();
             stackTrace = sw.toString();
             exceptionMessage = tr.getMessage();
 
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 1b1d341..89ee145 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -21,6 +21,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.LogWriter;
+import com.android.internal.util.FastPrintWriter;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -583,8 +584,9 @@
         if (FragmentManagerImpl.DEBUG) {
             Log.v(TAG, "Commit: " + this);
             LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
-            PrintWriter pw = new PrintWriter(logw);
+            PrintWriter pw = new FastPrintWriter(logw, false, 1024);
             dump("  ", null, pw, null);
+            pw.flush();
         }
         mCommitted = true;
         if (mAddToBackStack) {
@@ -691,8 +693,9 @@
         if (FragmentManagerImpl.DEBUG) {
             Log.v(TAG, "popFromBackStack: " + this);
             LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
-            PrintWriter pw = new PrintWriter(logw);
+            PrintWriter pw = new FastPrintWriter(logw, false, 1024);
             dump("  ", null, pw, null);
+            pw.flush();
         }
 
         bumpBackStackNesting(-1);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 72c9156..7358f73 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -36,6 +36,7 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
+import com.android.internal.util.FastPrintWriter;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -445,12 +446,13 @@
     private void throwException(RuntimeException ex) {
         Log.e(TAG, ex.getMessage());
         LogWriter logw = new LogWriter(Log.ERROR, TAG);
-        PrintWriter pw = new PrintWriter(logw);
+        PrintWriter pw = new FastPrintWriter(logw, false, 1024);
         if (mActivity != null) {
             Log.e(TAG, "Activity state:");
             try {
                 mActivity.dump("  ", null, pw, new String[] { });
             } catch (Exception e) {
+                pw.flush();
                 Log.e(TAG, "Failed dumping state", e);
             }
         } else {
@@ -458,9 +460,11 @@
             try {
                 dump("  ", null, pw, new String[] { });
             } catch (Exception e) {
+                pw.flush();
                 Log.e(TAG, "Failed dumping state", e);
             }
         }
+        pw.flush();
         throw ex;
     }
 
@@ -1806,8 +1810,9 @@
                     Log.v(TAG, "restoreAllState: back stack #" + i
                         + " (index " + bse.mIndex + "): " + bse);
                     LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
-                    PrintWriter pw = new PrintWriter(logw);
+                    PrintWriter pw = new FastPrintWriter(logw, false, 1024);
                     bse.dump("  ", pw, false);
+                    pw.flush();
                 }
                 mBackStack.add(bse);
                 if (bse.mIndex >= 0) {
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 2250331..870610b 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -315,6 +315,14 @@
     public static final int FLAG_IS_DATA_ONLY = 1<<24;
 
     /**
+     * Value for {@link #flags}: set to {@code true} if the application
+     * is permitted to hold privileged permissions.
+     *
+     * {@hide}
+     */
+    public static final int FLAG_PRIVILEGED = 1<<30;
+
+    /**
      * Value for {@link #flags}: Set to true if the application has been
      * installed using the forward lock option.
      *
@@ -338,14 +346,6 @@
     public static final int FLAG_CANT_SAVE_STATE = 1<<28;
 
     /**
-     * Value for {@link #flags}: set to {@code true} if the application
-     * is permitted to hold privileged permissions.
-     *
-     * {@hide}
-     */
-    public static final int FLAG_PRIVILEGED = 1<<29;
-
-    /**
      * Flags associated with the application.  Any combination of
      * {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE},
      * {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 362ae29..c5f473e 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.TypedProperties;
 
 import android.util.Log;
@@ -476,7 +477,7 @@
         PrintWriter outStream = null;
         try {
             FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
-            outStream = new PrintWriter(new OutputStreamWriter(fos));
+            outStream = new FastPrintWriter(fos);
             outStream.println("1");
         } catch (Exception e) {
         } finally {
@@ -504,7 +505,7 @@
         PrintWriter outStream = null;
         try {
             FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
-            outStream = new PrintWriter(new OutputStreamWriter(fos));
+            outStream = new FastPrintWriter(fos);
             outStream.println("0");
         } catch (Exception e) {
             // We could print an error message here but we probably want
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index a9abdc5..d794ca6 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -32,6 +32,7 @@
 
 import com.android.internal.os.RuntimeInit;
 
+import com.android.internal.util.FastPrintWriter;
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
 import dalvik.system.VMDebug;
@@ -1700,7 +1701,9 @@
     /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
         // Our own stack trace to append
         StringWriter sw = new StringWriter();
-        new LogStackTrace().printStackTrace(new PrintWriter(sw));
+        PrintWriter pw = new FastPrintWriter(sw, false, 256);
+        new LogStackTrace().printStackTrace(pw);
+        pw.flush();
         String ourStack = sw.toString();
 
         int policyMask = getThreadPolicyMask();
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 1c3709f..6a6f027 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -17,6 +17,7 @@
 package android.util;
 
 import com.android.internal.os.RuntimeInit;
+import com.android.internal.util.FastPrintWriter;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -315,8 +316,9 @@
         }
 
         StringWriter sw = new StringWriter();
-        PrintWriter pw = new PrintWriter(sw);
+        PrintWriter pw = new FastPrintWriter(sw, false, 256);
         tr.printStackTrace(pw);
+        pw.flush();
         return sw.toString();
     }
 
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index bcefdba..281bd7e 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -1360,7 +1360,7 @@
 
         @Override
         boolean validate() {
-            return checkCurrent() != SURFACE_STATE_ERROR;
+            return checkRenderContext() != SURFACE_STATE_ERROR;
         }
 
         @Override
@@ -1413,8 +1413,7 @@
                     return;
                 }
 
-                final int surfaceState = checkCurrent();
-                if (surfaceState != SURFACE_STATE_ERROR) {
+                if (checkRenderContext() != SURFACE_STATE_ERROR) {
                     int status = mCanvas.invokeFunctors(mRedrawClip);
                     handleFunctorStatus(attachInfo, status);
                 }
@@ -1433,7 +1432,8 @@
 
                 view.mPrivateFlags |= View.PFLAG_DRAWN;
 
-                final int surfaceState = checkCurrent();
+                // We are already on the correct thread
+                final int surfaceState = checkRenderContextUnsafe();
                 if (surfaceState != SURFACE_STATE_ERROR) {
                     HardwareCanvas canvas = mCanvas;
                     attachInfo.mHardwareCanvas = canvas;
@@ -1446,6 +1446,13 @@
 
                     DisplayList displayList = buildDisplayList(view, canvas);
 
+                    // buildDisplayList() calls into user code which can cause
+                    // an eglMakeCurrent to happen with a different surface/context.
+                    // We must therefore check again here.
+                    if (checkRenderContextUnsafe() == SURFACE_STATE_ERROR) {
+                        return;
+                    }
+
                     int saveCount = 0;
                     int status = DisplayList.STATUS_DONE;
 
@@ -1500,9 +1507,6 @@
                 HardwareCanvas canvas, DisplayList displayList) {
 
             if (mDebugOverdraw == OVERDRAW_TYPE_COUNT) {
-                // TODO: Use an alpha layer allocated from a GraphicBuffer
-                // The alpha format will help with rendering performance and
-                // the GraphicBuffer will let us skip the read pixels step
                 if (mDebugOverdrawLayer == null) {
                     mDebugOverdrawLayer = createHardwareLayer(mWidth, mHeight, true);
                 } else if (mDebugOverdrawLayer.getWidth() != mWidth ||
@@ -1725,21 +1729,39 @@
         }
 
         /**
-         * Ensures the current EGL context is the one we expect.
+         * Ensures the current EGL context and surface are the ones we expect.
+         * This method throws an IllegalStateException if invoked from a thread
+         * that did not initialize EGL.
          * 
          * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
          *         {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
          *         {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
+         *
+         * @see #checkRenderContextUnsafe()
          */
-        int checkCurrent() {
+        int checkRenderContext() {
             if (mEglThread != Thread.currentThread()) {
                 throw new IllegalStateException("Hardware acceleration can only be used with a " +
                         "single UI thread.\nOriginal thread: " + mEglThread + "\n" +
                         "Current thread: " + Thread.currentThread());
             }
 
-            if (!mEglContext.equals(sEgl.eglGetCurrentContext()) ||
-                    !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) {
+            return checkRenderContextUnsafe();
+        }
+
+        /**
+         * Ensures the current EGL context and surface are the ones we expect.
+         * This method does not check the current thread.
+         *
+         * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
+         *         {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
+         *         {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
+         *
+         * @see #checkRenderContext()
+         */
+        private int checkRenderContextUnsafe() {
+            if (!mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW)) ||
+                    !mEglContext.equals(sEgl.eglGetCurrentContext())) {
                 if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
                     Log.e(LOG_TAG, "eglMakeCurrent failed " +
                             GLUtils.getEGLErrorString(sEgl.eglGetError()));
@@ -2193,8 +2215,7 @@
 
         @Override
         boolean safelyRun(Runnable action) {
-            boolean needsContext = true;
-            if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false;
+            boolean needsContext = !isEnabled() || checkRenderContext() == SURFACE_STATE_ERROR;
 
             if (needsContext) {
                 Gl20RendererEglContext managedContext =
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 7cda01c..0eb6d63 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -29,6 +29,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 import android.view.inputmethod.InputMethodManager;
+import com.android.internal.util.FastPrintWriter;
 
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
@@ -414,7 +415,7 @@
 
     public void dumpGfxInfo(FileDescriptor fd) {
         FileOutputStream fout = new FileOutputStream(fd);
-        PrintWriter pw = new PrintWriter(fout);
+        PrintWriter pw = new FastPrintWriter(fout);
         try {
             synchronized (mLock) {
                 final int count = mViews.size();
diff --git a/core/java/com/android/internal/logging/AndroidHandler.java b/core/java/com/android/internal/logging/AndroidHandler.java
index 12f6a4f..f55a31f 100644
--- a/core/java/com/android/internal/logging/AndroidHandler.java
+++ b/core/java/com/android/internal/logging/AndroidHandler.java
@@ -17,6 +17,7 @@
 package com.android.internal.logging;
 
 import android.util.Log;
+import com.android.internal.util.FastPrintWriter;
 import dalvik.system.DalvikLogging;
 import dalvik.system.DalvikLogHandler;
 
@@ -91,7 +92,7 @@
             Throwable thrown = r.getThrown();
             if (thrown != null) {
                 StringWriter sw = new StringWriter();
-                PrintWriter pw = new PrintWriter(sw);
+                PrintWriter pw = new FastPrintWriter(sw, false, 256);
                 sw.write(r.getMessage());
                 sw.write("\n");
                 thrown.printStackTrace(pw);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 949a499..f95bb4c 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -47,6 +47,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.net.NetworkStatsFactory;
+import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.JournaledFile;
 import com.google.android.collect.Sets;
 
@@ -4461,12 +4462,13 @@
                 Slog.w(TAG, "New history ends before old history!");
             } else if (!out.same(mHistoryReadTmp)) {
                 long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
-                PrintWriter pw = new PrintWriter(new LogWriter(android.util.Log.WARN, TAG));
+                PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
                 pw.println("Histories differ!");
                 pw.println("Old history:");
                 (new HistoryPrinter()).printNextItem(pw, out, now);
                 pw.println("New history:");
                 (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, now);
+                pw.flush();
             }
         }
         return true;
diff --git a/core/java/com/android/internal/os/ProcessStats.java b/core/java/com/android/internal/os/ProcessStats.java
index bd0914d..b63dce5 100644
--- a/core/java/com/android/internal/os/ProcessStats.java
+++ b/core/java/com/android/internal/os/ProcessStats.java
@@ -22,6 +22,7 @@
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.util.Slog;
+import com.android.internal.util.FastPrintWriter;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -675,13 +676,14 @@
     
     final public String printCurrentLoad() {
         StringWriter sw = new StringWriter();
-        PrintWriter pw = new PrintWriter(sw);
+        PrintWriter pw = new FastPrintWriter(sw, false, 128);
         pw.print("Load: ");
         pw.print(mLoad1);
         pw.print(" / ");
         pw.print(mLoad5);
         pw.print(" / ");
         pw.println(mLoad15);
+        pw.flush();
         return sw.toString();
     }
 
@@ -689,7 +691,7 @@
         buildWorkingProcs();
         
         StringWriter sw = new StringWriter();
-        PrintWriter pw = new PrintWriter(sw);
+        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
         
         pw.print("CPU usage from ");
         if (now > mLastSampleTime) {
@@ -740,7 +742,8 @@
         
         printProcessCPU(pw, "", -1, "TOTAL", totalTime, mRelUserTime, mRelSystemTime,
                 mRelIoWaitTime, mRelIrqTime, mRelSoftIrqTime, 0, 0);
-        
+
+        pw.flush();
         return sw.toString();
     }
     
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
index 7b8c582..65b56ec 100644
--- a/core/java/com/android/internal/util/DumpUtils.java
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -40,7 +40,7 @@
         if (handler.runWithScissors(new Runnable() {
             @Override
             public void run() {
-                PrintWriter lpw = new PrintWriter(sw);
+                PrintWriter lpw = new FastPrintWriter(sw);
                 dump.dump(lpw);
                 lpw.close();
             }
diff --git a/core/java/com/android/internal/util/FastPrintWriter.java b/core/java/com/android/internal/util/FastPrintWriter.java
index 25dc80e..fa53cfa 100644
--- a/core/java/com/android/internal/util/FastPrintWriter.java
+++ b/core/java/com/android/internal/util/FastPrintWriter.java
@@ -13,8 +13,6 @@
 import java.nio.charset.CodingErrorAction;
 
 public class FastPrintWriter extends PrintWriter {
-    private static final int BUFFER_LEN = 8192;
-
     private static Writer sDummyWriter = new Writer() {
         @Override
         public void close() throws IOException {
@@ -34,15 +32,19 @@
         }
     };
 
-    private final char[] mText = new char[BUFFER_LEN];
+    private final int mBufferLen;
+    private final char[] mText;
     private int mPos;
 
     final private OutputStream mOutputStream;
-    final private Writer mWriter;
     final private boolean mAutoFlush;
     final private String mSeparator;
+
+    final private Writer mWriter;
+
     private CharsetEncoder mCharset;
-    final private ByteBuffer mBytes = ByteBuffer.allocate(BUFFER_LEN);
+    final private ByteBuffer mBytes;
+
     private boolean mIoError;
 
     /**
@@ -56,12 +58,7 @@
      *             if {@code out} is {@code null}.
      */
     public FastPrintWriter(OutputStream out) {
-        super(sDummyWriter);
-        mOutputStream = out;
-        mWriter = null;
-        mAutoFlush = false;
-        mSeparator = System.lineSeparator();
-        initDefaultEncoder();
+        this(out, false, 8192);
     }
 
     /**
@@ -79,7 +76,34 @@
      *             if {@code out} is {@code null}.
      */
     public FastPrintWriter(OutputStream out, boolean autoFlush) {
+        this(out, autoFlush, 8192);
+    }
+
+    /**
+     * Constructs a new {@code PrintWriter} with {@code out} as its target
+     * stream and a custom buffer size. The parameter {@code autoFlush} determines
+     * if the print writer automatically flushes its contents to the target stream
+     * when a newline is encountered.
+     *
+     * @param out
+     *            the target output stream.
+     * @param autoFlush
+     *            indicates whether contents are flushed upon encountering a
+     *            newline sequence.
+     * @param bufferLen
+     *            specifies the size of the FastPrintWriter's internal buffer; the
+     *            default is 8192.
+     * @throws NullPointerException
+     *             if {@code out} is {@code null}.
+     */
+    public FastPrintWriter(OutputStream out, boolean autoFlush, int bufferLen) {
         super(sDummyWriter, autoFlush);
+        if (out == null) {
+            throw new NullPointerException("out is null");
+        }
+        mBufferLen = bufferLen;
+        mText = new char[bufferLen];
+        mBytes = ByteBuffer.allocate(mBufferLen);
         mOutputStream = out;
         mWriter = null;
         mAutoFlush = autoFlush;
@@ -92,18 +116,17 @@
      * writer. By default, the new print writer does not automatically flush its
      * contents to the target writer when a newline is encountered.
      *
+     * <p>NOTE: Unlike PrintWriter, this version will still do buffering inside of
+     * FastPrintWriter before sending data to the Writer.  This means you must call
+     * flush() before retrieving any data from the Writer.</p>
+     *
      * @param wr
      *            the target writer.
      * @throws NullPointerException
      *             if {@code wr} is {@code null}.
      */
     public FastPrintWriter(Writer wr) {
-        super(sDummyWriter);
-        mOutputStream = null;
-        mWriter = wr;
-        mAutoFlush = false;
-        mSeparator = System.lineSeparator();
-        initDefaultEncoder();
+        this(wr, false, 8192);
     }
 
     /**
@@ -121,7 +144,34 @@
      *             if {@code out} is {@code null}.
      */
     public FastPrintWriter(Writer wr, boolean autoFlush) {
+        this(wr, autoFlush, 8192);
+    }
+
+    /**
+     * Constructs a new {@code PrintWriter} with {@code out} as its target
+     * writer and a custom buffer size. The parameter {@code autoFlush} determines
+     * if the print writer automatically flushes its contents to the target writer
+     * when a newline is encountered.
+     *
+     * @param wr
+     *            the target writer.
+     * @param autoFlush
+     *            indicates whether to flush contents upon encountering a
+     *            newline sequence.
+     * @param bufferLen
+     *            specifies the size of the FastPrintWriter's internal buffer; the
+     *            default is 8192.
+     * @throws NullPointerException
+     *             if {@code wr} is {@code null}.
+     */
+    public FastPrintWriter(Writer wr, boolean autoFlush, int bufferLen) {
         super(sDummyWriter, autoFlush);
+        if (wr == null) {
+            throw new NullPointerException("wr is null");
+        }
+        mBufferLen = bufferLen;
+        mText = new char[bufferLen];
+        mBytes = null;
         mOutputStream = null;
         mWriter = wr;
         mAutoFlush = autoFlush;
@@ -181,7 +231,7 @@
 
     private void appendLocked(char c) throws IOException {
         int pos = mPos;
-        if (pos >= (BUFFER_LEN-1)) {
+        if (pos >= (mBufferLen-1)) {
             flushLocked();
             pos = mPos;
         }
@@ -190,6 +240,7 @@
     }
 
     private void appendLocked(String str, int i, final int length) throws IOException {
+        final int BUFFER_LEN = mBufferLen;
         if (length > BUFFER_LEN) {
             final int end = i + length;
             while (i < end) {
@@ -209,6 +260,7 @@
     }
 
     private void appendLocked(char[] buf, int i, final int length) throws IOException {
+        final int BUFFER_LEN = mBufferLen;
         if (length > BUFFER_LEN) {
             final int end = i + length;
             while (i < end) {
diff --git a/docs/html/training/location/activity-recognition.jd b/docs/html/training/location/activity-recognition.jd
index 79804db..47ba5f8 100644
--- a/docs/html/training/location/activity-recognition.jd
+++ b/docs/html/training/location/activity-recognition.jd
@@ -171,11 +171,9 @@
             return true;
         // Google Play services was not available for some reason
         } else {
-            // Get the error code
-            int errorCode = connectionResult.getErrorCode();
             // Get the error dialog from Google Play services
             Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
-                    errorCode,
+                    resultCode,
                     this,
                     CONNECTION_FAILURE_RESOLUTION_REQUEST);
 
@@ -649,7 +647,7 @@
 public class MainActivity extends FragmentActivity implements
         ConnectionCallbacks, OnConnectionFailedListener {
     ...
-    public enum REQUEST_TYPE = {START, STOP}
+    public enum REQUEST_TYPE {START, STOP}
     private REQUEST_TYPE mRequestType;
     ...
 }
@@ -664,7 +662,7 @@
     ...
     public void startUpdates() {
         // Set the request type to START
-        mRequestType = START;
+        mRequestType = REQUEST_TYPE.START;
         /*
          * Test for Google Play services after setting the request type.
          * If Google Play services isn't present, the proper request type
@@ -686,9 +684,16 @@
                  */
                 mActivityRecognitionClient.requestActivityUpdates(
                         DETECTION_INTERVAL_MILLISECONDS,
-                        mActivityRecognitionPendingIntent());
+                        mActivityRecognitionPendingIntent);
                 break;
-            ...
+                ...
+                /*
+                 * An enum was added to the definition of REQUEST_TYPE,
+                 * but it doesn't match a known case. Throw an exception.
+                 */
+                default :
+                throw new Exception("Unknown request type in onConnected().");
+                break;
         }
         ...
     }
@@ -712,7 +717,7 @@
      */
     public void stopUpdates() {
         // Set the request type to STOP
-        mRequestType = STOP;
+        mRequestType = REQUEST_TYPE.STOP;
         /*
          * Test for Google Play services after setting the request type.
          * If Google Play services isn't present, the request can be
@@ -760,7 +765,7 @@
             mActivityRecognitionClient.removeActivityUpdates(
                     mActivityRecognitionPendingIntent);
             break;
-
+            ...
         }
         ...
     }
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index bd871c4..14ac901 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -61,6 +61,7 @@
     protected int mScreenDensity = Bitmap.DENSITY_NONE;
     
     // Used by native code
+    @SuppressWarnings("UnusedDeclaration")
     private int mSurfaceFormat;
 
     /**
@@ -381,8 +382,8 @@
      */
     public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
         return native_saveLayer(mNativeCanvas, bounds,
-                                paint != null ? paint.mNativePaint : 0,
-                                saveFlags);
+                paint != null ? paint.mNativePaint : 0,
+                saveFlags);
     }
     
     /**
@@ -391,8 +392,8 @@
     public int saveLayer(float left, float top, float right, float bottom, Paint paint,
             int saveFlags) {
         return native_saveLayer(mNativeCanvas, left, top, right, bottom,
-                                paint != null ? paint.mNativePaint : 0,
-                                saveFlags);
+                paint != null ? paint.mNativePaint : 0,
+                saveFlags);
     }
 
     /**
@@ -1039,7 +1040,7 @@
             throw new NullPointerException();
         }
         native_drawArc(mNativeCanvas, oval, startAngle, sweepAngle,
-                       useCenter, paint.mNativePaint);
+                useCenter, paint.mNativePaint);
     }
 
     /**
@@ -1079,8 +1080,6 @@
     /**
      * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
      *
-     * Note: Only supported by hardware accelerated canvas at the moment.
-     *
      * @param patch The ninepatch object to render
      * @param dst The destination rectangle.
      * @param paint The paint to draw the bitmap with. may be null
@@ -1088,13 +1087,12 @@
      * @hide
      */
     public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
+        patch.drawSoftware(this, dst, paint);
     }
 
     /**
      * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
      *
-     * Note: Only supported by hardware accelerated canvas at the moment.
-     *
      * @param patch The ninepatch object to render
      * @param dst The destination rectangle.
      * @param paint The paint to draw the bitmap with. may be null
@@ -1102,6 +1100,7 @@
      * @hide
      */
     public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
+        patch.drawSoftware(this, dst, paint);
     }
 
     /**
@@ -1188,7 +1187,7 @@
         }
         throwIfRecycled(bitmap);
         native_drawBitmap(mNativeCanvas, bitmap.ni(), src, dst,
-                          paint != null ? paint.mNativePaint : 0, mScreenDensity, bitmap.mDensity);
+                paint != null ? paint.mNativePaint : 0, mScreenDensity, bitmap.mDensity);
     }
     
     /**
@@ -1309,8 +1308,8 @@
             checkRange(colors.length, colorOffset, count);
         }
         nativeDrawBitmapMesh(mNativeCanvas, bitmap.ni(), meshWidth, meshHeight,
-                             verts, vertOffset, colors, colorOffset,
-                             paint != null ? paint.mNativePaint : 0);
+                verts, vertOffset, colors, colorOffset,
+                paint != null ? paint.mNativePaint : 0);
     }
 
     public enum VertexMode {
@@ -1372,8 +1371,8 @@
             checkRange(indices.length, indexOffset, indexCount);
         }
         nativeDrawVertices(mNativeCanvas, mode.nativeInt, vertexCount, verts,
-                           vertOffset, texs, texOffset, colors, colorOffset,
-                          indices, indexOffset, indexCount, paint.mNativePaint);
+                vertOffset, texs, texOffset, colors, colorOffset,
+                indices, indexOffset, indexCount, paint.mNativePaint);
     }
     
     /**
@@ -1444,10 +1443,10 @@
         if (text instanceof String || text instanceof SpannedString ||
             text instanceof SpannableString) {
             native_drawText(mNativeCanvas, text.toString(), start, end, x, y,
-                            paint.mBidiFlags, paint.mNativePaint);
+                    paint.mBidiFlags, paint.mNativePaint);
         } else if (text instanceof GraphicsOperations) {
             ((GraphicsOperations) text).drawText(this, start, end, x, y,
-                                                     paint);
+                    paint);
         } else {
             char[] buf = TemporaryBuffer.obtain(end - start);
             TextUtils.getChars(text, start, end, buf, 0);
@@ -1568,7 +1567,7 @@
             throw new IndexOutOfBoundsException();
         }
         native_drawPosText(mNativeCanvas, text, index, count, pos,
-                           paint.mNativePaint);
+                paint.mNativePaint);
     }
 
     /**
@@ -1609,8 +1608,8 @@
             throw new ArrayIndexOutOfBoundsException();
         }
         native_drawTextOnPath(mNativeCanvas, text, index, count,
-                              path.ni(), hOffset, vOffset,
-                              paint.mBidiFlags, paint.mNativePaint);
+                path.ni(), hOffset, vOffset,
+                paint.mBidiFlags, paint.mNativePaint);
     }
 
     /**
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index 932e474..ab1c328 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -100,16 +100,9 @@
      * @param location  Where to draw the bitmap.
      */
     public void draw(Canvas canvas, RectF location) {
-        if (canvas.isHardwareAccelerated()) {
-            canvas.drawPatch(this, location, mPaint);
-        } else {
-            nativeDraw(canvas.mNativeCanvas, location,
-                       mBitmap.ni(), mChunk,
-                       mPaint != null ? mPaint.mNativePaint : 0,
-                       canvas.mDensity, mBitmap.mDensity);
-        }
+        canvas.drawPatch(this, location, mPaint);
     }
-    
+
     /** 
      * Draw a bitmap of nine patches.
      *
@@ -117,14 +110,7 @@
      * @param location  Where to draw the bitmap.
      */
     public void draw(Canvas canvas, Rect location) {
-        if (canvas.isHardwareAccelerated()) {
-            canvas.drawPatch(this, location, mPaint);
-        } else {
-            nativeDraw(canvas.mNativeCanvas, location,
-                        mBitmap.ni(), mChunk,
-                        mPaint != null ? mPaint.mNativePaint : 0,
-                        canvas.mDensity, mBitmap.mDensity);
-        }
+        canvas.drawPatch(this, location, mPaint);
     }
 
     /** 
@@ -135,13 +121,23 @@
      * @param paint     The Paint to draw through.
      */
     public void draw(Canvas canvas, Rect location, Paint paint) {
-        if (canvas.isHardwareAccelerated()) {
-            canvas.drawPatch(this, location, paint);
-        } else {
-            nativeDraw(canvas.mNativeCanvas, location,
-                    mBitmap.ni(), mChunk, paint != null ? paint.mNativePaint : 0,
-                    canvas.mDensity, mBitmap.mDensity);
-        }
+        canvas.drawPatch(this, location, paint);
+    }
+
+    /**
+     * @hide
+     */
+    void drawSoftware(Canvas canvas, RectF location, Paint paint) {
+        nativeDraw(canvas.mNativeCanvas, location, mBitmap.ni(), mChunk,
+                paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity);
+    }
+
+    /**
+     * @hide
+     */
+    void drawSoftware(Canvas canvas, Rect location, Paint paint) {
+        nativeDraw(canvas.mNativeCanvas, location, mBitmap.ni(), mChunk,
+                paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity);
     }
 
     /**
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 9e3e701..7656f85 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -79,8 +79,8 @@
     uint32_t maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 4;
     if (maxVertices == 0) return NULL;
 
-    vertices = new TextureVertex[maxVertices];
-    TextureVertex* vertex = vertices;
+    TextureVertex* tempVertices = new TextureVertex[maxVertices];
+    TextureVertex* vertex = tempVertices;
 
     const int32_t* xDivs = patch->xDivs;
     const int32_t* yDivs = patch->yDivs;
@@ -159,6 +159,14 @@
                 width, bitmapWidth, quadCount);
     }
 
+    if (verticesCount == maxVertices) {
+        vertices = tempVertices;
+    } else {
+        vertices = new TextureVertex[verticesCount];
+        memcpy(vertices, tempVertices, verticesCount * sizeof(TextureVertex));
+        delete[] tempVertices;
+    }
+
     return vertices;
 }
 
diff --git a/location/lib/java/com/android/location/provider/LocationProviderBase.java b/location/lib/java/com/android/location/provider/LocationProviderBase.java
index 8a5a739..150c289 100644
--- a/location/lib/java/com/android/location/provider/LocationProviderBase.java
+++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java
@@ -35,6 +35,7 @@
 import com.android.internal.location.ILocationProvider;
 import com.android.internal.location.ProviderProperties;
 import com.android.internal.location.ProviderRequest;
+import com.android.internal.util.FastPrintWriter;
 
 /**
  * Base class for location providers implemented as unbundled services.
@@ -106,7 +107,7 @@
         }
         @Override
         public void dump(FileDescriptor fd, String[] args) {
-            PrintWriter pw = new PrintWriter(new FileOutputStream(fd));
+            PrintWriter pw = new FastPrintWriter(new FileOutputStream(fd));
             onDump(fd, pw, args);
             pw.flush();
         }
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 4bb44af..dfc68f4 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -38,7 +38,6 @@
     <uses-permission android:name="android.permission.MANAGE_USB" />
     <uses-permission android:name="android.permission.DEVICE_POWER" />
     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
-    <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
     <uses-permission android:name="android.permission.MASTER_CLEAR" />
     <uses-permission android:name="android.permission.VIBRATE" />
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 0e40140..fb2348e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -27,11 +27,9 @@
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.net.wimax.WimaxManagerConstants;
-import android.os.Binder;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Messenger;
-import android.os.RemoteException;
 import android.provider.Settings;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
@@ -42,12 +40,10 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import com.android.internal.app.IBatteryStats;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.cdma.EriInfo;
 import com.android.internal.util.AsyncChannel;
-import com.android.server.am.BatteryStatsService;
 import com.android.systemui.R;
 
 import java.io.FileDescriptor;
@@ -166,9 +162,6 @@
 
     boolean mDataAndWifiStacked = false;
 
-    // yuck -- stop doing this here and put it in the framework
-    IBatteryStats mBatteryStats;
-
     public interface SignalCluster {
         void setWifiIndicators(boolean visible, int strengthIcon, int activityIcon,
                 String contentDescription);
@@ -253,9 +246,6 @@
         // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
         updateAirplaneMode();
 
-        // yuck
-        mBatteryStats = BatteryStatsService.getService();
-
         mLastLocale = mContext.getResources().getConfiguration().locale;
     }
 
@@ -792,15 +782,6 @@
             }
         }
 
-        // yuck - this should NOT be done by the status bar
-        long ident = Binder.clearCallingIdentity();
-        try {
-            mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
-        } catch (RemoteException e) {
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-
         mDataDirectionIconId = iconId;
         mDataConnected = visible;
     }
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index 32fc18e..12a0549 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import android.os.BatteryStats;
 import com.android.internal.app.IBatteryStats;
 import com.android.server.am.BatteryStatsService;
 
@@ -89,7 +90,6 @@
 
     private static final int DUMP_MAX_LENGTH = 24 * 1024;
     private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "--unplugged" };
-    private static final String BATTERY_STATS_SERVICE_NAME = "batteryinfo";
 
     private static final String DUMPSYS_DATA_PATH = "/data/system/";
 
@@ -509,7 +509,7 @@
     }
 
     private void logBatteryStatsLocked() {
-        IBinder batteryInfoService = ServiceManager.getService(BATTERY_STATS_SERVICE_NAME);
+        IBinder batteryInfoService = ServiceManager.getService(BatteryStats.SERVICE_NAME);
         if (batteryInfoService == null) return;
 
         DropBoxManager db = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
@@ -519,7 +519,7 @@
         FileOutputStream dumpStream = null;
         try {
             // dump the service to a file
-            dumpFile = new File(DUMPSYS_DATA_PATH + BATTERY_STATS_SERVICE_NAME + ".dump");
+            dumpFile = new File(DUMPSYS_DATA_PATH + BatteryStats.SERVICE_NAME + ".dump");
             dumpStream = new FileOutputStream(dumpFile);
             batteryInfoService.dump(dumpStream.getFD(), DUMPSYS_ARGS);
             FileUtils.sync(dumpStream);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 6f8c323..54f6118 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -97,6 +97,7 @@
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.am.BatteryStatsService;
+import com.android.server.connectivity.DataConnectionStats;
 import com.android.server.connectivity.Nat464Xlat;
 import com.android.server.connectivity.Tethering;
 import com.android.server.connectivity.Vpn;
@@ -346,6 +347,8 @@
     // the set of network types that can only be enabled by system/sig apps
     List mProtectedNetworks;
 
+    private DataConnectionStats mDataConnectionStats;
+
     public ConnectivityService(Context context, INetworkManagementService netd,
             INetworkStatsService statsService, INetworkPolicyManager policyManager) {
         // Currently, omitting a NetworkFactory will create one internally
@@ -574,6 +577,9 @@
 
         mCaptivePortalTracker = CaptivePortalTracker.makeCaptivePortalTracker(mContext, this);
         loadGlobalProxy();
+
+        mDataConnectionStats = new DataConnectionStats(mContext);
+        mDataConnectionStats.startMonitoring();
     }
 
     /**
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 6b13fc7..351849b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -33,6 +33,7 @@
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.ProcessStats;
 import com.android.internal.os.TransferPipe;
+import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.server.AppOpsService;
 import com.android.server.AttributeCache;
@@ -1367,9 +1368,9 @@
                         StringBuilder dropBuilder = new StringBuilder(1024);
                         StringBuilder logBuilder = new StringBuilder(1024);
                         StringWriter oomSw = new StringWriter();
-                        PrintWriter oomPw = new PrintWriter(oomSw);
+                        PrintWriter oomPw = new FastPrintWriter(oomSw, false, 256);
                         StringWriter catSw = new StringWriter();
-                        PrintWriter catPw = new PrintWriter(catSw);
+                        PrintWriter catPw = new FastPrintWriter(catSw, false, 256);
                         String[] emptyArgs = new String[] { };
                         StringBuilder tag = new StringBuilder(128);
                         StringBuilder stack = new StringBuilder(128);
@@ -1379,6 +1380,7 @@
                         dropBuilder.append(stack);
                         dropBuilder.append('\n');
                         dropBuilder.append('\n');
+                        oomPw.flush();
                         String oomString = oomSw.toString();
                         dropBuilder.append(oomString);
                         dropBuilder.append('\n');
@@ -1414,6 +1416,7 @@
                             catPw.println();
                             dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
                         }
+                        catPw.flush();
                         dropBuilder.append(catSw.toString());
                         addErrorToDropBox("lowmem", null, "system_server", null,
                                 null, tag.toString(), dropBuilder.toString(), null, null);
diff --git a/services/java/com/android/server/connectivity/DataConnectionStats.java b/services/java/com/android/server/connectivity/DataConnectionStats.java
new file mode 100644
index 0000000..227ab23
--- /dev/null
+++ b/services/java/com/android/server/connectivity/DataConnectionStats.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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.android.server.connectivity;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.os.RemoteException;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.server.am.BatteryStatsService;
+
+public class DataConnectionStats extends BroadcastReceiver {
+    private static final String TAG = "DataConnectionStats";
+    private static final boolean DEBUG = false;
+
+    private final Context mContext;
+    private final IBatteryStats mBatteryStats;
+
+    private IccCardConstants.State mSimState = IccCardConstants.State.READY;
+    private SignalStrength mSignalStrength;
+    private ServiceState mServiceState;
+    private int mDataState = TelephonyManager.DATA_DISCONNECTED;
+
+    public DataConnectionStats(Context context) {
+        mContext = context;
+        mBatteryStats = BatteryStatsService.getService();
+    }
+
+    public void startMonitoring() {
+        TelephonyManager phone =
+                (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
+        phone.listen(mPhoneStateListener,
+                PhoneStateListener.LISTEN_SERVICE_STATE
+              | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
+              | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
+              | PhoneStateListener.LISTEN_DATA_ACTIVITY);
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+        filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
+        mContext.registerReceiver(this, filter);
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final String action = intent.getAction();
+        if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
+            updateSimState(intent);
+            notePhoneDataConnectionState();
+        } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
+                action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
+            notePhoneDataConnectionState();
+       }
+    }
+
+    private void notePhoneDataConnectionState() {
+        if (mServiceState == null) {
+            return;
+        }
+        boolean simReadyOrUnknown = mSimState == IccCardConstants.State.READY
+                || mSimState == IccCardConstants.State.UNKNOWN;
+        boolean visible = (simReadyOrUnknown || isCdma()) // we only check the sim state for GSM
+                && hasService()
+                && mDataState == TelephonyManager.DATA_CONNECTED;
+        int networkType = mServiceState.getDataNetworkType();
+        if (DEBUG) Log.d(TAG, String.format("Noting data connection for network type %s: %svisible",
+                networkType, visible ? "" : "not "));
+        try {
+            mBatteryStats.notePhoneDataConnectionState(networkType, visible);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Error noting data connection state", e);
+        }
+    }
+
+    private final void updateSimState(Intent intent) {
+        String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
+        if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
+            mSimState = IccCardConstants.State.ABSENT;
+        } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
+            mSimState = IccCardConstants.State.READY;
+        } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+            final String lockedReason =
+                    intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
+            if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
+                mSimState = IccCardConstants.State.PIN_REQUIRED;
+            } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
+                mSimState = IccCardConstants.State.PUK_REQUIRED;
+            } else {
+                mSimState = IccCardConstants.State.NETWORK_LOCKED;
+            }
+        } else {
+            mSimState = IccCardConstants.State.UNKNOWN;
+        }
+    }
+
+    private boolean isCdma() {
+        return mSignalStrength != null && !mSignalStrength.isGsm();
+    }
+
+    private boolean hasService() {
+        return mServiceState != null
+                && mServiceState.getState() != ServiceState.STATE_OUT_OF_SERVICE
+                && mServiceState.getState() != ServiceState.STATE_POWER_OFF;
+    }
+
+    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+        @Override
+        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+            mSignalStrength = signalStrength;
+        }
+
+        @Override
+        public void onServiceStateChanged(ServiceState state) {
+            mServiceState = state;
+            notePhoneDataConnectionState();
+        }
+
+        @Override
+        public void onDataConnectionStateChanged(int state, int networkType) {
+            mDataState = state;
+            notePhoneDataConnectionState();
+        }
+
+        @Override
+        public void onDataActivity(int direction) {
+            notePhoneDataConnectionState();
+        }
+    };
+}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 9ea4262..9308feb 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -35,6 +35,7 @@
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.content.NativeLibraryHelper;
 import com.android.internal.content.PackageHelper;
+import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
 import com.android.server.DeviceStorageMonitorService;
@@ -3363,7 +3364,7 @@
         try {
             File fname = getSettingsProblemFile();
             FileOutputStream out = new FileOutputStream(fname, true);
-            PrintWriter pw = new PrintWriter(out);
+            PrintWriter pw = new FastPrintWriter(out);
             SimpleDateFormat formatter = new SimpleDateFormat();
             String dateString = formatter.format(new Date(System.currentTimeMillis()));
             pw.println(dateString + ": " + msg);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 65ca00d..0babeea 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -28,6 +28,7 @@
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.policy.PolicyManager;
 import com.android.internal.policy.impl.PhoneWindowManager;
+import com.android.internal.util.FastPrintWriter;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
 import com.android.internal.view.IInputMethodManager;
@@ -5318,8 +5319,9 @@
             if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
             if (false) {
                 StringWriter sw = new StringWriter();
-                PrintWriter pw = new PrintWriter(sw);
+                PrintWriter pw = new FastPrintWriter(sw, false, 1024);
                 this.dump(null, pw, null);
+                pw.flush();
                 Slog.i(TAG, sw.toString());
             }
             try {
@@ -7898,7 +7900,7 @@
                 WindowState ws = mRebuildTmp[i];
                 if (ws.mRebuilding) {
                     StringWriter sw = new StringWriter();
-                    PrintWriter pw = new PrintWriter(sw);
+                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
                     ws.dump(pw, "", true);
                     pw.flush();
                     Slog.w(TAG, "This window was lost: " + ws);
@@ -10473,7 +10475,7 @@
      */
     public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState) {
         StringWriter sw = new StringWriter();
-        PrintWriter pw = new PrintWriter(sw);
+        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
         pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
         if (appWindowToken != null) {
             pw.println("  Application at fault: " + appWindowToken.stringName);