Merge "Delay sending Plugin Draw event until the surface is ready."
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index abeeb74..9a20951 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -332,60 +332,60 @@
         BulkCursorToCursorAdaptor adaptor) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IContentProvider.descriptor);
 
-        data.writeInterfaceToken(IContentProvider.descriptor);
+            url.writeToParcel(data, 0);
+            int length = 0;
+            if (projection != null) {
+                length = projection.length;
+            }
+            data.writeInt(length);
+            for (int i = 0; i < length; i++) {
+                data.writeString(projection[i]);
+            }
+            data.writeString(selection);
+            if (selectionArgs != null) {
+                length = selectionArgs.length;
+            } else {
+                length = 0;
+            }
+            data.writeInt(length);
+            for (int i = 0; i < length; i++) {
+                data.writeString(selectionArgs[i]);
+            }
+            data.writeString(sortOrder);
+            data.writeStrongBinder(observer.asBinder());
+            window.writeToParcel(data, 0);
 
-        url.writeToParcel(data, 0);
-        int length = 0;
-        if (projection != null) {
-            length = projection.length;
-        }
-        data.writeInt(length);
-        for (int i = 0; i < length; i++) {
-            data.writeString(projection[i]);
-        }
-        data.writeString(selection);
-        if (selectionArgs != null) {
-            length = selectionArgs.length;
-        } else {
-            length = 0;
-        }
-        data.writeInt(length);
-        for (int i = 0; i < length; i++) {
-            data.writeString(selectionArgs[i]);
-        }
-        data.writeString(sortOrder);
-        data.writeStrongBinder(observer.asBinder());
-        window.writeToParcel(data, 0);
+            // Flag for whether or not we want the number of rows in the
+            // cursor and the position of the "_id" column index (or -1 if
+            // non-existent).  Only to be returned if binder != null.
+            final boolean wantsCursorMetadata = (adaptor != null);
+            data.writeInt(wantsCursorMetadata ? 1 : 0);
 
-        // Flag for whether or not we want the number of rows in the
-        // cursor and the position of the "_id" column index (or -1 if
-        // non-existent).  Only to be returned if binder != null.
-        final boolean wantsCursorMetadata = (adaptor != null);
-        data.writeInt(wantsCursorMetadata ? 1 : 0);
+            mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
 
-        mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
+            DatabaseUtils.readExceptionFromParcel(reply);
 
