Merge "Improve camera face detection javadoc." into ics-mr1
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index f9896f7..303f81b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2734,8 +2734,9 @@
         CharSequence description;
     }
 
-    private class ProviderRefCount {
+    private static final class ProviderRefCount {
         public int count;
+
         ProviderRefCount(int pCount) {
             count = pCount;
         }
@@ -3988,16 +3989,14 @@
             buf.append(": ");
             buf.append(cpi.name);
             Log.i(TAG, buf.toString());
-            IContentProvider cp = installProvider(context, null, cpi, false);
+            IContentProvider cp = installProvider(context, null, cpi,
+                    false /*noisy*/, true /*noReleaseNeeded*/);
             if (cp != null) {
                 IActivityManager.ContentProviderHolder cph =
-                    new IActivityManager.ContentProviderHolder(cpi);
+                        new IActivityManager.ContentProviderHolder(cpi);
                 cph.provider = cp;
+                cph.noReleaseNeeded = true;
                 results.add(cph);
-                // Don't ever unload this provider from the process.
-                synchronized(mProviderMap) {
-                    mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000));
-                }
             }
         }
 
@@ -4008,26 +4007,22 @@
         }
     }
 
-    private IContentProvider getExistingProvider(Context context, String name) {
-        synchronized(mProviderMap) {
-            final ProviderClientRecord pr = mProviderMap.get(name);
-            if (pr != null) {
-                return pr.mProvider;
-            }
-            return null;
-        }
-    }
-
-    private IContentProvider getProvider(Context context, String name) {
-        IContentProvider existing = getExistingProvider(context, name);
-        if (existing != null) {
-            return existing;
+    public final IContentProvider acquireProvider(Context c, String name) {
+        IContentProvider provider = acquireExistingProvider(c, name);
+        if (provider != null) {
+            return provider;
         }
 
+        // There is a possible race here.  Another thread may try to acquire
+        // the same provider at the same time.  When this happens, we want to ensure
+        // that the first one wins.
+        // Note that we cannot hold the lock while acquiring and installing the
+        // provider since it might take a long time to run and it could also potentially
+        // be re-entrant in the case where the provider is in the same process.
         IActivityManager.ContentProviderHolder holder = null;
         try {
             holder = ActivityManagerNative.getDefault().getContentProvider(
-                getApplicationThread(), name);
+                    getApplicationThread(), name);
         } catch (RemoteException ex) {
         }
         if (holder == null) {
@@ -4035,136 +4030,137 @@
             return null;
         }
 
-        IContentProvider prov = installProvider(context, holder.provider,
-                holder.info, true);
-        //Slog.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded);
-        if (holder.noReleaseNeeded || holder.provider == null) {
-            // We are not going to release the provider if it is an external
-            // provider that doesn't care about being released, or if it is
-            // a local provider running in this process.
-            //Slog.i(TAG, "*** NO RELEASE NEEDED");
-            synchronized(mProviderMap) {
-                mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000));
+        // Install provider will increment the reference count for us, and break
+        // any ties in the race.
+        provider = installProvider(c, holder.provider, holder.info,
+                true /*noisy*/, holder.noReleaseNeeded);
+        if (holder.provider != null && provider != holder.provider) {
+            if (localLOGV) {
+                Slog.v(TAG, "acquireProvider: lost the race, releasing extraneous "
+                        + "reference to the content provider");
+            }
+            try {
+                ActivityManagerNative.getDefault().removeContentProvider(
+                        getApplicationThread(), name);
+            } catch (RemoteException ex) {
             }
         }
-        return prov;
-    }
-
-    public final IContentProvider acquireProvider(Context c, String name) {
-        IContentProvider provider = getProvider(c, name);
-        if(provider == null)
-            return null;
-        IBinder jBinder = provider.asBinder();
-        synchronized(mProviderMap) {
-            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
-            if(prc == null) {
-                mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
-            } else {
-                prc.count++;
-            } //end else
-        } //end synchronized
         return provider;
     }
 
     public final IContentProvider acquireExistingProvider(Context c, String name) {
-        IContentProvider provider = getExistingProvider(c, name);
-        if(provider == null)
-            return null;
-        IBinder jBinder = provider.asBinder();
-        synchronized(mProviderMap) {
+        synchronized (mProviderMap) {
+            ProviderClientRecord pr = mProviderMap.get(name);
+            if (pr == null) {
+                return null;
+            }
+
+            IContentProvider provider = pr.mProvider;
+            IBinder jBinder = provider.asBinder();
+
+            // Only increment the ref count if we have one.  If we don't then the
+            // provider is not reference counted and never needs to be released.
             ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
-            if(prc == null) {
-                mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
-            } else {
-                prc.count++;
-            } //end else
-        } //end synchronized
-        return provider;
+            if (prc != null) {
+                prc.count += 1;
+                if (prc.count == 1) {
+                    if (localLOGV) {
+                        Slog.v(TAG, "acquireExistingProvider: "
+                                + "snatched provider from the jaws of death");
+                    }
+                    // Because the provider previously had a reference count of zero,
+                    // it was scheduled to be removed.  Cancel that.
+                    mH.removeMessages(H.REMOVE_PROVIDER, provider);
+                }
+            }
+            return provider;
+        }
     }
 
     public final boolean releaseProvider(IContentProvider provider) {
         if(provider == null) {
             return false;
         }
+
         IBinder jBinder = provider.asBinder();
-        synchronized(mProviderMap) {
+        synchronized (mProviderMap) {
             ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
-            if(prc == null) {
-                if(localLOGV) Slog.v(TAG, "releaseProvider::Weird shouldn't be here");
+            if (prc == null) {
+                // The provider has no ref count, no release is needed.
                 return false;
-            } else {
-                prc.count--;
-                if(prc.count == 0) {
-                    // Schedule the actual remove asynchronously, since we
-                    // don't know the context this will be called in.
-                    // TODO: it would be nice to post a delayed message, so
-                    // if we come back and need the same provider quickly
-                    // we will still have it available.
-                    Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider);
-                    mH.sendMessage(msg);
-                } //end if
-            } //end else
-        } //end synchronized
-        return true;
+            }
+
+            if (prc.count == 0) {
+                if (localLOGV) Slog.v(TAG, "releaseProvider: ref count already 0, how?");
+                return false;
+            }
+
+            prc.count -= 1;
+            if (prc.count == 0) {
+                // Schedule the actual remove asynchronously, since we don't know the context
+                // this will be called in.
+                // TODO: it would be nice to post a delayed message, so
+                // if we come back and need the same provider quickly
+                // we will still have it available.
+                Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider);
+                mH.sendMessage(msg);
+            }
+            return true;
+        }
     }
 
     final void completeRemoveProvider(IContentProvider provider) {
         IBinder jBinder = provider.asBinder();
-        String name = null;
+        String remoteProviderName = null;
         synchronized(mProviderMap) {
             ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
-            if(prc != null && prc.count == 0) {
-                mProviderRefCountMap.remove(jBinder);
-                //invoke removeProvider to dereference provider
-                name = removeProviderLocked(provider);
+            if (prc == null) {
+                // Either no release is needed (so we shouldn't be here) or the
+                // provider was already released.
+                if (localLOGV) Slog.v(TAG, "completeRemoveProvider: release not needed");
+                return;
+            }
+
+            if (prc.count != 0) {
+                // There was a race!  Some other client managed to acquire
+                // the provider before the removal was completed.
+                // Abort the removal.  We will do it later.
+                if (localLOGV) Slog.v(TAG, "completeRemoveProvider: lost the race, "
+                        + "provider still in use");
+                return;
+            }
+
+            mProviderRefCountMap.remove(jBinder);
+
+            Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator();
+            while (iter.hasNext()) {
+                ProviderClientRecord pr = iter.next();
+                IBinder myBinder = pr.mProvider.asBinder();
+                if (myBinder == jBinder) {
+                    iter.remove();
+                    if (pr.mLocalProvider == null) {
+                        myBinder.unlinkToDeath(pr, 0);
+                        if (remoteProviderName == null) {
+                            remoteProviderName = pr.mName;
+                        }
+                    }
+                }
             }
         }
-        
-        if (name != null) {
+
+        if (remoteProviderName != null) {
             try {
-                if(localLOGV) Slog.v(TAG, "removeProvider::Invoking " +
-                        "ActivityManagerNative.removeContentProvider(" + name);
+                if (localLOGV) {
+                    Slog.v(TAG, "removeProvider: Invoking ActivityManagerNative."
+                            + "removeContentProvider(" + remoteProviderName + ")");
+                }
                 ActivityManagerNative.getDefault().removeContentProvider(
-                        getApplicationThread(), name);
+                        getApplicationThread(), remoteProviderName);
             } catch (RemoteException e) {
                 //do nothing content provider object is dead any way
-            } //end catch
+            }
         }
     }
-    
-    public final String removeProviderLocked(IContentProvider provider) {
-        if (provider == null) {
-            return null;
-        }
-        IBinder providerBinder = provider.asBinder();
-
-        String name = null;
-        
-        // remove the provider from mProviderMap
-        Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator();
-        while (iter.hasNext()) {
-            ProviderClientRecord pr = iter.next();
-            IBinder myBinder = pr.mProvider.asBinder();
-            if (myBinder == providerBinder) {
-                //find if its published by this process itself
-                if(pr.mLocalProvider != null) {
-                    if(localLOGV) Slog.i(TAG, "removeProvider::found local provider returning");
-                    return name;
-                }
-                if(localLOGV) Slog.v(TAG, "removeProvider::Not local provider Unlinking " +
-                        "death recipient");
-                //content provider is in another process
-                myBinder.unlinkToDeath(pr, 0);
-                iter.remove();
-                //invoke remove only once for the very first name seen
-                if(name == null) {
-                    name = pr.mName;
-                }
-            } //end if myBinder
-        }  //end while iter
-        
-        return name;
-    }
 
     final void removeDeadProvider(String name, IContentProvider provider) {
         synchronized(mProviderMap) {
@@ -4179,8 +4175,23 @@
         }
     }
 
+    /**
+     * Installs the provider.
+     *
+     * Providers that are local to the process or that come from the system server
+     * may be installed permanently which is indicated by setting noReleaseNeeded to true.
+     * Other remote providers are reference counted.  The initial reference count
+     * for all reference counted providers is one.  Providers that are not reference
+     * counted do not have a reference count (at all).
+     *
+     * This method detects when a provider has already been installed.  When this happens,
+     * it increments the reference count of the existing provider (if appropriate)
+     * and returns the existing provider.  This can happen due to concurrent
+     * attempts to acquire the same provider.
+     */
     private IContentProvider installProvider(Context context,
-            IContentProvider provider, ProviderInfo info, boolean noisy) {
+            IContentProvider provider, ProviderInfo info,
+            boolean noisy, boolean noReleaseNeeded) {
         ContentProvider localProvider = null;
         if (provider == null) {
             if (noisy) {
@@ -4238,24 +4249,69 @@
         }
 
         synchronized (mProviderMap) {
-            // Cache the pointer for the remote provider.
+            // There is a possibility that this thread raced with another thread to
+            // add the provider.  If we find another thread got there first then we
+            // just get out of the way and return the original provider.
+            IBinder jBinder = provider.asBinder();
             String names[] = PATTERN_SEMICOLON.split(info.authority);
-            for (int i=0; i<names.length; i++) {
-                ProviderClientRecord pr = new ProviderClientRecord(names[i], provider,
-                        localProvider);
-                try {
-                    provider.asBinder().linkToDeath(pr, 0);
+            for (int i = 0; i < names.length; i++) {
+                ProviderClientRecord pr = mProviderMap.get(names[i]);
+                if (pr != null) {
+                    if (localLOGV) {
+                        Slog.v(TAG, "installProvider: lost the race, "
+                                + "using existing named provider");
+                    }
+                    provider = pr.mProvider;
+                } else {
+                    pr = new ProviderClientRecord(names[i], provider, localProvider);
+                    if (localProvider == null) {
+                        try {
+                            jBinder.linkToDeath(pr, 0);
+                        } catch (RemoteException e) {
+                            // Provider already dead.  Bail out of here without making
+                            // any changes to the provider map or other data structures.
+                            return null;
+                        }
+                    }
                     mProviderMap.put(names[i], pr);
-                } catch (RemoteException e) {
-                    return null;
                 }
             }
+
             if (localProvider != null) {
-                mLocalProviders.put(provider.asBinder(),
-                        new ProviderClientRecord(null, provider, localProvider));
+                ProviderClientRecord pr = mLocalProviders.get(jBinder);
+                if (pr != null) {
+                    if (localLOGV) {
+                        Slog.v(TAG, "installProvider: lost the race, "
+                                + "using existing local provider");
+                    }
+                    provider = pr.mProvider;
+                } else {
+                    pr = new ProviderClientRecord(null, provider, localProvider);
+                    mLocalProviders.put(jBinder, pr);
+                }
+            }
+
+            if (!noReleaseNeeded) {
+                ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
+                if (prc != null) {
+                    if (localLOGV) {
+                        Slog.v(TAG, "installProvider: lost the race, incrementing ref count");
+                    }
+                    prc.count += 1;
+                    if (prc.count == 1) {
+                        if (localLOGV) {
+                            Slog.v(TAG, "installProvider: "
+                                    + "snatched provider from the jaws of death");
+                        }
+                        // Because the provider previously had a reference count of zero,
+                        // it was scheduled to be removed.  Cancel that.
+                        mH.removeMessages(H.REMOVE_PROVIDER, provider);
+                    }
+                } else {
+                    mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
+                }
             }
         }
-
         return provider;
     }
 
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 91398bc..b1c1f30 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -635,6 +635,9 @@
                     //Log.v(TAG, "...app returning after sending offsets!");
                 } catch (RemoteException e) {
                     // Ignore.
+                } catch (IllegalArgumentException e) {
+                    // Since this is being posted, it's possible that this windowToken is no longer
+                    // valid, for example, if setWallpaperOffsets is called just before rotation.
                 }
             }
         });
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 821b6df..83acef8 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -187,6 +187,16 @@
     public static final String DEFERRED_SNIPPETING_QUERY = "deferred_snippeting_query";
 
     /**
+     * A boolean parameter for {@link CommonDataKinds.Phone#CONTENT_URI},
+     * {@link CommonDataKinds.Email#CONTENT_URI}, and
+     * {@link CommonDataKinds.StructuredPostal#CONTENT_URI}.
+     * This enables a content provider to remove duplicate entries in results.
+     *
+     * @hide
+     */
+    public static final String REMOVE_DUPLICATE_ENTRIES = "remove_duplicate_entries";
+
+    /**
      * <p>
      * API for obtaining a pre-authorized version of a URI that normally requires special
      * permission (beyond READ_CONTACTS) to read.  The caller obtaining the pre-authorized URI
diff --git a/core/java/com/android/internal/widget/DigitalClock.java b/core/java/com/android/internal/widget/DigitalClock.java
index 6f24eba..daefc9a 100644
--- a/core/java/com/android/internal/widget/DigitalClock.java
+++ b/core/java/com/android/internal/widget/DigitalClock.java
@@ -106,7 +106,8 @@
         private String mAmString, mPmString;
 
         AmPm(View parent, Typeface tf) {
-            mAmPmTextView = (TextView) parent.findViewById(R.id.am_pm);
+            // No longer used, uncomment if we decide to use AM/PM indicator again
+            // mAmPmTextView = (TextView) parent.findViewById(R.id.am_pm);
             if (mAmPmTextView != null && tf != null) {
                 mAmPmTextView.setTypeface(tf);
             }
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index ffcd1a0..de2d8c4 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -212,10 +212,10 @@
     surfaceTexture->setDefaultBufferSize(width, height);
 }
 
-static void SurfaceTexture_updateTexImage(JNIEnv* env, jobject thiz)
+static jint SurfaceTexture_updateTexImage(JNIEnv* env, jobject thiz)
 {
     sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
-    surfaceTexture->updateTexImage();
+    return surfaceTexture->updateTexImage();
 }
 
 static void SurfaceTexture_getTransformMatrix(JNIEnv* env, jobject thiz,
@@ -246,7 +246,7 @@
     {"nativeInit",               "(ILjava/lang/Object;Z)V", (void*)SurfaceTexture_init },
     {"nativeFinalize",           "()V",   (void*)SurfaceTexture_finalize },
     {"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize },
-    {"nativeUpdateTexImage",     "()V",   (void*)SurfaceTexture_updateTexImage },
+    {"nativeUpdateTexImage",     "()I",   (void*)SurfaceTexture_updateTexImage },
     {"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix },
     {"nativeGetTimestamp",       "()J",   (void*)SurfaceTexture_getTimestamp },
     {"nativeRelease",            "()V",   (void*)SurfaceTexture_release },
diff --git a/core/res/res/drawable-hdpi/transportcontrol_bg.9.png b/core/res/res/drawable-hdpi/transportcontrol_bg.9.png
new file mode 100644
index 0000000..ebd6f8a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/transportcontrol_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/transportcontrol_bg.9.png b/core/res/res/drawable-mdpi/transportcontrol_bg.9.png
new file mode 100644
index 0000000..d5a339f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/transportcontrol_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png b/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png
new file mode 100644
index 0000000..b690a2a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png
Binary files differ
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
index b58f081..f972843 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
@@ -17,45 +17,69 @@
 */
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
+    android:layout_height="match_parent">
 
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="0dip"
-        android:layout_weight="1"
-    />
-
+    <!-- left side: status and music -->
     <RelativeLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content">
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:layout_width="0dip"
+        android:gravity="center">
 
