Merge "Revert "Import translations. DO NOT MERGE"" into jb-mr1-lockscreen-dev
diff --git a/core/java/com/android/internal/policy/IFaceLockInterface.aidl b/core/java/com/android/internal/policy/IFaceLockInterface.aidl
index a017722..017801b 100644
--- a/core/java/com/android/internal/policy/IFaceLockInterface.aidl
+++ b/core/java/com/android/internal/policy/IFaceLockInterface.aidl
@@ -23,7 +23,6 @@
     void startUi(IBinder containingWindowToken, int x, int y, int width, int height,
             boolean useLiveliness);
     void stopUi();
-    void makeInvisible();
     void registerCallback(IFaceLockCallback cb);
     void unregisterCallback(IFaceLockCallback cb);
 }
diff --git a/core/java/com/android/internal/widget/FaceUnlockView.java b/core/java/com/android/internal/widget/FaceUnlockView.java
index c8d65fc..e3c1247 100644
--- a/core/java/com/android/internal/widget/FaceUnlockView.java
+++ b/core/java/com/android/internal/widget/FaceUnlockView.java
@@ -53,15 +53,17 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
         final int minimumWidth = getSuggestedMinimumWidth();
         final int minimumHeight = getSuggestedMinimumHeight();
         int viewWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
         int viewHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
 
-        viewWidth = viewHeight = Math.min(viewWidth, viewHeight);
-        Log.v(TAG, "FaceUnlockView dimensions: " + viewWidth + "x" + viewHeight);
-        setMeasuredDimension(viewWidth, viewHeight);
+        final int chosenSize = Math.min(viewWidth, viewHeight);
+        final int newWidthMeasureSpec =
+                MeasureSpec.makeMeasureSpec(chosenSize, MeasureSpec.AT_MOST);
+        final int newHeightMeasureSpec =
+                MeasureSpec.makeMeasureSpec(chosenSize, MeasureSpec.AT_MOST);
+
+        super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec);
     }
 }
diff --git a/core/res/res/layout-port/keyguard_host_view.xml b/core/res/res/layout-port/keyguard_host_view.xml
index 5444471..a3c8105 100644
--- a/core/res/res/layout-port/keyguard_host_view.xml
+++ b/core/res/res/layout-port/keyguard_host_view.xml
@@ -36,7 +36,8 @@
 
         <FrameLayout
             android:layout_width="match_parent"
-            android:layout_height="match_parent">
+            android:layout_height="match_parent"
+            androidprv:layout_childType="widgets">
             <include layout="@layout/keyguard_widget_pager"
                 android:id="@+id/app_widget_container"
                 android:layout_width="match_parent"
@@ -51,12 +52,11 @@
 
         <com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer
             android:id="@+id/keyguard_security_container"
-            android:layout_width="@dimen/keyguard_security_width"
+            android:layout_width="wrap_content"
             android:layout_height="@dimen/keyguard_security_height"
             androidprv:layout_childType="challenge"
-            android:layout_marginLeft="@dimen/kg_edge_swipe_region_size"
-            android:layout_marginRight="@dimen/kg_edge_swipe_region_size"
             android:background="@drawable/kg_bouncer_bg_white"
+            android:padding="0dp"
             android:gravity="bottom|center_horizontal">
             <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper
                 android:id="@+id/view_flipper"
@@ -64,9 +64,7 @@
                 android:layout_height="match_parent"
                 android:clipChildren="false"
                 android:clipToPadding="false"
-                android:paddingLeft="@dimen/keyguard_security_view_margin"
                 android:paddingTop="@dimen/keyguard_security_view_margin"
-                android:paddingRight="@dimen/keyguard_security_view_margin"
                 android:gravity="center">
             </com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper>
         </com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d186c4a..627099c 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5798,6 +5798,8 @@
         <!-- Scrim. This will block access to child views that
              come before it in the child list in bouncer mode. -->
         <enum name="scrim" value="4" />
+        <!-- The home for widgets. All widgets will be descendents of this. -->
+        <enum name="widgets" value="5" />
     </attr>
 
     <declare-styleable name="SlidingChallengeLayout">
diff --git a/core/res/res/values/integers.xml b/core/res/res/values/integers.xml
index d1df2a4..053fc85 100644
--- a/core/res/res/values/integers.xml
+++ b/core/res/res/values/integers.xml
@@ -18,7 +18,7 @@
 -->
 <resources>
     <integer name="kg_carousel_angle">75</integer>
-    <integer name="kg_security_flip_duration">75</integer>
-    <integer name="kg_security_fade_duration">75</integer>
+    <integer name="kg_security_flip_duration">100</integer>
+    <integer name="kg_security_fade_duration">100</integer>
     <integer name="kg_glowpad_rotation_offset">0</integer>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 159eec1..a86405d 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2283,7 +2283,7 @@
     <!-- Accessibility description of the event of collapsing an unlock area. [CHAR_LIMIT=none] -->
     <string name="keyguard_accessibility_unlock_area_collapsed">Unlock area collapsed.</string>
     <!-- Accessibility description of a lock screen widget. [CHAR_LIMIT=none] -->