-        DatabaseUtils.readExceptionFromParcel(reply);
+            IBulkCursor bulkCursor = null;
+            IBinder bulkCursorBinder = reply.readStrongBinder();
+            if (bulkCursorBinder != null) {
+                bulkCursor = BulkCursorNative.asInterface(bulkCursorBinder);
 
-        IBulkCursor bulkCursor = null;
-        IBinder bulkCursorBinder = reply.readStrongBinder();
-        if (bulkCursorBinder != null) {
-            bulkCursor = BulkCursorNative.asInterface(bulkCursorBinder);
-
-            if (wantsCursorMetadata) {
-                int rowCount = reply.readInt();
-                int idColumnPosition = reply.readInt();
-                if (bulkCursor != null) {
-                    adaptor.set(bulkCursor, rowCount, idColumnPosition);
+                if (wantsCursorMetadata) {
+                    int rowCount = reply.readInt();
+                    int idColumnPosition = reply.readInt();
+                    if (bulkCursor != null) {
+                        adaptor.set(bulkCursor, rowCount, idColumnPosition);
+                    }
                 }
             }
+            return bulkCursor;
+        } finally {
+            data.recycle();
+            reply.recycle();
         }
-
-        data.recycle();
-        reply.recycle();
-
-        return bulkCursor;
     }
 
     public IBulkCursor bulkQuery(Uri url, String[] projection,
@@ -416,240 +416,240 @@
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IContentProvider.descriptor);
 
-        data.writeInterfaceToken(IContentProvider.descriptor);
+            url.writeToParcel(data, 0);
 
-        url.writeToParcel(data, 0);
+            mRemote.transact(IContentProvider.GET_TYPE_TRANSACTION, data, reply, 0);
 
-        mRemote.transact(IContentProvider.GET_TYPE_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionFromParcel(reply);
-        String out = reply.readString();
-
-        data.recycle();
-        reply.recycle();
-
-        return out;
+            DatabaseUtils.readExceptionFromParcel(reply);
+            String out = reply.readString();
+            return out;
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
 
     public Uri insert(Uri url, ContentValues values) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IContentProvider.descriptor);
 
-        data.writeInterfaceToken(IContentProvider.descriptor);
+            url.writeToParcel(data, 0);
+            values.writeToParcel(data, 0);
 
-        url.writeToParcel(data, 0);
-        values.writeToParcel(data, 0);
+            mRemote.transact(IContentProvider.INSERT_TRANSACTION, data, reply, 0);
 
-        mRemote.transact(IContentProvider.INSERT_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionFromParcel(reply);
-        Uri out = Uri.CREATOR.createFromParcel(reply);
-
-        data.recycle();
-        reply.recycle();
-
-        return out;
+            DatabaseUtils.readExceptionFromParcel(reply);
+            Uri out = Uri.CREATOR.createFromParcel(reply);
+            return out;
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
 
     public int bulkInsert(Uri url, ContentValues[] values) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IContentProvider.descriptor);
 
-        data.writeInterfaceToken(IContentProvider.descriptor);
+            url.writeToParcel(data, 0);
+            data.writeTypedArray(values, 0);
 
-        url.writeToParcel(data, 0);
-        data.writeTypedArray(values, 0);
+            mRemote.transact(IContentProvider.BULK_INSERT_TRANSACTION, data, reply, 0);
 
-        mRemote.transact(IContentProvider.BULK_INSERT_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionFromParcel(reply);
-        int count = reply.readInt();
-
-        data.recycle();
-        reply.recycle();
-
-        return count;
+            DatabaseUtils.readExceptionFromParcel(reply);
+            int count = reply.readInt();
+            return count;
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
 
     public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
             throws RemoteException, OperationApplicationException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IContentProvider.descriptor);
+            data.writeInt(operations.size());
+            for (ContentProviderOperation operation : operations) {
+                operation.writeToParcel(data, 0);
+            }
+            mRemote.transact(IContentProvider.APPLY_BATCH_TRANSACTION, data, reply, 0);
 
-        data.writeInterfaceToken(IContentProvider.descriptor);
-        data.writeInt(operations.size());
-        for (ContentProviderOperation operation : operations) {
-            operation.writeToParcel(data, 0);
+            DatabaseUtils.readExceptionWithOperationApplicationExceptionFromParcel(reply);
+            final ContentProviderResult[] results =
+                    reply.createTypedArray(ContentProviderResult.CREATOR);
+            return results;
+        } finally {
+            data.recycle();
+            reply.recycle();
         }
-        mRemote.transact(IContentProvider.APPLY_BATCH_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionWithOperationApplicationExceptionFromParcel(reply);
-        final ContentProviderResult[] results =
-                reply.createTypedArray(ContentProviderResult.CREATOR);
-
-        data.recycle();
-        reply.recycle();
-
-        return results;
     }
 
     public int delete(Uri url, String selection, String[] selectionArgs)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IContentProvider.descriptor);
 
-        data.writeInterfaceToken(IContentProvider.descriptor);
+            url.writeToParcel(data, 0);
+            data.writeString(selection);
+            data.writeStringArray(selectionArgs);
 
-        url.writeToParcel(data, 0);
-        data.writeString(selection);
-        data.writeStringArray(selectionArgs);
+            mRemote.transact(IContentProvider.DELETE_TRANSACTION, data, reply, 0);
 
-        mRemote.transact(IContentProvider.DELETE_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionFromParcel(reply);
-        int count = reply.readInt();
-
-        data.recycle();
-        reply.recycle();
-
-        return count;
+            DatabaseUtils.readExceptionFromParcel(reply);
+            int count = reply.readInt();
+            return count;
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
 
     public int update(Uri url, ContentValues values, String selection,
             String[] selectionArgs) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IContentProvider.descriptor);
 