-        <!-- left side: status -->
-        <include layout="@layout/keyguard_screen_status_land"
-            android:layout_width="wrap_content"
+        <RelativeLayout android:id="@+id/transport_bg_protect"
+            android:layout_width="512dip"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="102dip"
-            android:paddingTop="50dip"
-            android:layout_centerVertical="true"
-            android:layout_alignParentLeft="true"/>
+            android:layout_marginBottom="24dip">
 
-        <!-- right side: password -->
+            <!-- Music transport control underneath -->
+            <include android:id="@+id/transport"
+                layout="@layout/keyguard_transport_control"
+                android:layout_row="0"
+                android:layout_column="0"
+                android:layout_rowSpan="3"
+                android:layout_columnSpan="1"
+                android:layout_gravity="fill"
+                android:layout_width="match_parent"
+                android:layout_height="512dip"
+                />
+
+            <!-- Status -->
+            <include layout="@layout/keyguard_screen_status_land"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="50dip"
+                android:layout_marginTop="50dip"
+                android:layout_marginBottom="50dip"
+                android:layout_marginRight="64dip"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentLeft="true"/>
+
+        </RelativeLayout>
+
+    </RelativeLayout>
+
+    <!-- right side: password -->
+    <LinearLayout
+        android:layout_width="0dip"
+        android:layout_weight="1"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:gravity="center">
+
         <LinearLayout
-            android:layout_width="330dip"
-            android:layout_height="wrap_content"
             android:orientation="vertical"
-            android:layout_alignParentRight="true"
-            android:layout_centerVertical="true"
-            android:layout_marginRight="155dip">
-
+            android:layout_width="330dip"
+            android:layout_height="wrap_content">
 
             <LinearLayout
                 android:orientation="horizontal"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_gravity="center_vertical"
+                android:layout_gravity="center"
                 android:background="@drawable/lockscreen_password_field_dark">
 
                 <EditText android:id="@+id/passwordEntry"
@@ -88,6 +112,7 @@
                     android:visibility="gone"
                     />
 
+                <!-- The IME switcher button is only shown in ASCII password mode (not PIN) -->
                 <ImageView android:id="@+id/switch_ime_button"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
@@ -103,33 +128,29 @@
 
             <!-- Numeric keyboard -->
             <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
-                android:layout_width="330dip"
+                android:layout_width="match_parent"
                 android:layout_height="330dip"
                 android:background="#40000000"
                 android:layout_marginTop="5dip"
                 android:keyBackground="@drawable/btn_keyboard_key_ics"
                 android:visibility="gone"
             />
+
+            <!-- Emergency call button. Generally not used on tablet devices. -->
+            <Button
+                android:id="@+id/emergencyCallButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:drawableLeft="@drawable/ic_emergency"
+                android:drawablePadding="8dip"
+                android:text="@string/lockscreen_emergency_call"
+                android:visibility="gone"
+                style="@style/Widget.Button.Transparent"
+            />
+
         </LinearLayout>
 
-    </RelativeLayout>
-
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="0dip"
-        android:layout_weight="1"
-    />
-
-    <!-- emergency call button NOT CURRENTLY USED -->
-    <Button
-        android:id="@+id/emergencyCallButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:drawableLeft="@drawable/ic_emergency"
-        android:drawablePadding="8dip"
-        android:text="@string/lockscreen_emergency_call"
-        android:visibility="gone"
-        style="@style/Widget.Button.Transparent"
-    />
+    </LinearLayout>
 
 </LinearLayout>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
index cadb5f8..8b65b22 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
@@ -16,23 +16,48 @@
 ** limitations under the License.
 */
 -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
+    android:layout_height="match_parent">
 
-    <!-- top: status -->
+    <!-- top: status and emergency/forgot pattern buttons -->
     <RelativeLayout
-            android:layout_width="match_parent"
-            android:layout_height="0dip"
-            android:layout_weight="1">
-        <include layout="@layout/keyguard_screen_status_port"
-            android:layout_width="wrap_content"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:layout_width="match_parent"
+        android:gravity="center">
+
+        <RelativeLayout android:id="@+id/transport_bg_protect"
+            android:layout_width="512dip"
             android:layout_height="wrap_content"
-            android:layout_marginTop="134dip"
-            android:layout_marginLeft="266dip"
-            android:layout_alignParentTop="true"
-            android:layout_alignParentLeft="true"/>
+            android:gravity="center">
+
+            <!-- Music transport control -->
+            <include android:id="@+id/transport"
+                layout="@layout/keyguard_transport_control"
+                android:layout_row="0"
+                android:layout_column="0"
+                android:layout_rowSpan="3"
+                android:layout_columnSpan="1"
+                android:layout_gravity="fill"
+                android:layout_width="match_parent"
+                android:layout_height="512dip"
+                />
+
+            <include layout="@layout/keyguard_screen_status_port"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="50dip"
+                android:layout_marginTop="50dip"
+                android:layout_marginBottom="100dip"
+                android:layout_marginRight="64dip"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentLeft="true"/>
+
+        </RelativeLayout>
+
     </RelativeLayout>
 
     <!-- bottom: password -->
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
index 3a7c1e1..4fafc3c 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
@@ -23,15 +23,14 @@
         android:orientation="vertical"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:gravity="left"
-        >
+        android:gravity="right">
 
     <TextView
         android:id="@+id/carrier"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="17sp"
+        android:textSize="16sp"
         android:drawablePadding="4dip"
         android:layout_marginTop="32dip"
         android:singleLine="true"
@@ -72,19 +71,6 @@
             android:layout_marginBottom="6dip"
             />
 
-        <TextView android:id="@+id/am_pm"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/timeDisplayBackground"
-            android:layout_alignBaseline="@id/timeDisplayBackground"
-            android:singleLine="true"
-            android:ellipsize="none"
-            android:textSize="30sp"
-            android:layout_marginLeft="8dip"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textColor="@color/lockscreen_clock_am_pm"
-            />
-
     </com.android.internal.widget.DigitalClock>
 
     <LinearLayout
@@ -99,15 +85,16 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="17sp"/>
+            android:textSize="16sp"/>
 
         <TextView
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="30dip"
+            android:layout_marginLeft="16dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="17sp"/>
+            android:drawablePadding="4dip"
+            android:textSize="16sp"/>
 
     </LinearLayout>
 
@@ -117,7 +104,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="10dip"
-        android:textSize="17sp"
+        android:textSize="16sp"
         android:textAppearance="?android:attr/textAppearanceMedium"
         />
 
@@ -127,7 +114,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="17sp"
+        android:textSize="16sp"
         android:layout_marginTop="20dip"
         android:singleLine="false"
         android:textColor="@color/lockscreen_owner_info"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
index c02341e..dfab3e3 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
@@ -23,9 +23,8 @@
         android:orientation="vertical"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="140dip"
         android:layout_marginTop="20dip"
-        android:gravity="left"
+        android:gravity="right"
         >
 
     <TextView
@@ -33,7 +32,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="17sp"
+        android:textSize="16sp"
         android:drawablePadding="4dip"
         android:layout_marginTop="32dip"
         android:singleLine="true"
@@ -73,19 +72,6 @@
             android:layout_alignTop="@id/timeDisplayBackground"
             />
 
-        <TextView android:id="@+id/am_pm"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/timeDisplayBackground"
-            android:layout_alignBaseline="@id/timeDisplayBackground"
-            android:singleLine="true"
-            android:ellipsize="none"
-            android:textSize="30sp"
-            android:layout_marginLeft="8dip"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textColor="@color/lockscreen_clock_am_pm"
-            />
-
     </com.android.internal.widget.DigitalClock>
 
     <LinearLayout
@@ -100,15 +86,16 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="17sp"/>
+            android:textSize="16sp"/>
 
         <TextView
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="30dip"
+            android:layout_marginLeft="16dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="17sp"/>
+            android:drawablePadding="4dip"
+            android:textSize="16sp"/>
 
     </LinearLayout>
 
@@ -117,7 +104,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="10dip"
-        android:textSize="17sp"
+        android:textSize="16sp"
         android:textAppearance="?android:attr/textAppearanceMedium"
         />
 
@@ -128,7 +115,7 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="20dip"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="17sp"
+        android:textSize="16sp"
         android:singleLine="false"
         android:visibility="invisible"
         android:textColor="@color/lockscreen_owner_info"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
index 23b2fcb..73dadb4 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
@@ -30,15 +30,40 @@
 
     <!-- top: status -->
     <RelativeLayout
-        android:layout_width="match_parent"
         android:layout_height="0dip"
         android:layout_weight="1"
-        android:orientation="vertical">
-        <include layout="@layout/keyguard_screen_status_port"
-            android:layout_width="wrap_content"
+        android:layout_width="match_parent"
+        android:gravity="center">
+
+        <RelativeLayout android:id="@+id/transport_bg_protect"
+            android:layout_width="512dip"
             android:layout_height="wrap_content"
-            android:layout_marginTop="134dip"
-            android:layout_marginLeft="266dip"/>
+            android:gravity="center">
+
+            <!-- Music transport control -->
+            <include android:id="@+id/transport"
+                layout="@layout/keyguard_transport_control"
+                android:layout_row="0"
+                android:layout_column="0"
+                android:layout_rowSpan="3"
+                android:layout_columnSpan="1"
+                android:layout_gravity="fill"
+                android:layout_width="match_parent"
+                android:layout_height="512dip"
+                />
+
+            <include layout="@layout/keyguard_screen_status_port"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="50dip"
+                android:layout_marginTop="50dip"
+                android:layout_marginBottom="100dip"
+                android:layout_marginRight="64dip"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentLeft="true"/>
+
+        </RelativeLayout>
+
     </RelativeLayout>
 
     <LinearLayout
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
index 66223f2..10b1ace 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
@@ -27,19 +27,40 @@
     android:orientation="horizontal"
     android:id="@+id/root">
 
-    <!-- left side: status -->
+    <!-- left side: status and music -->
     <RelativeLayout
         android:layout_height="match_parent"
         android:layout_weight="1"
-        android:layout_width="0dip">
+        android:layout_width="0dip"
+        android:gravity="center">
 
-        <include layout="@layout/keyguard_screen_status_land"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="102dip"
-            android:layout_marginTop="320dip"
-            android:layout_alignParentTop="true"
-            android:layout_alignParentLeft="true"/>
+        <RelativeLayout android:id="@+id/transport_bg_protect"
+            android:layout_width="512dip"
+            android:layout_height="wrap_content">
+
+            <!-- Music transport control underneath -->
+            <include android:id="@+id/transport"
+                layout="@layout/keyguard_transport_control"
+                android:layout_row="0"
+                android:layout_column="0"
+                android:layout_rowSpan="3"
+                android:layout_columnSpan="1"
+                android:layout_gravity="fill"
+                android:layout_width="match_parent"
+                android:layout_height="512dip"
+                />
+
+            <include layout="@layout/keyguard_screen_status_land"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="50dip"
+                android:layout_marginTop="50dip"
+                android:layout_marginBottom="82dip"
+                android:layout_marginRight="64dip"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentLeft="true"/>
+
+        </RelativeLayout>
 
     </RelativeLayout>
 
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml
index 7ac41b5..70d18cc 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml
@@ -27,19 +27,41 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <!-- left side: status  -->
+    <!-- left side: status and music -->
     <RelativeLayout
         android:layout_height="match_parent"
         android:layout_weight="1"
-        android:layout_width="0dip">
+        android:layout_width="0dip"
+        android:gravity="center">
 
-        <include layout="@layout/keyguard_screen_status_land"
-            android:layout_width="wrap_content"
+        <RelativeLayout android:id="@+id/transport_bg_protect"
+            android:layout_width="512dip"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="102dip"
-            android:layout_marginTop="320dip"
-            android:layout_alignParentTop="true"
-            android:layout_alignParentLeft="true"/>
+            android:layout_marginBottom="24dip">
+
+            <!-- Music transport control underneath -->
+            <include android:id="@+id/transport"
+                layout="@layout/keyguard_transport_control"
+                android:layout_row="0"
+                android:layout_column="0"
+                android:layout_rowSpan="3"
+                android:layout_columnSpan="1"
+                android:layout_gravity="fill"
+                android:layout_width="match_parent"
+                android:layout_height="512dip"
+                />
+
+            <include layout="@layout/keyguard_screen_status_land"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="50dip"
+                android:layout_marginTop="50dip"
+                android:layout_marginBottom="50dip"
+                android:layout_marginRight="64dip"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentLeft="true"/>
+
+        </RelativeLayout>
 
     </RelativeLayout>
 
@@ -58,22 +80,23 @@
 
         <!-- Emergency and forgot pattern buttons. -->
         <LinearLayout
+            android:orientation="horizontal"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_below="@id/lockPattern"
             android:layout_alignLeft="@id/lockPattern"
             android:layout_alignRight="@id/lockPattern"
             android:layout_marginTop="28dip"