-    <string name="keyguard_accessibility_widget">%1$s widget.</string>
+    <string name="keyguard_accessibility_widget"><xliff:g id="widget_index">%1$s</xliff:g> widget.</string>
     <!-- Accessibility description of the lock screen user selector widget. [CHAR_LIMIT=none] -->
     <string name="keyguard_accessibility_user_selector">User selector</string>
     <!-- Accessibility description of the lock screen status widget. [CHAR_LIMIT=none] -->
@@ -2292,6 +2292,14 @@
     <string name="keyguard_accessibility_camera">Camera</string>
     <!-- Accessibility description of the lock media control widget. [CHAR_LIMIT=none] -->
     <string name="keygaurd_accessibility_media_controls">Media controls</string>
+    <!-- Accessibility description of widget reordering start. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_widget_reorder_start">Widget reordering started.</string>
+    <!-- Accessibility description of widget reordering end. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_widget_reorder_end">Widget reordering ended.</string>
+    <!-- Accessibility description of the a widget deletion event. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_widget_deleted">Widget <xliff:g id="widget_index">%1$s</xliff:g> deleted.</string>
+    <!-- Accessibility description of the button to expand the lock area. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_expand_lock_area">Expand unlock area.</string>
 
     <!-- Password keyboard strings. Used by LockScreen and Settings --><skip />
     <!-- Label for "switch to symbols" key.  Must be short to fit on key! -->
diff --git a/docs/html/distribute/googleplay/publish/preparing.jd b/docs/html/distribute/googleplay/publish/preparing.jd
index 463343d..a3538a9 100644
--- a/docs/html/distribute/googleplay/publish/preparing.jd
+++ b/docs/html/distribute/googleplay/publish/preparing.jd
@@ -15,7 +15,7 @@
 <li><a href="#inapp-billing">9. Consider In-app Billing</a></li>
 <li><a href="#pricing">10. Set prices for your apps</a></li>
 <li><a href="#localize">11. Start localization early</a></li>
-<li><a href="#localize">12. Prepare promotional graphics</a></li>
+<li><a href="#graphics">12. Prepare promotional graphics</a></li>
 <li><a href="#apk">13. Build the release-ready APK</a></li>
 <li><a href="#product-page">14. Complete the product details</a></li>
 <li><a href="#badges">15. Use Google Play badges</a></li>
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 e940c85..8fdde92 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
@@ -41,8 +41,7 @@
             android:fadingEdge="horizontal"
             android:scrollbars="none"
             android:layout_gravity="right"
-            android:fadingEdgeLength="@dimen/status_bar_recents_scroll_fading_edge_length"
-            android:importantForAccessibility="no">
+            android:fadingEdgeLength="@dimen/status_bar_recents_scroll_fading_edge_length">
 
             <LinearLayout android:id="@+id/recents_linear_layout"
                 android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/status_bar_recent_panel.xml b/packages/SystemUI/res/layout/status_bar_recent_panel.xml
index 12599f8..7335f86 100644
--- a/packages/SystemUI/res/layout/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout/status_bar_recent_panel.xml
@@ -45,8 +45,7 @@
             android:fadingEdgeLength="@dimen/status_bar_recents_scroll_fading_edge_length"
             android:layout_gravity="bottom|left"
             android:clipToPadding="false"
-            android:clipChildren="false"
-            android:importantForAccessibility="no">
+            android:clipChildren="false">
 
             <LinearLayout android:id="@+id/recents_linear_layout"
                 android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/system_bar_recent_panel.xml b/packages/SystemUI/res/layout/system_bar_recent_panel.xml
index 8afed22..3951bba 100644
--- a/packages/SystemUI/res/layout/system_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout/system_bar_recent_panel.xml
@@ -49,8 +49,7 @@
             android:fadingEdgeLength="20dip"
             android:layout_gravity="bottom|left"
             android:clipToPadding="false"
-            android:clipChildren="false"
-            android:importantForAccessibility="no">
+            android:clipChildren="false">
 
             <LinearLayout android:id="@+id/recents_linear_layout"
                 android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index c34ca3e..7f7a51c 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -174,7 +174,7 @@
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skærmen er nu låst i liggende retning."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skærmen er nu låst i stående retning."</string>
     <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
-    <string name="start_dreams" msgid="7219575858348719790">"Dagdrømme"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Dagdrøm"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
     <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flytilstand"</string>
     <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Oplader, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index d5af0cd..d619de1 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -176,7 +176,7 @@
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"La pantalla está bloqueada en modo horizontal."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"La pantalla está bloqueada en modo vertical."</string>
     <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
-    <string name="start_dreams" msgid="7219575858348719790">"Activar Daydreams"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Activar protector"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
     <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo de avión"</string>
     <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index e8bc08d..19de9b6 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -174,7 +174,7 @@
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"La pantalla está bloqueada en modo horizontal."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"La pantalla está bloqueada en modo vertical."</string>
     <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
-    <string name="start_dreams" msgid="7219575858348719790">"Suspender"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Salvapantallas"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
     <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo avión"</string>
     <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index a12ccf0..babbcce 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -176,7 +176,7 @@
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"L\'écran est verrouillé en mode paysage."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"L\'écran est verrouillé en mode portrait."</string>
     <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