-        data.writeInterfaceToken(IContentProvider.descriptor);
+            url.writeToParcel(data, 0);
+            values.writeToParcel(data, 0);
+            data.writeString(selection);
+            data.writeStringArray(selectionArgs);
 
-        url.writeToParcel(data, 0);
-        values.writeToParcel(data, 0);
-        data.writeString(selection);
-        data.writeStringArray(selectionArgs);
+            mRemote.transact(IContentProvider.UPDATE_TRANSACTION, data, reply, 0);
 
-        mRemote.transact(IContentProvider.UPDATE_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionFromParcel(reply);
-        int count = reply.readInt();
-
-        data.recycle();
-        reply.recycle();
-
-        return count;
+            DatabaseUtils.readExceptionFromParcel(reply);
+            int count = reply.readInt();
+            return count;
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
 
     public ParcelFileDescriptor openFile(Uri url, String mode)
             throws RemoteException, FileNotFoundException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IContentProvider.descriptor);
 
-        data.writeInterfaceToken(IContentProvider.descriptor);
+            url.writeToParcel(data, 0);
+            data.writeString(mode);
 
-        url.writeToParcel(data, 0);
-        data.writeString(mode);
+            mRemote.transact(IContentProvider.OPEN_FILE_TRANSACTION, data, reply, 0);
 
-        mRemote.transact(IContentProvider.OPEN_FILE_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
-        int has = reply.readInt();
-        ParcelFileDescriptor fd = has != 0 ? reply.readFileDescriptor() : null;
-
-        data.recycle();
-        reply.recycle();
-
-        return fd;
+            DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
+            int has = reply.readInt();
+            ParcelFileDescriptor fd = has != 0 ? reply.readFileDescriptor() : null;
+            return fd;
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
 
     public AssetFileDescriptor openAssetFile(Uri url, String mode)
             throws RemoteException, FileNotFoundException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IContentProvider.descriptor);
 
-        data.writeInterfaceToken(IContentProvider.descriptor);
+            url.writeToParcel(data, 0);
+            data.writeString(mode);
 
-        url.writeToParcel(data, 0);
-        data.writeString(mode);
+            mRemote.transact(IContentProvider.OPEN_ASSET_FILE_TRANSACTION, data, reply, 0);
 
-        mRemote.transact(IContentProvider.OPEN_ASSET_FILE_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
-        int has = reply.readInt();
-        AssetFileDescriptor fd = has != 0
-                ? AssetFileDescriptor.CREATOR.createFromParcel(reply) : null;
-
-        data.recycle();
-        reply.recycle();
-
-        return fd;
+            DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
+            int has = reply.readInt();
+            AssetFileDescriptor fd = has != 0
+                    ? AssetFileDescriptor.CREATOR.createFromParcel(reply) : null;
+            return fd;
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
 
     public Bundle call(String method, String request, Bundle args)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IContentProvider.descriptor);
 
-        data.writeInterfaceToken(IContentProvider.descriptor);
+            data.writeString(method);
+            data.writeString(request);
+            data.writeBundle(args);
 
-        data.writeString(method);
-        data.writeString(request);
-        data.writeBundle(args);
+            mRemote.transact(IContentProvider.CALL_TRANSACTION, data, reply, 0);
 
-        mRemote.transact(IContentProvider.CALL_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionFromParcel(reply);
-        Bundle bundle = reply.readBundle();
-
-        data.recycle();
-        reply.recycle();
-
-        return bundle;
+            DatabaseUtils.readExceptionFromParcel(reply);
+            Bundle bundle = reply.readBundle();
+            return bundle;
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
 
     public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IContentProvider.descriptor);
 
-        data.writeInterfaceToken(IContentProvider.descriptor);
+            url.writeToParcel(data, 0);
+            data.writeString(mimeTypeFilter);
 
