Merge "Enable display lists."
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f08d88d..378a8bd 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -645,11 +645,13 @@
     Activity mParent;
     boolean mCalled;
     boolean mCheckedForLoaderManager;
-    boolean mStarted;
+    boolean mLoadersStarted;
     private boolean mResumed;
     private boolean mStopped;
     boolean mFinished;
     boolean mStartedActivity;
+    /** true if the activity is going through a transient pause */
+    /*package*/ boolean mTemporaryPause = false;
     /** true if the activity is being destroyed in order to recreate it with a new configuration */
     /*package*/ boolean mChangingConfigurations = false;
     /*package*/ int mConfigChangeFlags;
@@ -768,7 +770,7 @@
             return mLoaderManager;
         }
         mCheckedForLoaderManager = true;
-        mLoaderManager = getLoaderManager(-1, mStarted, true);
+        mLoaderManager = getLoaderManager(-1, mLoadersStarted, true);
         return mLoaderManager;
     }
     
@@ -777,9 +779,13 @@
             mAllLoaderManagers = new SparseArray<LoaderManagerImpl>();
         }
         LoaderManagerImpl lm = mAllLoaderManagers.get(index);
-        if (lm == null && create) {
-            lm = new LoaderManagerImpl(started);
-            mAllLoaderManagers.put(index, lm);
+        if (lm == null) {
+            if (create) {
+                lm = new LoaderManagerImpl(this, started);
+                mAllLoaderManagers.put(index, lm);
+            }
+        } else {
+            lm.updateActivity(this);
         }
         return lm;
     }
@@ -979,13 +985,16 @@
      */
     protected void onStart() {
         mCalled = true;
-        mStarted = true;
-        if (mLoaderManager != null) {
-            mLoaderManager.doStart();
-        } else if (!mCheckedForLoaderManager) {
-            mLoaderManager = getLoaderManager(-1, mStarted, false);
+        
+        if (!mLoadersStarted) {
+            mLoadersStarted = true;
+            if (mLoaderManager != null) {
+                mLoaderManager.doStart();
+            } else if (!mCheckedForLoaderManager) {
+                mLoaderManager = getLoaderManager(-1, mLoadersStarted, false);
+            }
+            mCheckedForLoaderManager = true;
         }
-        mCheckedForLoaderManager = true;
     }
 
     /**
@@ -4249,7 +4258,7 @@
     }
     
     final void performStart() {
-        mFragments.mStateSaved = false;
+        mFragments.noteStateNotSaved();
         mCalled = false;
         mFragments.execPendingActions();
         mInstrumentation.callActivityOnStart(this);
@@ -4267,7 +4276,7 @@
     }
     
     final void performRestart() {
-        mFragments.mStateSaved = false;
+        mFragments.noteStateNotSaved();
 
         synchronized (mManagedCursors) {
             final int N = mManagedCursors.size();
@@ -4347,8 +4356,8 @@
     }
     
     final void performStop() {
-        if (mStarted) {
-            mStarted = false;
+        if (mLoadersStarted) {
+            mLoadersStarted = false;
             if (mLoaderManager != null) {
                 if (!mChangingConfigurations) {
                     mLoaderManager.doStop();
@@ -4407,7 +4416,7 @@
         if (Config.LOGV) Log.v(
             TAG, "Dispatching result: who=" + who + ", reqCode=" + requestCode
             + ", resCode=" + resultCode + ", data=" + data);
-        mFragments.mStateSaved = false;
+        mFragments.noteStateNotSaved();
         if (who == null) {
             onActivityResult(requestCode, resultCode, data);
         } else {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index f3f7ee7..2abe822 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1757,6 +1757,7 @@
         for (int i=0; i<N; i++) {
             Intent intent = intents.get(i);
             intent.setExtrasClassLoader(r.activity.getClassLoader());
+            r.activity.mFragments.noteStateNotSaved();
             mInstrumentation.callActivityOnNewIntent(r.activity, intent);
         }
     }
@@ -1767,11 +1768,13 @@
         if (r != null) {
             final boolean resumed = !r.paused;
             if (resumed) {
+                r.activity.mTemporaryPause = true;
                 mInstrumentation.callActivityOnPause(r.activity);
             }
             deliverNewIntents(r, intents);
             if (resumed) {
                 mInstrumentation.callActivityOnResume(r.activity);
+                r.activity.mTemporaryPause = false;
             }
         }
     }
@@ -2594,6 +2597,7 @@
                 try {
                     // Now we are idle.
                     r.activity.mCalled = false;
+                    r.activity.mTemporaryPause = true;
                     mInstrumentation.callActivityOnPause(r.activity);
                     if (!r.activity.mCalled) {
                         throw new SuperNotCalledException(
@@ -2614,6 +2618,7 @@
             deliverResults(r, res.results);
             if (resumed) {
                 mInstrumentation.callActivityOnResume(r.activity);
+                r.activity.mTemporaryPause = false;
             }
         }
     }
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 12bf7e5..3ec0912 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -403,7 +403,7 @@
     View mView;
     
     LoaderManagerImpl mLoaderManager;
-    boolean mStarted;
+    boolean mLoadersStarted;
     boolean mCheckedForLoaderManager;
     
     /**
@@ -728,7 +728,7 @@
             return mLoaderManager;
         }
         mCheckedForLoaderManager = true;
-        mLoaderManager = mActivity.getLoaderManager(mIndex, mStarted, true);
+        mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, true);
         return mLoaderManager;
     }
     
@@ -880,13 +880,16 @@
      */
     public void onStart() {
         mCalled = true;
-        mStarted = true;
-        if (!mCheckedForLoaderManager) {
-            mCheckedForLoaderManager = true;
-            mLoaderManager = mActivity.getLoaderManager(mIndex, mStarted, false);
-        }
-        if (mLoaderManager != null) {
-            mLoaderManager.doStart();
+        
+        if (!mLoadersStarted) {
+            mLoadersStarted = true;
+            if (!mCheckedForLoaderManager) {
+                mCheckedForLoaderManager = true;
+                mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, false);
+            }
+            if (mLoaderManager != null) {
+                mLoaderManager.doStart();
+            }
         }
     }
     
@@ -971,7 +974,7 @@
         //        + " mLoaderManager=" + mLoaderManager);
         if (!mCheckedForLoaderManager) {
             mCheckedForLoaderManager = true;
-            mLoaderManager = mActivity.getLoaderManager(mIndex, mStarted, false);
+            mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, false);
         }
         if (mLoaderManager != null) {
             mLoaderManager.doDestroy();
@@ -1182,7 +1185,7 @@
         }
         if (mLoaderManager != null) {
             writer.print(prefix); writer.print("mLoaderManager="); writer.print(mLoaderManager);
-                    writer.print(" mStarted="); writer.print(mStarted);
+                    writer.print(" mLoadersStarted="); writer.print(mLoadersStarted);
                     writer.print(" mCheckedForLoaderManager=");
                     writer.println(mCheckedForLoaderManager);
         }
@@ -1190,11 +1193,12 @@
 
     void performStop() {
         onStop();
-        if (mStarted) {
-            mStarted = false;
+        
+        if (mLoadersStarted) {
+            mLoadersStarted = false;
             if (!mCheckedForLoaderManager) {
                 mCheckedForLoaderManager = true;
-                mLoaderManager = mActivity.getLoaderManager(mIndex, mStarted, false);
+                mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, false);
             }
             if (mLoaderManager != null) {
                 if (mActivity == null || !mActivity.mChangingConfigurations) {
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 37e7253..d9a6171 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -86,6 +86,15 @@
     /**
      * Start a series of edit operations on the Fragments associated with
      * this FragmentManager.
+     * 
+     * <p>Note: A fragment transaction can only be created/committed prior
+     * to an activity saving its state.  If you try to commit a transaction
+     * after {@link Activity#onSaveInstanceState Activity.onSaveInstanceState()}
+     * (and prior to a following {@link Activity#onStart Activity.onStart}
+     * or {@link Activity#onResume Activity.onResume()}, you will get an error.
+     * This is because the framework takes care of saving your current fragments
+     * in the state, and if changes are made after the state is saved then they
+     * will be lost.</p>
      */
     public FragmentTransaction openTransaction();
 
@@ -271,6 +280,7 @@
     
     boolean mNeedMenuInvalidate;
     boolean mStateSaved;
+    String mNoTransactionsBecause;
     
     // Temporary vars for state save and restore.
     Bundle mStateBundle = null;
@@ -843,6 +853,10 @@
             throw new IllegalStateException(
                     "Can not perform this action after onSaveInstanceState");
         }
+        if (mNoTransactionsBecause != null) {
+            throw new IllegalStateException(
+                    "Can not perform this action inside of " + mNoTransactionsBecause);
+        }
         synchronized (this) {
             if (mPendingActions == null) {
                 mPendingActions = new ArrayList<Runnable>();
@@ -1271,6 +1285,10 @@
         mActivity = activity;
     }
     
+    public void noteStateNotSaved() {
+        mStateSaved = false;
+    }
+    
     public void dispatchCreate() {
         mStateSaved = false;
         moveToState(Fragment.CREATED, false);
diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java
index 28abcaa..4d4ea9a 100644
--- a/core/java/android/app/LoaderManager.java
+++ b/core/java/android/app/LoaderManager.java
@@ -40,7 +40,12 @@
         public Loader<D> onCreateLoader(int id, Bundle args);
 
         /**
-         * Called when a previously created loader has finished its load.
+         * Called when a previously created loader has finished its load.  Note
+         * that normally an application is <em>not</em> allowed to commit fragment
+         * transactions while in this call, since it can happen after an
+         * activity's state is saved.  See {@link FragmentManager#openTransaction()
+         * FragmentManager.openTransaction()} for further discussion on this.
+         * 
          * @param loader The Loader that has finished.
          * @param data The data generated by the Loader.
          */
@@ -102,6 +107,7 @@
     // previously run loader until the new loader's data is available.
     final SparseArray<LoaderInfo> mInactiveLoaders = new SparseArray<LoaderInfo>();
 
+    Activity mActivity;
     boolean mStarted;
     boolean mRetaining;
     boolean mRetainingStarted;
@@ -172,12 +178,12 @@
                         stop();
                     }
                 }
-                if (mStarted && mData != null && mCallbacks != null) {
+                if (mStarted && mData != null) {
                     // This loader was retained, and now at the point of
                     // finishing the retain we find we remain started, have
                     // our data, and the owner has a new callback...  so
                     // let's deliver the data now.
-                    mCallbacks.onLoadFinished(mLoader, mData);
+                    callOnLoadFinished(mLoader, mData);
                 }
             }
         }
@@ -219,9 +225,7 @@
             // Notify of the new data so the app can switch out the old data before
             // we try to destroy it.
             mData = data;
-            if (mCallbacks != null) {
-                mCallbacks.onLoadFinished(loader, data);
-            }
+            callOnLoadFinished(loader, data);
 
             if (DEBUG) Log.v(TAG, "onLoadFinished returned: " + this);
 
@@ -236,6 +240,23 @@
             }
         }
 