-    <string name="start_dreams" msgid="7219575858348719790">"Écran de veille"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Écran de veille interactif"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
     <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode avion"</string>
     <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"En charge (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index a05aa8f..c454bb1 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -174,7 +174,7 @@
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ekran jest zablokowany w orientacji poziomej."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ekran jest zablokowany w orientacji pionowej."</string>
     <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
-    <string name="start_dreams" msgid="7219575858348719790">"Śnij na jawie"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Wygaszacz ekranu"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
     <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Tryb samolotowy"</string>
     <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Ładowanie (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 1ca085c..1b8370b 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -174,7 +174,7 @@
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"O ecrã está bloqueado na orientação horizontal."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"O ecrã está bloqueado na orientação vertical."</string>
     <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
-    <string name="start_dreams" msgid="7219575858348719790">"Sonho"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
     <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo de avião"</string>
     <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"A carregar, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index fba3da5..7e2d030 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -172,7 +172,7 @@
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skrini imefungwa sasa katika uelekezo wa mandhari."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skrini imefungwa katika uelekeo wa picha."</string>
     <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
-    <string name="start_dreams" msgid="7219575858348719790">"Ndoto ya mchana"</string>
+    <string name="start_dreams" msgid="7219575858348719790">"Hali Tulivu"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
     <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modi ya ndege"</string>
     <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Inachaji, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index 599b7e2..cc9c601 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -202,21 +202,18 @@
             Log.e(TAG, "Couldn't get user info", e);
         }
         final int userId = userInfo.id;