-        url.writeToParcel(data, 0);
-        data.writeString(mimeTypeFilter);
+            mRemote.transact(IContentProvider.GET_STREAM_TYPES_TRANSACTION, data, reply, 0);
 
-        mRemote.transact(IContentProvider.GET_STREAM_TYPES_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionFromParcel(reply);
-        String[] out = reply.createStringArray();
-
-        data.recycle();
-        reply.recycle();
-
-        return out;
+            DatabaseUtils.readExceptionFromParcel(reply);
+            String[] out = reply.createStringArray();
+            return out;
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
 
     public AssetFileDescriptor openTypedAssetFile(Uri url, String mimeType, Bundle opts)
             throws RemoteException, FileNotFoundException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IContentProvider.descriptor);
 
-        data.writeInterfaceToken(IContentProvider.descriptor);
+            url.writeToParcel(data, 0);
+            data.writeString(mimeType);
+            data.writeBundle(opts);
 
-        url.writeToParcel(data, 0);
-        data.writeString(mimeType);
-        data.writeBundle(opts);
+            mRemote.transact(IContentProvider.OPEN_TYPED_ASSET_FILE_TRANSACTION, data, reply, 0);
 
-        mRemote.transact(IContentProvider.OPEN_TYPED_ASSET_FILE_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
-        int has = reply.readInt();
-        AssetFileDescriptor fd = has != 0
-                ? AssetFileDescriptor.CREATOR.createFromParcel(reply) : null;
-
-        data.recycle();
-        reply.recycle();
-
-        return fd;
+            DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
+            int has = reply.readInt();
+            AssetFileDescriptor fd = has != 0
+                    ? AssetFileDescriptor.CREATOR.createFromParcel(reply) : null;
+            return fd;
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
 
     private IBinder mRemote;
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 1e72092..0d25926 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -16,6 +16,8 @@
 
 package android.content;
 
+import dalvik.system.CloseGuard;
+
 import android.accounts.Account;
 import android.app.ActivityManagerNative;
 import android.app.ActivityThread;
@@ -33,6 +35,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.StrictMode;
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.EventLog;
@@ -1562,27 +1565,39 @@
     private final class CursorWrapperInner extends CursorWrapper {
         private final IContentProvider mContentProvider;
         public static final String TAG="CursorWrapperInner";
-        private boolean mCloseFlag = false;
+
+        private final CloseGuard mCloseGuard = CloseGuard.get();
+        private boolean mProviderReleased;
 
         CursorWrapperInner(Cursor cursor, IContentProvider icp) {
             super(cursor);
             mContentProvider = icp;
+            mCloseGuard.open("close");
         }
 
         @Override
         public void close() {
             super.close();
             ContentResolver.this.releaseProvider(mContentProvider);
-            mCloseFlag = true;
+            mProviderReleased = true;
+
+            if (mCloseGuard != null) {
+                mCloseGuard.close();
+            }
         }
 
         @Override
         protected void finalize() throws Throwable {
-            // TODO: integrate CloseGuard support.
             try {
-                if(!mCloseFlag) {
+                if (mCloseGuard != null) {
+                    mCloseGuard.warnIfOpen();
+                }
+
+                if (!mProviderReleased && mContentProvider != null) {
+                    // Even though we are using CloseGuard, log this anyway so that
+                    // application developers always see the message in the log.
                     Log.w(TAG, "Cursor finalized without prior close()");
-                    close();
+                    ContentResolver.this.releaseProvider(mContentProvider);
                 }
             } finally {
                 super.finalize();
diff --git a/core/java/android/database/BulkCursorNative.java b/core/java/android/database/BulkCursorNative.java
index fa62d69..9925a9a 100644
--- a/core/java/android/database/BulkCursorNative.java
+++ b/core/java/android/database/BulkCursorNative.java
@@ -20,12 +20,13 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.RemoteException;
 
 /**
  * Native implementation of the bulk cursor. This is only for use in implementing
  * IPC, application code should use the Cursor interface.
- * 
+ *
  * {@hide}
  */
 public abstract class BulkCursorNative extends Binder implements IBulkCursor
@@ -67,7 +68,7 @@
                     }
                     reply.writeNoException();
                     reply.writeInt(1);
-                    window.writeToParcel(reply, 0);
+                    window.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                     return true;
                 }
 
@@ -184,172 +185,172 @@
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IBulkCursor.descriptor);
+            data.writeInt(startPos);
 
-        data.writeInterfaceToken(IBulkCursor.descriptor);
+            mRemote.transact(GET_CURSOR_WINDOW_TRANSACTION, data, reply, 0);
+            DatabaseUtils.readExceptionFromParcel(reply);
 
-        data.writeInt(startPos);
-
-        mRemote.transact(GET_CURSOR_WINDOW_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionFromParcel(reply);
-        
-        CursorWindow window = null;
-        if (reply.readInt() == 1) {
-            window = CursorWindow.newFromParcel(reply);
+            CursorWindow window = null;
+            if (reply.readInt() == 1) {
+                window = CursorWindow.newFromParcel(reply);
+            }
+            return window;
+        } finally {
+            data.recycle();
+            reply.recycle();
         }
-
-        data.recycle();
-        reply.recycle();
-
-        return window;
     }
 
     public void onMove(int position) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IBulkCursor.descriptor);
+            data.writeInt(position);
 
-        data.writeInterfaceToken(IBulkCursor.descriptor);
-
-        data.writeInt(position);
-
-        mRemote.transact(ON_MOVE_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionFromParcel(reply);
-
-        data.recycle();
-        reply.recycle();
+            mRemote.transact(ON_MOVE_TRANSACTION, data, reply, 0);
+            DatabaseUtils.readExceptionFromParcel(reply);
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
 
     public int count() throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IBulkCursor.descriptor);
 
-        data.writeInterfaceToken(IBulkCursor.descriptor);
+            boolean result = mRemote.transact(COUNT_TRANSACTION, data, reply, 0);
+            DatabaseUtils.readExceptionFromParcel(reply);
 
-        boolean result = mRemote.transact(COUNT_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionFromParcel(reply);
-        
-        int count;
-        if (result == false) {
-            count = -1;
-        } else {
-            count = reply.readInt();
+            int count;
+            if (result == false) {
+                count = -1;
+            } else {
+                count = reply.readInt();
+            }
+            return count;
+        } finally {
+            data.recycle();
+            reply.recycle();
         }
-        data.recycle();
-        reply.recycle();
-        return count;
     }
 
     public String[] getColumnNames() throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IBulkCursor.descriptor);
 