+        void callOnLoadFinished(Loader<Object> loader, Object data) {
+            if (mCallbacks != null) {
+                String lastBecause = null;
+                if (mActivity != null) {
+                    lastBecause = mActivity.mFragments.mNoTransactionsBecause;
+                    mActivity.mFragments.mNoTransactionsBecause = "onLoadFinished";
+                }
+                try {
+                    mCallbacks.onLoadFinished(loader, data);
+                } finally {
+                    if (mActivity != null) {
+                        mActivity.mFragments.mNoTransactionsBecause = lastBecause;
+                    }
+                }
+            }
+        }
+        
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder(64);
@@ -252,10 +273,15 @@
         }
     }
     
-    LoaderManagerImpl(boolean started) {
+    LoaderManagerImpl(Activity activity, boolean started) {
+        mActivity = activity;
         mStarted = started;
     }
     
+    void updateActivity(Activity activity) {
+        mActivity = activity;
+    }
+    
     private LoaderInfo createLoader(int id, Bundle args,
             LoaderManager.LoaderCallbacks<Object> callback) {
         LoaderInfo info = new LoaderInfo(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);
@@ -286,7 +312,7 @@
         
         if (info.mData != null && mStarted) {
             // If the loader has already generated its data, report it now.
-            info.mCallbacks.onLoadFinished(info.mLoader, info.mData);
+            info.callOnLoadFinished(info.mLoader, info.mData);
         }
         
         return (Loader<D>)info.mLoader;
@@ -348,7 +374,13 @@
  
     void doStart() {
         if (DEBUG) Log.v(TAG, "Starting: " + this);
-
+        if (mStarted) {
+            RuntimeException e = new RuntimeException("here");
+            e.fillInStackTrace();
+            Log.w(TAG, "Called doStart when already started: " + this, e);
+            return;
+        }
+        
         // Call out to sub classes so they can start their loaders
         // Let the existing loaders know that we want to be notified when a load is complete
         for (int i = mLoaders.size()-1; i >= 0; i--) {
@@ -359,6 +391,12 @@
     
     void doStop() {
         if (DEBUG) Log.v(TAG, "Stopping: " + this);
+        if (!mStarted) {
+            RuntimeException e = new RuntimeException("here");
+            e.fillInStackTrace();
+            Log.w(TAG, "Called doStop when not started: " + this, e);
+            return;
+        }
 
         for (int i = mLoaders.size()-1; i >= 0; i--) {
             mLoaders.valueAt(i).stop();
@@ -368,6 +406,12 @@
     
     void doRetain() {
         if (DEBUG) Log.v(TAG, "Retaining: " + this);
+        if (!mStarted) {
+            RuntimeException e = new RuntimeException("here");
+            e.fillInStackTrace();
+            Log.w(TAG, "Called doRetain when not started: " + this, e);
+            return;
+        }
 
         mRetaining = true;
         mStarted = false;
diff --git a/core/java/android/nfc/ErrorCodes.java b/core/java/android/nfc/ErrorCodes.java
index 5b76d84..69329df 100644
--- a/core/java/android/nfc/ErrorCodes.java
+++ b/core/java/android/nfc/ErrorCodes.java
@@ -33,6 +33,34 @@
         }
     }
 
+    public static String asString(int code) {
+        switch (code) {
+            case SUCCESS: return "SUCCESS";
+            case ERROR_IO: return "IO";
+            case ERROR_CANCELLED: return "CANCELLED";
+            case ERROR_TIMEOUT: return "TIMEOUT";
+            case ERROR_BUSY: return "BUSY";
+            case ERROR_CONNECT: return "CONNECT/DISCONNECT";
+//            case ERROR_DISCONNECT: return "DISCONNECT";
+            case ERROR_READ: return "READ";
+            case ERROR_WRITE: return "WRITE";
+            case ERROR_INVALID_PARAM: return "INVALID_PARAM";
+            case ERROR_INSUFFICIENT_RESOURCES: return "INSUFFICIENT_RESOURCES";
+            case ERROR_SOCKET_CREATION: return "SOCKET_CREATION";
+            case ERROR_SOCKET_NOT_CONNECTED: return "SOCKET_NOT_CONNECTED";
+            case ERROR_BUFFER_TO_SMALL: return "BUFFER_TO_SMALL";
+            case ERROR_SAP_USED: return "SAP_USED";
+            case ERROR_SERVICE_NAME_USED: return "SERVICE_NAME_USED";
+            case ERROR_SOCKET_OPTIONS: return "SOCKET_OPTIONS";
+            case ERROR_NFC_ON: return "NFC_ON";
+            case ERROR_NOT_INITIALIZED: return "NOT_INITIALIZED";
+            case ERROR_SE_ALREADY_SELECTED: return "SE_ALREADY_SELECTED";
+            case ERROR_SE_CONNECTED: return "SE_CONNECTED";
+            case ERROR_NO_SE_CONNECTED: return "NO_SE_CONNECTED";
+            default: return "UNKNOWN ERROR";
+        }
+    }
+
     public static final int SUCCESS = 0;
 
     public static final int ERROR_IO = -1;
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index b6da308..b5e85a0 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -498,6 +498,7 @@
                     handleSinkPlayingStateChange(device, BluetoothA2dp.STATE_NOT_PLAYING,
                         BluetoothA2dp.STATE_PLAYING);
                 } else {
+                   mPlayingA2dpDevice = null;
                    int prevState = mAudioDevices.get(device);
                    handleSinkStateChange(device, prevState, state);
                 }
@@ -512,7 +513,6 @@
                 mSinkCount--;
             } else if (state == BluetoothA2dp.STATE_CONNECTED) {
                 mSinkCount ++;
-                mPlayingA2dpDevice = null;
             }
             mAudioDevices.put(device, state);
 
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index ff31dec..2949208 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -21,6 +21,7 @@
 import android.app.LocalActivityManager;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.util.AttributeSet;
@@ -63,6 +64,8 @@
     private OnTabChangeListener mOnTabChangeListener;
     private OnKeyListener mTabKeyListener;
 
+    private int mTabLayoutId;
+
     public TabHost(Context context) {
         super(context);
         initTabHost();
@@ -70,6 +73,18 @@
 
     public TabHost(Context context, AttributeSet attrs) {
         super(context, attrs);
+
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.TabWidget,
+                com.android.internal.R.attr.tabWidgetStyle, 0);
+
+        mTabLayoutId = a.getResourceId(R.styleable.TabWidget_tabLayout, 0);
+        if (mTabLayoutId == 0) {
+            throw new IllegalArgumentException("Invalid TabWidget tabLayout id");
+        }
+
+        a.recycle();
+
         initTabHost();
     }
 
@@ -214,6 +229,7 @@
         if (tabSpec.mIndicatorStrategy instanceof ViewIndicatorStrategy) {
             mTabWidget.setStripEnabled(false);
         }
+
         mTabWidget.addView(tabIndicator);
         mTabSpecs.add(tabSpec);
 
@@ -513,7 +529,7 @@
             final Context context = getContext();
             LayoutInflater inflater =
                     (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-            View tabIndicator = inflater.inflate(R.layout.tab_indicator,
+            View tabIndicator = inflater.inflate(mTabLayoutId,
                     mTabWidget, // tab widget is the parent
                     false); // no inflate params
 
@@ -525,7 +541,7 @@
                 tabIndicator.setBackgroundResource(R.drawable.tab_indicator_v4);
                 tv.setTextColor(context.getResources().getColorStateList(R.color.tab_indicator_text_v4));
             }
-            
+
             return tabIndicator;
         }
     }
@@ -547,7 +563,7 @@
             final Context context = getContext();
             LayoutInflater inflater =
                     (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-            View tabIndicator = inflater.inflate(R.layout.tab_indicator,
+            View tabIndicator = inflater.inflate(mTabLayoutId,
                     mTabWidget, // tab widget is the parent
                     false); // no inflate params
 
@@ -555,14 +571,17 @@
             tv.setText(mLabel);
 
             final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.icon);
-            iconView.setImageDrawable(mIcon);
+            if (mIcon != null) {
+                iconView.setImageDrawable(mIcon);
+                iconView.setVisibility(VISIBLE);
+            }
 
             if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.DONUT) {
                 // Donut apps get old color scheme
                 tabIndicator.setBackgroundResource(R.drawable.tab_indicator_v4);
                 tv.setTextColor(context.getResources().getColorStateList(R.color.tab_indicator_text_v4));
             }
-            
+
             return tabIndicator;
         }
     }
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 0469e7b..36adacd 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -120,7 +120,9 @@
 
         final Context context = mContext;
         final Resources resources = context.getResources();
-        
+
+        // Tests the target Sdk version, as set in the Manifest. Could not be set using styles.xml
+        // in a values-v? directory which targets the current platform Sdk version instead.
         if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.DONUT) {
             // Donut apps get old color scheme
             if (mLeftStrip == null) {
@@ -131,16 +133,6 @@
                 mRightStrip = resources.getDrawable(
                         com.android.internal.R.drawable.tab_bottom_right_v4);
             }
-        } else {
-            // Use modern color scheme for Eclair and beyond
-            if (mLeftStrip == null) {
-                mLeftStrip = resources.getDrawable(
-                        com.android.internal.R.drawable.tab_bottom_left);
-            }
-            if (mRightStrip == null) {
-                mRightStrip = resources.getDrawable(
-                        com.android.internal.R.drawable.tab_bottom_right);
-            }
         }
 
         // Deal with focus, as we don't want the focus to go by default
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 09563fc..6897537 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -7142,6 +7142,7 @@
                     case Gravity.RIGHT:
                         return 0.0f;
                     case Gravity.CENTER_HORIZONTAL:
+                    case Gravity.FILL_HORIZONTAL:
                         return (mLayout.getLineWidth(0) - ((mRight - mLeft) -
                                 getCompoundPaddingLeft() - getCompoundPaddingRight())) /
                                 getHorizontalFadingEdgeLength();
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index f3be8b0..e2a959d 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -24,6 +24,7 @@
 #include "SkPorterDuff.h"
 
 #include <SkiaColorFilter.h>
+#include <Caches.h>
 
 namespace android {
 
@@ -32,28 +33,37 @@
 class SkColorFilterGlue {
 public:
     static void finalizer(JNIEnv* env, jobject clazz, SkColorFilter* obj, SkiaColorFilter* f) {
-        delete f;
         obj->safeUnref();
+        // f == NULL when not !USE_OPENGL_RENDERER, so no need to delete outside the ifdef
+#ifdef USE_OPENGL_RENDERER
+        if (android::uirenderer::Caches::hasInstance()) {
+            android::uirenderer::Caches::getInstance().resourceCache.destructor(f);
+        } else {
+            delete f;
+        }
+#endif
     }
 
-    static SkiaColorFilter* glCreatePorterDuffFilter(JNIEnv* env, jobject, jint srcColor,
-            SkPorterDuff::Mode mode) {
+    static SkiaColorFilter* glCreatePorterDuffFilter(JNIEnv* env, jobject, SkColorFilter *skFilter,
+            jint srcColor, SkPorterDuff::Mode mode) {
 #ifdef USE_OPENGL_RENDERER
-        return new SkiaBlendFilter(srcColor, SkPorterDuff::ToXfermodeMode(mode));
+        return new SkiaBlendFilter(skFilter, srcColor, SkPorterDuff::ToXfermodeMode(mode));
 #else
         return NULL;
 #endif
     }
 
-    static SkiaColorFilter* glCreateLightingFilter(JNIEnv* env, jobject, jint mul, jint add) {
+    static SkiaColorFilter* glCreateLightingFilter(JNIEnv* env, jobject, SkColorFilter *skFilter,
+            jint mul, jint add) {
 #ifdef USE_OPENGL_RENDERER
-        return new SkiaLightingFilter(mul, add);
+        return new SkiaLightingFilter(skFilter, mul, add);
 #else
         return NULL;
 #endif
     }
 
-    static SkiaColorFilter* glCreateColorMatrixFilter(JNIEnv* env, jobject, jfloatArray jarray) {
+    static SkiaColorFilter* glCreateColorMatrixFilter(JNIEnv* env, jobject, SkColorFilter *skFilter,
+            jfloatArray jarray) {
 #ifdef USE_OPENGL_RENDERER
         AutoJavaFloatArray autoArray(env, jarray, 20);
         const float* src = autoArray.ptr();
@@ -70,7 +80,7 @@
         colorVector[2] = src[14];
         colorVector[3] = src[19];
 
-        return new SkiaColorMatrixFilter(colorMatrix, colorVector);
+        return new SkiaColorMatrixFilter(skFilter, colorMatrix, colorVector);
 #else
         return NULL;
 #endif
@@ -107,17 +117,17 @@
 
 static JNINativeMethod porterduff_methods[] = {
     { "native_CreatePorterDuffFilter", "(II)I", (void*) SkColorFilterGlue::CreatePorterDuffFilter   },
-    { "nCreatePorterDuffFilter",       "(II)I", (void*) SkColorFilterGlue::glCreatePorterDuffFilter }
+    { "nCreatePorterDuffFilter",       "(III)I", (void*) SkColorFilterGlue::glCreatePorterDuffFilter }
 };
 
 static JNINativeMethod lighting_methods[] = {
     { "native_CreateLightingFilter", "(II)I", (void*) SkColorFilterGlue::CreateLightingFilter   },
-    { "nCreateLightingFilter",       "(II)I", (void*) SkColorFilterGlue::glCreateLightingFilter },
+    { "nCreateLightingFilter",       "(III)I", (void*) SkColorFilterGlue::glCreateLightingFilter },
 };
 
 static JNINativeMethod colormatrix_methods[] = {
     { "nativeColorMatrixFilter", "([F)I", (void*) SkColorFilterGlue::CreateColorMatrixFilter   },
-    { "nColorMatrixFilter",      "([F)I", (void*) SkColorFilterGlue::glCreateColorMatrixFilter }
+    { "nColorMatrixFilter",      "(I[F)I", (void*) SkColorFilterGlue::glCreateColorMatrixFilter }
 };
 
 #define REG(env, name, array) \
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 79051c2..4be1321 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -58,6 +58,8 @@
 #ifdef USE_OPENGL_RENDERER
     if (android::uirenderer::Caches::hasInstance()) {
         android::uirenderer::Caches::getInstance().resourceCache.destructor(skiaShader);
+    } else {
+        delete skiaShader;
     }
 #endif
 }
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 45fd5a0..a586f49 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -1029,7 +1029,7 @@
 
 #define FIND_CLASS(var, className) \
         var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className); \
+        LOG_FATAL_IF(! var, "Unable to find class %s", className); \
         var = jclass(env->NewGlobalRef(var));
 
 #define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index defd0a0..27d4b9e 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -25,6 +25,7 @@
 #include "wifi.h"
 
 #define WIFI_PKG_NAME "android/net/wifi/WifiNative"
+#define BUF_SIZE 256
 
 namespace android {
 
@@ -67,7 +68,7 @@
 
 static jint doIntCommand(const char *cmd)
 {
-    char reply[256];
+    char reply[BUF_SIZE];
 
     if (doCommand(cmd, reply, sizeof(reply)) != 0) {
         return (jint)-1;
@@ -78,7 +79,7 @@
 
 static jboolean doBooleanCommand(const char *cmd, const char *expect)
 {
-    char reply[256];
+    char reply[BUF_SIZE];
 
     if (doCommand(cmd, reply, sizeof(reply)) != 0) {
         return (jboolean)JNI_FALSE;
@@ -137,7 +138,7 @@
 
 static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject clazz)
 {
-    char buf[256];
+    char buf[BUF_SIZE];
 
     int nread = ::wifi_wait_for_event(buf, sizeof buf);
     if (nread > 0) {
@@ -159,7 +160,7 @@
 
 static jboolean android_net_wifi_wpsPbcCommand(JNIEnv* env, jobject clazz, jstring bssid)
 {
-    char cmdstr[50];
+    char cmdstr[BUF_SIZE];
     jboolean isCopy;
 
     const char *bssidStr = env->GetStringUTFChars(bssid, &isCopy);
@@ -172,9 +173,9 @@
     return doBooleanCommand(cmdstr, "OK");
 }
 
-static jboolean android_net_wifi_wpsPinCommand(JNIEnv* env, jobject clazz, jstring bssid, int apPin)
+static jboolean android_net_wifi_wpsPinFromAccessPointCommand(JNIEnv* env, jobject clazz, jstring bssid, int apPin)
 {
-    char cmdstr[50];
+    char cmdstr[BUF_SIZE];
     jboolean isCopy;
 
     const char *bssidStr = env->GetStringUTFChars(bssid, &isCopy);
@@ -187,13 +188,29 @@
     return doBooleanCommand(cmdstr, "OK");
 }
 
+static jint android_net_wifi_wpsPinFromDeviceCommand(JNIEnv* env, jobject clazz, jstring bssid)
+{
+    char cmdstr[BUF_SIZE];
+    jboolean isCopy;
+
+    const char *bssidStr = env->GetStringUTFChars(bssid, &isCopy);
+    int numWritten = snprintf(cmdstr, sizeof(cmdstr), "WPS_PIN %s", bssidStr);
+    env->ReleaseStringUTFChars(bssid, bssidStr);
+
+    if ((numWritten == -1) || (numWritten >= (int)sizeof(cmdstr))) {
+        return false;
+    }
+    return doIntCommand(cmdstr);
+}
+
+
 static jboolean android_net_wifi_setNetworkVariableCommand(JNIEnv* env,
                                                            jobject clazz,
                                                            jint netId,
                                                            jstring name,
                                                            jstring value)
 {
-    char cmdstr[256];
+    char cmdstr[BUF_SIZE];
     jboolean isCopy;
 
     const char *nameStr = env->GetStringUTFChars(name, &isCopy);
@@ -216,7 +233,7 @@
                                                           jint netId,
                                                           jstring name)
 {
-    char cmdstr[256];
+    char cmdstr[BUF_SIZE];
     jboolean isCopy;
 
     const char *nameStr = env->GetStringUTFChars(name, &isCopy);
@@ -234,7 +251,7 @@
 
 static jboolean android_net_wifi_removeNetworkCommand(JNIEnv* env, jobject clazz, jint netId)
 {
-    char cmdstr[256];
+    char cmdstr[BUF_SIZE];
 
     int numWritten = snprintf(cmdstr, sizeof(cmdstr), "REMOVE_NETWORK %d", netId);
     int cmdTooLong = numWritten >= (int)sizeof(cmdstr);
@@ -247,7 +264,7 @@
                                                   jint netId,
                                                   jboolean disableOthers)
 {
-    char cmdstr[256];
+    char cmdstr[BUF_SIZE];
     const char *cmd = disableOthers ? "SELECT_NETWORK" : "ENABLE_NETWORK";
 
     int numWritten = snprintf(cmdstr, sizeof(cmdstr), "%s %d", cmd, netId);
@@ -258,7 +275,7 @@
 
 static jboolean android_net_wifi_disableNetworkCommand(JNIEnv* env, jobject clazz, jint netId)
 {
-    char cmdstr[256];
+    char cmdstr[BUF_SIZE];
 
     int numWritten = snprintf(cmdstr, sizeof(cmdstr), "DISABLE_NETWORK %d", netId);
     int cmdTooLong = numWritten >= (int)sizeof(cmdstr);
@@ -352,7 +369,7 @@
 
 static jint android_net_wifi_getRssiHelper(const char *cmd)
 {
-    char reply[256];
+    char reply[BUF_SIZE];
     int rssi = -200;
 
     if (doCommand(cmd, reply, sizeof(reply)) != 0) {
@@ -391,7 +408,7 @@
 
 static jint android_net_wifi_getLinkSpeedCommand(JNIEnv* env, jobject clazz)
 {
-    char reply[256];
+    char reply[BUF_SIZE];
     int linkspeed;
 
     if (doCommand("DRIVER LINKSPEED", reply, sizeof(reply)) != 0) {
@@ -405,8 +422,8 @@
 
 static jstring android_net_wifi_getMacAddressCommand(JNIEnv* env, jobject clazz)
 {
-    char reply[256];
-    char buf[256];
+    char reply[BUF_SIZE];
+    char buf[BUF_SIZE];
 
     if (doCommand("DRIVER MACADDR", reply, sizeof(reply)) != 0) {
         return env->NewStringUTF(NULL);
@@ -421,7 +438,7 @@
 
 static jboolean android_net_wifi_setPowerModeCommand(JNIEnv* env, jobject clazz, jint mode)
 {
-    char cmdstr[256];
+    char cmdstr[BUF_SIZE];
 
     int numWritten = snprintf(cmdstr, sizeof(cmdstr), "DRIVER POWERMODE %d", mode);
     int cmdTooLong = numWritten >= (int)sizeof(cmdstr);
@@ -431,7 +448,7 @@
 
 static jint android_net_wifi_getPowerModeCommand(JNIEnv* env, jobject clazz)
 {
-    char reply[256];
+    char reply[BUF_SIZE];
     int power;
 
     if (doCommand("DRIVER GETPOWER", reply, sizeof(reply)) != 0) {
@@ -469,7 +486,7 @@
 
 static jboolean android_net_wifi_setNumAllowedChannelsCommand(JNIEnv* env, jobject clazz, jint numChannels)
 {
-    char cmdstr[256];
+    char cmdstr[BUF_SIZE];
 
     int numWritten = snprintf(cmdstr, sizeof(cmdstr), "DRIVER SCAN-CHANNELS %u", numChannels);
     int cmdTooLong = numWritten >= (int)sizeof(cmdstr);
@@ -479,7 +496,7 @@
 
 static jint android_net_wifi_getNumAllowedChannelsCommand(JNIEnv* env, jobject clazz)
 {
-    char reply[256];
+    char reply[BUF_SIZE];
     int numChannels;
 
     if (doCommand("DRIVER SCAN-CHANNELS", reply, sizeof(reply)) != 0) {
@@ -495,7 +512,7 @@
 
 static jboolean android_net_wifi_setBluetoothCoexistenceModeCommand(JNIEnv* env, jobject clazz, jint mode)
 {
-    char cmdstr[256];
+    char cmdstr[BUF_SIZE];
 
     int numWritten = snprintf(cmdstr, sizeof(cmdstr), "DRIVER BTCOEXMODE %d", mode);
     int cmdTooLong = numWritten >= (int)sizeof(cmdstr);
@@ -505,7 +522,7 @@
 
 static jboolean android_net_wifi_setBluetoothCoexistenceScanModeCommand(JNIEnv* env, jobject clazz, jboolean setCoexScanMode)
 {
-    char cmdstr[256];
+    char cmdstr[BUF_SIZE];
 
     int numWritten = snprintf(cmdstr, sizeof(cmdstr), "DRIVER BTCOEXSCAN-%s", setCoexScanMode ? "START" : "STOP");
     int cmdTooLong = numWritten >= (int)sizeof(cmdstr);
@@ -527,7 +544,7 @@
 
 static jboolean android_net_wifi_setScanResultHandlingCommand(JNIEnv* env, jobject clazz, jint mode)
 {
-    char cmdstr[256];
+    char cmdstr[BUF_SIZE];
 
     int numWritten = snprintf(cmdstr, sizeof(cmdstr), "AP_SCAN %d", mode);
     int cmdTooLong = numWritten >= (int)sizeof(cmdstr);
@@ -537,7 +554,7 @@
 
 static jboolean android_net_wifi_addToBlacklistCommand(JNIEnv* env, jobject clazz, jstring bssid)
 {
-    char cmdstr[256];
+    char cmdstr[BUF_SIZE];
     jboolean isCopy;
 
     const char *bssidStr = env->GetStringUTFChars(bssid, &isCopy);
@@ -636,7 +653,10 @@
     { "addToBlacklistCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_addToBlacklistCommand },
     { "clearBlacklistCommand", "()Z", (void*) android_net_wifi_clearBlacklistCommand },
     { "startWpsPbcCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_wpsPbcCommand },
-    { "startWpsPinCommand", "(Ljava/lang/String;I)Z", (void*) android_net_wifi_wpsPinCommand },
+    { "startWpsWithPinFromAccessPointCommand", "(Ljava/lang/String;I)Z",
+        (void*) android_net_wifi_wpsPinFromAccessPointCommand },
+    { "startWpsWithPinFromDeviceCommand", "(Ljava/lang/String;)I",
+        (void*) android_net_wifi_wpsPinFromDeviceCommand },
     { "doDhcpRequest", "(Landroid/net/DhcpInfo;)Z", (void*) android_net_wifi_doDhcpRequest },
     { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_wifi_getDhcpError },
 };
diff --git a/core/res/res/drawable-hdpi/tab_arrow_left_holo_dark.png b/core/res/res/drawable-hdpi/tab_arrow_left_holo_dark.png
deleted file mode 100644
index cfd6f78..0000000
--- a/core/res/res/drawable-hdpi/tab_arrow_left_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_arrow_left_holo_light.png b/core/res/res/drawable-hdpi/tab_arrow_left_holo_light.png
deleted file mode 100644
index 036aa8c..0000000
--- a/core/res/res/drawable-hdpi/tab_arrow_left_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_arrow_right_holo_dark.png b/core/res/res/drawable-hdpi/tab_arrow_right_holo_dark.png
deleted file mode 100644
index b226038..0000000
--- a/core/res/res/drawable-hdpi/tab_arrow_right_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_arrow_right_holo_light.png b/core/res/res/drawable-hdpi/tab_arrow_right_holo_light.png
deleted file mode 100644
index 0e5fbe6..0000000
--- a/core/res/res/drawable-hdpi/tab_arrow_right_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_bottom_holo.9.png b/core/res/res/drawable-hdpi/tab_bottom_holo.9.png
new file mode 100644
index 0000000..ec9fa8d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_bottom_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_divider_holo_dark.png b/core/res/res/drawable-hdpi/tab_divider_holo_dark.png
deleted file mode 100644
index 112cb04..0000000
--- a/core/res/res/drawable-hdpi/tab_divider_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_divider_holo_light.png b/core/res/res/drawable-hdpi/tab_divider_holo_light.png
deleted file mode 100644
index 1bf4d38..0000000
--- a/core/res/res/drawable-hdpi/tab_divider_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selected_focused_holo.9.png b/core/res/res/drawable-hdpi/tab_selected_focused_holo.9.png
new file mode 100644
index 0000000..1ba35d5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selected_holo.9.png b/core/res/res/drawable-hdpi/tab_selected_holo.9.png
new file mode 100644
index 0000000..ef913cc
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png b/core/res/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..d7e9688
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selected_pressed_holo.9.png b/core/res/res/drawable-hdpi/tab_selected_pressed_holo.9.png
new file mode 100644
index 0000000..b8b1fcf
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selector_holo_dark.9.png b/core/res/res/drawable-hdpi/tab_selector_holo_dark.9.png
deleted file mode 100644
index f01b9bc..0000000
--- a/core/res/res/drawable-hdpi/tab_selector_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_strip_holo.9.png b/core/res/res/drawable-hdpi/tab_strip_holo.9.png
deleted file mode 100644
index d937f6b..0000000
--- a/core/res/res/drawable-hdpi/tab_strip_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_unselected_focused_holo.9.png b/core/res/res/drawable-hdpi/tab_unselected_focused_holo.9.png
new file mode 100644
index 0000000..256e8e7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_unselected_holo.9.png b/core/res/res/drawable-hdpi/tab_unselected_holo.9.png
new file mode 100644
index 0000000..eaa306a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_unselected_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png b/core/res/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..d17b820
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_unselected_pressed_holo.9.png b/core/res/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
new file mode 100644
index 0000000..a344994
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_arrow_left_holo_dark.png b/core/res/res/drawable-mdpi/tab_arrow_left_holo_dark.png
deleted file mode 100644
index 4f8bafe..0000000
--- a/core/res/res/drawable-mdpi/tab_arrow_left_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_arrow_left_holo_light.png b/core/res/res/drawable-mdpi/tab_arrow_left_holo_light.png
deleted file mode 100644
index 8e225fc..0000000
--- a/core/res/res/drawable-mdpi/tab_arrow_left_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_arrow_right_holo_dark.png b/core/res/res/drawable-mdpi/tab_arrow_right_holo_dark.png
deleted file mode 100644
index 0a8006d..0000000
--- a/core/res/res/drawable-mdpi/tab_arrow_right_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_arrow_right_holo_light.png b/core/res/res/drawable-mdpi/tab_arrow_right_holo_light.png
deleted file mode 100644
index 85aae47..0000000
--- a/core/res/res/drawable-mdpi/tab_arrow_right_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_bottom_holo.9.png b/core/res/res/drawable-mdpi/tab_bottom_holo.9.png
new file mode 100644
index 0000000..1e40b9c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_bottom_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_divider_holo_dark.png b/core/res/res/drawable-mdpi/tab_divider_holo_dark.png
deleted file mode 100644
index 89d7b8b..0000000
--- a/core/res/res/drawable-mdpi/tab_divider_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_divider_holo_light.png b/core/res/res/drawable-mdpi/tab_divider_holo_light.png
deleted file mode 100644
index 878b2b4..0000000
--- a/core/res/res/drawable-mdpi/tab_divider_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_focused_holo.9.png b/core/res/res/drawable-mdpi/tab_focused_holo.9.png
new file mode 100644
index 0000000..187d8c5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_pressed_holo.9.png b/core/res/res/drawable-mdpi/tab_pressed_holo.9.png
new file mode 100644
index 0000000..a76fbae
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected_focused_holo.9.png b/core/res/res/drawable-mdpi/tab_selected_focused_holo.9.png
new file mode 100644
index 0000000..9a33cd2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected_holo.9.png b/core/res/res/drawable-mdpi/tab_selected_holo.9.png
new file mode 100644
index 0000000..e029e57
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png b/core/res/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..285116e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected_pressed_holo.9.png b/core/res/res/drawable-mdpi/tab_selected_pressed_holo.9.png
new file mode 100644
index 0000000..dadefa7
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selector_holo_dark.9.png b/core/res/res/drawable-mdpi/tab_selector_holo_dark.9.png
deleted file mode 100644
index 30d30df..0000000
--- a/core/res/res/drawable-mdpi/tab_selector_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_unselected_focused_holo.9.png b/core/res/res/drawable-mdpi/tab_unselected_focused_holo.9.png
new file mode 100644
index 0000000..032a992
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_unselected_holo.9.png b/core/res/res/drawable-mdpi/tab_unselected_holo.9.png
new file mode 100644
index 0000000..848f3f1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_unselected_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png b/core/res/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..3845135
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_unselected_pressed_holo.9.png b/core/res/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
new file mode 100644
index 0000000..23fd8c9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable/tab_bottom_right.xml b/core/res/res/drawable/tab_bottom_right.xml
index f7f5c2f..450c461 100644
--- a/core/res/res/drawable/tab_bottom_right.xml
+++ b/core/res/res/drawable/tab_bottom_right.xml
@@ -16,6 +16,6 @@
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_pressed="true" android:drawable="@drawable/tab_press_bar_right"/>
-    <item android:state_focused="false" android:state_pressed="false" android:drawable="@drawable/tab_selected_bar_right"/>
-    <item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/tab_focus_bar_right"/>
+    <item android:state_focused="false" android:drawable="@drawable/tab_selected_bar_right"/>
+    <item android:state_focused="true" android:drawable="@drawable/tab_focus_bar_right"/>
 </selector>
diff --git a/core/res/res/drawable/tab_indicator_holo.xml b/core/res/res/drawable/tab_indicator_holo.xml
new file mode 100644
index 0000000..0d46e0c
--- /dev/null
+++ b/core/res/res/drawable/tab_indicator_holo.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- Non focused states -->
+    <item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/tab_unselected_holo" />
+    <item android:state_focused="false" android:state_selected="true"  android:state_pressed="false" android:drawable="@drawable/tab_selected_holo" />
+
+    <!-- Focused states -->
+    <item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/tab_unselected_focused_holo" />
+    <item android:state_focused="true" android:state_selected="true"  android:state_pressed="false" android:drawable="@drawable/tab_selected_focused_holo" />
+
+    <!-- Pressed -->
+    <!--    Non focused states -->
+    <item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed_holo" />
+    <item android:state_focused="false" android:state_selected="true"  android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed_holo" />
+
+    <!--    Focused states -->
+    <item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed_focused_holo" />
+    <item android:state_focused="true" android:state_selected="true"  android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed_focused_holo" />
+</selector>
diff --git a/core/res/res/layout/tab_indicator.xml b/core/res/res/layout/tab_indicator.xml
index 71e4001..bc657c3 100644
--- a/core/res/res/layout/tab_indicator.xml
+++ b/core/res/res/layout/tab_indicator.xml
@@ -20,7 +20,6 @@
     android:layout_weight="1"
     android:layout_marginLeft="-3dip"
     android:layout_marginRight="-3dip"
-    android:orientation="vertical"
     android:background="@android:drawable/tab_indicator">
 
     <ImageView android:id="@+id/icon"
diff --git a/core/res/res/layout/tab_indicator_holo.xml b/core/res/res/layout/tab_indicator_holo.xml
new file mode 100644
index 0000000..d37476b
--- /dev/null
+++ b/core/res/res/layout/tab_indicator_holo.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="56dip"
+    android:layout_weight="0"
+    android:layout_marginLeft="0dip"
+    android:layout_marginRight="0dip"
+    android:background="@android:drawable/tab_indicator_holo">
+
+    <View android:id="@+id/tab_indicator_left_spacer"
+        android:layout_width="16dip"
+        android:layout_height="0dip" />
+
+    <ImageView android:id="@+id/icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:visibility="gone"
+        android:layout_toRightOf="@id/tab_indicator_left_spacer"
+        android:paddingRight="8dip" />
+
+    <TextView android:id="@+id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_toRightOf="@id/icon"
+        android:paddingLeft="0dip"
+        android:paddingRight="16dip"
+        style="?android:attr/tabWidgetStyle" />
+
+</RelativeLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d5f1610..dab627c 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2137,6 +2137,8 @@
         <attr name="tabStripLeft" format="reference" />
         <!-- Drawable used to draw the right part of the strip underneath the tabs. -->
         <attr name="tabStripRight" format="reference" />
+        <!-- Layout used to organize each tab's content. -->
+        <attr name="tabLayout" format="reference" />
     </declare-styleable>
     <declare-styleable name="TextAppearance">
         <!-- Text color. -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index c441f5a..76a3c34 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -560,6 +560,12 @@
         <item name="android:textAppearance">@style/TextAppearance.Widget.TabWidget</item>
         <item name="ellipsize">marquee</item>
         <item name="singleLine">true</item>
+        <item name="android:tabStripLeft">@android:drawable/tab_bottom_left</item>
+        <item name="android:tabStripRight">@android:drawable/tab_bottom_right</item>
+        <item name="android:tabStripEnabled">true</item>
+        <item name="android:divider">@null</item>
+        <item name="android:gravity">fill_horizontal|center_vertical</item>
+        <item name="android:tabLayout">@android:layout/tab_indicator</item>
     </style>
 
     <style name="Widget.Gallery">
@@ -1070,7 +1076,7 @@
     </style>
 
     <style name="TextAppearance.Holo.Widget.TabWidget">
-        <item name="android:textSize">14sp</item>
+        <item name="android:textSize">18sp</item>
         <item name="android:textStyle">normal</item>
         <item name="android:textColor">@android:color/tab_indicator_text</item>
     </style>
@@ -1421,6 +1427,13 @@
     </style>
 
     <style name="Widget.Holo.TabWidget" parent="Widget.TabWidget">
+        <item name="android:textAppearance">@style/TextAppearance.Holo.Widget.TabWidget</item>
+        <item name="android:tabStripLeft">@null</item>
+        <item name="android:tabStripRight">@null</item>
+        <item name="android:tabStripEnabled">false</item>
+        <item name="android:divider">@null</item>
+        <item name="android:gravity">left|center_vertical</item>
+        <item name="android:tabLayout">@android:layout/tab_indicator_holo</item>
     </style>
 
     <style name="Widget.Holo.WebTextView" parent="Widget.WebTextView">
@@ -1693,7 +1706,7 @@
     <style name="Widget.Holo.Light.CompoundButton.Star" parent="Widget.CompoundButton.Star">
     </style>
 
-    <style name="Widget.Holo.Light.TabWidget" parent="Widget.TabWidget">
+    <style name="Widget.Holo.Light.TabWidget" parent="Widget.Holo.TabWidget">
     </style>
 
     <style name="Widget.Holo.Light.WebTextView" parent="Widget.WebTextView">
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 843dddb..cf9bab1 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -28,25 +28,10 @@
 using namespace android;
 
 #define SUCCESS 0
-#define DRM_DIRECTORY_PERMISSION 0700
-#define DRM_PLUGINS_ROOT "/data/drm/plugins"
-#define DRM_PLUGINS_NATIVE "/data/drm/plugins/native"
-#define DRM_PLUGINS_NATIVE_DATABASES "/data/drm/plugins/native/databases"
 
 void DrmManagerService::instantiate() {
     LOGV("instantiate");
-
-    int res = mkdir(DRM_PLUGINS_ROOT, DRM_DIRECTORY_PERMISSION);
-    if (SUCCESS == res || EEXIST == errno) {
-        res = mkdir(DRM_PLUGINS_NATIVE, DRM_DIRECTORY_PERMISSION);
-        if (SUCCESS == res || EEXIST == errno) {
-            res = mkdir(DRM_PLUGINS_NATIVE_DATABASES, DRM_DIRECTORY_PERMISSION);
-            if (SUCCESS == res || EEXIST == errno) {
-                defaultServiceManager()
-                    ->addService(String16("drm.drmManager"), new DrmManagerService());
-            }
-        }
-    }
+    defaultServiceManager()->addService(String16("drm.drmManager"), new DrmManagerService());
 }
 
 DrmManagerService::DrmManagerService() {
diff --git a/graphics/java/android/graphics/ColorMatrixColorFilter.java b/graphics/java/android/graphics/ColorMatrixColorFilter.java
index 245c615..4f32342 100644
--- a/graphics/java/android/graphics/ColorMatrixColorFilter.java
+++ b/graphics/java/android/graphics/ColorMatrixColorFilter.java
@@ -27,7 +27,7 @@
     public ColorMatrixColorFilter(ColorMatrix matrix) {
         final float[] colorMatrix = matrix.getArray();
         native_instance = nativeColorMatrixFilter(colorMatrix);
-        nativeColorFilter = nColorMatrixFilter(colorMatrix);
+        nativeColorFilter = nColorMatrixFilter(native_instance, colorMatrix);
     }
 
     /**
@@ -42,9 +42,9 @@
             throw new ArrayIndexOutOfBoundsException();
         }
         native_instance = nativeColorMatrixFilter(array);
-        nativeColorFilter = nColorMatrixFilter(array);
+        nativeColorFilter = nColorMatrixFilter(native_instance, array);
     }
 
     private static native int nativeColorMatrixFilter(float[] array);
-    private static native int nColorMatrixFilter(float[] array);
+    private static native int nColorMatrixFilter(int nativeFilter, float[] array);
 }
diff --git a/graphics/java/android/graphics/LightingColorFilter.java b/graphics/java/android/graphics/LightingColorFilter.java
index 715ce86..c621de6 100644
--- a/graphics/java/android/graphics/LightingColorFilter.java
+++ b/graphics/java/android/graphics/LightingColorFilter.java
@@ -30,9 +30,9 @@
      */
     public LightingColorFilter(int mul, int add) {
         native_instance = native_CreateLightingFilter(mul, add);
-        nativeColorFilter = nCreateLightingFilter(mul, add);
+        nativeColorFilter = nCreateLightingFilter(native_instance, mul, add);
     }
 
     private static native int native_CreateLightingFilter(int mul, int add);
-    private static native int nCreateLightingFilter(int mul, int add);
+    private static native int nCreateLightingFilter(int nativeFilter, int mul, int add);
 }
diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java
index b02dab1..ecc7c24 100644
--- a/graphics/java/android/graphics/PorterDuffColorFilter.java
+++ b/graphics/java/android/graphics/PorterDuffColorFilter.java
@@ -26,9 +26,10 @@
      */
     public PorterDuffColorFilter(int srcColor, PorterDuff.Mode mode) {
         native_instance = native_CreatePorterDuffFilter(srcColor, mode.nativeInt);
-        nativeColorFilter = nCreatePorterDuffFilter(srcColor, mode.nativeInt);
+        nativeColorFilter = nCreatePorterDuffFilter(native_instance, srcColor, mode.nativeInt);
     }
 
     private static native int native_CreatePorterDuffFilter(int srcColor, int porterDuffMode);
-    private static native int nCreatePorterDuffFilter(int srcColor, int porterDuffMode);
+    private static native int nCreatePorterDuffFilter(int nativeFilter, int srcColor,
+            int porterDuffMode);
 }
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index a9cd5be..0dd9c5a 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -288,7 +288,7 @@
             }
             break;
             case SetupColorFilter: {
-                // TODO: Implement
+                renderer.setupColorFilter(getColorFilter());
             }
             break;
             case ResetShadow: {
@@ -512,7 +512,6 @@
 
 void DisplayListRenderer::resetShader() {
     addOp(DisplayList::ResetShader);
-    OpenGLRenderer::resetShader();
 }
 
 void DisplayListRenderer::setupShader(SkiaShader* shader) {
@@ -522,17 +521,15 @@
 
 void DisplayListRenderer::resetColorFilter() {
     addOp(DisplayList::ResetColorFilter);
-    OpenGLRenderer::resetColorFilter();
 }
 
 void DisplayListRenderer::setupColorFilter(SkiaColorFilter* filter) {
-    // TODO: Implement
-    OpenGLRenderer::setupColorFilter(filter);
+    addOp(DisplayList::SetupColorFilter);
+    addColorFilter(filter);
 }
 
 void DisplayListRenderer::resetShadow() {
     addOp(DisplayList::ResetShadow);
-    OpenGLRenderer::resetShadow();
 }
 
 void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) {
@@ -540,7 +537,6 @@
     addFloat(radius);
     addPoint(dx, dy);
     addInt(color);
-    OpenGLRenderer::setupShadow(radius, dx, dy, color);
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index ce4cfc5..6636de6 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -135,6 +135,10 @@
         return (SkiaShader*) getInt();
     }
 
+    SkiaColorFilter* getColorFilter() {
+        return (SkiaColorFilter*) getInt();
+    }
+
     inline int getIndex() {
         return mReader.readInt();
     }
@@ -183,6 +187,7 @@
 
     Vector<SkBitmap*> mBitmapResources;
     Vector<SkiaShader*> mShaderResources;
+    Vector<SkiaColorFilter*> mFilterResources;
 
     Vector<SkPaint*> mPaints;
     Vector<SkMatrix*> mMatrices;
@@ -276,6 +281,10 @@
         return mMatrices;
     }
 
+    const Vector<SkiaColorFilter*>& getFilterResources() const {
+        return mFilterResources;
+    }
+
 private:
     inline void addOp(DisplayList::Op drawOp) {
         mWriter.writeInt(drawOp);
@@ -372,10 +381,18 @@
         caches.resourceCache.incrementRefcount(shader);
     }
 
+    inline void addColorFilter(SkiaColorFilter* colorFilter) {
+        addInt((int)colorFilter);
+        mFilterResources.add(colorFilter);
+        Caches& caches = Caches::getInstance();
+        caches.resourceCache.incrementRefcount(colorFilter);
+    }
+
     SkChunkAlloc mHeap;
 
     Vector<SkBitmap*> mBitmapResources;
     Vector<SkiaShader*> mShaderResources;
+    Vector<SkiaColorFilter*> mFilterResources;
 
     Vector<SkPaint*> mPaints;
     DefaultKeyedVector<SkPaint *, SkPaint *> mPaintMap;
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index b0fbe65..47c5d48 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -67,6 +67,11 @@
     incrementRefcount((void*)shaderResource, kShader);
 }
 
+void ResourceCache::incrementRefcount(SkiaColorFilter* filterResource) {
+    filterResource->getSkColorFilter()->safeRef();
+    incrementRefcount((void*)filterResource, kColorFilter);
+}
+
 void ResourceCache::decrementRefcount(void* resource) {
     ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
     if (ref == NULL) {
@@ -90,6 +95,11 @@
     decrementRefcount((void*)shaderResource);
 }
 
+void ResourceCache::decrementRefcount(SkiaColorFilter* filterResource) {
+    filterResource->getSkColorFilter()->safeUnref();
+    decrementRefcount((void*)filterResource);
+}
+
 void ResourceCache::recycle(SkBitmap* resource) {
     if (mCache->indexOfKey(resource) < 0) {
         // not tracking this resource; just recycle the pixel data
@@ -145,6 +155,20 @@
     }
 }
 
+void ResourceCache::destructor(SkiaColorFilter* resource) {
+    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    if (ref == NULL) {
+        // If we're not tracking this resource, just delete it
+        delete resource;
+        return;
+    }
+    ref->destroyed = true;
+    if (ref->refCount == 0) {
+        deleteResourceReference(resource, ref);
+        return;
+    }
+}
+
 void ResourceCache::deleteResourceReference(void* resource, ResourceReference* ref) {
     if (ref->recycled && ref->resourceType == kBitmap) {
         ((SkBitmap*) resource)->setPixels(NULL, NULL);
@@ -161,12 +185,20 @@
             }
             break;
             case kShader:
+            {
                 SkiaShader* shader = (SkiaShader*)resource;
                 if (Caches::hasInstance()) {
                     Caches::getInstance().gradientCache.remove(shader->getSkShader());
                 }
                 delete shader;
-                break;
+            }
+            break;
+            case kColorFilter:
+            {
+                SkiaColorFilter* filter = (SkiaColorFilter*)resource;
+                delete filter;
+            }
+            break;
         }
     }
     mCache->removeItem(resource);
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index b550367..d9b3718 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -18,6 +18,7 @@
 #define ANDROID_UI_RESOURCE_CACHE_H
 
 #include <SkBitmap.h>
+#include <SkiaColorFilter.h>
 #include <SkiaShader.h>
 #include <utils/KeyedVector.h>
 
@@ -30,6 +31,7 @@
 enum ResourceType {
     kBitmap,
     kShader,
+    kColorFilter,
 };
 
 class ResourceReference {
@@ -53,14 +55,17 @@
     ~ResourceCache();
     void incrementRefcount(SkBitmap* resource);
     void incrementRefcount(SkiaShader* resource);
+    void incrementRefcount(SkiaColorFilter* resource);
     void incrementRefcount(const void* resource, ResourceType resourceType);
     void decrementRefcount(void* resource);
     void decrementRefcount(SkBitmap* resource);
     void decrementRefcount(SkiaShader* resource);
+    void decrementRefcount(SkiaColorFilter* resource);
     void recycle(void* resource);
     void recycle(SkBitmap* resource);
     void destructor(SkBitmap* resource);
     void destructor(SkiaShader* resource);
+    void destructor(SkiaColorFilter* resource);
 private:
     void deleteResourceReference(void* resource, ResourceReference* ref);
     void incrementRefcount(void* resource, ResourceType resourceType);
diff --git a/libs/hwui/SkiaColorFilter.cpp b/libs/hwui/SkiaColorFilter.cpp
index fe57ae7..91b1c32 100644
--- a/libs/hwui/SkiaColorFilter.cpp
+++ b/libs/hwui/SkiaColorFilter.cpp
@@ -23,7 +23,8 @@
 // Base color filter
 ///////////////////////////////////////////////////////////////////////////////
 
-SkiaColorFilter::SkiaColorFilter(Type type, bool blend): mType(type), mBlend(blend) {
+SkiaColorFilter::SkiaColorFilter(SkColorFilter *skFilter, Type type, bool blend):
+        mType(type), mBlend(blend), mSkFilter(skFilter) {
 }
 
 SkiaColorFilter::~SkiaColorFilter() {
@@ -33,8 +34,8 @@
 // Color matrix filter
 ///////////////////////////////////////////////////////////////////////////////
 
-SkiaColorMatrixFilter::SkiaColorMatrixFilter(float* matrix, float* vector):
-        SkiaColorFilter(kColorMatrix, true), mMatrix(matrix), mVector(vector) {
+SkiaColorMatrixFilter::SkiaColorMatrixFilter(SkColorFilter *skFilter, float* matrix, float* vector):
+        SkiaColorFilter(skFilter, kColorMatrix, true), mMatrix(matrix), mVector(vector) {
 }
 
 SkiaColorMatrixFilter::~SkiaColorMatrixFilter() {
@@ -56,8 +57,8 @@
 // Lighting color filter
 ///////////////////////////////////////////////////////////////////////////////
 
-SkiaLightingFilter::SkiaLightingFilter(int multiply, int add):
-        SkiaColorFilter(kLighting, true) {
+SkiaLightingFilter::SkiaLightingFilter(SkColorFilter *skFilter, int multiply, int add):
+        SkiaColorFilter(skFilter, kLighting, true) {
     mMulR = ((multiply >> 16) & 0xFF) / 255.0f;
     mMulG = ((multiply >>  8) & 0xFF) / 255.0f;
     mMulB = ((multiply      ) & 0xFF) / 255.0f;
@@ -80,8 +81,8 @@
 // Blend color filter
 ///////////////////////////////////////////////////////////////////////////////
 
-SkiaBlendFilter::SkiaBlendFilter(int color, SkXfermode::Mode mode):
-        SkiaColorFilter(kBlend, true), mMode(mode) {
+SkiaBlendFilter::SkiaBlendFilter(SkColorFilter *skFilter, int color, SkXfermode::Mode mode):
+        SkiaColorFilter(skFilter, kBlend, true), mMode(mode) {
     const int alpha = (color >> 24) & 0xFF;
     mA = alpha / 255.0f;
     mR = mA * ((color >> 16) & 0xFF) / 255.0f;
diff --git a/libs/hwui/SkiaColorFilter.h b/libs/hwui/SkiaColorFilter.h
index 865b6f0..17f49f9 100644
--- a/libs/hwui/SkiaColorFilter.h
+++ b/libs/hwui/SkiaColorFilter.h
@@ -18,6 +18,7 @@
 #define ANDROID_UI_SKIA_COLOR_FILTER_H
 
 #include <GLES2/gl2.h>
+#include <SkColorFilter.h>
 
 #include "ProgramCache.h"
 #include "Extensions.h"
@@ -44,7 +45,7 @@
         kBlend,
     };
 
-    SkiaColorFilter(Type type, bool blend);
+    SkiaColorFilter(SkColorFilter *skFilter, Type type, bool blend);
     virtual ~SkiaColorFilter();
 
     virtual void describe(ProgramDescription& description, const Extensions& extensions) = 0;
@@ -58,9 +59,16 @@
         return mType;
     }
 
+    SkColorFilter *getSkColorFilter() {
+        return mSkFilter;
+    }
+
 protected:
     Type mType;
     bool mBlend;
+
+private:
+    SkColorFilter *mSkFilter;
 }; // struct SkiaColorFilter
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -71,7 +79,7 @@
  * A color filter that multiplies the source color with a matrix and adds a vector.
  */
 struct SkiaColorMatrixFilter: public SkiaColorFilter {
-    SkiaColorMatrixFilter(float* matrix, float* vector);
+    SkiaColorMatrixFilter(SkColorFilter *skFilter, float* matrix, float* vector);
     ~SkiaColorMatrixFilter();
 
     void describe(ProgramDescription& description, const Extensions& extensions);
@@ -87,7 +95,7 @@
  * another fixed value. Ignores the alpha channel of both arguments.
  */
 struct SkiaLightingFilter: public SkiaColorFilter {
-    SkiaLightingFilter(int multiply, int add);
+    SkiaLightingFilter(SkColorFilter *skFilter, int multiply, int add);
 
     void describe(ProgramDescription& description, const Extensions& extensions);
     void setupProgram(Program* program);
@@ -102,7 +110,7 @@
  * and PorterDuff blending mode.
  */
 struct SkiaBlendFilter: public SkiaColorFilter {
-    SkiaBlendFilter(int color, SkXfermode::Mode mode);
+    SkiaBlendFilter(SkColorFilter *skFilter, int color, SkXfermode::Mode mode);
 
     void describe(ProgramDescription& description, const Extensions& extensions);
     void setupProgram(Program* program);
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index 0994980..7af6ce8 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -867,7 +867,18 @@
         return BAD_VALUE;
 
     Mutex::Autolock _l(mSurfaceLock);
+    if (mConnected == NATIVE_WINDOW_API_EGL) {
+        return INVALID_OPERATION;
+    }
+
     mBufferInfo.set(w, h, format);
+    if (format != 0) {
+        // we update the format of the surface as reported by query().
+        // this is to allow applications to change the format of a surface's
+        // buffer, and have it reflected in EGL; which is needed for
+        // EGLConfig validation.
+        mFormat = format;
+    }
     return NO_ERROR;
 }
 
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 68524c3..fcf6510 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -480,16 +480,6 @@
     }
 
     /**
-     * Sets the level of the encoder. Call this before prepare().
-     *
-     * @param encoderLevel the video encoder level.
-     * @hide
-     */
-    public void setVideoEncoderLevel(int encoderLevel) {
-        setParameter(String.format("video-param-encoder-level=%d", encoderLevel));
-    }
-
-    /**
      * Sets the auxiliary time lapse video's resolution and bitrate.
      *
      * The auxiliary video's resolution and bitrate are determined by the CamcorderProfile
diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
index df3c5fb..d2f3694 100755
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ b/media/java/android/media/videoeditor/MediaImageItem.java
@@ -163,7 +163,9 @@
     public void setDuration(long durationMs) {

         mDurationMs = durationMs;

 

-        adjustElementsDuration();

+        adjustTransitions();

+        adjustOverlays();

+        adjustEffects();

     }

 

     /*

diff --git a/media/java/android/media/videoeditor/MediaItem.java b/media/java/android/media/videoeditor/MediaItem.java
index d9c38af..40d3619 100755
--- a/media/java/android/media/videoeditor/MediaItem.java
+++ b/media/java/android/media/videoeditor/MediaItem.java
@@ -40,13 +40,21 @@
      * clip are rendered black.

      */

     public static final int RENDERING_MODE_BLACK_BORDER = 0;

+

     /**

      * When using the RENDERING_MODE_STRETCH rendering mode video frames are

      * stretched horizontally or vertically to match the current aspect ratio of

-     * the movie.

+     * the video editor.

      */

     public static final int RENDERING_MODE_STRETCH = 1;

 

+    /**

+     * When using the RENDERING_MODE_CROPPING rendering mode video frames are

+     * scaled horizontally or vertically by preserving the original aspect

+     * ratio of the media item.

+     */

+    public static final int RENDERING_MODE_CROPPING = 2;

+

 

     // The unique id of the MediaItem

     private final String mUniqueId;

@@ -476,10 +484,9 @@
     }

 

     /**

-     * Adjust the duration of effects, overlays and transitions.

-     * This method will be called after a media item duration is changed.

+     * Adjust the duration transitions.

      */

-    protected void adjustElementsDuration() {

+    protected void adjustTransitions() {

         // Check if the duration of transitions need to be adjusted

         if (mBeginTransition != null) {

             final long maxDurationMs = mBeginTransition.getMaximumDuration();

@@ -494,31 +501,12 @@
                 mEndTransition.setDuration(maxDurationMs);

             }

         }

+    }

 

-        final List<Overlay> overlays = getAllOverlays();

-        for (Overlay overlay : overlays) {

-            // Adjust the start time if necessary

-            final long overlayStartTimeMs;

-            if (overlay.getStartTime() > getTimelineDuration()) {

-                overlayStartTimeMs = 0;

-            } else {

-                overlayStartTimeMs = overlay.getStartTime();

-            }

-

-            // Adjust the duration if necessary

-            final long overlayDurationMs;

-            if (overlayStartTimeMs + overlay.getDuration() > getTimelineDuration()) {

-                overlayDurationMs = getTimelineDuration() - overlayStartTimeMs;

-            } else {

-                overlayDurationMs = overlay.getDuration();

-            }

-

-            if (overlayStartTimeMs != overlay.getStartTime() ||

-                    overlayDurationMs != overlay.getDuration()) {

-                overlay.setStartTimeAndDuration(overlayStartTimeMs, overlayDurationMs);

-            }

-        }

-

+    /**

+     * Adjust the start time and/or duration of effects.

+     */

+    protected void adjustEffects() {

         final List<Effect> effects = getAllEffects();

         for (Effect effect : effects) {

             // Adjust the start time if necessary

@@ -543,4 +531,33 @@
             }

         }

     }

+

+    /**

+     * Adjust the start time and/or duration of overlays.

+     */

+    protected void adjustOverlays() {

+        final List<Overlay> overlays = getAllOverlays();

+        for (Overlay overlay : overlays) {

+            // Adjust the start time if necessary

+            final long overlayStartTimeMs;

+            if (overlay.getStartTime() > getTimelineDuration()) {

+                overlayStartTimeMs = 0;

+            } else {

+                overlayStartTimeMs = overlay.getStartTime();

+            }

+

+            // Adjust the duration if necessary

+            final long overlayDurationMs;

+            if (overlayStartTimeMs + overlay.getDuration() > getTimelineDuration()) {

+                overlayDurationMs = getTimelineDuration() - overlayStartTimeMs;

+            } else {

+                overlayDurationMs = overlay.getDuration();

+            }

+

+            if (overlayStartTimeMs != overlay.getStartTime() ||

+                    overlayDurationMs != overlay.getDuration()) {

+                overlay.setStartTimeAndDuration(overlayStartTimeMs, overlayDurationMs);

+            }

+        }

+    }

 }

diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
index f71f4f4..341bf8e 100755
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ b/media/java/android/media/videoeditor/MediaVideoItem.java
@@ -155,7 +155,11 @@
         mBeginBoundaryTimeMs = beginMs;

         mEndBoundaryTimeMs = endMs;

 

-        adjustElementsDuration();

+        adjustTransitions();

+

+        // Note that the start and duration of any effects and overlays are

+        // not adjusted nor are they automatically removed if they fall

+        // outside the new boundaries.

     }

 

     /**

diff --git a/native/android/native_window.cpp b/native/android/native_window.cpp
index bada078..7f92eec 100644
--- a/native/android/native_window.cpp
+++ b/native/android/native_window.cpp
@@ -58,8 +58,8 @@
 }
 
 int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window, int32_t width,
-        int32_t height) {
-    native_window_set_buffers_geometry(window, width, height, 0);
+        int32_t height, int32_t format) {
+    native_window_set_buffers_geometry(window, width, height, format);
     return 0;
 }
 
diff --git a/native/include/android/native_window.h b/native/include/android/native_window.h
index ad03d0e..f3d7550 100644
--- a/native/include/android/native_window.h
+++ b/native/include/android/native_window.h
@@ -96,7 +96,7 @@
  * For all of these parameters, if 0 is supplied then the window's base
  * value will come back in force.
  */
-int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window, int32_t width, int32_t height);
+int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window, int32_t width, int32_t height, int32_t format);
 
 /**
  * Lock the window's next drawing surface for writing.
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index e38b9cc..e44c485 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -833,6 +833,9 @@
     static bool mask(GLint reqValue, GLint confValue) {
         return (confValue & reqValue) == reqValue;
     }
+    static bool ignore(GLint reqValue, GLint confValue) {
+        return true;
+    }
 };
 
 // ----------------------------------------------------------------------------
@@ -1060,11 +1063,11 @@
         { EGL_CONFIG_CAVEAT,              config_management_t::exact   },
         { EGL_CONFIG_ID,                  config_management_t::exact   },
         { EGL_LEVEL,                      config_management_t::exact   },
-        { EGL_MAX_PBUFFER_HEIGHT,         config_management_t::exact   },
-        { EGL_MAX_PBUFFER_PIXELS,         config_management_t::exact   },
-        { EGL_MAX_PBUFFER_WIDTH,          config_management_t::exact   },
+        { EGL_MAX_PBUFFER_HEIGHT,         config_management_t::ignore   },
+        { EGL_MAX_PBUFFER_PIXELS,         config_management_t::ignore   },
+        { EGL_MAX_PBUFFER_WIDTH,          config_management_t::ignore   },
         { EGL_NATIVE_RENDERABLE,          config_management_t::exact   },
-        { EGL_NATIVE_VISUAL_ID,           config_management_t::exact   },
+        { EGL_NATIVE_VISUAL_ID,           config_management_t::ignore   },
         { EGL_NATIVE_VISUAL_TYPE,         config_management_t::exact   },
         { EGL_SAMPLES,                    config_management_t::exact   },
         { EGL_SAMPLE_BUFFERS,             config_management_t::exact   },
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
index 7234557..fff70bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
@@ -648,7 +648,6 @@
                     if (mVT == null) break;
                     mVT.addMovement(event);
                     mVT.computeCurrentVelocity(1000);
-                    Slog.d("ClockTouchListener", "dy=" + mVT.getYVelocity());
                     if (mVT.getYVelocity() < -200 && mSystemPanel.getVisibility() == View.GONE) {
                         mHandler.removeMessages(MSG_OPEN_SYSTEM_PANEL);
                         mHandler.sendEmptyMessage(MSG_OPEN_SYSTEM_PANEL);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 4f75366..92588fc 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -872,9 +872,19 @@
         mWifiStateMachine.startWpsPbc(bssid);
     }
 
-    public void startWpsPin(String bssid, int apPin) {
+    public void startWpsWithPinFromAccessPoint(String bssid, int apPin) {
         enforceChangePermission();
-        mWifiStateMachine.startWpsPin(bssid, apPin);
+        mWifiStateMachine.startWpsWithPinFromAccessPoint(bssid, apPin);
+    }
+
+    public int startWpsWithPinFromDevice(String bssid) {
+        enforceChangePermission();
+        if (mChannel != null) {
+            return mWifiStateMachine.syncStartWpsWithPinFromDevice(mChannel, bssid);
+        } else {
+            Slog.e(TAG, "mChannel is not initialized");
+            return -1;
+        }
     }
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index cee8546..8551b0f 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -203,13 +203,9 @@
                 }
             }
             if (xliffDepth == 0 && pseudolocalize) {
-#ifdef ENABLE_PSEUDOLOCALIZE
                 std::string orig(String8(text).string());
                 std::string pseudo = pseudolocalize_string(orig);
                 curString.append(String16(String8(pseudo.c_str())));
-#else
-                assert(false);
-#endif
             } else {
                 if (isFormatted && hasSubstitutionErrors(fileName, inXml, text) != NO_ERROR) {
                     return UNKNOWN_ERROR;
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index f760d27..720f6ac 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -108,6 +108,8 @@
 
     void startWpsPbc(String bssid);
 
-    void startWpsPin(String bssid, int apPin);
+    void startWpsWithPinFromAccessPoint(String bssid, int apPin);
+
+    int startWpsWithPinFromDevice(String bssid);
 }
 
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index be5fab4..04b3891 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -361,10 +361,11 @@
     }
 
     /**
-     * Start WPS pin method configuration
+     * Start WPS pin method configuration with pin obtained
+     * from the access point
      */
-    static boolean startWpsPin(String bssid, int apPin) {
-        if (WifiNative.startWpsPinCommand(bssid, apPin)) {
+    static boolean startWpsWithPinFromAccessPoint(String bssid, int apPin) {
+        if (WifiNative.startWpsWithPinFromAccessPointCommand(bssid, apPin)) {
             /* WPS leaves all networks disabled */
             markAllNetworksDisabled();
             return true;
@@ -374,6 +375,21 @@
     }
 
     /**
+     * Start WPS pin method configuration with pin obtained
+     * from the device
+     */
+    static int startWpsWithPinFromDevice(String bssid) {
+        int pin = WifiNative.startWpsWithPinFromDeviceCommand(bssid);
+        /* WPS leaves all networks disabled */
+        if (pin != -1) {
+            markAllNetworksDisabled();
+        } else {
+            Log.e(TAG, "Failed to start WPS pin method configuration");
+        }
+        return pin;
+    }
+
+    /**
      * Start WPS push button configuration
      */
     static boolean startWpsPbc(String bssid) {
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 0b3a782..84d615c 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1050,19 +1050,36 @@
 
     /**
      * Start Wi-fi Protected Setup pin method configuration
+     * with pin obtained from the access point
      *
      * @param bssid BSSID of the access point
      * @param apPin PIN issued by the access point
      *
      * @hide
      */
-    public void startWpsPin(String bssid, int apPin) {
+    public void startWpsWithPinFromAccessPoint(String bssid, int apPin) {
         try {
-            mService.startWpsPin(bssid, apPin);
+            mService.startWpsWithPinFromAccessPoint(bssid, apPin);
         } catch (RemoteException e) { }
     }
 
     /**
+     * Start Wi-fi Protected Setup pin method configuration
+     * with pin obtained from the device
+     *
+     * @param bssid BSSID of the access point
+     * @return pin generated by device
+     * @hide
+     */
+    public int startWpsWithPinFromDevice(String bssid) {
+        try {
+            return mService.startWpsWithPinFromDevice(bssid);
+        } catch (RemoteException e) {
+            return -1;
+        }
+    }
+
+    /**
      * Allows an application to keep the Wi-Fi radio awake.
      * Normally the Wi-Fi radio may turn off when the user has not used the device in a while.
      * Acquiring a WifiLock will keep the radio on until the lock is released.  Multiple 
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 1251a25..313ae0b 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -153,7 +153,9 @@
 
     public native static boolean startWpsPbcCommand(String bssid);
 
-    public native static boolean startWpsPinCommand(String bssid, int apPin);
+    public native static boolean startWpsWithPinFromAccessPointCommand(String bssid, int apPin);
+
+    public native static int startWpsWithPinFromDeviceCommand(String bssid);
 
     public native static boolean doDhcpRequest(DhcpInfo results);
 
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index e3deeb3..faafb7a 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -301,9 +301,10 @@
      * supplicant config.
      */
     private static final int CMD_FORGET_NETWORK                   = 92;
-    /* Start Wi-Fi protected setup */
-    private static final int CMD_START_WPS                        = 93;
-
+    /* Start Wi-Fi protected setup push button configuration */
+    private static final int CMD_START_WPS_PBC                    = 93;
+    /* Start Wi-Fi protected setup pin method configuration */
+    private static final int CMD_START_WPS_PIN                    = 94;
     /**
      * Interval in milliseconds between polling for connection
      * status items that are not sent via asynchronous events.
@@ -787,11 +788,18 @@
     }
 
     public void startWpsPbc(String bssid) {
-        sendMessage(obtainMessage(CMD_START_WPS, bssid));
+        sendMessage(obtainMessage(CMD_START_WPS_PBC, bssid));
     }
 
-    public void startWpsPin(String bssid, int apPin) {
-        sendMessage(obtainMessage(CMD_START_WPS, apPin, 0, bssid));
+    public void startWpsWithPinFromAccessPoint(String bssid, int apPin) {
+        sendMessage(obtainMessage(CMD_START_WPS_PIN, apPin, 0, bssid));
+    }
+
+    public int syncStartWpsWithPinFromDevice(AsyncChannel channel, String bssid) {
+        Message resultMsg = channel.sendMessageSynchronously(CMD_START_WPS_PIN, bssid);
+        int result = resultMsg.arg1;
+        resultMsg.recycle();
+        return result;
     }
 
     public void enableRssiPolling(boolean enabled) {
@@ -1654,7 +1662,8 @@
                 case CMD_CONNECT_NETWORK:
                 case CMD_SAVE_NETWORK:
                 case CMD_FORGET_NETWORK:
-                case CMD_START_WPS:
+                case CMD_START_WPS_PBC:
+                case CMD_START_WPS_PIN:
                     break;
                 default:
                     Log.e(TAG, "Error! unhandled message" + message);
@@ -2395,17 +2404,11 @@
                     /* Expect a disconnection from the old connection */
                     transitionTo(mDisconnectingState);
                     break;
-                case CMD_START_WPS:
+                case CMD_START_WPS_PBC:
                     String bssid = (String) message.obj;
-                    int apPin = message.arg1;
-                    boolean success;
-                    if (apPin != 0) {
-                        /* WPS pin method configuration */
-                        success = WifiConfigStore.startWpsPin(bssid, apPin);
-                    } else {
-                        /* WPS push button configuration */
-                        success = WifiConfigStore.startWpsPbc(bssid);
-                    }
+                    /* WPS push button configuration */
+                    boolean success = WifiConfigStore.startWpsPbc(bssid);
+
                     /* During WPS setup, all other networks are disabled. After
                      * a successful connect a new config is created in the supplicant.
                      *
@@ -2422,6 +2425,24 @@
                         transitionTo(mDisconnectingState);
                     }
                     break;
+                case CMD_START_WPS_PIN:
+                    bssid = (String) message.obj;
+                    int apPin = message.arg1;
+                    int pin;
+                    if (apPin != 0) {
+                        /* WPS pin from access point */
+                        success = WifiConfigStore.startWpsWithPinFromAccessPoint(bssid, apPin);
+                    } else {
+                        pin = WifiConfigStore.startWpsWithPinFromDevice(bssid);
+                        success = (pin != -1);
+                        mReplyChannel.replyToMessage(message, CMD_START_WPS_PIN, pin);
+                    }
+                    if (success) {
+                        mWpsStarted = true;
+                        /* Expect a disconnection from the old connection */
+                        transitionTo(mDisconnectingState);
+                    }
+                    break;
                 case SCAN_RESULTS_EVENT:
                     /* Set the scan setting back to "connect" mode */
                     WifiNative.setScanResultHandlingCommand(CONNECT_MODE);