+        final String userName = userInfo.name;
 
         final Context context = currentUserContext;
         mUserInfoTask = new AsyncTask<Void, Void, Pair<String, Drawable>>() {
             @Override
             protected Pair<String, Drawable> doInBackground(Void... params) {
-                final Cursor cursor = context.getContentResolver().query(
-                        Profile.CONTENT_URI, new String[] {Phone._ID, Phone.DISPLAY_NAME},
-                        null, null, null);
                 final UserManager um =
                         (UserManager) mContext.getSystemService(Context.USER_SERVICE);
 
                 // Fall back to the UserManager nickname if we can't read the name from the local
                 // profile below.
-                String nickName = um.getUserName();
-                String name = nickName;
+                String name = userName;
                 Drawable avatar = null;
                 Bitmap rawAvatar = um.getUserIcon(userId);
                 if (rawAvatar != null) {
@@ -225,17 +222,23 @@
                     avatar = mContext.getResources().getDrawable(R.drawable.ic_qs_default_user);
                 }
 
-                // Try and read the display name from the local profile
-                if (cursor != null) {
-                    try {
-                        if (cursor.moveToFirst()) {
-                            name = cursor.getString(cursor.getColumnIndex(Phone.DISPLAY_NAME));
+                // If it's a single-user device, get the profile name, since the nickname is not
+                // usually valid
+                if (um.getUsers().size() <= 1) {
+                    // Try and read the display name from the local profile
+                    final Cursor cursor = context.getContentResolver().query(
+                            Profile.CONTENT_URI, new String[] {Phone._ID, Phone.DISPLAY_NAME},
+                            null, null, null);
+                    if (cursor != null) {
+                        try {
+                            if (cursor.moveToFirst()) {
+                                name = cursor.getString(cursor.getColumnIndex(Phone.DISPLAY_NAME));
+                            }
+                        } finally {
+                            cursor.close();
                         }
-                    } finally {
-                        cursor.close();
                     }
                 }
-
                 return new Pair<String, Drawable>(name, avatar);
             }
 
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
index cae598c..faf0ca0 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
@@ -151,13 +151,6 @@
         }
 
         boolean mWasRunning = mIsRunning;
-        try {
-            if (mService != null) {
-                mService.makeInvisible();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Caught exception making Face Unlock invisible: " + e.toString());
-        }
 
         stopUi();
 
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
index edb9d51..4ea875b 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -146,6 +146,8 @@
 
     @Override
     protected void onFinishInflate() {
+        mViewStateManager = new KeyguardViewStateManager();
+
         // Grab instances of and make any necessary changes to the main layouts. Create
         // view state manager and wire up necessary listeners / callbacks.
         mAppWidgetContainer = (KeyguardWidgetPager) findViewById(R.id.app_widget_container);
@@ -153,10 +155,12 @@
         mAppWidgetContainer.setCallbacks(mWidgetCallbacks);
         mAppWidgetContainer.setMinScale(0.5f);
 
+        mViewStateManager = new KeyguardViewStateManager();
+
         addDefaultWidgets();
         addWidgetsFromSettings();
+        mSwitchPageRunnable.run();
 
-        mViewStateManager = new KeyguardViewStateManager();
         SlidingChallengeLayout slider =
                 (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
         if (slider != null) {
@@ -210,7 +214,6 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         mAppWidgetHost.startListening();
-        post(mSwitchPageRunnable);
     }
 
     @Override
@@ -669,13 +672,10 @@
         // Find and show this child.
         final int childCount = mSecurityViewContainer.getChildCount();
 
-        // Do flip animation to the next screen
-        if (false) {
-            mSecurityViewContainer.setInAnimation(
-                    AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_animate_in));
-            mSecurityViewContainer.setOutAnimation(
-                    AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_animate_out));
-        }
+        mSecurityViewContainer.setInAnimation(
+                AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_in));
+        mSecurityViewContainer.setOutAnimation(
+                AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_out));
         final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
         for (int i = 0; i < childCount; i++) {
             if (mSecurityViewContainer.getChildAt(i).getId() == securityViewIdForMode) {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java
index e42cf1d..c89e880 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java
@@ -93,6 +93,14 @@
         mChallengeLayout.showBouncer();
     }
 
+    public void fadeOutSecurity(int duration) {
+        ((View) mKeyguardSecurityContainer).animate().alpha(0).setDuration(duration);
+    }
+
+    public void fadeInSecurity(int duration) {
+        ((View) mKeyguardSecurityContainer).animate().alpha(1f).setDuration(duration);
+    }
+
     public void onPageSwitch(View newPage, int newPageIndex) {
         // Reset the previous page size and ensure the current page is sized appropriately.
         // We only modify the page state if it is not currently under control by the slider.
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java
index cf16ef2..2e83b42 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java
@@ -15,9 +15,19 @@
  */
 package com.android.internal.policy.impl.keyguard;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+
+import java.util.ArrayList;
 
 import com.android.internal.R;
 
@@ -26,6 +36,8 @@
     private float mAdjacentPagesAngle;
     private static float MAX_SCROLL_PROGRESS = 1.3f;
     private static float CAMERA_DISTANCE = 10000;
+    protected AnimatorSet mChildrenTransformsAnimator;
+    float[] mTmpTransform = new float[3];
 
     public KeyguardWidgetCarousel(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
@@ -51,10 +63,10 @@
         float scrollProgress = getScrollProgress(screenCenter, child, index);
         if (!isOverScrollChild(index, scrollProgress)) {
             scrollProgress = getBoundedScrollProgress(screenCenter, child, index);
-            float alpha = 1 - Math.abs(scrollProgress / MAX_SCROLL_PROGRESS);
+            float alpha = 1.0f - 1.0f * Math.abs(scrollProgress / MAX_SCROLL_PROGRESS);
             return alpha;
         } else {
-            return 1f;
+            return 1.0f;
         }
     }
 
@@ -67,22 +79,22 @@
             for (int i = 0; i < getChildCount(); i++) {
                 KeyguardWidgetFrame child = getWidgetPageAt(i);
                 if (child != null) {
-                    float alpha = getAlphaForPage(screenCenter, i);
-                    child.setBackgroundAlpha(alpha);
-                    child.setContentAlpha(alpha);
+                    child.setBackgroundAlpha(getOutlineAlphaForPage(screenCenter, i));
+                    child.setContentAlpha(getAlphaForPage(screenCenter, i));
                 }
             }
         }
-
     }
 
     @Override
     protected void screenScrolled(int screenCenter) {
         mScreenCenter = screenCenter;
         updatePageAlphaValues(screenCenter);
+        if (isReordering(false)) return;
         for (int i = 0; i < getChildCount(); i++) {
             KeyguardWidgetFrame v = getWidgetPageAt(i);
             float scrollProgress = getScrollProgress(screenCenter, v, i);
+            float boundedProgress = getBoundedScrollProgress(screenCenter, v, i);
             if (v == mDragView || v == null) continue;
             v.setCameraDistance(CAMERA_DISTANCE);
 
@@ -90,17 +102,15 @@
                 v.setRotationY(- OVERSCROLL_MAX_ROTATION * scrollProgress);
                 v.setOverScrollAmount(Math.abs(scrollProgress), scrollProgress < 0);
             } else {
-                scrollProgress = getBoundedScrollProgress(screenCenter, v, i);
                 int width = v.getMeasuredWidth();
-                float pivotX = (width / 2f) + scrollProgress * (width / 2f);
+                float pivotX = (width / 2f) + boundedProgress * (width / 2f);
                 float pivotY = v.getMeasuredHeight() / 2;
-                float rotationY = - mAdjacentPagesAngle * scrollProgress;
+                float rotationY = - mAdjacentPagesAngle * boundedProgress;
                 v.setPivotX(pivotX);
                 v.setPivotY(pivotY);
                 v.setRotationY(rotationY);
                 v.setOverScrollAmount(0f, false);
             }
-
             float alpha = v.getAlpha();
             // If the view has 0 alpha, we set it to be invisible so as to prevent
             // it from accepting touches
@@ -111,4 +121,139 @@
             }
         }
     }