-        data.writeInterfaceToken(IBulkCursor.descriptor);
+            mRemote.transact(GET_COLUMN_NAMES_TRANSACTION, data, reply, 0);
+            DatabaseUtils.readExceptionFromParcel(reply);
 
-        mRemote.transact(GET_COLUMN_NAMES_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionFromParcel(reply);
-        
-        String[] columnNames = null;
-        int numColumns = reply.readInt();
-        columnNames = new String[numColumns];
-        for (int i = 0; i < numColumns; i++) {
-            columnNames[i] = reply.readString();
+            String[] columnNames = null;
+            int numColumns = reply.readInt();
+            columnNames = new String[numColumns];
+            for (int i = 0; i < numColumns; i++) {
+                columnNames[i] = reply.readString();
+            }
+            return columnNames;
+        } finally {
+            data.recycle();
+            reply.recycle();
         }
-        
-        data.recycle();
-        reply.recycle();
-        return columnNames;
     }
 
     public void deactivate() throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IBulkCursor.descriptor);
 
-        data.writeInterfaceToken(IBulkCursor.descriptor);
-
-        mRemote.transact(DEACTIVATE_TRANSACTION, data, reply, 0);
-        DatabaseUtils.readExceptionFromParcel(reply);
-
-        data.recycle();
-        reply.recycle();
+            mRemote.transact(DEACTIVATE_TRANSACTION, data, reply, 0);
+            DatabaseUtils.readExceptionFromParcel(reply);
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
 
     public void close() throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IBulkCursor.descriptor);
 