-            android:layout_marginLeft="28dip"
-            android:layout_marginRight="28dip"
-            android:orientation="horizontal">
+            android:gravity="center"
+            style="?android:attr/buttonBarStyle"
+            android:weightSum="2">
 
             <Button android:id="@+id/forgotPatternButton"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center"
-                style="@style/Widget.Button.Transparent"
-                android:drawableLeft="@drawable/ic_emergency"
+                style="?android:attr/buttonBarButtonStyle"
+                android:drawableLeft="@drawable/lockscreen_forgot_password_button"
                 android:drawablePadding="8dip"
                 android:text="@string/lockscreen_forgot_pattern_button_text"
                 android:visibility="gone"
@@ -83,7 +106,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center"
-                style="@style/Widget.Button.Transparent"
+                style="?android:attr/buttonBarButtonStyle"
                 android:drawableLeft="@drawable/ic_emergency"
                 android:drawablePadding="8dip"
                 android:text="@string/lockscreen_emergency_call"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
index 1f6058f..7a623ce 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
@@ -23,32 +23,72 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <!-- top: status and emergency/forgot pattern buttons -->
-    <LinearLayout
+    <!-- top: status -->
+    <RelativeLayout
         android:layout_height="0dip"
         android:layout_weight="1"
         android:layout_width="match_parent"
-        android:orientation="vertical">
+        android:gravity="center">
 
-        <include layout="@layout/keyguard_screen_status_port"
-            android:layout_width="wrap_content"
+        <RelativeLayout android:id="@+id/transport_bg_protect"
+            android:layout_width="512dip"
             android:layout_height="wrap_content"
-            android:layout_marginTop="134dip"
-            android:layout_marginLeft="266dip"/>
+            android:gravity="center">
+
+            <!-- Music transport control -->
+            <include android:id="@+id/transport"
+                layout="@layout/keyguard_transport_control"
+                android:layout_row="0"
+                android:layout_column="0"
+                android:layout_rowSpan="3"
+                android:layout_columnSpan="1"
+                android:layout_gravity="fill"
+                android:layout_width="match_parent"
+                android:layout_height="512dip"
+                />
+
+            <include layout="@layout/keyguard_screen_status_land"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="50dip"
+                android:layout_marginTop="50dip"
+                android:layout_marginBottom="100dip"
+                android:layout_marginRight="64dip"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentLeft="true"/>
+
+        </RelativeLayout>
+
+    </RelativeLayout>
+
+    <!-- bottom: lock pattern, emergency dialer and forgot pattern button -->
+    <LinearLayout
+        android:layout_weight="1"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:orientation="vertical"
+        android:gravity="center">
+
+        <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
+            android:layout_width="354dip"
+            android:layout_height="354dip"
+            android:layout_marginTop="50dip"/>
 
         <!-- Emergency and forgot pattern buttons. -->
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            android:gravity="center_horizontal">
+            style="?android:attr/buttonBarStyle"
+            android:gravity="center"
+            android:weightSum="2">
 
             <Button android:id="@+id/forgotPatternButton"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center"
-                style="@style/Widget.Button.Transparent"
-                android:drawableLeft="@drawable/ic_emergency"
+                style="?android:attr/buttonBarButtonStyle"
+                android:drawableLeft="@drawable/lockscreen_forgot_password_button"
                 android:drawablePadding="8dip"
                 android:text="@string/lockscreen_forgot_pattern_button_text"
                 android:visibility="gone"
@@ -58,7 +98,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center"
-                style="@style/Widget.Button.Transparent"
+                style="?android:attr/buttonBarButtonStyle"
                 android:drawableLeft="@drawable/ic_emergency"
                 android:drawablePadding="8dip"
                 android:text="@string/lockscreen_emergency_call"
@@ -69,19 +109,5 @@
 
     </LinearLayout>
 
-    <!-- right side: lock pattern -->
-    <LinearLayout
-        android:layout_weight="1"
-        android:layout_width="match_parent"
-        android:layout_height="0dip"
-        android:gravity="center"
-        >
-        <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
-            android:layout_width="354dip"
-            android:layout_height="354dip"
-            android:layout_marginTop="50dip"
-          />
-    </LinearLayout>
-
 </com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
 
diff --git a/core/res/res/layout-sw600dp/keyguard_transport_control.xml b/core/res/res/layout-sw600dp/keyguard_transport_control.xml
new file mode 100644
index 0000000..86b103e
--- /dev/null
+++ b/core/res/res/layout-sw600dp/keyguard_transport_control.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<!-- *** Note *** This should mirror the file in layout/ with the exception of the background set
+     here for adding a drop shadow on tablets. -->
+
+<com.android.internal.widget.TransportControlView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/transport_controls"
+    android:background="@drawable/transportcontrol_bg">
+
+    <!-- FrameLayout used as scrim to show between album art and buttons -->
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:foreground="@drawable/ic_lockscreen_player_background">
+        <!-- We use ImageView for its cropping features, otherwise could be android:background -->
+        <ImageView
+            android:id="@+id/albumart"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="fill"
+            android:scaleType="centerCrop"
+            android:adjustViewBounds="false"
+        />
+    </FrameLayout>
+
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom">
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dip"
+            android:layout_marginLeft="16dip"
+            android:layout_marginRight="16dip"
+            android:gravity="center_horizontal"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+        />
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:layout_marginTop="5dip">
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1">
+                <ImageView
+                    android:id="@+id/btn_prev"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:src="@drawable/ic_media_previous"
+                    android:clickable="true"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:padding="10dip"
+                    android:contentDescription="@string/lockscreen_transport_prev_description"/>
+            </FrameLayout>
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1">
+                <ImageView
+                    android:id="@+id/btn_play"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:clickable="true"
+                    android:src="@drawable/ic_media_play"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:padding="10dip"
+                    android:contentDescription="@string/lockscreen_transport_play_description"/>
+            </FrameLayout>
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1">
+                <ImageView
+                    android:id="@+id/btn_next"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:clickable="true"
+                    android:src="@drawable/ic_media_next"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:padding="10dip"
+                    android:contentDescription="@string/lockscreen_transport_next_description"/>
+            </FrameLayout>
+        </LinearLayout>
+    </LinearLayout>
+
+</com.android.internal.widget.TransportControlView>
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index 2392618..b0f1bc5 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -19,6 +19,8 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:orientation="vertical"
     android:fitsSystemWindows="true">
     <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
diff --git a/core/res/res/layout/screen_action_bar_overlay.xml b/core/res/res/layout/screen_action_bar_overlay.xml
index 19b861c..2a8c7c3 100644
--- a/core/res/res/layout/screen_action_bar_overlay.xml
+++ b/core/res/res/layout/screen_action_bar_overlay.xml
@@ -19,38 +19,45 @@
 the Action Bar enabled overlaying application content.
 -->
 
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:fitsSystemWindows="true">
     <FrameLayout android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
-    <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        style="?android:attr/actionBarStyle"
-        android:gravity="top">
-        <com.android.internal.widget.ActionBarView
-            android:id="@+id/action_bar"
+    <LinearLayout android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:layout_gravity="top">
+        <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            style="?android:attr/actionBarStyle" />
-        <com.android.internal.widget.ActionBarContextView
-            android:id="@+id/action_context_bar"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:visibility="gone"
-            style="?android:attr/actionModeStyle" />
-    </com.android.internal.widget.ActionBarContainer>
-    <ImageView android:src="?android:attr/windowContentOverlay"
-               android:scaleType="fitXY"
-               android:layout_width="match_parent"
-               android:layout_height="wrap_content"
-               android:layout_below="@id/action_bar_container" />
+            android:layout_alignParentTop="true"
+            style="?android:attr/actionBarStyle"
+            android:gravity="top">
+            <com.android.internal.widget.ActionBarView
+                android:id="@+id/action_bar"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                style="?android:attr/actionBarStyle" />
+            <com.android.internal.widget.ActionBarContextView
+                android:id="@+id/action_context_bar"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:visibility="gone"
+                style="?android:attr/actionModeStyle" />
+        </com.android.internal.widget.ActionBarContainer>
+        <ImageView android:src="?android:attr/windowContentOverlay"
+                   android:scaleType="fitXY"
+                   android:layout_width="match_parent"
+                   android:layout_height="wrap_content"
+                   android:layout_below="@id/action_bar_container" />
+    </LinearLayout>
     <com.android.internal.widget.ActionBarContainer android:id="@+id/split_action_bar"
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
-                  android:layout_alignParentBottom="true"
+                  android:layout_gravity="bottom"
                   style="?android:attr/actionBarSplitStyle"
                   android:visibility="gone"
                   android:gravity="center"/>
-</RelativeLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/screen_simple.xml b/core/res/res/layout/screen_simple.xml
index 87c29f6..c1914e7 100644
--- a/core/res/res/layout/screen_simple.xml
+++ b/core/res/res/layout/screen_simple.xml
@@ -22,6 +22,8 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:fitsSystemWindows="true"
     android:orientation="vertical">
     <ViewStub android:id="@+id/action_mode_bar_stub"
diff --git a/core/res/res/layout/screen_simple_overlay_action_mode.xml b/core/res/res/layout/screen_simple_overlay_action_mode.xml
index eb093e7..c790d10 100644
--- a/core/res/res/layout/screen_simple_overlay_action_mode.xml
+++ b/core/res/res/layout/screen_simple_overlay_action_mode.xml
@@ -21,6 +21,8 @@
 -->
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:fitsSystemWindows="true">
     <FrameLayout
          android:id="@android:id/content"
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 5b488c0..921bcf4 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -43,7 +43,7 @@
     <dimen name="action_bar_subtitle_bottom_margin">9dip</dimen>
 
     <!-- Size of clock font in LockScreen. -->
-    <dimen name="keyguard_pattern_unlock_clock_font_size">98sp</dimen>
+    <dimen name="keyguard_pattern_unlock_clock_font_size">112sp</dimen>
 
     <!-- Size of lockscreen outerring on unsecure unlock LockScreen -->
     <dimen name="keyguard_lockscreen_outerring_diameter">364dp</dimen>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 9b8be85..c8ba26a 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <!--
 /* //device/apps/common/assets/res/any/strings.xml
 **
@@ -3365,4 +3365,13 @@
     <!-- Delimeter used between each item in a textual list; for example "Alpha, Beta". [CHAR LIMIT=3] -->
     <string name="list_delimeter">", "</string>
 
+    <!-- STK sending DTMF, SMS, USSD, SS -->
+    <string name="sending">Sending...</string>
+
+    <!-- STK launch Browser -->
+    <string name="launchBrowserDefault">Launch Browser?</string>
+
+    <!-- STK setup Call -->
+    <string name="SetupCallDefault">Accept Call?</string>
+
 </resources>
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
index 0cc883f..01a5fd0 100644
--- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
@@ -90,7 +90,26 @@
      */
     @LargeTest
     public void testWifiDownload() throws Exception {
-        assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
+        assertTrue("Could not connect to wifi!", setDeviceWifiAndAirplaneMode(mSsid));
+        downloadFile();
+    }
+
+    /**
+     * Ensure that downloading on mobile reports reasonable stats.
+     */
+    @LargeTest
+    public void testMobileDownload() throws Exception {
+        // As part of the setup we disconnected from wifi; make sure we are connected to mobile and
+        // that we have data.
+        assertTrue("Do not have mobile data!", hasMobileData());
+        downloadFile();
+    }
+
+    /**
+     * Helper method that downloads a file using http connection from a test server and reports the
+     * data usage stats to instrumentation out.
+     */
+    protected void downloadFile() throws Exception {
         NetworkStats pre_test_stats = fetchDataFromProc(mUid);
         String ts = Long.toString(System.currentTimeMillis());
 
@@ -120,11 +139,28 @@
     }
 
     /**
-     * Ensure that downloading on wifi reports reasonable stats.
+     * Ensure that uploading on wifi reports reasonable stats.
      */
     @LargeTest
     public void testWifiUpload() throws Exception {
         assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
+        uploadFile();
+    }
+
+    /**
+     *  Ensure that uploading on wifi reports reasonable stats.
+     */
+    @LargeTest
+    public void testMobileUpload() throws Exception {
+        assertTrue(hasMobileData());
+        uploadFile();
+    }
+
+    /**
+     * Helper method that downloads a test file to upload. The stats reported to instrumentation out
+     * only include upload stats.
+     */
+    protected void uploadFile() throws Exception {
         // Download a file from the server.
         String ts = Long.toString(System.currentTimeMillis());
         String targetUrl = BandwidthTestUtil.buildDownloadUrl(
@@ -156,12 +192,30 @@
     }
 
     /**
-     * We want to make sure that if we use the Download Manager to download stuff,
+     * We want to make sure that if we use wifi and the  Download Manager to download stuff,
      * accounting still goes to the app making the call and that the numbers still make sense.
      */
     @LargeTest
     public void testWifiDownloadWithDownloadManager() throws Exception {
         assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
+        downloadFileUsingDownloadManager();
+    }
+
+    /**
+     * We want to make sure that if we use mobile data and the Download Manager to download stuff,
+     * accounting still goes to the app making the call and that the numbers still make sense.
+     */
+    @LargeTest
+    public void testMobileDownloadWithDownloadManager() throws Exception {
+        assertTrue(hasMobileData());
+        downloadFileUsingDownloadManager();
+    }
+
+    /**
+     * Helper method that downloads a file from a test server using the download manager and reports
+     * the stats to instrumentation out.
+     */
+    protected void downloadFileUsingDownloadManager() throws Exception {
         // If we are using the download manager, then the data that is written to /proc/uid_stat/
         // is accounted against download manager's uid, since it uses pre-ICS API.
         int downloadManagerUid = mConnectionUtil.downloadManagerUid();
@@ -195,6 +249,7 @@
 
     /**
      * Fetch network data from /proc/uid_stat/uid
+     *
      * @return populated {@link NetworkStats}
      */
     public NetworkStats fetchDataFromProc(int uid) {
@@ -210,7 +265,8 @@
     }
 
     /**
-     * Turn on Airplane mode and connect to the wifi
+     * Turn on Airplane mode and connect to the wifi.
+     *
      * @param ssid of the wifi to connect to
      * @return true if we successfully connected to a given network.
      */
@@ -219,12 +275,25 @@
         assertTrue(mConnectionUtil.connectToWifi(ssid));
         assertTrue(mConnectionUtil.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
                 ConnectionUtil.LONG_TIMEOUT));
-        return mConnectionUtil.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectionUtil.LONG_TIMEOUT);
+        assertTrue(mConnectionUtil.waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+                State.CONNECTED, ConnectionUtil.LONG_TIMEOUT));
+        return mConnectionUtil.hasData();
+    }
+
+    /**
+     * Helper method to make sure we are connected to mobile data.
+     *
+     * @return true if we successfully connect to mobile data.
+     */
+    public boolean hasMobileData() {
+        assertTrue("Not connected to mobile", mConnectionUtil.isConnectedToMobile());
+        assertFalse("Still connected to wifi.", mConnectionUtil.isConnectedToWifi());
+        return mConnectionUtil.hasData();
     }
 
     /**
      * Output the {@link NetworkStats} to Instrumentation out.
+     *
      * @param label to attach to this given stats.
      * @param stats {@link NetworkStats} to add.
      * @param results {@link Bundle} to be added to.
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
index d663aad..a5e5ab0e 100644
--- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
@@ -44,6 +44,8 @@
 import com.android.bandwidthtest.NetworkState.StateTransitionDirection;
 import com.android.internal.util.AsyncChannel;
 
+import java.io.IOException;
+import java.net.UnknownHostException;
 import java.util.List;
 
 /*
@@ -257,14 +259,14 @@
         mConnectivityState[networkType].recordState(networkState);
     }
 
-   /**
-    * Set the state transition criteria
-    *
-    * @param networkType
-    * @param initState
-    * @param transitionDir
-    * @param targetState
-    */
+    /**
+     * Set the state transition criteria
+     *
+     * @param networkType
+     * @param initState
+     * @param transitionDir
+     * @param targetState
+     */
     public void setStateTransitionCriteria(int networkType, State initState,
             StateTransitionDirection transitionDir, State targetState) {
         mConnectivityState[networkType].setStateTransitionCriteria(
@@ -495,7 +497,8 @@
      * @return true if connected to a mobile network, false otherwise.
      */
     public boolean isConnectedToMobile() {
-        return (mNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE);
+        NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+        return networkInfo.isConnected();
     }
 
     /**
@@ -503,10 +506,10 @@
      * @return true if connected to wifi, false otherwise.
      */
     public boolean isConnectedToWifi() {
-        return (mNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI);
+        NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+        return networkInfo.isConnected();
     }
 
-
     /**
      * Associate the device to given SSID
      * If the device is already associated with a WiFi, disconnect and forget it,
@@ -681,4 +684,30 @@
         }
         Log.v(LOG_TAG, "onDestroy, inst=" + Integer.toHexString(hashCode()));
     }
+
+    /**
+     * Helper method used to test data connectivity by pinging a series of popular sites.
+     * @return true if device has data connectivity, false otherwise.
+     */
+    public boolean hasData() {
+        String[] hostList = {"www.google.com", "www.yahoo.com",
+                "www.bing.com", "www.facebook.com", "www.ask.com"};
+        try {
+            for (int i = 0; i < hostList.length; ++i) {
+                String host = hostList[i];
+                Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host);
+                int status = p.waitFor();
+                if (status == 0) {
+                    return true;
+                }
+            }
+        } catch (UnknownHostException e) {
+            Log.e(LOG_TAG, "Ping test Failed: Unknown Host");
+        } catch (IOException e) {
+            Log.e(LOG_TAG, "Ping test Failed: IOException");
+        } catch (InterruptedException e) {
+            Log.e(LOG_TAG, "Ping test Failed: InterruptedException");
+        }
+        return false;
+    }
 }
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
index e1db073..1df763a 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
@@ -256,6 +256,10 @@
         stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 24L, 24L);
         assertEquals(24, stats.size());
 