+
+    void animatePagesToNeutral() {
+        if (mChildrenTransformsAnimator != null) {
+            mChildrenTransformsAnimator.cancel();
+            mChildrenTransformsAnimator = null;
+        }
+
+        int count = getChildCount();
+        PropertyValuesHolder alpha;
+        PropertyValuesHolder outlineAlpha;
+        PropertyValuesHolder rotationY;
+        ArrayList<Animator> anims = new ArrayList<Animator>();
+
+        for (int i = 0; i < count; i++) {
+            KeyguardWidgetFrame child = getWidgetPageAt(i);
+            boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1);
+            if (!inVisibleRange) {
+                child.setRotationY(0f);
+            }
+            alpha = PropertyValuesHolder.ofFloat("contentAlpha", 1.0f);
+            outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha",
+                    KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
+            rotationY = PropertyValuesHolder.ofFloat("rotationY", 0f);
+            ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha, rotationY);
+            child.setVisibility(VISIBLE);
+            if (!inVisibleRange) {
+                a.setInterpolator(mSlowFadeInterpolator);
+            }
+            anims.add(a);
+        }
+
+        int duration = REORDERING_ZOOM_IN_OUT_DURATION;
+        mChildrenTransformsAnimator = new AnimatorSet();
+        mChildrenTransformsAnimator.playTogether(anims);
+
+        mChildrenTransformsAnimator.setDuration(duration);
+        mChildrenTransformsAnimator.start();
+    }
+
+    private void getTransformForPage(int screenCenter, int index, float[] transform) {
+        View child = getChildAt(index);
+        float boundedProgress = getBoundedScrollProgress(screenCenter, child, index);
+        float rotationY = - mAdjacentPagesAngle * boundedProgress;
+        int width = child.getMeasuredWidth();
+        float pivotX = (width / 2f) + boundedProgress * (width / 2f);
+        float pivotY = child.getMeasuredHeight() / 2;
+
+        transform[0] = pivotX;
+        transform[1] = pivotY;
+        transform[2] = rotationY;
+    }
+
+    Interpolator mFastFadeInterpolator = new Interpolator() {
+        Interpolator mInternal = new DecelerateInterpolator(1.5f);
+        float mFactor = 2.5f;
+        @Override
+        public float getInterpolation(float input) {
+            return mInternal.getInterpolation(Math.min(mFactor * input, 1f));
+        }
+    };
+
+    Interpolator mSlowFadeInterpolator = new Interpolator() {
+        Interpolator mInternal = new AccelerateInterpolator(1.5f);
+        float mFactor = 1.3f;
+        @Override
+        public float getInterpolation(float input) {
+            input -= (1 - 1 / mFactor);
+            input = mFactor * Math.max(input, 0f);
+            return mInternal.getInterpolation(input);
+        }
+    };
+
+    void animatePagesToCarousel() {
+        if (mChildrenTransformsAnimator != null) {
+            mChildrenTransformsAnimator.cancel();
+            mChildrenTransformsAnimator = null;
+        }
+
+        int count = getChildCount();
+        PropertyValuesHolder alpha;
+        PropertyValuesHolder outlineAlpha;
+        PropertyValuesHolder rotationY;
+        PropertyValuesHolder pivotX;
+        PropertyValuesHolder pivotY;
+        ArrayList<Animator> anims = new ArrayList<Animator>();
+
+        for (int i = 0; i < count; i++) {
+            KeyguardWidgetFrame child = getWidgetPageAt(i);
+            float finalAlpha = getAlphaForPage(mScreenCenter, i);
+            float finalOutlineAlpha = getOutlineAlphaForPage(mScreenCenter, i);
+            getTransformForPage(mScreenCenter, i, mTmpTransform);
+
+            boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1);
+
+            ObjectAnimator a;
+            alpha = PropertyValuesHolder.ofFloat("contentAlpha", finalAlpha);
+            outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", finalOutlineAlpha);
+            pivotX = PropertyValuesHolder.ofFloat("pivotX", mTmpTransform[0]);
+            pivotY = PropertyValuesHolder.ofFloat("pivotY", mTmpTransform[1]);
+            rotationY = PropertyValuesHolder.ofFloat("rotationY", mTmpTransform[2]);
+
+            if (inVisibleRange) {
+                // for the central pages we animate into a rotated state
+                a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha,
+                        pivotX, pivotY, rotationY);
+            } else {
+                a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha);
+                a.setInterpolator(mFastFadeInterpolator);
+            }
+            anims.add(a);
+        }
+
+        int duration = REORDERING_ZOOM_IN_OUT_DURATION;
+        mChildrenTransformsAnimator = new AnimatorSet();
+        mChildrenTransformsAnimator.playTogether(anims);
+
+        mChildrenTransformsAnimator.setDuration(duration);
+        mChildrenTransformsAnimator.start();
+    }
+
+    protected void reorderStarting() {
+        mViewStateManager.fadeOutSecurity(REORDERING_ZOOM_IN_OUT_DURATION);
+        animatePagesToNeutral();
+    }
+
+    protected boolean zoomIn(final Runnable onCompleteRunnable) {
+        animatePagesToCarousel();
+        return super.zoomIn(onCompleteRunnable);
+    }
+
+    @Override
+    protected void onEndReordering() {
+        super.onEndReordering();
+        mViewStateManager.fadeInSecurity(REORDERING_ZOOM_IN_OUT_DURATION);
+    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
index e24e9f9..667b2d6 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
@@ -48,7 +48,7 @@
     protected static float OVERSCROLL_MAX_ROTATION = 30;
     private static final boolean PERFORM_OVERSCROLL_ROTATION = true;
 
-    private KeyguardViewStateManager mViewStateManager;
+    protected KeyguardViewStateManager mViewStateManager;
     private LockPatternUtils mLockPatternUtils;
 
     // Related to the fading in / out background outlines
@@ -60,7 +60,7 @@
     protected int mScreenCenter;
     private boolean mHasLayout = false;
     private boolean mHasMeasure = false;
-    private boolean mShowHintsOnLayout = false;
+    boolean showHintsAfterLayout = false;
 
     private static final long CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT = 30000;
     private static final String TAG = "KeyguardWidgetPager";
@@ -308,7 +308,9 @@
         if (mViewStateManager != null) {
             mViewStateManager.onPageBeginMoving();
         }
-        showOutlinesAndSidePages();
+        if (!isReordering(false)) {
+            showOutlinesAndSidePages();
+        }
         userActivity();
     }
 
