Merge "Implement Notification.DEFAULT_LIGHTS flag."
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index a4b692f..832f599 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -82,6 +82,11 @@
     public long time;
 
     /**
+     * Set if the app is on the system image.
+     */
+    public boolean systemApp;
+
+    /**
      * If this report is of type {@link #TYPE_CRASH}, contains an instance
      * of CrashInfo describing the crash; otherwise null.
      */
@@ -113,6 +118,7 @@
         dest.writeString(installerPackageName);
         dest.writeString(processName);
         dest.writeLong(time);
+        dest.writeInt(systemApp ? 1 : 0);
 
         switch (type) {
             case TYPE_CRASH:
@@ -130,6 +136,7 @@
         installerPackageName = in.readString();
         processName = in.readString();
         time = in.readLong();
+        systemApp = in.readInt() == 1;
 
         switch (type) {
             case TYPE_CRASH:
@@ -331,6 +338,7 @@
         pw.println(prefix + "installerPackageName: " + installerPackageName);
         pw.println(prefix + "processName: " + processName);
         pw.println(prefix + "time: " + time);
+        pw.println(prefix + "systemApp: " + systemApp);
 
         switch (type) {
             case TYPE_CRASH:
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index fb44a62..180051e 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -249,6 +249,8 @@
      */
     public static final int MAX_SQL_CACHE_SIZE = 250;
     private int mMaxSqlCacheSize = MAX_SQL_CACHE_SIZE; // max cache size per Database instance
+    private int mCacheFullWarnings;
+    private static final int MAX_WARNINGS_ON_CACHESIZE_CONDITION = 5;
 
     /** maintain stats about number of cache hits and misses */
     private int mNumCacheHits;
@@ -1873,13 +1875,30 @@
                  * JNI method. If entire cache is wiped out, it could cause a big GC activity
                  * just because a (rogue) process is using the cache incorrectly.
                  */
-                Log.w(TAG, "Too many sql statements in database cache. Make sure your sql " +
+                Log.w(TAG, "Reached MAX size for compiled-sql statement cache for database " +
+                        getPath() + "; i.e., NO space for this sql statement in cache: " +
+                        sql + ". Make sure your sql " +
                         "statements are using prepared-sql-statement syntax with '?' for " +
                         "bindargs, instead of using actual values");
-                Set<String> keySet = mCompiledQueries.keySet();
-                for (String s : keySet) {
-                    mCompiledQueries.remove(s);
-                    break;
+                
+                /* increment the number of times this warnings has been printed.
+                 * if this warning is printed too many times, clear the whole cache - the app
+                 * is doing something weird or incorrect and printing more warnings will only
+                 * flood the logfile.
+                 */
+                if (++mCacheFullWarnings > MAX_WARNINGS_ON_CACHESIZE_CONDITION) {
+                    mCacheFullWarnings = 0;
+                    // clear the cache
+                    mCompiledQueries.clear();
+                    Log.w(TAG, "compiled-sql statement cache cleared for the database " +
+                            getPath());
+                } else {
+                    // clear just a single entry from cache
+                    Set<String> keySet = mCompiledQueries.keySet();
+                    for (String s : keySet) {
+                        mCompiledQueries.remove(s);
+                        break;
+                    }
                 }
             }
             mCompiledQueries.put(sql, compiledStatement);
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index bd6cabb..fe416c5 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -102,4 +102,25 @@
      *  Disables Network Address Translation between two interfaces.
      */
     void disableNat(String internalInterface, String externalInterface);
+
+    /**
+     ** PPPD
+     **/
+
+    /**
+     * Returns the list of currently known TTY devices on the system
+     */
+    String[] listTtys();
+
+    /**
+     * Attaches a PPP server daemon to the specified TTY with the specified
+     * local/remote addresses.
+     */
+    void attachPppd(String tty, String localAddr, String remoteAddr);
+
+    /**
+     * Detaches a PPP server daemon from the specified TTY.
+     */
+    void detachPppd(String tty);
+
 }
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 5819b59..16746d4 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1102,6 +1102,33 @@
          * <P>Type: INTEGER</P>
          */
         public static final String DELETED = "deleted";
+
+        /**
+         * The "name_verified" flag: "1" means that the name fields on this raw
+         * contact can be trusted and therefore should be used for the entire
+         * aggregated contact.
+         * <p>
+         * If an aggregated contact contains more than one raw contact with a
+         * verified name, one of those verified names is chosen at random.
+         * If an aggregated contact contains no verified names, the
+         * name is chosen randomly from the constituent raw contacts.
+         * </p>
+         * <p>
+         * Updating this flag from "0" to "1" automatically resets it to "0" on
+         * all other raw contacts in the same aggregated contact.
+         * </p>
+         * <p>
+         * Sync adapters should only specify a value for this column when
+         * inserting a raw contact and leave it out when doing an update.
+         * </p>
+         * <p>
+         * The default value is "0"
+         * </p>
+         * <p>Type: INTEGER</p>
+         *
+         * @hide
+         */
+        public static final String NAME_VERIFIED = "name_verified";
     }
 
     /**
@@ -1673,6 +1700,7 @@
                 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, CONTACT_ID);
                 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, STARRED);
                 DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, IS_RESTRICTED);
+                DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, NAME_VERIFIED);
                 android.content.Entity contact = new android.content.Entity(cv);
 
                 // read data rows until the contact id changes
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 404c513..b677b1e 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -66,6 +66,13 @@
     /** when preloading, GC after allocating this many bytes */
     private static final int PRELOAD_GC_THRESHOLD = 50000;
 
+    /** throw on missing preload, only if this looks like a developer */
+    private static final boolean THROW_ON_MISSING_PRELOAD =
+            "1".equals(SystemProperties.get("persist.service.adb.enable"));
+
+    public static final String USAGE_STRING =
+            " <\"true\"|\"false\" for startSystemServer>";
+
     private static LocalServerSocket sServerSocket;
 
     /**
@@ -322,8 +329,8 @@
                     }
                 }
 
-                if (missingClasses != null &&
-                        "1".equals(SystemProperties.get("persist.service.adb.enable"))) {
+                if (THROW_ON_MISSING_PRELOAD &&
+                    missingClasses != null) {
                     throw new IllegalStateException(
                             "Missing class(es) for preloading, update preloaded-classes ["
                             + missingClasses + "]");
@@ -597,12 +604,13 @@
 
             // If requested, start system server directly from Zygote
             if (argv.length != 2) {
-                throw new RuntimeException(
-                        "ZygoteInit.main expects two arguments");
+                throw new RuntimeException(argv[0] + USAGE_STRING);
             }
 
             if (argv[1].equals("true")) {
                 startSystemServer();
+            } else if (!argv[1].equals("false")) {
+                throw new RuntimeException(argv[0] + USAGE_STRING);
             }
 
             Log.i(TAG, "Accepting command socket connections");
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 3c5a753..9f7a370 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -16,7 +16,10 @@
 
 package com.android.internal.widget;
 
+import android.app.DevicePolicyManager;
+import android.content.ComponentName;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.security.MessageDigest;
@@ -93,15 +96,17 @@
     public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
 
     private final ContentResolver mContentResolver;
-
+    private DevicePolicyManager mDevicePolicyManager;
     private static String sLockPatternFilename;
     private static String sLockPasswordFilename;
 
     /**
      * @param contentResolver Used to look up and save settings.
      */
-    public LockPatternUtils(ContentResolver contentResolver) {
-        mContentResolver = contentResolver;
+    public LockPatternUtils(Context context) {
+        mContentResolver = context.getContentResolver();
+        mDevicePolicyManager =
+                (DevicePolicyManager)context.getSystemService(Context.DEVICE_POLICY_SERVICE);
         // Initialize the location of gesture lock file
         if (sLockPatternFilename == null) {
             sLockPatternFilename = android.os.Environment.getDataDirectory()
@@ -112,6 +117,71 @@
 
     }
 
+    public boolean isDevicePolicyActive() {
+        ComponentName admin = mDevicePolicyManager.getActiveAdmin();
+        return admin != null ? mDevicePolicyManager.isAdminActive(admin) : false;
+    }
+
+    public int getRequestedMinimumPasswordLength() {
+        return mDevicePolicyManager.getMinimumPasswordLength();
+    }
+
+    public int getActiveMinimumPasswordLength() {
+        return mDevicePolicyManager.getActiveMinimumPasswordLength();
+    }
+
+    /**
+     * Gets the device policy password mode. If the mode is non-specific, returns
+     * MODE_PATTERN which allows the user to choose anything.
+     *
+     * @return
+     */
+    public int getRequestedPasswordMode() {
+        int policyMode = mDevicePolicyManager.getPasswordMode();
+        switch (policyMode) {
+            case DevicePolicyManager.PASSWORD_MODE_ALPHANUMERIC:
+                return MODE_PASSWORD;
+            case DevicePolicyManager.PASSWORD_MODE_NUMERIC:
+                return MODE_PIN;
+            case DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED:
+                return MODE_PATTERN;
+        }
+        return MODE_PATTERN;
+    }
+
+    /**
+     * Returns the actual password mode, as set by keyguard after updating the password.
+     *
+     * @return
+     */
+    public int getActivePasswordMode() {
+        return mDevicePolicyManager.getActivePasswordMode();
+    }
+
+    public void reportFailedPasswordAttempt() {
+        mDevicePolicyManager.reportFailedPasswordAttempt();
+    }
+
+    public void reportSuccessfulPasswordAttempt() {
+        mDevicePolicyManager.reportSuccessfulPasswordAttempt();
+    }
+
+    public void setActivePasswordState(int mode, int length) {
+        int policyMode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
+        switch (mode) {
+            case MODE_PATTERN:
+                policyMode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
+                break;
+            case MODE_PIN:
+                policyMode = DevicePolicyManager.PASSWORD_MODE_NUMERIC;
+                break;
+            case MODE_PASSWORD:
+                policyMode = DevicePolicyManager.PASSWORD_MODE_ALPHANUMERIC;
+                break;
+        }
+        mDevicePolicyManager.setActivePasswordState(policyMode, length);
+    }
+
     /**
      * Check to see if a pattern matches the saved pattern.  If no pattern exists,
      * always returns true.
@@ -227,6 +297,10 @@
             raf.close();
             setBoolean(PATTERN_EVER_CHOSEN_KEY, true);
             setLong(PASSWORD_TYPE_KEY, MODE_PATTERN);
+            if (pattern != null && isDevicePolicyActive()) {
+                setActivePasswordState(DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED,
+                        pattern.size());
+            }
         } catch (FileNotFoundException fnfe) {
             // Cant do much, unless we want to fail over to using the settings provider
             Log.e(TAG, "Unable to save lock pattern to " + sLockPatternFilename);
@@ -255,6 +329,10 @@
             }
             raf.close();
             setLong(PASSWORD_TYPE_KEY, numericHint ? MODE_PIN : MODE_PASSWORD);
+            if (password != null && isDevicePolicyActive()) {
+                setActivePasswordState(numericHint ? DevicePolicyManager.PASSWORD_MODE_NUMERIC
+                    : DevicePolicyManager.PASSWORD_MODE_ALPHANUMERIC, password.length());
+            }
         } catch (FileNotFoundException fnfe) {
             // Cant do much, unless we want to fail over to using the settings provider
             Log.e(TAG, "Unable to save lock pattern to " + sLockPasswordFilename);
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index d38c177..bb7677df 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -82,9 +82,13 @@
             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
             buffer_id *buffer) = 0;
 
+    // This API clearly only makes sense if the caller lives in the
+    // same process as the callee, i.e. is the media_server, as the
+    // returned "buffer_data" pointer is just that, a pointer into local
+    // address space.
     virtual status_t allocateBuffer(
             node_id node, OMX_U32 port_index, size_t size,
-            buffer_id *buffer) = 0;
+            buffer_id *buffer, void **buffer_data) = 0;
 
     virtual status_t allocateBufferWithBackup(
             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 2c32386..ac2f662 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -100,6 +100,8 @@
         IOMX::buffer_id mBuffer;
         bool mOwnedByComponent;
         sp<IMemory> mMem;
+        size_t mSize;
+        void *mData;
         MediaBuffer *mMediaBuffer;
     };
 
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index 3080ab0..88521f6 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -110,9 +110,5 @@
 
 include $(BUILD_SHARED_LIBRARY)
 
-# Include the subdirectories ====================
-include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk,\
-            java \
-    	))
 
 endif #simulator
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index 3ba9cee..eeb9468 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -778,6 +778,17 @@
     rsc->setVertex((ProgramVertex *)tmp.get());
 }
 
+static void SC_drawSpriteScreenspaceCropped(float x, float y, float z, float w, float h,
+        float cx0, float cy0, float cx1, float cy1)
+{
+    GET_TLS();
+    rsc->setupCheck();
+
+    GLint crop[4] = {cx0, cy0, cx1, cy1};
+    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
+    glDrawTexfOES(x, y, z, w, h);
+}
+
 static void SC_drawSprite(float x, float y, float z, float w, float h)
 {
     GET_TLS();
@@ -1289,6 +1300,8 @@
         "void", "(float x, float y, float z, float w, float h)" },
     { "drawSpriteScreenspace", (void *)&SC_drawSpriteScreenspace,
         "void", "(float x, float y, float z, float w, float h)" },
+    { "drawSpriteScreenspaceCropped", (void *)&SC_drawSpriteScreenspaceCropped,
+        "void", "(float x, float y, float z, float w, float h, float cx0, float cy0, float cx1, float cy1)" },
     { "drawLine", (void *)&SC_drawLine,
         "void", "(float x1, float y1, float z1, float x2, float y2, float z2)" },
     { "drawPoint", (void *)&SC_drawPoint,
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 2ff6167..091856f 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -261,7 +261,7 @@
 // ============================================================================
 
 LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset)
-    : mBufferHeap(buffers)
+    : mBufferHeap(buffers), mSupportsCopybit(false)
 {
     NativeBuffer& src(mNativeBuffer);
     src.crop.l = 0;
@@ -283,10 +283,8 @@
                 offset, buffers.heap->base(),
                 &src.img.handle);
 
-        LOGE_IF(err, "CREATE_HANDLE_FROM_BUFFER (heapId=%d, size=%d, "
-             "offset=%ld, base=%p) failed (%s)",
-                buffers.heap->heapID(), buffers.heap->getSize(),
-                offset, buffers.heap->base(), strerror(-err));
+        // we can fail here is the passed buffer is purely software
+        mSupportsCopybit = (err == NO_ERROR);
     }
  }
 
@@ -446,14 +444,10 @@
     NativeBuffer src(ourBuffer->getBuffer());
     const Rect transformedBounds(mLayer.getTransformedBounds());
 
-    if (UNLIKELY(mTexture.name == -1LU)) {
-        mTexture.name = mLayer.createTexture();
-    }
-
 #if defined(EGL_ANDROID_image_native_buffer)
     if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) {
         copybit_device_t* copybit = mLayer.mBlitEngine;
-        if (copybit) {
+        if (copybit && ourBuffer->supportsCopybit()) {
             // create our EGLImageKHR the first time
             err = initTempBuffer();
             if (err == NO_ERROR) {
@@ -465,7 +459,9 @@
                 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
                 err = copybit->stretch(copybit, &dst.img, &src.img,
                         &dst.crop, &src.crop, &clip);
-
+                if (err != NO_ERROR) {
+                    clearTempBufferImage();
+                }
             }
         } else {
             err = INVALID_OPERATION;
@@ -487,6 +483,9 @@
         t.format = src.img.format;
         t.data = (GGLubyte*)src.img.base;
         const Region dirty(Rect(t.width, t.height));
+        if (UNLIKELY(mTexture.name == -1LU)) {
+            mTexture.name = mLayer.createTexture();
+        }
         mLayer.loadTexture(&mTexture, dirty, t);
     }
 
@@ -504,16 +503,21 @@
         int t = w; w = h; h = t;
     }
 
+    // we're in the copybit case, so make sure we can handle this blit
+    // we don't have to keep the aspect ratio here
+    copybit_device_t* copybit = mLayer.mBlitEngine;
+    const int down = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
+    const int up = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
+    if (buffers.w > w*down)     w = buffers.w / down;
+    else if (w > buffers.w*up)  w = buffers.w*up;
+    if (buffers.h > h*down)     h = buffers.h / down;
+    else if (h > buffers.h*up)  h = buffers.h*up;
+
     if (mTexture.image != EGL_NO_IMAGE_KHR) {
         // we have an EGLImage, make sure the needed size didn't change
         if (w!=mTexture.width || h!= mTexture.height) {
             // delete the EGLImage and texture
-            EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
-            glDeleteTextures(1, &mTexture.name);
-            eglDestroyImageKHR(dpy, mTexture.image);
-            Texture defaultTexture;
-            mTexture = defaultTexture;
-            mTempGraphicBuffer.clear();
+            clearTempBufferImage();
         } else {
             // we're good, we have an EGLImageKHR and it's (still) the
             // right size
@@ -560,6 +564,16 @@
     return err;
 }
 
+void LayerBuffer::BufferSource::clearTempBufferImage() const
+{
+    EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
+    glDeleteTextures(1, &mTexture.name);
+    eglDestroyImageKHR(dpy, mTexture.image);
+    Texture defaultTexture;
+    mTexture = defaultTexture;
+    mTempGraphicBuffer.clear();
+}
+
 // ---------------------------------------------------------------------------
 
 LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer,
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 2ca63ac..1b31435 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -99,6 +99,9 @@
     class Buffer : public LightRefBase<Buffer> {
     public:
         Buffer(const ISurface::BufferHeap& buffers, ssize_t offset);
+        inline bool supportsCopybit() const {
+            return mSupportsCopybit;
+        }
         inline status_t getStatus() const {
             return mBufferHeap.heap!=0 ? NO_ERROR : NO_INIT;
         }
@@ -113,6 +116,7 @@
     private:
         ISurface::BufferHeap    mBufferHeap;
         NativeBuffer            mNativeBuffer;
+        bool                    mSupportsCopybit;
     };
 
     class BufferSource : public Source {
@@ -131,6 +135,7 @@
         virtual void destroy() { }
     private:
         status_t initTempBuffer() const;
+        void clearTempBufferImage() const;
         mutable Mutex                   mBufferSourceLock;
         sp<Buffer>                      mBuffer;
         status_t                        mStatus;
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 277bce1..0469fd5 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -240,7 +240,7 @@
 
     virtual status_t allocateBuffer(
             node_id node, OMX_U32 port_index, size_t size,
-            buffer_id *buffer) {
+            buffer_id *buffer, void **buffer_data) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeIntPtr((intptr_t)node);
@@ -255,7 +255,8 @@
             return err;
         }
 
-        *buffer = (void*)reply.readIntPtr();
+        *buffer = (void *)reply.readIntPtr();
+        *buffer_data = (void *)reply.readIntPtr();
 
         return err;
     }
@@ -569,11 +570,14 @@
             size_t size = data.readInt32();
 
             buffer_id buffer;
-            status_t err = allocateBuffer(node, port_index, size, &buffer);
+            void *buffer_data;
+            status_t err = allocateBuffer(
+                    node, port_index, size, &buffer, &buffer_data);
             reply->writeInt32(err);
 
             if (err == OK) {
                 reply->writeIntPtr((intptr_t)buffer);
+                reply->writeIntPtr((intptr_t)buffer_data);
             }
 
             return NO_ERROR;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index c583b93..2686489 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1189,12 +1189,19 @@
         sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
         CHECK(mem.get() != NULL);
 
+        BufferInfo info;
+        info.mData = NULL;
+        info.mSize = def.nBufferSize;
+
         IOMX::buffer_id buffer;
         if (portIndex == kPortIndexInput
                 && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
             if (mOMXLivesLocally) {
+                mem.clear();
+
                 err = mOMX->allocateBuffer(
-                        mNode, portIndex, def.nBufferSize, &buffer);
+                        mNode, portIndex, def.nBufferSize, &buffer,
+                        &info.mData);
             } else {
                 err = mOMX->allocateBufferWithBackup(
                         mNode, portIndex, mem, &buffer);
@@ -1202,8 +1209,11 @@
         } else if (portIndex == kPortIndexOutput
                 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
             if (mOMXLivesLocally) {
+                mem.clear();
+
                 err = mOMX->allocateBuffer(
-                        mNode, portIndex, def.nBufferSize, &buffer);
+                        mNode, portIndex, def.nBufferSize, &buffer,
+                        &info.mData);
             } else {
                 err = mOMX->allocateBufferWithBackup(
                         mNode, portIndex, mem, &buffer);
@@ -1217,14 +1227,17 @@
             return err;
         }
 
-        BufferInfo info;
+        if (mem != NULL) {
+            info.mData = mem->pointer();
+        }
+
         info.mBuffer = buffer;
         info.mOwnedByComponent = false;
         info.mMem = mem;
         info.mMediaBuffer = NULL;
 
         if (portIndex == kPortIndexOutput) {
-            info.mMediaBuffer = new MediaBuffer(mem->pointer(), mem->size());
+            info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize);
             info.mMediaBuffer->setObserver(this);
         }
 
@@ -1599,6 +1612,8 @@
 }
 
 void OMXCodec::onStateChange(OMX_STATETYPE newState) {
+    CODEC_LOGV("onStateChange %d", newState);
+
     switch (newState) {
         case OMX_StateIdle:
         {
@@ -1666,6 +1681,12 @@
             break;
         }
 
+        case OMX_StateInvalid:
+        {
+            setState(ERROR);
+            break;
+        }
+
         default:
         {
             CHECK(!"should not be here.");
@@ -1845,16 +1866,16 @@
             static const uint8_t kNALStartCode[4] =
                     { 0x00, 0x00, 0x00, 0x01 };
 
-            CHECK(info->mMem->size() >= specific->mSize + 4);
+            CHECK(info->mSize >= specific->mSize + 4);
 
             size += 4;
 
-            memcpy(info->mMem->pointer(), kNALStartCode, 4);
-            memcpy((uint8_t *)info->mMem->pointer() + 4,
+            memcpy(info->mData, kNALStartCode, 4);
+            memcpy((uint8_t *)info->mData + 4,
                    specific->mData, specific->mSize);
         } else {
-            CHECK(info->mMem->size() >= specific->mSize);
-            memcpy(info->mMem->pointer(), specific->mData, specific->mSize);
+            CHECK(info->mSize >= specific->mSize);
+            memcpy(info->mData, specific->mData, specific->mSize);
         }
 
         mNoMoreOutputData = false;
@@ -1901,12 +1922,12 @@
 
         srcLength = srcBuffer->range_length();
 
-        if (info->mMem->size() < srcLength) {
-            LOGE("info->mMem->size() = %d, srcLength = %d",
-                 info->mMem->size(), srcLength);
+        if (info->mSize < srcLength) {
+            LOGE("info->mSize = %d, srcLength = %d",
+                 info->mSize, srcLength);
         }
-        CHECK(info->mMem->size() >= srcLength);
-        memcpy(info->mMem->pointer(),
+        CHECK(info->mSize >= srcLength);
+        memcpy(info->mData,
                (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
                srcLength);
 
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index b559101..ea131e8 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -65,7 +65,7 @@
 
     virtual status_t allocateBuffer(
             node_id node, OMX_U32 port_index, size_t size,
-            buffer_id *buffer);
+            buffer_id *buffer, void **buffer_data);
 
     virtual status_t allocateBufferWithBackup(
             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 923b801..b5b31ac 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -54,7 +54,8 @@
             OMX::buffer_id *buffer);
 
     status_t allocateBuffer(
-            OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer);
+            OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
+            void **buffer_data);
 
     status_t allocateBufferWithBackup(
             OMX_U32 portIndex, const sp<IMemory> &params,
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 2121321..918d055c 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -280,9 +280,9 @@
 
 status_t OMX::allocateBuffer(
         node_id node, OMX_U32 port_index, size_t size,
-        buffer_id *buffer) {
+        buffer_id *buffer, void **buffer_data) {
     return findInstance(node)->allocateBuffer(
-            port_index, size, buffer);
+            port_index, size, buffer, buffer_data);
 }
 
 status_t OMX::allocateBufferWithBackup(
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 4eb6417..70c6a58 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -258,7 +258,8 @@
 }
 
 status_t OMXNodeInstance::allocateBuffer(
-        OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer) {
+        OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
+        void **buffer_data) {
     Mutex::Autolock autoLock(mLock);
 
     BufferMeta *buffer_meta = new BufferMeta(size);
@@ -280,6 +281,7 @@
     }
 
     *buffer = header;
+    *buffer_data = header->pBuffer;
 
     addActiveBuffer(portIndex, *buffer);
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java
index ca60e8c..95dbb97 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java
@@ -250,7 +250,11 @@
         
         value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
         Log.v(TAG, "Expected = " + meta_data_file[fileIndex][meta.DURATION.ordinal()] + "reult = " + value);
-        assertEquals(TAG, meta_data_file[fileIndex][meta.DURATION.ordinal()], value);
+        // Only require that the returned duration is within 100ms of the expected
+        // one as PV and stagefright differ slightly in their implementation.
+        assertTrue(TAG, Math.abs(Integer.parseInt(
+                        meta_data_file[fileIndex][meta.DURATION.ordinal()])
+                            - Integer.parseInt(value)) < 100);
         
         //METADATA_KEY_NUM_TRACKS should return the total number of tracks in the media
         //include the video and audio
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index a1dca7e..89d75b7 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -580,7 +580,7 @@
             upgradeVersion = 46;
         }
 
- 
+
         if (upgradeVersion != currentVersion) {
             Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion
                     + ", must wipe the settings provider");
@@ -608,7 +608,7 @@
             if (!TextUtils.isEmpty(lockPattern)) {
                 // Convert lock pattern
                 try {
-                    LockPatternUtils lpu = new LockPatternUtils(mContext.getContentResolver());
+                    LockPatternUtils lpu = new LockPatternUtils(mContext);
                     List<LockPatternView.Cell> cellPattern =
                             LockPatternUtils.stringToPattern(lockPattern);
                     lpu.saveLockPattern(cellPattern);
@@ -928,11 +928,11 @@
     private void loadSecure35Settings(SQLiteStatement stmt) {
         loadBooleanSetting(stmt, Settings.Secure.BACKUP_ENABLED,
                 R.bool.def_backup_enabled);
-        
+
         loadStringSetting(stmt, Settings.Secure.BACKUP_TRANSPORT,
                 R.string.def_backup_transport);
     }
-    
+
     private void loadSetting(SQLiteStatement stmt, String key, Object value) {
         stmt.bindString(1, key);
         stmt.bindString(2, value.toString());
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 6ea50c7..363e93e 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -99,7 +99,7 @@
     public DockObserver(Context context, PowerManagerService pm) {
         mContext = context;
         mPowerManager = pm;
-        mLockPatternUtils = new LockPatternUtils(context.getContentResolver());
+        mLockPatternUtils = new LockPatternUtils(context);
         init();  // set initial status
         startObserving(DOCK_UEVENT_MATCH);
     }
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 0d9f98f..381a300 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -1024,23 +1024,7 @@
     }
 
     public String[] getSecureContainerList() throws IllegalStateException {
-        ArrayList<String> rsp = mConnector.doCommand("list_asec");
-
-        String[] rdata = new String[rsp.size()];
-        int idx = 0;
-
-        for (String line : rsp) {
-            String []tok = line.split(" ");
-            int code = Integer.parseInt(tok[0]);
-            if (code == VoldResponseCode.AsecListResult) {
-                rdata[idx++] = tok[1];
-            } else if (code == NativeDaemonConnector.ResponseCode.CommandOkay) {
-                return rdata;
-            } else {
-                throw new IllegalStateException(String.format("Unexpected response code %d", code));
-            }
-        }
-        throw new IllegalStateException("Got an empty response");
+        return mConnector.doListCommand("list_asec", VoldResponseCode.AsecListResult);
     }
 
     public String createSecureContainer(String id, int sizeMb, String fstype,
diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java
index da3e562..98e00dc 100644
--- a/services/java/com/android/server/NativeDaemonConnector.java
+++ b/services/java/com/android/server/NativeDaemonConnector.java
@@ -201,6 +201,9 @@
         }
     }
 
+    /**
+     * Issue a command to the native daemon and return the responses
+     */
     public synchronized ArrayList<String> doCommand(String cmd) throws IllegalStateException {
         sendCommand(cmd);
 
@@ -236,4 +239,38 @@
         }
         return response;
     }
+
+    /*
+     * Issues a list command and returns the cooked list
+     */
+    public String[] doListCommand(String cmd, int expectedResponseCode)
+            throws IllegalStateException {
+
+        ArrayList<String> rsp = doCommand(cmd);
+        String[] rdata = new String[rsp.size()-1];
+        int idx = 0;
+
+        for (String line : rsp) {
+            try {
+                String[] tok = line.split(" ");
+                int code = Integer.parseInt(tok[0]);
+                if (code == expectedResponseCode) {
+                    if (tok.length !=2) {
+                        throw new IllegalStateException(
+                                String.format("Malformatted list entry '%s'", line));
+                    }
+                    rdata[idx++] = tok[1];
+                } else if (code == NativeDaemonConnector.ResponseCode.CommandOkay) {
+                    return rdata;
+                } else {
+                    throw new IllegalStateException(
+                            String.format("Expected list response %d, but got %d",
+                                    expectedResponseCode, code));
+                }
+            } catch (NumberFormatException nfe) {
+                throw new IllegalStateException(String.format("Error reading code '%s'", line));
+            }
+        }
+        throw new IllegalStateException("Got an empty response");
+    }
 }
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 97fa0cc..a4abddb 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -52,6 +52,7 @@
         public static final int InterfaceListResult       = 110;
         public static final int TetherInterfaceListResult = 111;
         public static final int TetherDnsFwdTgtListResult = 112;
+        public static final int TtyListResult             = 113;
 
         public static final int TetherStatusResult        = 210;
         public static final int IpFwdStatusResult         = 211;
@@ -106,27 +107,7 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
 
-        ArrayList<String> rsp = mConnector.doCommand("list_interfaces");
-
-        String[] rdata = new String[rsp.size()];
-        int idx = 0;
-
-        for (String line : rsp) {
-            String []tok = line.split(" ");
-            int code = Integer.parseInt(tok[0]);
-            if (code == NetdResponseCode.InterfaceListResult) {
-                if (tok.length !=2) {
-                    throw new IllegalStateException(
-                            String.format("Malformatted list entry '%s'", line));
-                }
-                rdata[idx++] = tok[1];
-            } else if (code == NativeDaemonConnector.ResponseCode.CommandOkay) {
-                return rdata;
-            } else {
-                throw new IllegalStateException(String.format("Unexpected response code %d", code));
-            }
-        }
-        throw new IllegalStateException("Got an empty response");
+        return mConnector.doListCommand("list_interfaces", NetdResponseCode.InterfaceListResult);
     }
 
     public void shutdown() {
@@ -219,28 +200,8 @@
     public String[] listTetheredInterfaces() throws IllegalStateException {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
-
-        ArrayList<String> rsp = mConnector.doCommand("tether interface list");
-
-        String[] rdata = new String[rsp.size()];
-        int idx = 0;
-
-        for (String line : rsp) {
-            String []tok = line.split(" ");
-            int code = Integer.parseInt(tok[0]);
-            if (code == NetdResponseCode.TetherInterfaceListResult) {
-                if (tok.length !=2) {
-                    throw new IllegalStateException(
-                            String.format("Malformatted list entry '%s'", line));
-                }
-                rdata[idx++] = tok[1];
-            } else if (code == NativeDaemonConnector.ResponseCode.CommandOkay) {
-                return rdata;
-            } else {
-                throw new IllegalStateException(String.format("Unexpected response code %d", code));
-            }
-        }
-        throw new IllegalStateException("Got an empty response");
+        return mConnector.doListCommand(
+                "tether interface list", NetdResponseCode.TetherInterfaceListResult);
     }
 
     public void setDnsForwarders(String[] dns) throws IllegalStateException {
@@ -260,28 +221,8 @@
     public String[] getDnsForwarders() throws IllegalStateException {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
-
-        ArrayList<String> rsp = mConnector.doCommand("tether dns list");
-
-        String[] rdata = new String[rsp.size()];
-        int idx = 0;
-
-        for (String line : rsp) {
-            String []tok = line.split(" ");
-            int code = Integer.parseInt(tok[0]);
-            if (code == NetdResponseCode.TetherDnsFwdTgtListResult) {
-                if (tok.length !=2) {
-                    throw new IllegalStateException(
-                            String.format("Malformatted list entry '%s'", line));
-                }
-                rdata[idx++] = tok[1];
-            } else if (code == NativeDaemonConnector.ResponseCode.CommandOkay) {
-                return rdata;
-            } else {
-                throw new IllegalStateException(String.format("Unexpected response code %d", code));
-            }
-        }
-        throw new IllegalStateException("Got an empty response");
+        return mConnector.doListCommand(
+                "tether dns list", NetdResponseCode.TetherDnsFwdTgtListResult);
     }
 
     public void enableNat(String internalInterface, String externalInterface)
@@ -299,5 +240,30 @@
         mConnector.doCommand(
                 String.format("nat disable %s %s", internalInterface, externalInterface));
     }
+
+    public String[] listTtys() throws IllegalStateException {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
+        return mConnector.doListCommand("list_ttys", NetdResponseCode.TtyListResult);
+    }
+
+    public void attachPppd(String tty, String localAddr, String remoteAddr)
+            throws IllegalStateException {
+        try {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
+            mConnector.doCommand(String.format("pppd attach %s %s %s", tty,
+                    InetAddress.getByName(localAddr).toString(),
+                    InetAddress.getByName(localAddr).toString()));
+        } catch (UnknownHostException e) {
+            throw new IllegalStateException("Error resolving addr", e);
+        }
+    }
+
+    public void detachPppd(String tty) throws IllegalStateException {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
+        mConnector.doCommand(String.format("pppd detach %s", tty));
+    }
 }
 
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 843058c..5b50a3a 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -8994,6 +8994,7 @@
         report.installerPackageName = r.errorReportReceiver.getPackageName();
         report.processName = r.processName;
         report.time = timeMillis;
+        report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
 
         if (r.crashing) {
             report.type = ApplicationErrorReport.TYPE_CRASH;