+        // try removing invalid data; should be no change
+        stats.removeBucketsBefore(0 - DAY_IN_MILLIS);
+        assertEquals(24, stats.size());
+
         // try removing far before buckets; should be no change
         stats.removeBucketsBefore(TEST_START - YEAR_IN_MILLIS);
         assertEquals(24, stats.size());
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 29fab11..0521e69 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -17,6 +17,7 @@
 package android.graphics;
 
 import java.lang.ref.WeakReference;
+
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -141,6 +142,12 @@
      * android.view.Surface#lockCanvas} is called.  For OpenGL ES, the EGLSurface should be
      * destroyed (via eglDestroySurface), made not-current (via eglMakeCurrent), and then recreated
      * (via eglCreateWindowSurface) to ensure that the new default size has taken effect.
+     * 
+     * The width and height parameters must be no greater than the minimum of
+     * GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see 
+     * {@link javax.microedition.khronos.opengles.GL10#glGetIntegerv glGetIntegerv}).
+     * An error due to invalid dimensions might not be reported until
+     * updateTexImage() is called.
      */
     public void setDefaultBufferSize(int width, int height) {
         nativeSetDefaultBufferSize(width, height);
@@ -152,7 +159,10 @@
      * implicitly bind its texture to the GL_TEXTURE_EXTERNAL_OES texture target.
      */
     public void updateTexImage() {
-        nativeUpdateTexImage();
+        int err = nativeUpdateTexImage(); 
+        if (err != 0) {
+            throw new RuntimeException("Error during updateTexImage (see logs)");
+        }
     }
 
     /**
@@ -258,7 +268,7 @@
     private native void nativeGetTransformMatrix(float[] mtx);
     private native long nativeGetTimestamp();
     private native void nativeSetDefaultBufferSize(int width, int height);
-    private native void nativeUpdateTexImage();
+    private native int nativeUpdateTexImage();
     private native int nativeGetQueuedCount();
     private native void nativeRelease();
 
diff --git a/graphics/java/android/renderscript/RSSurfaceView.java b/graphics/java/android/renderscript/RSSurfaceView.java
index 199952c..20eb93f 100644
--- a/graphics/java/android/renderscript/RSSurfaceView.java
+++ b/graphics/java/android/renderscript/RSSurfaceView.java
@@ -30,7 +30,7 @@
 import android.view.SurfaceView;
 
 /**
- * The Surface View for a graphics renderscript (RenderScriptGL) to draw on. 
+ * The Surface View for a graphics renderscript (RenderScriptGL) to draw on.
  */
 public class RSSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
     private SurfaceHolder mSurfaceHolder;
@@ -77,7 +77,7 @@
      * This method is part of the SurfaceHolder.Callback interface, and is
      * not normally called or subclassed by clients of RSSurfaceView.
      */
-    public void surfaceDestroyed(SurfaceHolder holder) {
+    public synchronized void surfaceDestroyed(SurfaceHolder holder) {
         // Surface will be destroyed when we return
         if (mRS != null) {
             mRS.setSurface(null, 0, 0);
@@ -88,7 +88,7 @@
      * This method is part of the SurfaceHolder.Callback interface, and is
      * not normally called or subclassed by clients of RSSurfaceView.
      */
-    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+    public synchronized void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
         if (mRS != null) {
             mRS.setSurface(holder, w, h);
         }
@@ -125,7 +125,7 @@
         return rs;
     }
 
-    public void destroyRenderScriptGL() {
+    public synchronized void destroyRenderScriptGL() {
         mRS.destroy();
         mRS = null;
     }
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index e2d6179e..d7dd4d6 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -79,7 +79,11 @@
     // pointed to by the buf argument and a status of OK is returned.  If no
     // slot is available then a status of -EBUSY is returned and buf is
     // unmodified.
-    virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
+    // The width and height parameters must be no greater than the minimum of
+    // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
+    // An error due to invalid dimensions might not be reported until
+    // updateTexImage() is called.
+    virtual status_t dequeueBuffer(int *buf, uint32_t width, uint32_t height,
             uint32_t format, uint32_t usage);
 
     // queueBuffer returns a filled buffer to the SurfaceTexture. In addition, a
@@ -176,7 +180,11 @@
     // requestBuffers when a with and height of zero is requested.
     // A call to setDefaultBufferSize() may trigger requestBuffers() to
     // be called from the client.
-    status_t setDefaultBufferSize(uint32_t w, uint32_t h);
+    // The width and height parameters must be no greater than the minimum of
+    // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
+    // An error due to invalid dimensions might not be reported until
+    // updateTexImage() is called.
+    status_t setDefaultBufferSize(uint32_t width, uint32_t height);
 
     // getCurrentBuffer returns the buffer associated with the current image.
     sp<GraphicBuffer> getCurrentBuffer() const;
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 5daafd5..93ebfb9 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -1520,4 +1520,36 @@
     EXPECT_EQ(1, buffers[2]->getStrongCount());
 }
 
+TEST_F(SurfaceTextureGLTest, InvalidWidthOrHeightFails) {
+    int texHeight = 16;
+    ANativeWindowBuffer* anb;
+
+    GLint maxTextureSize;
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
+
+    // make sure it works with small textures
+    mST->setDefaultBufferSize(16, texHeight);
+    EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    EXPECT_EQ(16, anb->width);
+    EXPECT_EQ(texHeight, anb->height);
+    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
+    EXPECT_EQ(NO_ERROR, mST->updateTexImage());
+
+    // make sure it works with GL_MAX_TEXTURE_SIZE
+    mST->setDefaultBufferSize(maxTextureSize, texHeight);
+    EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    EXPECT_EQ(maxTextureSize, anb->width);
+    EXPECT_EQ(texHeight, anb->height);
+    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
+    EXPECT_EQ(NO_ERROR, mST->updateTexImage());
+
+    // make sure it fails with GL_MAX_TEXTURE_SIZE+1
+    mST->setDefaultBufferSize(maxTextureSize+1, texHeight);
+    EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    EXPECT_EQ(maxTextureSize+1, anb->width);
+    EXPECT_EQ(texHeight, anb->height);
+    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
+    ASSERT_NE(NO_ERROR, mST->updateTexImage());
+}
+
 } // namespace android
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index fe15605..a8daab0 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -2693,11 +2693,22 @@
             mCallingUid = uid;
         }
 
-        public void unlinkToDeath() {
+        private void unlinkToDeath() {
             if (mSourceRef != null && mHandler != null) {
                 mSourceRef.unlinkToDeath(mHandler, 0);
             }
         }
+
+        @Override
+        protected void finalize() throws Throwable {
+            try {
+                unlinkToDeath();
+            } catch (java.util.NoSuchElementException e) {
+                Log.w(TAG, e + " thrown by unlinkToDeath() during finalize, ignoring");
+            } finally {
+                super.finalize();
+            }
+        }
     }
 
     private Stack<FocusStackEntry> mFocusStack = new Stack<FocusStackEntry>();
@@ -2732,8 +2743,7 @@
         if (!mFocusStack.empty() && mFocusStack.peek().mClientId.equals(clientToRemove))
         {
             //Log.i(TAG, "   removeFocusStackEntry() removing top of stack");
-            FocusStackEntry fse = mFocusStack.pop();
-            fse.unlinkToDeath();
+            mFocusStack.pop();
             if (signal) {
                 // notify the new top of the stack it gained focus
                 notifyTopOfAudioFocusStack();
@@ -2752,7 +2762,6 @@
                     Log.i(TAG, " AudioFocus  abandonAudioFocus(): removing entry for "
                             + fse.mClientId);
                     stackIterator.remove();
-                    fse.unlinkToDeath();
                 }
             }
         }
@@ -2858,6 +2867,9 @@
                 // if focus is already owned by this client and the reason for acquiring the focus
                 // hasn't changed, don't do anything
                 if (mFocusStack.peek().mFocusChangeType == focusChangeHint) {
+                    // unlink death handler so it can be gc'ed.
+                    // linkToDeath() creates a JNI global reference preventing collection.
+                    cb.unlinkToDeath(afdh, 0);
                     return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
                 }
                 // the reason for the audio focus request has changed: remove the current top of
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
index 62213de..9c87c22 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
@@ -16,6 +16,8 @@
 
 package com.android.nfc_extras;
 
+import java.util.HashMap;
+
 import android.content.Context;
 import android.nfc.INfcAdapterExtras;
 import android.nfc.NfcAdapter;
@@ -57,20 +59,22 @@
     // protected by NfcAdapterExtras.class, and final after first construction,
     // except for attemptDeadServiceRecovery() when NFC crashes - we accept a
     // best effort recovery
-    private static NfcAdapter sAdapter;
     private static INfcAdapterExtras sService;
     private static final CardEmulationRoute ROUTE_OFF =
             new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
 
+    // contents protected by NfcAdapterExtras.class
+    private static final HashMap<NfcAdapter, NfcAdapterExtras> sNfcExtras = new HashMap();
+
     private final NfcExecutionEnvironment mEmbeddedEe;
     private final CardEmulationRoute mRouteOnWhenScreenOn;
 
-    final Context mContext;
+    private final NfcAdapter mAdapter;
     final String mPackageName;
 
     /** get service handles */
-    private static void initService() {
-        final INfcAdapterExtras service = sAdapter.getNfcAdapterExtrasInterface();
+    private static void initService(NfcAdapter adapter) {
+        final INfcAdapterExtras service = adapter.getNfcAdapterExtrasInterface();
         if (service != null) {
             // Leave stale rather than receive a null value.
             sService = service;
@@ -95,23 +99,20 @@
 
         synchronized (NfcAdapterExtras.class) {
             if (sService == null) {
-                try {
-                    sAdapter = adapter;
-                    initService();
-                } finally {
-                    if (sService == null) {
-                        sAdapter = null;
-                    }
-                }
+                initService(adapter);
             }
+            NfcAdapterExtras extras = sNfcExtras.get(adapter);
+            if (extras == null) {
+                extras = new NfcAdapterExtras(adapter);
+                sNfcExtras.put(adapter,  extras);
+            }
+            return extras;
         }
-
-        return new NfcAdapterExtras(context);
     }
 
-    private NfcAdapterExtras(Context context) {
-        mContext = context.getApplicationContext();
-        mPackageName = context.getPackageName();
+    private NfcAdapterExtras(NfcAdapter adapter) {
+        mAdapter = adapter;
+        mPackageName = adapter.getContext().getPackageName();
         mEmbeddedEe = new NfcExecutionEnvironment(this);
         mRouteOnWhenScreenOn = new CardEmulationRoute(CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON,
                 mEmbeddedEe);
@@ -160,8 +161,8 @@
      */
     void attemptDeadServiceRecovery(Exception e) {
         Log.e(TAG, "NFC Adapter Extras dead - attempting to recover");
-        sAdapter.attemptDeadServiceRecovery(e);
-        initService();
+        mAdapter.attemptDeadServiceRecovery(e);
+        initService(mAdapter);
     }
 
     INfcAdapterExtras getService() {
diff --git a/nfc-extras/tests/Android.mk b/nfc-extras/tests/Android.mk
new file mode 100644
index 0000000..3eca76d
--- /dev/null
+++ b/nfc-extras/tests/Android.mk
@@ -0,0 +1,32 @@
+# Copyright 2011, 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_JAVA_LIBRARIES := \
+    android.test.runner \
+    com.android.nfc_extras
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := NfcExtrasTests
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/nfc-extras/tests/AndroidManifest.xml b/nfc-extras/tests/AndroidManifest.xml
new file mode 100644
index 0000000..0cc6653
--- /dev/null
+++ b/nfc-extras/tests/AndroidManifest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.nfc_extras.tests">
+
+    <!-- We add an application tag here just so that we can indicate that
+         this package needs to link against the android.test library,
+         which is needed when building test cases. -->
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <uses-library android:name="com.android.nfc_extras" />
+    </application>
+
+    <uses-permission android:name="android.permission.NFC"/>
+
+    <!--
+    Run all tests with
+    adb shell am instrument -w com.android.nfc_extras.tests/android.test.InstrumentationTestRunner
+    -->
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.nfc_extras.tests"
+                     android:label="Tests for NFC Extras library"/>
+
+</manifest>
diff --git a/nfc-extras/tests/src/com/android/nfc_extras/BasicNfcEeTest.java b/nfc-extras/tests/src/com/android/nfc_extras/BasicNfcEeTest.java
new file mode 100644
index 0000000..e1025aa
--- /dev/null
+++ b/nfc-extras/tests/src/com/android/nfc_extras/BasicNfcEeTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.nfc_extras;
+
+import android.content.Context;
+import android.nfc.NfcAdapter;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import com.android.nfc_extras.NfcAdapterExtras;
+import com.android.nfc_extras.NfcAdapterExtras.CardEmulationRoute;
+import com.android.nfc_extras.NfcExecutionEnvironment;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+public class BasicNfcEeTest extends InstrumentationTestCase {
+    private Context mContext;
+    private NfcAdapterExtras mAdapterExtras;
+    private NfcExecutionEnvironment mEe;
+
+    public static final byte[] SELECT_CARD_MANAGER_COMMAND = new byte[] {
+        (byte)0x00, (byte)0xA4, (byte)0x04, (byte)0x00,  // command
+        (byte)0x08,  // data length
+        (byte)0xA0, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x03, (byte)0x00, (byte)0x00,
+        (byte)0x00,  // card manager AID
+        (byte)0x00  // trailer
+    };
+
+    public static final byte[] SELECT_CARD_MANAGER_RESPONSE = new byte[] {
+        (byte)0x90, (byte)0x00,
+    };
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getInstrumentation().getContext();
+        mAdapterExtras = NfcAdapterExtras.get(NfcAdapter.getDefaultAdapter(mContext));
+        mEe = mAdapterExtras.getEmbeddedExecutionEnvironment();
+    }
+
+    public void testSendCardManagerApdu() throws IOException {
+        mEe.open();
+
+        try {
+            byte[] out = mEe.transceive(SELECT_CARD_MANAGER_COMMAND);
+            assertTrue(out.length >= SELECT_CARD_MANAGER_RESPONSE.length);
+            byte[] trailing = Arrays.copyOfRange(out,
+                    out.length - SELECT_CARD_MANAGER_RESPONSE.length,
+                    out.length);
+            assertByteArrayEquals(SELECT_CARD_MANAGER_RESPONSE, trailing);
+
+        } finally {
+            mEe.close();
+        }
+
+    }
+
+    public void testSendCardManagerApduMultiple() throws IOException {
+        for (int i=0; i<10; i++) {
+            try {
+            mEe.open();
+
+            try {
+                byte[] out = mEe.transceive(SELECT_CARD_MANAGER_COMMAND);
+                byte[] trailing = Arrays.copyOfRange(out,
+                        out.length - SELECT_CARD_MANAGER_RESPONSE.length,
+                        out.length);
+
+            } finally {
+                try {Thread.sleep(1000);} catch (InterruptedException e) {}
+                mEe.close();
+            }
+            } catch (IOException e) {}
+        }
+
+        testSendCardManagerApdu();
+
+    }
+
+    public void testEnableEe() {
+        mAdapterExtras.setCardEmulationRoute(
+                new CardEmulationRoute(CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, mEe));
+        CardEmulationRoute newRoute = mAdapterExtras.getCardEmulationRoute();
+        assertEquals(CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, newRoute.route);
+        assertEquals(mEe, newRoute.nfcEe);
+    }
+
+    public void testDisableEe() {
+        mAdapterExtras.setCardEmulationRoute(
+                new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null));
+        CardEmulationRoute newRoute = mAdapterExtras.getCardEmulationRoute();
+        assertEquals(CardEmulationRoute.ROUTE_OFF, newRoute.route);
+        assertNull(newRoute.nfcEe);
+    }
+
+    private static void assertByteArrayEquals(byte[] b1, byte[] b2) {
+        assertEquals(b1.length, b2.length);
+        for (int i = 0; i < b1.length; i++) {
+            assertEquals(b1[i], b2[i]);
+        }
+    }
+}
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 8e8e26c..c926670 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -261,14 +261,14 @@
  */
 #ifndef EGL_ANDROID_blob_cache
 #define EGL_ANDROID_blob_cache 1
-typedef khronos_ssize_t EGLsizei;
-typedef void (*EGLSetBlobFunc) (const void* key, EGLsizei keySize, const void* value, EGLsizei valueSize);
-typedef EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize, void* value, EGLsizei valueSize);
+typedef khronos_ssize_t EGLsizeiANDROID;
+typedef void (*EGLSetBlobFuncANDROID) (const void* key, EGLsizeiANDROID keySize, const void* value, EGLsizeiANDROID valueSize);
+typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void* key, EGLsizeiANDROID keySize, void* value, EGLsizeiANDROID valueSize);
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncs(EGLDisplay dpy, EGLSetBlobFunc set, EGLGetBlobFunc get);
+EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
 #endif /* EGL_EGLEXT_PROTOTYPES */
-typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSPROC) (EGLDisplay dpy,
-        EGLSetBlobFunc set, EGLGetBlobFunc get);
+typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy,
+        EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
 #endif
 
 #ifdef __cplusplus
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 60ac34b..63f02e4 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -860,7 +860,7 @@
 
     // The EGL_ANDROID_blob_cache extension should not be exposed to
     // applications.  It is used internally by the Android EGL layer.
-    if (!strcmp(procname, "eglSetBlobCacheFuncs")) {
+    if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID")) {
         return NULL;
     }
 
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index 522421b..13a4929 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -46,13 +46,13 @@
 //
 // Callback functions passed to EGL.
 //
-static void setBlob(const void* key, EGLsizei keySize, const void* value,
-        EGLsizei valueSize) {
+static void setBlob(const void* key, EGLsizeiANDROID keySize,
+        const void* value, EGLsizeiANDROID valueSize) {
     egl_cache_t::get()->setBlob(key, keySize, value, valueSize);
 }
 
-static EGLsizei getBlob(const void* key, EGLsizei keySize, void* value,
-        EGLsizei valueSize) {
+static EGLsizeiANDROID getBlob(const void* key, EGLsizeiANDROID keySize,
+        void* value, EGLsizeiANDROID valueSize) {
     return egl_cache_t::get()->getBlob(key, keySize, value, valueSize);
 }
 
@@ -87,22 +87,23 @@
                     !strcmp(" " BC_EXT_STR, exts + extsLen - (bcExtLen+1));
             bool inMiddle = strstr(" " BC_EXT_STR " ", exts);
             if (equal || atStart || atEnd || inMiddle) {
-                PFNEGLSETBLOBCACHEFUNCSPROC eglSetBlobCacheFuncs;
-                eglSetBlobCacheFuncs =
-                        reinterpret_cast<PFNEGLSETBLOBCACHEFUNCSPROC>(
-                            cnx->egl.eglGetProcAddress("eglSetBlobCacheFuncs"));
-                if (eglSetBlobCacheFuncs == NULL) {
+                PFNEGLSETBLOBCACHEFUNCSANDROIDPROC eglSetBlobCacheFuncsANDROID;
+                eglSetBlobCacheFuncsANDROID =
+                        reinterpret_cast<PFNEGLSETBLOBCACHEFUNCSANDROIDPROC>(
+                            cnx->egl.eglGetProcAddress(
+                                    "eglSetBlobCacheFuncsANDROID"));
+                if (eglSetBlobCacheFuncsANDROID == NULL) {
                     LOGE("EGL_ANDROID_blob_cache advertised by display %d, "
-                            "but unable to get eglSetBlobCacheFuncs", i);
+                            "but unable to get eglSetBlobCacheFuncsANDROID", i);
                     continue;
                 }
 
-                eglSetBlobCacheFuncs(display->disp[i].dpy, android::setBlob,
-                        android::getBlob);
+                eglSetBlobCacheFuncsANDROID(display->disp[i].dpy,
+                        android::setBlob, android::getBlob);
                 EGLint err = cnx->egl.eglGetError();
                 if (err != EGL_SUCCESS) {
-                    LOGE("eglSetBlobCacheFuncs resulted in an error: %#x",
-                            err);
+                    LOGE("eglSetBlobCacheFuncsANDROID resulted in an error: "
+                            "%#x", err);
                 }
             }
         }
@@ -119,8 +120,8 @@
     mInitialized = false;
 }
 
-void egl_cache_t::setBlob(const void* key, EGLsizei keySize, const void* value,
-        EGLsizei valueSize) {
+void egl_cache_t::setBlob(const void* key, EGLsizeiANDROID keySize,
+        const void* value, EGLsizeiANDROID valueSize) {
     Mutex::Autolock lock(mMutex);
 
     if (keySize < 0 || valueSize < 0) {
@@ -158,8 +159,8 @@
     }
 }
 
-EGLsizei egl_cache_t::getBlob(const void* key, EGLsizei keySize, void* value,
-        EGLsizei valueSize) {
+EGLsizeiANDROID egl_cache_t::getBlob(const void* key, EGLsizeiANDROID keySize,
+        void* value, EGLsizeiANDROID valueSize) {
     Mutex::Autolock lock(mMutex);
 
     if (keySize < 0 || valueSize < 0) {
@@ -323,7 +324,8 @@
             return;
         }
 
-        status_t err = mBlobCache->unflatten(buf + headerSize, cacheSize, NULL, 0);
+        status_t err = mBlobCache->unflatten(buf + headerSize, cacheSize, NULL,
+                0);
         if (err != OK) {
             LOGE("error reading cache contents: %s (%d)", strerror(-err),
                     -err);
diff --git a/opengl/libs/EGL/egl_cache.h b/opengl/libs/EGL/egl_cache.h
index 4389623..8760009 100644
--- a/opengl/libs/EGL/egl_cache.h
+++ b/opengl/libs/EGL/egl_cache.h
@@ -52,14 +52,14 @@
     // setBlob attempts to insert a new key/value blob pair into the cache.
     // This will be called by the hardware vendor's EGL implementation via the
     // EGL_ANDROID_blob_cache extension.
-    void setBlob(const void* key, EGLsizei keySize, const void* value,
-        EGLsizei valueSize);
+    void setBlob(const void* key, EGLsizeiANDROID keySize, const void* value,
+        EGLsizeiANDROID valueSize);
 
     // getBlob attempts to retrieve the value blob associated with a given key
     // blob from cache.  This will be called by the hardware vendor's EGL
     // implementation via the EGL_ANDROID_blob_cache extension.
-    EGLsizei getBlob(const void* key, EGLsizei keySize, void* value,
-        EGLsizei valueSize);
+    EGLsizeiANDROID getBlob(const void* key, EGLsizeiANDROID keySize,
+        void* value, EGLsizeiANDROID valueSize);
 
     // setCacheFilename sets the name of the file that should be used to store
     // cache contents from one program invocation to another.
diff --git a/opengl/specs/EGL_ANDROID_blob_cache.txt b/opengl/specs/EGL_ANDROID_blob_cache.txt
index 55dc900..61f45d3 100644
--- a/opengl/specs/EGL_ANDROID_blob_cache.txt
+++ b/opengl/specs/EGL_ANDROID_blob_cache.txt
@@ -63,33 +63,33 @@
 New Types
 
     /*
-     * EGLsizei is a signed integer type for representing the size of a memory
-     * buffer.
+     * EGLsizeiANDROID is a signed integer type for representing the size of a
+     * memory buffer.
      */
     #include <khrplatform.h>
-    typedef khronos_ssize_t EGLsizei;
+    typedef khronos_ssize_t EGLsizeiANDROID;
 
     /*
      * EGLSetBlobFunc is a pointer to an application-provided function that a
      * client API implementation may use to insert a key/value pair into the
      * cache.
      */
-    typedef void (*EGLSetBlobFunc) (const void* key, EGLsizei keySize,
-        const void* value, EGLsizei valueSize)
+    typedef void (*EGLSetBlobFuncANDROID) (const void* key,
+        EGLsizeiANDROID keySize, const void* value, EGLsizeiANDROID valueSize)
 
     /*
      * EGLGetBlobFunc is a pointer to an application-provided function that a
      * client API implementation may use to retrieve a cached value from the
      * cache.
      */
-    typedef EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize,
-        void* value, EGLsizei valueSize)
+    typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void* key,
+        EGLsizeiANDROID keySize, void* value, EGLsizeiANDROID valueSize)
 
 New Procedures and Functions
 
-    void eglSetBlobCacheFuncs(EGLDisplay dpy,
-                              EGLSetBlobFunc set,
-                              EGLGetBlobFunc get);
+    void eglSetBlobCacheFuncsANDROID(EGLDisplay dpy,
+                                     EGLSetBlobFunc set,
+                                     EGLGetBlobFunc get);
 
 New Tokens
 
@@ -107,8 +107,8 @@
     function pointers through which the client APIs can request data be cached
     and retrieved.  The command
 
-        void eglSetBlobCacheFuncs(EGLDisplay dpy,
-            EGLSetBlobFunc set, EGLGetBlobFunc get);
+        void eglSetBlobCacheFuncsANDROID(EGLDisplay dpy,
+            EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
 
     sets the callback function pointers that client APIs associated with
     display <dpy> can use to interact with caching functionality provided by
@@ -120,17 +120,17 @@
 
     Cache functions may only be specified once during the lifetime of an
     EGLDisplay.  The <set> and <get> functions may be called at any time and
-    from any thread from the time at which eglSetBlobCacheFuncs is called until
-    the time that the last resource associated with <dpy> is deleted and <dpy>
-    itself is terminated.  Concurrent calls to these functions from different
-    threads is also allowed.
+    from any thread from the time at which eglSetBlobCacheFuncsANDROID is
+    called until the time that the last resource associated with <dpy> is
+    deleted and <dpy> itself is terminated.  Concurrent calls to these
+    functions from different threads is also allowed.
 
-    If eglSetBlobCacheFuncs generates an error then all client APIs must behave
-    as though eglSetBlobCacheFuncs was not called for the display <dpy>.  If
-    <set> or <get> is NULL then an EGL_BAD_PARAMETER error is generated.  If a
-    successful eglSetBlobCacheFuncs call was already made for <dpy> and the
-    display has not since been terminated then an EGL_BAD_PARAMETER error is
-    generated.
+    If eglSetBlobCacheFuncsANDROID generates an error then all client APIs must
+    behave as though eglSetBlobCacheFuncsANDROID was not called for the display
+    <dpy>.  If <set> or <get> is NULL then an EGL_BAD_PARAMETER error is
+    generated.  If a successful eglSetBlobCacheFuncsANDROID call was already
+    made for <dpy> and the display has not since been terminated then an
+    EGL_BAD_PARAMETER error is generated.
 
     3.9.1 Cache Operations
 
@@ -138,8 +138,8 @@
     key, a client API implementation can call the application-provided callback
     function
 
-        void (*set) (const void* key, EGLsizei keySize, const void* value,
-            EGLsizei valueSize)
+        void (*set) (const void* key, EGLsizeiANDROID keySize,
+            const void* value, EGLsizeiANDROID valueSize)
 
     <key> and <value> are pointers to the beginning of the key and value,
     respectively, that are to be inserted.  <keySize> and <valueSize> specify
@@ -157,8 +157,8 @@
     client API implementation can call the application-provided callback
     function
 
-        EGLsizei (*get) (const void* key, EGLsizei keySize, void* value,
-            EGLsizei valueSize)
+        EGLsizeiANDROID (*get) (const void* key, EGLsizeiANDROID keySize,
+            void* value, EGLsizeiANDROID valueSize)
 
     <key> is a pointer to the beginning of the key.  <keySize> specifies the
     size in bytes of the binary key pointed to by <key>.  If the cache contains
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
index 3ee9e77..180f022 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
@@ -33,39 +33,29 @@
         android:clipToPadding="false"
         android:clipChildren="false">
 
-        <LinearLayout android:id="@+id/recents_glow"
+        <com.android.systemui.recent.RecentsHorizontalScrollView android:id="@+id/recents_container"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:layout_gravity="bottom|right"
+            android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin"
+            android:divider="@null"
+            android:stackFromBottom="true"
+            android:fadingEdge="horizontal"
+            android:scrollbars="none"
+            android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length"
+            android:layout_gravity="bottom|left"
             android:orientation="horizontal"
             android:clipToPadding="false"
-            android:clipChildren="false"
-            >
-            <com.android.systemui.recent.RecentsHorizontalScrollView android:id="@+id/recents_container"
+            android:clipChildren="false">
+
+            <LinearLayout android:id="@+id/recents_linear_layout"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
-                android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin"
-                android:divider="@null"
-                android:stackFromBottom="true"
-                android:fadingEdge="horizontal"
-                android:scrollbars="none"
-                android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length"
-                android:layout_gravity="bottom|left"
                 android:orientation="horizontal"
                 android:clipToPadding="false"
                 android:clipChildren="false">
+            </LinearLayout>
 
-                <LinearLayout android:id="@+id/recents_linear_layout"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    android:orientation="horizontal"
-                    android:clipToPadding="false"
-                    android:clipChildren="false">
-                </LinearLayout>
-
-            </com.android.systemui.recent.RecentsHorizontalScrollView>
-
-        </LinearLayout>
+        </com.android.systemui.recent.RecentsHorizontalScrollView>
 
     </FrameLayout>
 
diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
index d040544..e6a077a 100644
--- a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
@@ -31,39 +31,29 @@
         android:layout_height="match_parent"
         android:layout_alignParentBottom="true">
 
-        <LinearLayout android:id="@+id/recents_glow"
+        <com.android.systemui.recent.RecentsVerticalScrollView
+            android:id="@+id/recents_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_gravity="bottom"
-            android:orientation="horizontal"
-            android:clipChildren="false"
-            android:layout_marginTop="@*android:dimen/status_bar_height">
+            android:layout_marginRight="0dp"
+            android:divider="@null"
+            android:stackFromBottom="true"
+            android:fadingEdge="vertical"
+            android:scrollbars="none"
+            android:fadingEdgeLength="@*android:dimen/status_bar_height"
+            android:layout_gravity="bottom|left"
+            android:clipToPadding="false"
+            android:clipChildren="false">
 
-            <com.android.systemui.recent.RecentsVerticalScrollView
-                android:id="@+id/recents_container"
+            <LinearLayout android:id="@+id/recents_linear_layout"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="0dp"
-                android:divider="@null"
-                android:stackFromBottom="true"
-                android:fadingEdge="vertical"
-                android:scrollbars="none"
-                android:fadingEdgeLength="@*android:dimen/status_bar_height"
-                android:layout_gravity="bottom|left"
+                android:orientation="vertical"
                 android:clipToPadding="false"
                 android:clipChildren="false">
+            </LinearLayout>
 
-                <LinearLayout android:id="@+id/recents_linear_layout"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:orientation="vertical"
-                    android:clipToPadding="false"
-                    android:clipChildren="false">
-                </LinearLayout>
-
-            </com.android.systemui.recent.RecentsVerticalScrollView>
-
-        </LinearLayout>
+        </com.android.systemui.recent.RecentsVerticalScrollView>
 
     </FrameLayout>
 
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_no_recent_apps.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_no_recent_apps.xml
new file mode 100644
index 0000000..bc89281
--- /dev/null
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_no_recent_apps.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2011, 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.
+*/
+-->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    >
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="20dp"
+        android:textColor="@android:color/holo_blue_light"
+        android:text="@string/status_bar_no_recent_apps"
+        android:gravity="left"
+        android:layout_gravity="bottom|left"
+    />
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
index 18a31f7..cb26db00 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
@@ -23,31 +23,6 @@
     android:layout_height="wrap_content"
     android:layout_width="wrap_content">
 
-    <FrameLayout android:id="@+id/app_thumbnail"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentTop="true"
-        android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
-        android:scaleType="center"
-        android:background="@drawable/recents_thumbnail_bg"
-        android:foreground="@drawable/recents_thumbnail_fg"
-        android:visibility="invisible">
-        <ImageView android:id="@+id/app_thumbnail_image"
-            android:layout_width="@dimen/status_bar_recents_thumbnail_width"
-            android:layout_height="@dimen/status_bar_recents_thumbnail_height"
-        />
-        <ImageView android:id="@+id/app_icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin"
-            android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin"
-            android:maxWidth="@dimen/status_bar_recents_app_icon_max_width"
-            android:maxHeight="@dimen/status_bar_recents_app_icon_max_height"
-            android:adjustViewBounds="true"
-        />
-    </FrameLayout>
-
     <TextView android:id="@+id/app_label"
         android:layout_width="@dimen/status_bar_recents_app_label_width"
         android:layout_height="wrap_content"
@@ -64,6 +39,35 @@
         android:textColor="@color/status_bar_recents_app_label_color"
     />
 
+    <FrameLayout android:id="@+id/app_thumbnail"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toRightOf="@id/app_label"
+        android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
+        android:scaleType="center"
+        android:background="@drawable/recents_thumbnail_bg"
+        android:foreground="@drawable/recents_thumbnail_fg"
+        android:visibility="invisible">
+        <ImageView android:id="@+id/app_thumbnail_image"
+            android:layout_width="@dimen/status_bar_recents_thumbnail_width"
+            android:layout_height="@dimen/status_bar_recents_thumbnail_height"
+        />
+    </FrameLayout>
+
+
+    <ImageView android:id="@+id/app_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toRightOf="@id/app_label"
+        android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin"
+        android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin"
+        android:maxWidth="@dimen/status_bar_recents_app_icon_max_width"
+        android:maxHeight="@dimen/status_bar_recents_app_icon_max_height"
+        android:scaleType="centerInside"
+        android:adjustViewBounds="true"
+    />
+
+
     <View android:id="@+id/recents_callout_line"
         android:layout_width="@dimen/status_bar_recents_app_label_width"
         android:layout_height="1dip"
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml
index 5dd101e..111f9a4 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml
@@ -36,40 +36,36 @@
         android:clipToPadding="false"
         android:clipChildren="false">
 
-        <LinearLayout android:id="@+id/recents_glow"
+        <com.android.systemui.recent.RecentsVerticalScrollView android:id="@+id/recents_container"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginBottom="-49dip"
-            android:layout_gravity="bottom"
-            android:background="@drawable/recents_blue_glow"
-            android:orientation="horizontal"
+            android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin"
+            android:divider="@null"
+            android:stackFromBottom="true"
+            android:fadingEdge="vertical"
+            android:scrollbars="none"
+            android:fadingEdgeLength="20dip"
+            android:layout_gravity="bottom|left"
             android:clipToPadding="false"
-            android:clipChildren="false"
-            >
-            <com.android.systemui.recent.RecentsVerticalScrollView android:id="@+id/recents_container"
+            android:clipChildren="false">
+
+            <LinearLayout android:id="@+id/recents_linear_layout"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin"
-                android:divider="@null"
-                android:stackFromBottom="true"
-                android:fadingEdge="vertical"
-                android:scrollbars="none"
-                android:fadingEdgeLength="20dip"
-                android:layout_gravity="bottom|left"
+                android:orientation="vertical"
                 android:clipToPadding="false"
                 android:clipChildren="false">
+            </LinearLayout>
 
-                <LinearLayout android:id="@+id/recents_linear_layout"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="vertical"
-                    android:clipToPadding="false"
-                    android:clipChildren="false">
-                </LinearLayout>
+        </com.android.systemui.recent.RecentsVerticalScrollView>
 
-            </com.android.systemui.recent.RecentsVerticalScrollView>
-
-        </LinearLayout>
+        <include layout="@layout/status_bar_no_recent_apps"
+            android:id="@+id/recents_no_apps"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="58dip"
+            android:layout_marginBottom="36dip"
+            android:visibility="invisible" />
 
     </FrameLayout>
 
@@ -82,4 +78,5 @@
         android:contentDescription="@string/status_bar_accessibility_dismiss_recents"
     />
 
+
 </com.android.systemui.recent.RecentsPanelView>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index 3e2ec59..24185a4f 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -18,8 +18,11 @@
 -->
 
 <resources>
-
     <!-- Whether we're using the tablet-optimized recents interface (we use this
      value at runtime for some things) -->
     <bool name="config_recents_interface_for_tablets">true</bool>
+
+    <!-- Whether recents thumbnails should stretch in both x and y to fill their
+     ImageView -->
+    <bool name="config_recents_thumbnail_image_fits_to_xy">true</bool>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index fe9245d..f522285 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -31,15 +31,15 @@
 
     <!-- Recent Applications parameters -->
     <!-- How far the thumbnail for a recent app appears from left edge -->
-    <dimen name="status_bar_recents_thumbnail_left_margin">121dp</dimen>
+    <dimen name="status_bar_recents_thumbnail_left_margin">28dp</dimen>
     <!-- Upper width limit for application icon -->
     <dimen name="status_bar_recents_app_icon_max_width">64dp</dimen>
     <!-- Upper height limit for application icon -->
     <dimen name="status_bar_recents_app_icon_max_height">64dp</dimen>
 
     <!-- Size of application icon -->
-    <dimen name="status_bar_recents_thumbnail_width">245dp</dimen>
-    <dimen name="status_bar_recents_thumbnail_height">144dp</dimen>
+    <dimen name="status_bar_recents_thumbnail_width">208dp</dimen>
+    <dimen name="status_bar_recents_thumbnail_height">130dp</dimen>
 
     <!-- Width of recents panel -->
     <dimen name="status_bar_recents_width">600dp</dimen>
@@ -59,8 +59,8 @@
     <dimen name="status_bar_recents_right_glow_margin">100dip</dimen>
 
     <!-- Where to place the app icon over the thumbnail -->
-    <dimen name="status_bar_recents_app_icon_left_margin">13dp</dimen>
-    <dimen name="status_bar_recents_app_icon_top_margin">13dp</dimen>
+    <dimen name="status_bar_recents_app_icon_left_margin">0dp</dimen>
+    <dimen name="status_bar_recents_app_icon_top_margin">8dp</dimen>
 
     <!-- size at which Notification icons will be drawn in the status bar -->
     <dimen name="status_bar_icon_drawing_size">24dip</dimen>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1fe4ebb..1f22507 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -25,6 +25,10 @@
      value at runtime for some things) -->
     <bool name="config_recents_interface_for_tablets">false</bool>
 
+    <!-- Whether recents thumbnails should stretch in both x and y to fill their
+     ImageView -->
+    <bool name="config_recents_thumbnail_image_fits_to_xy">false</bool>
+
     <!-- Control whether status bar should distinguish HSPA data icon form UMTS
     data icon on devices -->
     <bool name="config_hspa_data_distinguishable">false</bool>
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
index 886a14d..ad38a11 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
@@ -120,8 +120,13 @@
 
         createAnimation(appearing);
 
-        mContentView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-        mContentView.buildLayer();
+        // isHardwareAccelerated() checks if we're attached to a window and if that
+        // window is HW accelerated-- we were sometimes not attached to a window
+        // and buildLayer was throwing an IllegalStateException
+        if (mContentView.isHardwareAccelerated()) {
+            mContentView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            mContentView.buildLayer();
+        }
         mContentAnim.start();
 
         mVisible = appearing;
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 6b8b65e..8bfd711 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -16,14 +16,13 @@
 
 package com.android.systemui.recent;
 
-import java.util.ArrayList;
-
 import android.animation.Animator;
 import android.animation.LayoutTransition;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Matrix;
 import android.graphics.Shader.TileMode;
@@ -42,15 +41,15 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AnimationUtils;
 import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
 import android.widget.BaseAdapter;
 import android.widget.HorizontalScrollView;
 import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
 import android.widget.PopupMenu;
 import android.widget.RelativeLayout;
 import android.widget.ScrollView;
 import android.widget.TextView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.ImageView.ScaleType;
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.StatusBar;
@@ -58,6 +57,8 @@
 import com.android.systemui.statusbar.tablet.StatusBarPanel;
 import com.android.systemui.statusbar.tablet.TabletStatusBar;
 
+import java.util.ArrayList;
+
 public class RecentsPanelView extends RelativeLayout implements OnItemClickListener, RecentsCallback,
         StatusBarPanel, Animator.AnimatorListener, View.OnTouchListener {
     static final String TAG = "RecentsPanelView";
@@ -65,7 +66,6 @@
     private Context mContext;
     private StatusBar mBar;
     private View mRecentsScrim;
-    private View mRecentsGlowView;
     private View mRecentsNoApps;
     private ViewGroup mRecentsContainer;
 
@@ -79,6 +79,7 @@
     private boolean mRecentTasksDirty = true;
     private TaskDescriptionAdapter mListAdapter;
     private int mThumbnailWidth;
+    private boolean mFitThumbnailToXY;
 
     public void setRecentTasksLoader(RecentTasksLoader loader) {
         mRecentTasksLoader = loader;
@@ -174,9 +175,8 @@
         // use mRecentsContainer's exact bounds to determine horizontal position
         final int l = mRecentsContainer.getLeft();
         final int r = mRecentsContainer.getRight();
-        // use surrounding mRecentsGlowView's position in parent determine vertical bounds
-        final int t = mRecentsGlowView.getTop();
-        final int b = mRecentsGlowView.getBottom();
+        final int t = mRecentsContainer.getTop();
+        final int b = mRecentsContainer.getBottom();
         return x >= l && x < r && y >= t && y < b;
     }
 
@@ -194,7 +194,7 @@
             // if there are no apps, either bring up a "No recent apps" message, or just
             // quit early
             boolean noApps = (mRecentTaskDescriptions.size() == 0);
-            if (mRecentsNoApps != null) { // doesn't exist on large devices
+            if (mRecentsNoApps != null) {
                 mRecentsNoApps.setVisibility(noApps ? View.VISIBLE : View.INVISIBLE);
             } else {
                 if (noApps) {
@@ -325,8 +325,9 @@
     }
 
     public void updateValuesFromResources() {
-        mThumbnailWidth =
-            (int) mContext.getResources().getDimension(R.dimen.status_bar_recents_thumbnail_width);
+        final Resources res = mContext.getResources();
+        mThumbnailWidth = Math.round(res.getDimension(R.dimen.status_bar_recents_thumbnail_width));
+        mFitThumbnailToXY = res.getBoolean(R.bool.config_recents_thumbnail_image_fits_to_xy);
     }
 
     @Override
@@ -351,10 +352,9 @@
         }
 
 
-        mRecentsGlowView = findViewById(R.id.recents_glow);
         mRecentsScrim = findViewById(R.id.recents_bg_protect);
         mRecentsNoApps = findViewById(R.id.recents_no_apps);
-        mChoreo = new Choreographer(this, mRecentsScrim, mRecentsGlowView, mRecentsNoApps, this);
+        mChoreo = new Choreographer(this, mRecentsScrim, mRecentsContainer, mRecentsNoApps, this);
         mRecentsDismissButton = findViewById(R.id.recents_dismiss_button);
         if (mRecentsDismissButton != null) {
             mRecentsDismissButton.setOnClickListener(new OnClickListener() {
@@ -409,11 +409,15 @@
             if (h.thumbnailViewImageBitmap == null ||
                 h.thumbnailViewImageBitmap.getWidth() != thumbnail.getWidth() ||
                 h.thumbnailViewImageBitmap.getHeight() != thumbnail.getHeight()) {
-                Matrix scaleMatrix = new Matrix();
-                float scale = mThumbnailWidth / (float) thumbnail.getWidth();
-                scaleMatrix.setScale(scale, scale);
-                h.thumbnailViewImage.setScaleType(ScaleType.MATRIX);
-                h.thumbnailViewImage.setImageMatrix(scaleMatrix);
+                if (mFitThumbnailToXY) {
+                    h.thumbnailViewImage.setScaleType(ScaleType.FIT_XY);
+                } else {
+                    Matrix scaleMatrix = new Matrix();
+                    float scale = mThumbnailWidth / (float) thumbnail.getWidth();
+                    scaleMatrix.setScale(scale, scale);
+                    h.thumbnailViewImage.setScaleType(ScaleType.MATRIX);
+                    h.thumbnailViewImage.setImageMatrix(scaleMatrix);
+                }
             }
             if (show && h.thumbnailView.getVisibility() != View.VISIBLE) {
                 if (anim) {
@@ -444,7 +448,7 @@
                             // only fade in the thumbnail if recents is already visible-- we
                             // show it immediately otherwise
                             boolean animateShow = mShowing &&
-                                mRecentsGlowView.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD;
+                                mRecentsContainer.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD;
                             updateThumbnail(h, ad.getThumbnail(), true, animateShow);
                         }
                     }
@@ -516,7 +520,6 @@
         final int items = mRecentTaskDescriptions.size();
 
         mRecentsContainer.setVisibility(items > 0 ? View.VISIBLE : View.GONE);
-        mRecentsGlowView.setVisibility(items > 0 ? View.VISIBLE : View.GONE);
 
         // Set description for accessibility
         int numRecentApps = mRecentTaskDescriptions.size();
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 0f21bdb..dd3b75d 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -244,8 +244,14 @@
             // TODO: examine all widgets to derive clock status
             mUpdateMonitor.reportClockVisible(false);
 
-            // TODO: We should disable the wallpaper instead
-            setBackgroundColor(0xff000000);
+            // If there's not a bg protection view containing the transport, then show a black
+            // background. Otherwise, allow the normal background to show.
+            if (findViewById(R.id.transport_bg_protect) == null) {
+                // TODO: We should disable the wallpaper instead
+                setBackgroundColor(0xff000000);
+            } else {
+                resetBackground();
+            }
         }
 
         public void requestHide(View view) {
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index ff262f1..780c0d2 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -7028,11 +7028,17 @@
 
 AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& wThread,
                                         int sessionId)
-    : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0),
+    : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
       mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
       mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
 {
     mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread == 0) {
+        return;
+    }
+    mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
+                                    thread->frameCount();
 }
 
 AudioFlinger::EffectChain::~EffectChain()
@@ -7100,22 +7106,31 @@
     }
     bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
             (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
-    bool tracksOnSession = false;
+    // always process effects unless no more tracks are on the session and the effect tail
+    // has been rendered
+    bool doProcess = true;
     if (!isGlobalSession) {
-        tracksOnSession = (trackCnt() != 0);
-    }
+        bool tracksOnSession = (trackCnt() != 0);
 
-    // if no track is active, input buffer must be cleared here as the mixer process
-    // will not do it
-    if (tracksOnSession &&
-            activeTrackCnt() == 0) {
-        size_t numSamples = thread->frameCount() * thread->channelCount();
-        memset(mInBuffer, 0, numSamples * sizeof(int16_t));
+        if (!tracksOnSession && mTailBufferCount == 0) {
+            doProcess = false;
+        }
+
+        if (activeTrackCnt() == 0) {
+            // if no track is active and the effect tail has not been rendered,
+            // the input buffer must be cleared here as the mixer process will not do it
+            if (tracksOnSession || mTailBufferCount > 0) {
+                size_t numSamples = thread->frameCount() * thread->channelCount();
+                memset(mInBuffer, 0, numSamples * sizeof(int16_t));
+                if (mTailBufferCount > 0) {
+                    mTailBufferCount--;
+                }
+            }
+        }
     }
 
     size_t size = mEffects.size();
-    // do not process effect if no track is present in same audio session
-    if (isGlobalSession || tracksOnSession) {
+    if (doProcess) {
         for (size_t i = 0; i < size; i++) {
             mEffects[i]->process();
         }
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 4b794ef..897bc78 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -1247,6 +1247,10 @@
         // corresponding to a suspend all request.
         static const int        kKeyForSuspendAll = 0;
 
+        // minimum duration during which we force calling effect process when last track on
+        // a session is stopped or removed to allow effect tail to be rendered
+        static const int        kProcessTailDurationMs = 1000;
+
         void process_l();
 
         void lock() {
@@ -1287,7 +1291,8 @@
         void decTrackCnt() { android_atomic_dec(&mTrackCnt); }
         int32_t trackCnt() { return mTrackCnt;}
 
-        void incActiveTrackCnt() { android_atomic_inc(&mActiveTrackCnt); }
+        void incActiveTrackCnt() { android_atomic_inc(&mActiveTrackCnt);
+                                   mTailBufferCount = mMaxTailBuffers; }
         void decActiveTrackCnt() { android_atomic_dec(&mActiveTrackCnt); }
         int32_t activeTrackCnt() { return mActiveTrackCnt;}
 
@@ -1338,6 +1343,8 @@
         int16_t *mOutBuffer;        // chain output buffer
         volatile int32_t mActiveTrackCnt;  // number of active tracks connected
         volatile int32_t mTrackCnt;        // number of tracks connected
+        int32_t mTailBufferCount;   // current effect tail buffer count
+        int32_t mMaxTailBuffers;    // maximum effect tail buffers
         bool mOwnInBuffer;          // true if the chain owns its input buffer
         int mVolumeCtrlIdx;         // index of insert effect having control over volume
         uint32_t mLeftVolume;       // previous volume on left channel
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index cd63090..39e8c72 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1248,7 +1248,14 @@
                         PrintWriter pw = new PrintWriter(sw);
                         StringWriter catSw = new StringWriter();
                         PrintWriter catPw = new PrintWriter(catSw);
-                        dumpApplicationMemoryUsage(null, pw, "  ", new String[] { }, true, catPw);
+                        String[] emptyArgs = new String[] { };
+                        dumpApplicationMemoryUsage(null, pw, "  ", emptyArgs, true, catPw);
+                        pw.println();
+                        dumpProcessesLocked(null, pw, emptyArgs, 0, false);
+                        pw.println();
+                        dumpServicesLocked(null, pw, emptyArgs, 0, false, false);
+                        pw.println();
+                        dumpActivitiesLocked(null, pw, emptyArgs, 0, false, false);
                         String memUsage = sw.toString();
                         dropBuilder.append('\n');
                         dropBuilder.append(memUsage);
@@ -1479,6 +1486,7 @@
 
         mConfiguration.setToDefaults();
         mConfiguration.locale = Locale.getDefault();
+        mConfigurationSeq = mConfiguration.seq = 1;
         mProcessStats.init();
         
         mCompatModePackages = new CompatModePackages(this, systemDir);
@@ -2436,7 +2444,7 @@
                     r.mayFreezeScreenLocked(r.app) ? r.appToken : null);
             if (config != null) {
                 r.frozenBeforeDestroy = true;
-                if (!updateConfigurationLocked(config, r, false)) {
+                if (!updateConfigurationLocked(config, r, false, false)) {
                     mMainStack.resumeTopActivityLocked(null);
                 }
             }
@@ -3797,7 +3805,7 @@
                     app.instrumentationClass, profileFile, profileFd, profileAutoStop,
                     app.instrumentationArguments, app.instrumentationWatcher, testMode, 
                     isRestrictedBackupMode || !normalMode, app.persistent,
-                    mConfiguration, app.compat, getCommonServicesLocked(),
+                    new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
                     mCoreSettingsObserver.getCoreSettingsLocked());
             updateLruProcessLocked(app, false, true);
             app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
@@ -6707,8 +6715,7 @@
             mAlwaysFinishActivities = alwaysFinishActivities;
             // This happens before any activities are started, so we can
             // change mConfiguration in-place.
-            mConfiguration.updateFrom(configuration);
-            mConfigurationSeq = mConfiguration.seq = 1;
+            updateConfigurationLocked(configuration, null, false, true);
             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
         }
     }
@@ -8789,6 +8796,20 @@
                         TimeUtils.formatDuration(r.createTime, nowReal, pw);
                         pw.print(" started="); pw.print(r.startRequested);
                         pw.print(" connections="); pw.println(r.connections.size());
+                    if (r.connections.size() > 0) {
+                        pw.println("    Connections:");
+                        for (ArrayList<ConnectionRecord> clist : r.connections.values()) {
+                            for (int i=0; i<clist.size(); i++) {
+                                ConnectionRecord conn = clist.get(i);
+                                pw.print("      ");
+                                pw.print(conn.binding.intent.intent.getIntent().toShortString(
+                                        false, false, false));
+                                pw.print(" -> ");
+                                ProcessRecord proc = conn.binding.client;
+                                pw.println(proc != null ? proc.toShortString() : "null");
+                            }
+                        }
+                    }
                 }
                 if (dumpClient && r.app != null && r.app.thread != null) {
                     pw.println("    Client:");
@@ -8908,18 +8929,21 @@
                     continue;
                 }
                 pw.print("  * "); pw.print(cls); pw.print(" (");
-                        pw.print(comp.flattenToShortString()); pw.print(")");
+                        pw.print(comp.flattenToShortString()); pw.println(")");
                 if (dumpAll) {
-                    pw.println();
                     r.dump(pw, "      ");
                 } else {
-                    pw.print("  * "); pw.print(e.getKey().flattenToShortString());
                     if (r.proc != null) {
-                        pw.println(":");
                         pw.print("      "); pw.println(r.proc);
                     } else {
                         pw.println();
                     }
+                    if (r.clients.size() > 0) {
+                        pw.println("      Clients:");
+                        for (ProcessRecord cproc : r.clients) {
+                            pw.print("        - "); pw.println(cproc);
+                        }
+                    }
                 }
             }
             needSep = true;
@@ -12934,7 +12958,7 @@
 
         synchronized(this) {
             final long origId = Binder.clearCallingIdentity();
-            updateConfigurationLocked(values, null, true);
+            updateConfigurationLocked(values, null, true, false);
             Binder.restoreCallingIdentity(origId);
         }
     }
@@ -12957,7 +12981,7 @@
             if (values != null) {
                 Settings.System.clearConfiguration(values);
             }
-            updateConfigurationLocked(values, null, false);
+            updateConfigurationLocked(values, null, false, false);
             Binder.restoreCallingIdentity(origId);
         }
     }