@@ -317,17 +319,22 @@
         if (mViewStateManager != null) {
             mViewStateManager.onPageEndMoving();
         }
-        hideOutlinesAndSidePages();
+
+        // In the reordering case, the pages will be faded appropriately on completion
+        // of the zoom in animation.
+        if (!isReordering(false)) {
+            hideOutlinesAndSidePages();
+        }
     }
 
-    private void enablePageLayers() {
+    protected void enablePageLayers() {
         int children = getChildCount();
         for (int i = 0; i < children; i++) {
             getWidgetPageAt(i).enableHardwareLayersForContent();
         }
     }
 
-    private void disablePageLayers() {
+    protected void disablePageLayers() {
         int children = getChildCount();
         for (int i = 0; i < children; i++) {
             getWidgetPageAt(i).disableHardwareLayersForContent();
@@ -456,10 +463,15 @@
         return mCameraWidgetEnabled;
     }
 
+    protected void reorderStarting() {
+        showOutlinesAndSidePages();
+    }
+
     @Override
     protected void onStartReordering() {
         super.onStartReordering();
-        showOutlinesAndSidePages();
+        enablePageLayers();
+        reorderStarting();
     }
 
     @Override
@@ -469,7 +481,6 @@
     }
 
     void showOutlinesAndSidePages() {
-        enablePageLayers();
         animateOutlinesAndSidePages(true);
     }
 
@@ -482,7 +493,7 @@
             showOutlinesAndSidePages();
         } else {
             // The layout hints depend on layout being run once
-            mShowHintsOnLayout = true;
+            showHintsAfterLayout = true;
         }
     }
 
@@ -493,16 +504,17 @@
         mHasLayout = false;
     }
 
+    @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
-        if (mShowHintsOnLayout) {
+        if (showHintsAfterLayout) {
             post(new Runnable() {
                 @Override
                 public void run() {
                     showOutlinesAndSidePages();
                 }
             });
-            mShowHintsOnLayout = false;
+            showHintsAfterLayout = false;
         }
         mHasLayout = true;
     }