-        data.writeInterfaceToken(IBulkCursor.descriptor);
-
-        mRemote.transact(CLOSE_TRANSACTION, data, reply, 0);
-        DatabaseUtils.readExceptionFromParcel(reply);
-
-        data.recycle();
-        reply.recycle();
+            mRemote.transact(CLOSE_TRANSACTION, data, reply, 0);
+            DatabaseUtils.readExceptionFromParcel(reply);
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
     
     public int requery(IContentObserver observer, CursorWindow window) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IBulkCursor.descriptor);
+            data.writeStrongInterface(observer);
+            window.writeToParcel(data, 0);
 
-        data.writeInterfaceToken(IBulkCursor.descriptor);
+            boolean result = mRemote.transact(REQUERY_TRANSACTION, data, reply, 0);
+            DatabaseUtils.readExceptionFromParcel(reply);
 
-        data.writeStrongInterface(observer);
-        window.writeToParcel(data, 0);
-
-        boolean result = mRemote.transact(REQUERY_TRANSACTION, data, reply, 0);
-        
-        DatabaseUtils.readExceptionFromParcel(reply);
-
-        int count;
-        if (!result) {
-            count = -1;
-        } else {
-            count = reply.readInt();
-            mExtras = reply.readBundle();
+            int count;
+            if (!result) {
+                count = -1;
+            } else {
+                count = reply.readInt();
+                mExtras = reply.readBundle();
+            }
+            return count;
+        } finally {
+            data.recycle();
+            reply.recycle();
         }
-
-        data.recycle();
-        reply.recycle();
-
-        return count;
     }
 
     public boolean getWantsAllOnMoveCalls() throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IBulkCursor.descriptor);
 
-        data.writeInterfaceToken(IBulkCursor.descriptor);
+            mRemote.transact(WANTS_ON_MOVE_TRANSACTION, data, reply, 0);
+            DatabaseUtils.readExceptionFromParcel(reply);
 
-        mRemote.transact(WANTS_ON_MOVE_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionFromParcel(reply);
-
-        int result = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return result != 0;
+            int result = reply.readInt();
+            return result != 0;
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
 
     public Bundle getExtras() throws RemoteException {
         if (mExtras == null) {
             Parcel data = Parcel.obtain();
             Parcel reply = Parcel.obtain();
+            try {
+                data.writeInterfaceToken(IBulkCursor.descriptor);
 
-            data.writeInterfaceToken(IBulkCursor.descriptor);
+                mRemote.transact(GET_EXTRAS_TRANSACTION, data, reply, 0);
+                DatabaseUtils.readExceptionFromParcel(reply);
 
-            mRemote.transact(GET_EXTRAS_TRANSACTION, data, reply, 0);
-
-            DatabaseUtils.readExceptionFromParcel(reply);
-
-            mExtras = reply.readBundle();
-            data.recycle();
-            reply.recycle();
+                mExtras = reply.readBundle();
+            } finally {
+                data.recycle();
+                reply.recycle();
+            }
         }
         return mExtras;
     }
@@ -357,19 +358,19 @@
     public Bundle respond(Bundle extras) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IBulkCursor.descriptor);
+            data.writeBundle(extras);
 
-        data.writeInterfaceToken(IBulkCursor.descriptor);
+            mRemote.transact(RESPOND_TRANSACTION, data, reply, 0);
+            DatabaseUtils.readExceptionFromParcel(reply);
 