@@ -12971,7 +12995,7 @@
      * @param persistent TODO
      */
     public boolean updateConfigurationLocked(Configuration values,
-            ActivityRecord starting, boolean persistent) {
+            ActivityRecord starting, boolean persistent, boolean initLocale) {
         int changes = 0;
         
         boolean kept = true;
@@ -12986,7 +13010,7 @@
                 
                 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
 
-                if (values.locale != null) {
+                if (values.locale != null && !initLocale) {
                     saveLocaleLocked(values.locale, 
                                      !values.locale.equals(mConfiguration.locale),
                                      values.userSetLocale);
@@ -12999,10 +13023,12 @@
                 newConfig.seq = mConfigurationSeq;
                 mConfiguration = newConfig;
                 Slog.i(TAG, "Config changed: " + newConfig);
-                
+
+                final Configuration configCopy = new Configuration(mConfiguration);
+
                 AttributeCache ac = AttributeCache.instance();
                 if (ac != null) {
-                    ac.updateConfiguration(mConfiguration);
+                    ac.updateConfiguration(configCopy);
                 }
 
                 // Make sure all resources in our process are updated
@@ -13012,11 +13038,11 @@
                 // boot, where the first config change needs to guarantee
                 // all resources have that config before following boot
                 // code is executed.
-                mSystemThread.applyConfigurationToResources(newConfig);
+                mSystemThread.applyConfigurationToResources(configCopy);
 
                 if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
                     Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
-                    msg.obj = new Configuration(mConfiguration);
+                    msg.obj = new Configuration(configCopy);
                     mHandler.sendMessage(msg);
                 }
         
@@ -13026,7 +13052,7 @@
                         if (app.thread != null) {
                             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
                                     + app.processName + " new config " + mConfiguration);
-                            app.thread.scheduleConfigurationChanged(mConfiguration);
+                            app.thread.scheduleConfigurationChanged(configCopy);
                         }
                     } catch (Exception e) {
                     }
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index c892cb1..c7ce3c3 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -528,7 +528,7 @@
             Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
                     mService.mConfiguration,
                     r.mayFreezeScreenLocked(app) ? r.appToken : null);