@@ -539,17 +551,22 @@
     }
 
     void animateOutlinesAndSidePages(final boolean show) {
+        animateOutlinesAndSidePages(show, -1);
+    }
+
+    void animateOutlinesAndSidePages(final boolean show, int duration) {
         if (mChildrenOutlineFadeAnimation != null) {
             mChildrenOutlineFadeAnimation.cancel();
             mChildrenOutlineFadeAnimation = null;
         }
-
         int count = getChildCount();
         PropertyValuesHolder alpha;
         ArrayList<Animator> anims = new ArrayList<Animator>();
 
-        int duration = show ? CHILDREN_OUTLINE_FADE_IN_DURATION :
-            CHILDREN_OUTLINE_FADE_OUT_DURATION;
+        if (duration == -1) {
+            duration = show ? CHILDREN_OUTLINE_FADE_IN_DURATION :
+                CHILDREN_OUTLINE_FADE_OUT_DURATION;
+        }
 
         int curPage = getNextPage();
         for (int i = 0; i < count; i++) {
@@ -576,6 +593,12 @@
         mChildrenOutlineFadeAnimation.setDuration(duration);
         mChildrenOutlineFadeAnimation.addListener(new AnimatorListenerAdapter() {
             @Override
+            public void onAnimationStart(Animator animation) {
+                if (show) {
+                    enablePageLayers();
+                }
+            }
+            @Override
             public void onAnimationEnd(Animator animation) {
                 if (!show) {
                     disablePageLayers();
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
index 099ea07..c93b11a 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
@@ -1995,7 +1995,7 @@
     }
 
     // "Zooms out" the PagedView to reveal more side pages
-    boolean zoomOut() {
+    protected boolean zoomOut() {
         if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) {
             mZoomInOutAnim.cancel();
         }
@@ -2097,7 +2097,7 @@
     }
 
     // "Zooms in" the PagedView to highlight the current page
-    boolean zoomIn(final Runnable onCompleteRunnable) {
+    protected boolean zoomIn(final Runnable onCompleteRunnable) {
         if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) {
             mZoomInOutAnim.cancel();
         }
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
index 74b05dd..7cf995c 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
@@ -16,11 +16,14 @@
 
 package com.android.internal.policy.impl.keyguard;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Paint;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
@@ -61,10 +64,12 @@
     private Drawable mHandleDrawable;
     private Drawable mFrameDrawable;
     private Drawable mDragIconDrawable;
+    private boolean mEdgeCaptured;
 
     // Initialized during measurement from child layoutparams
     private View mChallengeView;
     private View mScrimView;
+    private View mWidgetsView;
 
     // Range: 0 (fully hidden) to 1 (fully visible)
     private float mChallengeOffset = 1.f;
@@ -110,9 +115,14 @@
 
     float mHandleAlpha;
     float mFrameAlpha;
+    float mFrameAnimationTarget = Float.MIN_VALUE;
     private ObjectAnimator mHandleAnimation;
     private ObjectAnimator mFrameAnimation;
 
+    private final Rect mTempRect = new Rect();
+
+    private boolean mHasGlowpad;
+
     static final Property<SlidingChallengeLayout, Float> HANDLE_ALPHA =
             new FloatProperty<SlidingChallengeLayout>("handleAlpha") {
         @Override
@@ -293,21 +303,43 @@
         mHandleAnimation.start();
     }
 
-    void animateFrame(boolean visible, boolean full) {
+    void animateFrame(final boolean visible, final boolean full) {
         if (mFrameDrawable == null) return;
 
-        if (mFrameAnimation != null) {
-            mFrameAnimation.cancel();
-            mFrameAnimation = null;
-        }
         final float targetAlpha = visible ? (full ? 1.f : 0.5f) : 0.f;
-        if (targetAlpha == mFrameAlpha) {
+        if (mFrameAnimation != null && targetAlpha != mFrameAnimationTarget) {
+            mFrameAnimation.cancel();
+            mFrameAnimationTarget = Float.MIN_VALUE;
+        }
+        if (targetAlpha == mFrameAlpha || targetAlpha == mFrameAnimationTarget) {
             return;
         }
+        mFrameAnimationTarget = targetAlpha;
 
         mFrameAnimation = ObjectAnimator.ofFloat(this, FRAME_ALPHA, targetAlpha);
         mFrameAnimation.setInterpolator(sHandleFadeInterpolator);
         mFrameAnimation.setDuration(HANDLE_ANIMATE_DURATION);
+        mFrameAnimation.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mFrameAnimationTarget = Float.MIN_VALUE;
+
+                if (!visible && full && mChallengeView != null) {
+                    // Mess with padding/margin to remove insets on the bouncer frame.
+                    mChallengeView.setPadding(0, 0, 0, 0);
+                    LayoutParams lp = (LayoutParams) mChallengeView.getLayoutParams();
+                    lp.leftMargin = lp.rightMargin = getChallengeMargin(true);
+                    mChallengeView.setLayoutParams(lp);
+                }
+                mFrameAnimation = null;
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mFrameAnimationTarget = Float.MIN_VALUE;
+                mFrameAnimation = null;
+            }
+        });
         mFrameAnimation.start();
     }
 
@@ -370,7 +402,9 @@
             mScrollState = state;
 
             animateHandle(state == SCROLL_STATE_IDLE && !mChallengeShowing);
-            animateFrame(false , false);
+            if (!mIsBouncing) {
+                animateFrame(false, false);
+            }
             if (mScrollListener != null) {
                 mScrollListener.onScrollStateChanged(state);
             }
@@ -380,6 +414,7 @@
     void completeChallengeScroll() {
         setChallengeShowing(mChallengeOffset != 0);
         setScrollState(SCROLL_STATE_IDLE);
+        mChallengeView.setLayerType(LAYER_TYPE_NONE, null);
     }
 
     void setScrimView(View scrim) {
@@ -461,7 +496,22 @@
         if (mScrimView != null) {
             mScrimView.setVisibility(VISIBLE);
         }
+
+        // Mess with padding/margin to inset the bouncer frame.
+        // We have more space available to us otherwise.
+        if (mChallengeView != null) {
+            if (mFrameDrawable == null || !mFrameDrawable.getPadding(mTempRect)) {
+                mTempRect.set(0, 0, 0, 0);
+            }
+            mChallengeView.setPadding(mTempRect.left, mTempRect.top, mTempRect.right,
+                    mTempRect.bottom);
+            final LayoutParams lp = (LayoutParams) mChallengeView.getLayoutParams();
+            lp.leftMargin = lp.rightMargin = getChallengeMargin(false);
+            mChallengeView.setLayoutParams(lp);
+        }
+
         animateFrame(true, true);
+
         if (mBouncerListener != null) {
             mBouncerListener.onBouncerStateChanged(true);
         }
@@ -470,17 +520,21 @@
     @Override
     public void hideBouncer() {
         if (!mIsBouncing) return;
-        setChallengeShowing(false);
+        showChallenge(false);
         mIsBouncing = false;
         if (mScrimView != null) {
             mScrimView.setVisibility(GONE);
         }
-        animateFrame(false, false);
+        animateFrame(false, true);
         if (mBouncerListener != null) {
             mBouncerListener.onBouncerStateChanged(false);
         }
     }
 
+    private int getChallengeMargin(boolean expanded) {
+        return expanded && mHasGlowpad ? 0 : mDragHandleEdgeSlop;
+    }
+
     @Override
     public void requestDisallowInterceptTouchEvent(boolean allowIntercept) {
         // We'll intercept whoever we feel like! ...as long as it isn't a challenge view.
@@ -495,8 +549,6 @@
         }
         mVelocityTracker.addMovement(ev);
 
-        //Log.v(TAG, "onIntercept: " + ev);
-
         final int action = ev.getActionMasked();
         switch (action) {
             case MotionEvent.ACTION_DOWN:
@@ -525,6 +577,7 @@
                         mGestureStartY = y;
                         mGestureStartChallengeBottom = getChallengeBottom();
                         mDragging = true;
+                        mChallengeView.setLayerType(LAYER_TYPE_HARDWARE, null);
                     } else if (isInChallengeView(x, y)) {
                         mBlockDrag = true;
                     }
@@ -601,6 +654,7 @@
                             mActivePointerId = ev.getPointerId(i);
                             mGestureStartChallengeBottom = getChallengeBottom();
                             mDragging = true;
+                            mChallengeView.setLayerType(LAYER_TYPE_HARDWARE, null);
                             break;
                         }
                     }
@@ -631,6 +685,52 @@
     }
 
     /**
+     * The lifecycle of touch events is subtle and it's very easy to do something
+     * that will cause bugs that will be nasty to track when overriding this method.
+     * Normally one should always override onInterceptTouchEvent instead.
+     *
+     * To put it another way, don't try this at home.
+     */
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        final int action = ev.getActionMasked();
+        boolean handled = false;
+        if (action == MotionEvent.ACTION_DOWN) {
+            // Defensive programming: if we didn't get the UP or CANCEL, reset anyway.
+            mEdgeCaptured = false;
+        }
+        if (mWidgetsView != null && !mIsBouncing && (mEdgeCaptured || isEdgeSwipeBeginEvent(ev))) {
+            // Normally we would need to do a lot of extra stuff here.
+            // We can only get away with this because we haven't padded in
+            // the widget pager or otherwise transformed it during layout.
+            // We also don't support things like splitting MotionEvents.
+
+            // We set handled to captured even if dispatch is returning false here so that
+            // we don't send a different view a busted or incomplete event stream.
+            handled = mEdgeCaptured |= mWidgetsView.dispatchTouchEvent(ev);
+        }
+
+        if (!handled && !mEdgeCaptured) {
+            handled = super.dispatchTouchEvent(ev);
+        }
+
+        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+            mEdgeCaptured = false;
+        }
+
+        return handled;
+    }
+
+    private boolean isEdgeSwipeBeginEvent(MotionEvent ev) {
+        if (ev.getActionMasked() != MotionEvent.ACTION_DOWN) {
+            return false;
+        }
+
+        final float x = ev.getX();
+        return x < mDragHandleEdgeSlop || x >= getWidth() - mDragHandleEdgeSlop;
+    }
+
+    /**
      * We only want to add additional vertical space to the drag handle when the panel is fully
      * closed.
      */
@@ -699,8 +799,16 @@
                 }
                 // We're going to play silly games with the frame's background drawable later.
                 mFrameDrawable = mChallengeView.getBackground();