-        data.writeBundle(extras);
-
-        mRemote.transact(RESPOND_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionFromParcel(reply);
-
-        Bundle returnExtras = reply.readBundle();
-        data.recycle();
-        reply.recycle();
-        return returnExtras;
+            Bundle returnExtras = reply.readBundle();
+            return returnExtras;
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
 }
 
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 68385b4..4d7a9bb 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -908,6 +908,9 @@
 
         if (!IS_USER_BUILD) {
             threadPolicyMask |= StrictMode.PENALTY_DROPBOX;
+            if (IS_ENG_BUILD) {
+                threadPolicyMask |= StrictMode.PENALTY_LOG;
+            }
         }
         if (doFlashes) {
             threadPolicyMask |= StrictMode.PENALTY_FLASH;
@@ -918,7 +921,11 @@
         if (IS_USER_BUILD) {
             setCloseGuardEnabled(false);
         } else {
-            setVmPolicy(new VmPolicy.Builder().detectAll().penaltyDropBox().build());
+            VmPolicy.Builder policyBuilder = new VmPolicy.Builder().detectAll().penaltyDropBox();
+            if (IS_ENG_BUILD) {
+                policyBuilder.penaltyLog();
+            }
+            setVmPolicy(policyBuilder.build());
             setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
         }
         return true;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 7a803f9..6d19c23 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2074,7 +2074,8 @@
      * If the value of the encoding parameter is 'base64', then the data must
      * be encoded as base64. Otherwise, the data must use ASCII encoding for
      * octets inside the range of safe URL characters and use the standard %xx
-     * hex encoding of URLs for octets outside that range.
+     * hex encoding of URLs for octets outside that range. For example,
+     * '#', '%', '\', '?' should be replaced by %23, %25, %27, %3f respectively.
      * <p>
      * The 'data' scheme URL formed by this method uses the default US-ASCII
      * charset. If you need need to set a different charset, you should form a
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index fa9417a..1165af5 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -2005,6 +2005,11 @@
             mConnectingDataSource->setUID(mUID);
         }
 
+        String8 cacheConfig;
+        bool disconnectAtHighwatermark;
+        NuCachedSource2::RemoveCacheSpecificHeaders(
+                &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);
+
         mLock.unlock();
         status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
         mLock.lock();
@@ -2024,7 +2029,10 @@
                     new ThrottledSource(
                         mConnectingDataSource, 50 * 1024 /* bytes/sec */));
 #else
-            mCachedSource = new NuCachedSource2(mConnectingDataSource);
+            mCachedSource = new NuCachedSource2(
+                    mConnectingDataSource,
+                    cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
+                    disconnectAtHighwatermark);
 #endif
 
             dataSource = mCachedSource;
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 9adb841..4f183f5 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -177,7 +177,10 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-NuCachedSource2::NuCachedSource2(const sp<DataSource> &source)
+NuCachedSource2::NuCachedSource2(
+        const sp<DataSource> &source,
+        const char *cacheConfig,
+        bool disconnectAtHighwatermark)
     : mSource(source),
       mReflector(new AHandlerReflector<NuCachedSource2>(this)),
       mLooper(new ALooper),
@@ -190,9 +193,24 @@
       mNumRetriesLeft(kMaxNumRetries),
       mHighwaterThresholdBytes(kDefaultHighWaterThreshold),
       mLowwaterThresholdBytes(kDefaultLowWaterThreshold),
-      mKeepAliveIntervalUs(kDefaultKeepAliveIntervalUs) {
+      mKeepAliveIntervalUs(kDefaultKeepAliveIntervalUs),
+      mDisconnectAtHighwatermark(disconnectAtHighwatermark) {
+    // We are NOT going to support disconnect-at-highwatermark indefinitely
+    // and we are not guaranteeing support for client-specified cache
+    // parameters. Both of these are temporary measures to solve a specific
+    // problem that will be solved in a better way going forward.
+
     updateCacheParamsFromSystemProperty();
 
+    if (cacheConfig != NULL) {
+        updateCacheParamsFromString(cacheConfig);
+    }
+
+    if (mDisconnectAtHighwatermark) {
+        // Makes no sense to disconnect and do keep-alives...
+        mKeepAliveIntervalUs = 0;
+    }
+
     mLooper->setName("NuCachedSource2");
     mLooper->registerHandler(mReflector);
     mLooper->start();
@@ -339,6 +357,12 @@
         if (mFetching && mCache->totalSize() >= mHighwaterThresholdBytes) {
             LOGI("Cache full, done prefetching for now");
             mFetching = false;
+
+            if (mDisconnectAtHighwatermark
+                    && (mSource->flags() & DataSource::kIsHTTPBasedSource)) {
+                LOGV("Disconnecting at high watermark");
+                static_cast<HTTPBase *>(mSource.get())->disconnect();
+            }
         }
     } else {
         Mutex::Autolock autoLock(mLock);
@@ -637,4 +661,34 @@
          mKeepAliveIntervalUs);
 }
 