-            mService.updateConfigurationLocked(config, r, false);
+            mService.updateConfigurationLocked(config, r, false, false);
         }
 
         r.app = app;
@@ -590,7 +590,8 @@
                 }
             }
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
-                    System.identityHashCode(r), r.info, mService.mConfiguration,
+                    System.identityHashCode(r), r.info,
+                    new Configuration(mService.mConfiguration),
                     r.compat, r.icicle, results, newIntents, !andResume,
                     mService.isNextTransitionForward(), profileFile, profileFd,
                     profileAutoStop);
@@ -1460,7 +1461,7 @@
                     if (config != null) {
                         next.frozenBeforeDestroy = true;
                     }
-                    updated = mService.updateConfigurationLocked(config, next, false);
+                    updated = mService.updateConfigurationLocked(config, next, false, false);
                 }
             }
             if (!updated) {
@@ -2917,7 +2918,7 @@
                 mConfigWillChange = false;
                 if (DEBUG_CONFIGURATION) Slog.v(TAG,
                         "Updating to new configuration after starting activity.");
-                mService.updateConfigurationLocked(config, null, false);
+                mService.updateConfigurationLocked(config, null, false, false);
             }
             
             Binder.restoreCallingIdentity(origId);
@@ -4190,7 +4191,7 @@
             if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
             r.forceNewConfig = false;
             r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents,