+
+                if (!mHasLayout) {
+                    // Set up the margin correctly based on our content for the first run.
+                    mHasGlowpad = child.findViewById(R.id.keyguard_selector_view) != null;
+                    lp.leftMargin = lp.rightMargin = getChallengeMargin(true);
+                }
             } else if (lp.childType == LayoutParams.CHILD_TYPE_SCRIM) {
                 setScrimView(child);
+            } else if (lp.childType == LayoutParams.CHILD_TYPE_WIDGETS) {
+                mWidgetsView = child;
             }
 
             if (child.getVisibility() == GONE) continue;
@@ -980,6 +1088,7 @@
         public static final int CHILD_TYPE_NONE = 0;
         public static final int CHILD_TYPE_CHALLENGE = 2;
         public static final int CHILD_TYPE_SCRIM = 4;
+        public static final int CHILD_TYPE_WIDGETS = 5;
 
         public LayoutParams() {
             this(MATCH_PARENT, WRAP_CONTENT);
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index a02fc8d..82dbf54 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -466,10 +466,13 @@
                 if (Intent.ACTION_USER_REMOVED.equals(action)) {
                     onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
                             UserHandle.USER_NULL));
-                } else if (Intent.ACTION_USER_STOPPING.equals(action)) {
-                    onStoppingUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
-                            UserHandle.USER_NULL));
                 }
+                // TODO: Race condition causing problems when cleaning up on stopping a user.
+                // Comment this out for now.
+                // else if (Intent.ACTION_USER_STOPPING.equals(action)) {
+                //     onStoppingUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+                //             UserHandle.USER_NULL));
+                // }
             }
         }, userFilter);
 
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 637f2de..3532c0c 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -8379,7 +8379,7 @@
             // windows, since that means "perform layout as normal,
             // just don't display").
             if (!gone || !win.mHaveFrame || win.mLayoutNeeded
-                    || win.isConfigChanged()
+                    || (win.mAttrs.type == TYPE_KEYGUARD && win.isConfigChanged())
                     || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
                 if (!win.mLayoutAttached) {
                     if (initial) {