+// static
+void NuCachedSource2::RemoveCacheSpecificHeaders(
+        KeyedVector<String8, String8> *headers,
+        String8 *cacheConfig,
+        bool *disconnectAtHighwatermark) {
+    *cacheConfig = String8();
+    *disconnectAtHighwatermark = false;
+
+    if (headers == NULL) {
+        return;
+    }
+
+    ssize_t index;
+    if ((index = headers->indexOfKey(String8("x-cache-config"))) >= 0) {
+        *cacheConfig = headers->valueAt(index);
+
+        headers->removeItemsAt(index);
+
+        LOGV("Using special cache config '%s'", cacheConfig->string());
+    }
+
+    if ((index = headers->indexOfKey(
+                    String8("x-disconnect-at-highwatermark"))) >= 0) {
+        *disconnectAtHighwatermark = true;
+        headers->removeItemsAt(index);
+
+        LOGV("Client requested disconnection at highwater mark");
+    }
+}
+
 }  // namespace android
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index f04c566..7a03e7e 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -28,7 +28,10 @@
 struct PageCache;
 
 struct NuCachedSource2 : public DataSource {
-    NuCachedSource2(const sp<DataSource> &source);
+    NuCachedSource2(
+            const sp<DataSource> &source,
+            const char *cacheConfig = NULL,
+            bool disconnectAtHighwatermark = false);
 
     virtual status_t initCheck() const;
 
@@ -56,6 +59,11 @@
     status_t getEstimatedBandwidthKbps(int32_t *kbps);
     status_t setCacheStatCollectFreq(int32_t freqMs);
 
+    static void RemoveCacheSpecificHeaders(
+            KeyedVector<String8, String8> *headers,
+            String8 *cacheConfig,
+            bool *disconnectAtHighwatermark);
+
 protected:
     virtual ~NuCachedSource2();
 
@@ -105,6 +113,8 @@
     // If the keep-alive interval is 0, keep-alives are disabled.
     int64_t mKeepAliveIntervalUs;
 
+    bool mDisconnectAtHighwatermark;
+
     void onMessageReceived(const sp<AMessage> &msg);
     void onFetch();
     void onRead(const sp<AMessage> &msg);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index b851ab7..2444829 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -350,16 +350,21 @@
     private byte[] getSystemSettings() {
         Cursor cursor = getContentResolver().query(Settings.System.CONTENT_URI, PROJECTION, null,
                 null, null);
-        byte[] result = extractRelevantValues(cursor, Settings.System.SETTINGS_TO_BACKUP);
-        cursor.close();
-        return result;
+        try {
+            return extractRelevantValues(cursor, Settings.System.SETTINGS_TO_BACKUP);
+        } finally {
+            cursor.close();
+        }
     }
 
     private byte[] getSecureSettings() {
         Cursor cursor = getContentResolver().query(Settings.Secure.CONTENT_URI, PROJECTION, null,
                 null, null);
-        byte[] result = extractRelevantValues(cursor, Settings.Secure.SETTINGS_TO_BACKUP);
-        return result;
+        try {
+            return extractRelevantValues(cursor, Settings.Secure.SETTINGS_TO_BACKUP);
+        } finally {
+            cursor.close();
+        }
     }
 
     private void restoreSettings(BackupDataInput data, Uri contentUri) {
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 51eb0a3..dab0705 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -22,6 +22,9 @@
 ifeq ($(TARGET_BOARD_PLATFORM), omap3)
 	LOCAL_CFLAGS += -DNO_RGBX_8888
 endif
+ifeq ($(TARGET_BOARD_PLATFORM), omap4)
+	LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
+endif
 ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
 	LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
 endif