-                    changes, !andResume, mService.mConfiguration);
+                    changes, !andResume, new Configuration(mService.mConfiguration));
             // Note: don't need to call pauseIfSleepingLocked() here, because
             // the caller will only pass in 'andResume' if this activity is
             // currently resumed, which implies we aren't sleeping.
diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java
index 9c55597..6f6266d 100644
--- a/services/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/java/com/android/server/am/ContentProviderRecord.java
@@ -74,6 +74,10 @@
                     pw.print(" initOrder="); pw.println(info.initOrder);
         }
         if (clients.size() > 0) {
+            pw.print(prefix); pw.println("Clients:");
+            for (ProcessRecord cproc : clients) {
+                pw.print(prefix); pw.println("  - "); pw.println(cproc);
+            }
             pw.print(prefix); pw.print("clients="); pw.println(clients);
         }
         if (externals != 0) {
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 6365525..28cb983 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -1243,7 +1243,8 @@
 
         // trim any history beyond max
         if (mTime.hasCache()) {
-            final long currentTime = mTime.currentTimeMillis();
+            final long currentTime = Math.min(
+                    System.currentTimeMillis(), mTime.currentTimeMillis());
             final long maxHistory = mSettings.getNetworkMaxHistory();
             for (NetworkStatsHistory history : input.values()) {
                 history.removeBucketsBefore(currentTime - maxHistory);
@@ -1287,7 +1288,8 @@
 
         // trim any history beyond max
         if (mTime.hasCache()) {
-            final long currentTime = mTime.currentTimeMillis();
+            final long currentTime = Math.min(
+                    System.currentTimeMillis(), mTime.currentTimeMillis());
             final long maxUidHistory = mSettings.getUidMaxHistory();
             final long maxTagHistory = mSettings.getTagMaxHistory();
             for (UidStatsKey key : mUidStats.keySet()) {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 50321b3..ebb13d5 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -5090,10 +5090,22 @@
 
             // Constrain thumbnail to smaller of screen width or height. Assumes aspect
             // of thumbnail is the same as the screen (in landscape) or square.
+            float targetWidthScale = width / (float) fw;
+            float targetHeightScale = height / (float) fh;
             if (dw <= dh) {
-                scale = width / (float) fw; // portrait
+                scale = targetWidthScale;
+                // If aspect of thumbnail is the same as the screen (in landscape),
+                // select the slightly larger value so we fill the entire bitmap
+                if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) {
+                    scale = targetHeightScale;
+                }
             } else {
-                scale = height / (float) fh; // landscape
+                scale = targetHeightScale;
+                // If aspect of thumbnail is the same as the screen (in landscape),
+                // select the slightly larger value so we fill the entire bitmap
+                if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) {
+                    scale = targetWidthScale;
+                }
             }
 
             // The screen shot will contain the entire screen.
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 368595f..0618374 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -80,7 +80,6 @@
 import org.easymock.Capture;
 import org.easymock.EasyMock;
 import org.easymock.IAnswer;
-import org.easymock.IExpectationSetters;
 
 import java.io.File;
 import java.util.LinkedHashSet;
@@ -537,6 +536,7 @@
                 .addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L);
         expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
                 .andReturn(stats).atLeastOnce();
+        expectPolicyDataEnable(TYPE_WIFI, true);
 
         // TODO: consider making strongly ordered mock
         expectRemoveInterfaceQuota(TEST_IFACE);
@@ -580,7 +580,7 @@
         NetworkState[] state = null;
         NetworkStats stats = null;
         Future<Void> future;
-        Capture<String> tag;
+        Future<String> tagFuture;
 
         final long TIME_FEB_15 = 1171497600000L;
         final long TIME_MAR_10 = 1173484800000L;
@@ -598,6 +598,7 @@
             expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
             expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
                     .andReturn(stats).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, true);
 
             expectClearNotifications();
             future = expectMeteredIfacesChanged();
@@ -620,6 +621,7 @@
             expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
             expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
                     .andReturn(stats).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, true);
 
             expectRemoveInterfaceQuota(TEST_IFACE);
             expectSetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
@@ -642,14 +644,15 @@
             expectCurrentTime();
             expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
                     .andReturn(stats).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, true);
 
             expectForceUpdate();
             expectClearNotifications();
-            tag = expectEnqueueNotification();
+            tagFuture = expectEnqueueNotification();
 
             replay();
             mNetworkObserver.limitReached(null, TEST_IFACE);
-            assertNotificationType(TYPE_WARNING, tag.getValue());
+            assertNotificationType(TYPE_WARNING, tagFuture.get());
             verifyAndReset();
         }
 
@@ -662,15 +665,15 @@
             expectCurrentTime();
             expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
                     .andReturn(stats).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, false).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, false);
 
             expectForceUpdate();
             expectClearNotifications();
-            tag = expectEnqueueNotification();
+            tagFuture = expectEnqueueNotification();
 
             replay();
             mNetworkObserver.limitReached(null, TEST_IFACE);
-            assertNotificationType(TYPE_LIMIT, tag.getValue());
+            assertNotificationType(TYPE_LIMIT, tagFuture.get());
             verifyAndReset();
         }
 
@@ -682,21 +685,20 @@
             expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
             expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
                     .andReturn(stats).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, true).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, true);
 
             // snoozed interface still has high quota so background data is
             // still restricted.
             expectRemoveInterfaceQuota(TEST_IFACE);
             expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
+            expectMeteredIfacesChanged(TEST_IFACE);
 
             expectClearNotifications();
-            tag = expectEnqueueNotification();
-            future = expectMeteredIfacesChanged(TEST_IFACE);
+            tagFuture = expectEnqueueNotification();
 
             replay();
             mService.snoozePolicy(sTemplateWifi);
-            future.get();
-            assertNotificationType(TYPE_LIMIT_SNOOZED, tag.getValue());
+            assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
             verifyAndReset();
         }
     }
@@ -737,9 +739,9 @@
         expectLastCall().anyTimes();
     }
 
-    private Capture<String> expectEnqueueNotification() throws Exception {
-        final Capture<String> tag = new Capture<String>();
-        mNotifManager.enqueueNotificationWithTag(isA(String.class), capture(tag), anyInt(),
+    private Future<String> expectEnqueueNotification() throws Exception {
+        final FutureCapture<String> tag = new FutureCapture<String>();
+        mNotifManager.enqueueNotificationWithTag(isA(String.class), capture(tag.capture), anyInt(),
                 isA(Notification.class), isA(int[].class));
         return tag;
     }
@@ -789,22 +791,25 @@
         return future;
     }
 
-    private <T> IExpectationSetters<T> expectPolicyDataEnable(int type, boolean enabled)
-            throws Exception {
+    private Future<Void> expectPolicyDataEnable(int type, boolean enabled) throws Exception {
+        final FutureAnswer future = new FutureAnswer();
         mConnManager.setPolicyDataEnable(type, enabled);
-        return expectLastCall();
+        expectLastCall().andAnswer(future);
+        return future;
     }
 
-    private static class FutureAnswer extends AbstractFuture<Void> implements IAnswer<Void> {
+    private static class TestAbstractFuture<T> extends AbstractFuture<T> {
         @Override
-        public Void get() throws InterruptedException, ExecutionException {
+        public T get() throws InterruptedException, ExecutionException {
             try {
                 return get(5, TimeUnit.SECONDS);
             } catch (TimeoutException e) {
                 throw new RuntimeException(e);
             }
         }
+    }
 
+    private static class FutureAnswer extends TestAbstractFuture<Void> implements IAnswer<Void> {
         @Override
         public Void answer() {
             set(null);
@@ -812,6 +817,16 @@
         }
     }
 
+    private static class FutureCapture<T> extends TestAbstractFuture<T> {
+        public Capture<T> capture = new Capture<T>() {
+            @Override
+            public void setValue(T value) {
+                super.setValue(value);
+                set(value);
+            }
+        };
+    }
+
     private static class IdleFuture extends AbstractFuture<Void> implements IdleHandler {
         @Override
         public Void get() throws InterruptedException, ExecutionException {
diff --git a/telephony/java/com/android/internal/telephony/cat/CatService.java b/telephony/java/com/android/internal/telephony/cat/CatService.java
index 5420264..5a994f3 100644
--- a/telephony/java/com/android/internal/telephony/cat/CatService.java
+++ b/telephony/java/com/android/internal/telephony/cat/CatService.java
@@ -94,6 +94,8 @@
     private static final int DEV_ID_TERMINAL    = 0x82;
     private static final int DEV_ID_NETWORK     = 0x83;
 
+    static final String STK_DEFAULT = "Defualt Message";
+
     /* Intentionally private for singleton */
     private CatService(CommandsInterface ci, IccRecords ir, Context context,
             IccFileHandler fh, IccCard ic) {
@@ -157,7 +159,15 @@
             }
             break;
         case MSG_ID_PROACTIVE_COMMAND:
-            cmdParams = (CommandParams) rilMsg.mData;
+            try {
+                cmdParams = (CommandParams) rilMsg.mData;
+            } catch (ClassCastException e) {
+                // for error handling : cast exception
+                CatLog.d(this, "Fail to parse proactive command");
+                sendTerminalResponse(mCurrntCmd.mCmdDet, ResultCode.CMD_DATA_NOT_UNDERSTOOD,
+                                     false, 0x00, null);
+                break;
+            }
             if (cmdParams != null) {
                 if (rilMsg.mResCode == ResultCode.OK) {
                     handleProactiveCommand(cmdParams);
@@ -194,6 +204,7 @@
     private void handleProactiveCommand(CommandParams cmdParams) {
         CatLog.d(this, cmdParams.getCommandType().name());
 
+        CharSequence message;
         CatCmdMessage cmdMsg = new CatCmdMessage(cmdParams);
         switch (cmdParams.getCommandType()) {
             case SET_UP_MENU:
@@ -224,26 +235,44 @@
                     case CommandParamsFactory.DTTZ_SETTING:
                         resp = new DTTZResponseData(null);
                         sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, resp);
-                        break;
+                        return;
                     case CommandParamsFactory.LANGUAGE_SETTING:
                         resp = new LanguageResponseData(Locale.getDefault().getLanguage());
                         sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, resp);
-                        break;
+                        return;
                     default:
                         sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
                         return;
                 }
             case LAUNCH_BROWSER:
+                if ((((LaunchBrowserParams) cmdParams).confirmMsg.text != null)
+                        && (((LaunchBrowserParams) cmdParams).confirmMsg.text.equals(STK_DEFAULT))) {
+                    message = mContext.getText(com.android.internal.R.string.launchBrowserDefault);
+                    ((LaunchBrowserParams) cmdParams).confirmMsg.text = message.toString();
+                }
+                break;
             case SELECT_ITEM:
             case GET_INPUT:
             case GET_INKEY:
+                break;
             case SEND_DTMF:
             case SEND_SMS:
             case SEND_SS:
             case SEND_USSD:
+                if ((((DisplayTextParams)cmdParams).textMsg.text != null)
+                        && (((DisplayTextParams)cmdParams).textMsg.text.equals(STK_DEFAULT))) {
+                    message = mContext.getText(com.android.internal.R.string.sending);
+                    ((DisplayTextParams)cmdParams).textMsg.text = message.toString();
+                }
+                break;
             case PLAY_TONE:
+                break;
             case SET_UP_CALL:
-                // nothing to do on telephony!
+                if ((((CallSetupParams) cmdParams).confirmMsg.text != null)
+                        && (((CallSetupParams) cmdParams).confirmMsg.text.equals(STK_DEFAULT))) {
+                    message = mContext.getText(com.android.internal.R.string.SetupCallDefault);
+                    ((CallSetupParams) cmdParams).confirmMsg.text = message.toString();
+                }
                 break;
             default:
                 CatLog.d(this, "Unsupported command");
diff --git a/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java b/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java
index 686fe46..e7fca5a 100644
--- a/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java
+++ b/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java
@@ -403,6 +403,7 @@
         input.ucs2 = (cmdDet.commandQualifier & 0x02) != 0;
         input.yesNo = (cmdDet.commandQualifier & 0x04) != 0;
         input.helpAvailable = (cmdDet.commandQualifier & 0x80) != 0;
+        input.echo = true;
 
         mCmdParams = new GetInputParams(cmdDet, input);
 
@@ -625,11 +626,7 @@
 
         ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID,
                 ctlvs);
-        if (ctlv != null) {
-            textMsg.text = ValueParser.retrieveAlphaId(ctlv);
-        } else {
-            throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
-        }
+        textMsg.text = ValueParser.retrieveAlphaId(ctlv);
 
         ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
         if (ctlv != null) {
@@ -714,9 +711,8 @@
 
         // parse alpha identifier.
         ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID, ctlvs);
-        if (ctlv != null) {
-            confirmMsg.text = ValueParser.retrieveAlphaId(ctlv);
-        }
+        confirmMsg.text = ValueParser.retrieveAlphaId(ctlv);
+
         // parse icon identifier
         ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
         if (ctlv != null) {
@@ -841,9 +837,7 @@
 
         // get confirmation message string.
         ctlv = searchForNextTag(ComprehensionTlvTag.ALPHA_ID, iter);
-        if (ctlv != null) {
-            confirmMsg.text = ValueParser.retrieveAlphaId(ctlv);
-        }
+        confirmMsg.text = ValueParser.retrieveAlphaId(ctlv);
 
         ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
         if (ctlv != null) {
diff --git a/telephony/java/com/android/internal/telephony/cat/ComprehensionTlv.java b/telephony/java/com/android/internal/telephony/cat/ComprehensionTlv.java
index e5a2d31..ab26d13 100644
--- a/telephony/java/com/android/internal/telephony/cat/ComprehensionTlv.java
+++ b/telephony/java/com/android/internal/telephony/cat/ComprehensionTlv.java
@@ -94,6 +94,7 @@
                 startIndex = ctlv.mValueIndex + ctlv.mLength;
             } else {
                 CatLog.d(LOG_TAG, "decodeMany: ctlv is null, stop decoding");
+                items.clear();
                 break;
             }
         }
@@ -123,7 +124,10 @@
             case 0:
             case 0xff:
             case 0x80:
-                throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+                // for error handling
+                // these one make exception while decoding the abnormal command.
+                // (in case of Ghana MTN simcard , JDI simcard)
+                return null;
 
             case 0x7f: // tag is in three-byte format
                 tag = ((data[curIndex] & 0xff) << 8)
diff --git a/telephony/java/com/android/internal/telephony/cat/ValueParser.java b/telephony/java/com/android/internal/telephony/cat/ValueParser.java
index 34e4811..584d96c 100644
--- a/telephony/java/com/android/internal/telephony/cat/ValueParser.java
+++ b/telephony/java/com/android/internal/telephony/cat/ValueParser.java
@@ -273,18 +273,23 @@
      */
     static String retrieveAlphaId(ComprehensionTlv ctlv) throws ResultException {
 
-        byte[] rawValue = ctlv.getRawValue();
-        int valueIndex = ctlv.getValueIndex();
-        int length = ctlv.getLength();
-        if (length != 0) {
-            try {
-                return IccUtils.adnStringFieldToString(rawValue, valueIndex,
-                        length);
-            } catch (IndexOutOfBoundsException e) {
-                throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+        if (ctlv != null) {
+            byte[] rawValue = ctlv.getRawValue();
+            int valueIndex = ctlv.getValueIndex();
+            int length = ctlv.getLength();
+            if (length != 0) {
+                try {
+                    return IccUtils.adnStringFieldToString(rawValue, valueIndex,
+                            length);
+                } catch (IndexOutOfBoundsException e) {
+                    throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+                }
+            } else {
+                return CatService.STK_DEFAULT;
             }
+        } else {
+            return CatService.STK_DEFAULT;
         }
-        return null;
     }
 
     /**