am 0de49148: Merge "Fix for BluetoothAdapter.getAddress() when BT is off on some devices" into jb-mr1-dev

* commit '0de49148f07c7f0b3b45cec0ef502db4b9163711':
  Fix for BluetoothAdapter.getAddress() when BT is off on some devices
diff --git a/api/17.txt b/api/17.txt
index fde6302..bdc7b19 100644
--- a/api/17.txt
+++ b/api/17.txt
@@ -1145,7 +1145,6 @@
     field public static final int weekSeparatorLineColor = 16843590; // 0x1010346
     field public static final int weightSum = 16843048; // 0x1010128
     field public static final int widgetCategory = 16843716; // 0x10103c4
-    field public static final int widgetFeatures = 16843715; // 0x10103c3
     field public static final int widgetLayout = 16843243; // 0x10101eb
     field public static final int width = 16843097; // 0x1010159
     field public static final int windowActionBar = 16843469; // 0x10102cd
@@ -4497,8 +4496,6 @@
     field public static final int RESIZE_VERTICAL = 2; // 0x2
     field public static final int WIDGET_CATEGORY_HOME_SCREEN = 1; // 0x1
     field public static final int WIDGET_CATEGORY_KEYGUARD = 2; // 0x2
-    field public static final int WIDGET_FEATURES_NONE = 0; // 0x0
-    field public static final int WIDGET_FEATURES_STATUS = 1; // 0x1
     field public int autoAdvanceViewId;
     field public android.content.ComponentName configure;
     field public int icon;
@@ -4514,7 +4511,6 @@
     field public int resizeMode;
     field public int updatePeriodMillis;
     field public int widgetCategory;
-    field public int widgetFeatures;
   }
 
 }
diff --git a/api/current.txt b/api/current.txt
index fde6302..bdc7b19 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1145,7 +1145,6 @@
     field public static final int weekSeparatorLineColor = 16843590; // 0x1010346
     field public static final int weightSum = 16843048; // 0x1010128
     field public static final int widgetCategory = 16843716; // 0x10103c4
-    field public static final int widgetFeatures = 16843715; // 0x10103c3
     field public static final int widgetLayout = 16843243; // 0x10101eb
     field public static final int width = 16843097; // 0x1010159
     field public static final int windowActionBar = 16843469; // 0x10102cd
@@ -4497,8 +4496,6 @@
     field public static final int RESIZE_VERTICAL = 2; // 0x2
     field public static final int WIDGET_CATEGORY_HOME_SCREEN = 1; // 0x1
     field public static final int WIDGET_CATEGORY_KEYGUARD = 2; // 0x2
-    field public static final int WIDGET_FEATURES_NONE = 0; // 0x0
-    field public static final int WIDGET_FEATURES_STATUS = 1; // 0x1
     field public int autoAdvanceViewId;
     field public android.content.ComponentName configure;
     field public int icon;
@@ -4514,7 +4511,6 @@
     field public int resizeMode;
     field public int updatePeriodMillis;
     field public int widgetCategory;
-    field public int widgetFeatures;
   }
 
 }
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index fcecd04..d56556f 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -144,6 +144,7 @@
             // We add padding to the AppWidgetHostView if necessary
             Rect padding = getDefaultPaddingForWidget(mContext, info.provider, null);
             setPadding(padding.left, padding.top, padding.right, padding.bottom);
+            setContentDescription(info.label);
         }
     }
 
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 8b62931..6bf12e6 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -54,18 +54,6 @@
     public static final int WIDGET_CATEGORY_KEYGUARD = 2;
 
     /**
-     * Indicates that the widget supports no special features.
-     */
-    public static final int WIDGET_FEATURES_NONE = 0;
-
-    /**
-     * Indicates that the widget is output only, ie. has nothing clickable. This may be enforced by
-     * the host. Presently, this flag is used by the keyguard to indicate that it can be placed
-     * in the first position.
-     */
-    public static final int WIDGET_FEATURES_STATUS = 1;
-
-    /**
      * Identity of this AppWidget component.  This component should be a {@link
      * android.content.BroadcastReceiver}, and it will be sent the AppWidget intents
      * {@link android.appwidget as described in the AppWidget package documentation}.
@@ -207,15 +195,6 @@
      */
     public int widgetCategory;
 
-    /**
-     * A field which specifies any special features that this widget supports. See
-     * {@link #WIDGET_FEATURES_NONE}, {@link #WIDGET_FEATURES_STATUS}.
-     *
-     * <p>This field corresponds to the <code>widgetFeatures</code> attribute in
-     * the AppWidget meta-data file.
-     */
-    public int widgetFeatures;
-
     public AppWidgetProviderInfo() {
     }
 
@@ -242,7 +221,6 @@
         this.autoAdvanceViewId = in.readInt();
         this.resizeMode = in.readInt();
         this.widgetCategory = in.readInt();
-        this.widgetFeatures = in.readInt();
     }
 
     public void writeToParcel(android.os.Parcel out, int flags) {
@@ -271,7 +249,6 @@
         out.writeInt(this.autoAdvanceViewId);
         out.writeInt(this.resizeMode);
         out.writeInt(this.widgetCategory);
-        out.writeInt(this.widgetFeatures);
     }
 
     @Override
@@ -292,7 +269,6 @@
         that.autoAdvanceViewId = this.autoAdvanceViewId;
         that.resizeMode = this.resizeMode;
         that.widgetCategory  = this.widgetCategory;
-        that.widgetFeatures = this.widgetFeatures;
         return that;
     }
 
diff --git a/core/java/com/android/internal/policy/IFaceLockCallback.aidl b/core/java/com/android/internal/policy/IFaceLockCallback.aidl
index eb902fd..280e4d5 100644
--- a/core/java/com/android/internal/policy/IFaceLockCallback.aidl
+++ b/core/java/com/android/internal/policy/IFaceLockCallback.aidl
@@ -22,6 +22,5 @@
     void unlock();
     void cancel();
     void reportFailedAttempt();
-    void exposeFallback();
     void pokeWakelock(int millis);
 }
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 6c5ed7e..7a76ab0 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -18,7 +18,6 @@
 
 
 import android.content.Context;
-import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -33,11 +32,9 @@
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.HapticFeedbackConstants;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.R;
@@ -657,9 +654,11 @@
                 handleActionMove(event);
                 return true;
             case MotionEvent.ACTION_CANCEL:
-                resetPattern();
-                mPatternInProgress = false;
-                notifyPatternCleared();
+                if (mPatternInProgress) {
+                    mPatternInProgress = false;
+                    resetPattern();
+                    notifyPatternCleared();
+                }
                 if (PROFILE_DRAWING) {
                     if (mDrawingProfilingStarted) {
                         Debug.stopMethodTracing();
@@ -826,7 +825,7 @@
             mPatternInProgress = true;
             mPatternDisplayMode = DisplayMode.Correct;
             notifyPatternStarted();
-        } else {
+        } else if (mPatternInProgress) {
             mPatternInProgress = false;
             notifyPatternCleared();
         }
diff --git a/core/res/res/drawable-hdpi/kg_security_lock_focused.png b/core/res/res/drawable-hdpi/kg_security_lock_focused.png
new file mode 100644
index 0000000..9a82799
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_security_lock_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_security_lock_normal.png b/core/res/res/drawable-hdpi/kg_security_lock_normal.png
new file mode 100644
index 0000000..d608707
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_security_lock_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/kg_security_lock_pressed.png b/core/res/res/drawable-hdpi/kg_security_lock_pressed.png
new file mode 100644
index 0000000..7ca995d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/kg_security_lock_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_security_lock_focused.png b/core/res/res/drawable-mdpi/kg_security_lock_focused.png
new file mode 100644
index 0000000..c3608f9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_security_lock_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_security_lock_normal.png b/core/res/res/drawable-mdpi/kg_security_lock_normal.png
new file mode 100644
index 0000000..7957c79
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_security_lock_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/kg_security_lock_pressed.png b/core/res/res/drawable-mdpi/kg_security_lock_pressed.png
new file mode 100644
index 0000000..41715f5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/kg_security_lock_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_security_lock_focused.png b/core/res/res/drawable-xhdpi/kg_security_lock_focused.png
new file mode 100644
index 0000000..db22016
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_security_lock_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_security_lock_normal.png b/core/res/res/drawable-xhdpi/kg_security_lock_normal.png
new file mode 100644
index 0000000..17ebb5f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_security_lock_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/kg_security_lock_pressed.png b/core/res/res/drawable-xhdpi/kg_security_lock_pressed.png
new file mode 100644
index 0000000..186b6ff
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/kg_security_lock_pressed.png
Binary files differ
diff --git a/core/res/res/drawable/keyguard_expand_challenge_handle.xml b/core/res/res/drawable/keyguard_expand_challenge_handle.xml
new file mode 100644
index 0000000..3e0780b
--- /dev/null
+++ b/core/res/res/drawable/keyguard_expand_challenge_handle.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_focused="true" android:drawable="@drawable/kg_security_lock_focused" />
+    <item android:state_pressed="true" android:drawable="@drawable/kg_security_lock_pressed" />
+    <item android:drawable="@drawable/kg_security_lock_normal" />
+</selector>
diff --git a/core/res/res/layout-port/keyguard_host_view.xml b/core/res/res/layout-port/keyguard_host_view.xml
index a3c8105..b3270e0 100644
--- a/core/res/res/layout-port/keyguard_host_view.xml
+++ b/core/res/res/layout-port/keyguard_host_view.xml
@@ -31,8 +31,7 @@
     <com.android.internal.policy.impl.keyguard.SlidingChallengeLayout
         android:id="@+id/sliding_layout"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        androidprv:dragIcon="@drawable/kg_security_lock">
+        android:layout_height="match_parent">
 
         <FrameLayout
             android:layout_width="match_parent"
@@ -68,6 +67,17 @@
                 android:gravity="center">
             </com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper>
         </com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer>
+
+        <ImageButton
+              android:layout_width="match_parent"
+              android:layout_height="@dimen/kg_widget_pager_bottom_padding"
+              androidprv:layout_childType="expandChallengeHandle"
+              android:focusable="true"
+              android:background="@null"
+              android:src="@drawable/keyguard_expand_challenge_handle"
+              android:scaleType="center"
+              android:contentDescription="@string/keyguard_accessibility_expand_lock_area" />
+
     </com.android.internal.policy.impl.keyguard.SlidingChallengeLayout>
 </com.android.internal.policy.impl.keyguard.KeyguardHostView>
 
diff --git a/core/res/res/layout-sw600dp-port/keyguard_host_view.xml b/core/res/res/layout-sw600dp-port/keyguard_host_view.xml
index 3953c95..5d858ae 100644
--- a/core/res/res/layout-sw600dp-port/keyguard_host_view.xml
+++ b/core/res/res/layout-sw600dp-port/keyguard_host_view.xml
@@ -38,7 +38,7 @@
             android:id="@+id/app_widget_container"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            androidprv:layout_centerWithinArea="0.55"
+            androidprv:layout_centerWithinArea="0.5"
             androidprv:layout_childType="widget"
             androidprv:layout_maxWidth="480dp"
             androidprv:layout_maxHeight="480dp" />
@@ -52,8 +52,11 @@
 
         <com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer
             android:id="@+id/keyguard_security_container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            androidprv:layout_maxWidth="@dimen/keyguard_security_width"
+            androidprv:layout_maxHeight="@dimen/keyguard_security_height"
+            androidprv:layout_centerWithinArea="0.5"
             androidprv:layout_childType="challenge"
             android:layout_gravity="center_horizontal|bottom">
             <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper
diff --git a/core/res/res/layout/keyguard_add_widget.xml b/core/res/res/layout/keyguard_add_widget.xml
index fd5e565..db166ac 100644
--- a/core/res/res/layout/keyguard_add_widget.xml
+++ b/core/res/res/layout/keyguard_add_widget.xml
@@ -27,6 +27,7 @@
     <FrameLayout
             android:layout_width="match_parent"
             android:layout_height="match_parent"
+            android:contentDescription="@string/keyguard_accessibility_widget_empty_slot"
             >
         <ImageView
             android:id="@+id/keyguard_add_widget_view"
@@ -35,6 +36,7 @@
             android:layout_height="wrap_content"
             android:layout_gravity="center"
             android:padding="24dp"
-            android:src="@drawable/kg_add_widget" />
+            android:src="@drawable/kg_add_widget"
+            android:contentDescription="@string/keyguard_accessibility_add_widget"/>
     </FrameLayout>
 </com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame>
diff --git a/core/res/res/layout/keyguard_emergency_carrier_area.xml b/core/res/res/layout/keyguard_emergency_carrier_area.xml
index 655b77d..52adc04 100644
--- a/core/res/res/layout/keyguard_emergency_carrier_area.xml
+++ b/core/res/res/layout/keyguard_emergency_carrier_area.xml
@@ -25,7 +25,8 @@
     android:orientation="vertical"
     android:gravity="center"
     android:layout_gravity="center_horizontal"
-    android:layout_alignParentBottom="true">
+    android:layout_alignParentBottom="true"
+    android:clickable="true">
 
     <com.android.internal.policy.impl.keyguard.CarrierText
         android:layout_width="wrap_content"
diff --git a/core/res/res/layout/keyguard_face_unlock_view.xml b/core/res/res/layout/keyguard_face_unlock_view.xml
index 976d0c6..39e8f31 100644
--- a/core/res/res/layout/keyguard_face_unlock_view.xml
+++ b/core/res/res/layout/keyguard_face_unlock_view.xml
@@ -23,7 +23,8 @@
     android:id="@+id/keyguard_face_unlock_view"
     android:orientation="vertical"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:contentDescription="@string/keyguard_accessibility_face_unlock">
 
     <include layout="@layout/keyguard_message_area"
         android:layout_width="match_parent"
diff --git a/core/res/res/layout/keyguard_glow_pad_view.xml b/core/res/res/layout/keyguard_glow_pad_view.xml
index a416a77..ef1c133 100644
--- a/core/res/res/layout/keyguard_glow_pad_view.xml
+++ b/core/res/res/layout/keyguard_glow_pad_view.xml
@@ -27,7 +27,7 @@
     android:layout_gravity="center"
     android:orientation="horizontal"
     android:gravity="@integer/kg_selector_gravity"
-    android:focusable="true"
+    android:contentDescription="@string/keyguard_accessibility_slide_area"
 
     prvandroid:targetDrawables="@array/lockscreen_targets_unlock_only"
     prvandroid:targetDescriptions="@array/lockscreen_target_descriptions_unlock_only"
diff --git a/core/res/res/layout/keyguard_message_area.xml b/core/res/res/layout/keyguard_message_area.xml
index 9f11a2c..37463cf 100644
--- a/core/res/res/layout/keyguard_message_area.xml
+++ b/core/res/res/layout/keyguard_message_area.xml
@@ -28,5 +28,6 @@
     android:ellipsize="marquee"
     android:textAppearance="?android:attr/textAppearance"
     android:textSize="@dimen/kg_status_line_font_size"
-    android:textColor="?android:attr/textColorSecondary" />
+    android:textColor="?android:attr/textColorSecondary"
+    android:clickable="true" />
 
diff --git a/core/res/res/layout/keyguard_password_view.xml b/core/res/res/layout/keyguard_password_view.xml
index b6faf5b..a054d07 100644
--- a/core/res/res/layout/keyguard_password_view.xml
+++ b/core/res/res/layout/keyguard_password_view.xml
@@ -23,6 +23,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:gravity="bottom"
+    android:contentDescription="@string/keyguard_accessibility_password_unlock"
     >
 
     <Space
diff --git a/core/res/res/layout/keyguard_pattern_view.xml b/core/res/res/layout/keyguard_pattern_view.xml
index 0f6256a..5ebc000 100644
--- a/core/res/res/layout/keyguard_pattern_view.xml
+++ b/core/res/res/layout/keyguard_pattern_view.xml
@@ -26,7 +26,8 @@
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:gravity="center_horizontal">
+    android:gravity="center_horizontal"
+    android:contentDescription="@string/keyguard_accessibility_pattern_unlock">
 
     <FrameLayout
         android:layout_width="match_parent"
@@ -55,7 +56,8 @@
                 android:layout_marginBottom="4dip"
                 android:layout_marginStart="8dip"
                 android:layout_gravity="center_horizontal"
-                android:gravity="center" />
+                android:gravity="center"
+                android:contentDescription="@string/keyguard_accessibility_pattern_area" />
 
             <include layout="@layout/keyguard_emergency_carrier_area"
                 android:id="@+id/keyguard_selector_fade_container"
diff --git a/core/res/res/layout/keyguard_pin_view.xml b/core/res/res/layout/keyguard_pin_view.xml
index 2529196..29e69f3 100644
--- a/core/res/res/layout/keyguard_pin_view.xml
+++ b/core/res/res/layout/keyguard_pin_view.xml
@@ -24,6 +24,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
+    android:contentDescription="@string/keyguard_accessibility_pin_unlock"
     >
     <include layout="@layout/keyguard_message_area"
         android:layout_width="match_parent"
diff --git a/core/res/res/layout/keyguard_selector_view.xml b/core/res/res/layout/keyguard_selector_view.xml
index 7403408..941e78e 100644
--- a/core/res/res/layout/keyguard_selector_view.xml
+++ b/core/res/res/layout/keyguard_selector_view.xml
@@ -26,7 +26,8 @@
     android:layout_height="match_parent"
     android:clipChildren="false"
     android:clipToPadding="false"
-    android:orientation="vertical">
+    android:orientation="vertical"
+    android:contentDescription="@string/keyguard_accessibility_slide_unlock">
 
     <FrameLayout
         android:layout_width="match_parent"
diff --git a/core/res/res/layout/keyguard_status_view.xml b/core/res/res/layout/keyguard_status_view.xml
index 9532a88..7467928 100644
--- a/core/res/res/layout/keyguard_status_view.xml
+++ b/core/res/res/layout/keyguard_status_view.xml
@@ -31,12 +31,13 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:gravity="center_horizontal|top"
-        android:contentDescription="@*android:string/keyguard_accessibility_status">
+        android:contentDescription="@android:string/keyguard_accessibility_status">
 
         <LinearLayout android:layout_width="match_parent"
                       android:layout_height="wrap_content"
                       android:layout_gravity="center_horizontal|top"
-                      android:orientation="vertical">
+                      android:orientation="vertical"
+                      android:focusable="true">
             <com.android.internal.policy.impl.keyguard.ClockView
                 android:id="@+id/clock_view"
                 android:layout_width="wrap_content"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 186c8b3..6f307a7 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5231,12 +5231,6 @@
             <flag name="home_screen" value="0x1" />
             <flag name="keyguard" value="0x2" />
         </attr>
-        <!-- Optional parameter which indicates any feature(s) that this widget
-             supports. Supports combined values using | operator. -->
-        <attr name="widgetFeatures" format="integer">
-            <flag name="none" value="0x0" />
-            <flag name="status" value="0x1" />
-        </attr>
     </declare-styleable>
 
     <!-- =============================== -->
@@ -5818,13 +5812,11 @@
         <enum name="scrim" value="4" />
         <!-- The home for widgets. All widgets will be descendents of this. -->
         <enum name="widgets" value="5" />
+        <!-- This is a handle that is used for expanding the
+             security challenge container when it is collapsed. -->
+        <enum name="expandChallengeHandle" value="6" />
     </attr>
 
-    <declare-styleable name="SlidingChallengeLayout">
-        <attr name="dragHandle" format="reference" />
-        <attr name="dragIcon" format="reference" />
-    </declare-styleable>
-
     <declare-styleable name="SlidingChallengeLayout_Layout">
         <attr name="layout_childType" />
     </declare-styleable>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 06d3110..a5dae7e 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2013,7 +2013,6 @@
   <public type="attr" name="presentationTheme" id="0x010103c0" />
   <public type="attr" name="subtypeId" id="0x010103c1" />
   <public type="attr" name="initialKeyguardLayout" id="0x010103c2" />
-  <public type="attr" name="widgetFeatures" id="0x010103c3" />
   <public type="attr" name="widgetCategory" id="0x010103c4" />
   <public type="attr" name="permissionGroupFlags" id="0x010103c5" />
   <public type="attr" name="labelFor" id="0x010103c6" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e820ace..05edbcc 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -555,10 +555,26 @@
   <java-symbol type="string" name="keyboardview_keycode_enter" />
   <java-symbol type="string" name="keyboardview_keycode_mode_change" />
   <java-symbol type="string" name="keyboardview_keycode_shift" />
+  <java-symbol type="string" name="keyguard_accessibility_add_widget" />
+  <java-symbol type="string" name="keyguard_accessibility_camera" />
+  <java-symbol type="string" name="keyguard_accessibility_expand_lock_area" />
+  <java-symbol type="string" name="keyguard_accessibility_face_unlock" />
   <java-symbol type="string" name="keygaurd_accessibility_media_controls" />
+  <java-symbol type="string" name="keyguard_accessibility_pattern_area" />
+  <java-symbol type="string" name="keyguard_accessibility_pattern_unlock" />
+  <java-symbol type="string" name="keyguard_accessibility_password_unlock" />
+  <java-symbol type="string" name="keyguard_accessibility_pin_unlock" />
+  <java-symbol type="string" name="keyguard_accessibility_slide_area" />
+  <java-symbol type="string" name="keyguard_accessibility_slide_unlock" />
   <java-symbol type="string" name="keyguard_accessibility_status" />
   <java-symbol type="string" name="keyguard_accessibility_user_selector" />
-  <java-symbol type="string" name="keyguard_accessibility_widget_changed" />
+  <java-symbol type="string" name="keyguard_accessibility_widget" />
+  <java-symbol type="string" name="keyguard_accessibility_widget_deleted" />
+  <java-symbol type="string" name="keyguard_accessibility_widget_empty_slot" />
+  <java-symbol type="string" name="keyguard_accessibility_widget_reorder_start" />
+  <java-symbol type="string" name="keyguard_accessibility_widget_reorder_end" />
+  <java-symbol type="string" name="keyguard_accessibility_unlock_area_collapsed" />
+  <java-symbol type="string" name="keyguard_accessibility_unlock_area_expanded" />
   <java-symbol type="string" name="kilobyteShort" />
   <java-symbol type="string" name="last_month" />
   <java-symbol type="string" name="launchBrowserDefault" />
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
index 3dd0a8f..2728bfc 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
@@ -34,6 +34,7 @@
 import android.widget.ImageView;
 import android.widget.ImageView.ScaleType;
 
+import com.android.internal.R;
 import com.android.internal.policy.impl.keyguard.KeyguardActivityLauncher.CameraWidgetInfo;
 
 public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnClickListener {
@@ -63,7 +64,10 @@
     private final Runnable mLaunchCameraRunnable = new Runnable() {
         @Override
         public void run() {
+            if (!mTransitioning)
+                return;
             mLaunchCameraStart = SystemClock.uptimeMillis();
+            if (DEBUG) Log.d(TAG, "Launching camera at " + mLaunchCameraStart);
             mActivityLauncher.launchCamera();
         }};
 
@@ -107,6 +111,8 @@
                 FrameLayout.LayoutParams.MATCH_PARENT,
                 FrameLayout.LayoutParams.MATCH_PARENT));
         preview.setScaleType(ScaleType.FIT_CENTER);
+        preview.setContentDescription(preview.getContext().getString(
+                R.string.keyguard_accessibility_camera));
         CameraWidgetFrame cameraWidgetFrame = new CameraWidgetFrame(context, callbacks, launcher);
         cameraWidgetFrame.addView(preview);
         cameraWidgetFrame.mWidgetView = widgetView;
@@ -271,7 +277,7 @@
 
     @Override
     protected void onFocusLost() {
-        Log.d(TAG, "onFocusLost");
+        if (DEBUG) Log.d(TAG, "onFocusLost");
         cancelTransitionToCamera();
         super.onFocusLost();
     }
@@ -290,6 +296,11 @@
         }
     }
 
+    public void onScreenTurnedOff() {
+        if (DEBUG) Log.d(TAG, "onScreenTurnedOff");
+        reset();
+    }
+
     private void rescheduleTransitionToCamera() {
         if (DEBUG) Log.d(TAG, "rescheduleTransitionToCamera at " + SystemClock.uptimeMillis());
         mHandler.removeCallbacks(mTransitionToCameraRunnable);
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 faf0ca0..9858c77 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
@@ -57,8 +57,7 @@
     private final int MSG_UNLOCK = 2;
     private final int MSG_CANCEL = 3;
     private final int MSG_REPORT_FAILED_ATTEMPT = 4;
-    private final int MSG_EXPOSE_FALLBACK = 5;
-    private final int MSG_POKE_WAKELOCK = 6;
+    private final int MSG_POKE_WAKELOCK = 5;
 
     // TODO: This was added for the purpose of adhering to what the biometric interface expects
     // the isRunning() function to return.  However, it is probably not necessary to have both
@@ -220,9 +219,6 @@
             case MSG_REPORT_FAILED_ATTEMPT:
                 handleReportFailedAttempt();
                 break;
-            case MSG_EXPOSE_FALLBACK:
-                handleExposeFallback();
-                break;
             case MSG_POKE_WAKELOCK:
                 handlePokeWakelock(msg.arg1);
                 break;
@@ -310,6 +306,10 @@
      */
     void handleCancel() {
         if (DEBUG) Log.d(TAG, "handleCancel()");
+        // We are going to the backup method, so we don't want to see Face Unlock again until the
+        // next time the user visits keyguard.
+        KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(false);
+
         mKeyguardScreenCallback.showBackupSecurity();
         stop();
         mKeyguardScreenCallback.userActivity(BACKUP_LOCK_TIMEOUT);
@@ -320,17 +320,11 @@
      */
     void handleReportFailedAttempt() {
         if (DEBUG) Log.d(TAG, "handleReportFailedAttempt()");
-        mKeyguardScreenCallback.reportFailedUnlockAttempt();
-    }
+        // We are going to the backup method, so we don't want to see Face Unlock again until the
+        // next time the user visits keyguard.
+        KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(false);
 
-    /**
-     * Hides the Face Unlock view to expose the backup lock.  Called when the Face Unlock service UI
-     * is started, indicating there is no need to continue displaying the underlying view because
-     * the service UI is now covering the backup lock.
-     */
-    void handleExposeFallback() {
-        if (DEBUG) Log.d(TAG, "handleExposeFallback()");
-        // No longer required because face unlock doesn't cover backup unlock.
+        mKeyguardScreenCallback.reportFailedUnlockAttempt();
     }
 
     /**
@@ -443,16 +437,6 @@
         }
 
         /**
-         * Called when the Face Unlock service starts displaying the UI, indicating that the backup
-         * unlock can be exposed because the Face Unlock service is now covering the backup with its
-         * UI.
-         */
-        public void exposeFallback() {
-            if (DEBUG) Log.d(TAG, "exposeFallback()");
-            mHandler.sendEmptyMessage(MSG_EXPOSE_FALLBACK);
-        }
-
-        /**
          * Called when Face Unlock wants to keep the screen alive and active for a specific amount
          * of time.
          */
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java
index 4c50069..8283af2 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java
@@ -25,6 +25,7 @@
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.MediaStore;
 import android.util.Log;
@@ -118,8 +119,7 @@
     public void launchActivity(final Intent intent, boolean showsWhileLocked, boolean animate) {
         final Context context = getContext();
         final Bundle animation = animate ? null :
-                ActivityOptions.makeCustomAnimation(context, com.android.internal.R.anim.fade_in,
-                        com.android.internal.R.anim.fade_out).toBundle();
+                ActivityOptions.makeCustomAnimation(context, 0, 0).toBundle();
         LockPatternUtils lockPatternUtils = getLockPatternUtils();
         intent.addFlags(
                 Intent.FLAG_ACTIVITY_NEW_TASK
@@ -133,6 +133,8 @@
                 Log.w(TAG, "can't dismiss keyguard on launch");
             }
             try {
+                if (DEBUG) Log.d(TAG, String.format("Starting activity for intent %s at %s",
+                        intent, SystemClock.uptimeMillis()));
                 context.startActivityAsUser(intent, animation,
                         new UserHandle(UserHandle.USER_CURRENT));
             } catch (ActivityNotFoundException e) {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
index a884568..c0095de 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
@@ -93,6 +93,7 @@
     @Override
     public void onResume() {
         if (DEBUG) Log.d(TAG, "onResume()");
+        mIsShowing = KeyguardUpdateMonitor.getInstance(mContext).isKeyguardVisible();
         maybeStartBiometricUnlock();
         KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateCallback);
     }
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 3b2ded2..ca3d0a2 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -39,6 +39,7 @@
 import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.AttributeSet;
@@ -49,6 +50,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.WindowManager;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AnimationUtils;
 import android.widget.RemoteViews.OnClickHandler;
 
@@ -115,8 +117,7 @@
 
         // The following enables the MENU key to work for testing automation
         mEnableMenuKey = shouldEnableMenuKey();
-        setFocusable(true);
-        setFocusableInTouchMode(true);
+        mViewStateManager = new KeyguardViewStateManager();
     }
 
     @Override
@@ -150,8 +151,6 @@
 
     @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);
@@ -423,8 +422,8 @@
     void showPrimarySecurityScreen(boolean turningOff) {
         SecurityMode securityMode = mSecurityModel.getSecurityMode();
         if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
-        if (!turningOff && KeyguardUpdateMonitor.getInstance(mContext).isAlternateUnlockEnabled()
-                && !KeyguardUpdateMonitor.getInstance(mContext).getIsFirstBoot()) {
+        if (!turningOff &&
+                KeyguardUpdateMonitor.getInstance(mContext).isAlternateUnlockEnabled()) {
             // If we're not turning off, then allow biometric alternate.
             // We'll reload it when the device comes back on.
             securityMode = mSecurityModel.getAlternateFor(securityMode);
@@ -500,7 +499,6 @@
             // If the alternate unlock was suppressed, it can now be safely
             // enabled because the user has left keyguard.
             KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
-            KeyguardUpdateMonitor.getInstance(mContext).setIsFirstBoot(false);
 
             // If there's a pending runnable because the user interacted with a widget
             // and we're leaving keyguard, then run it.
@@ -711,10 +709,18 @@
 
     @Override
     public void onScreenTurnedOff() {
-        if (DEBUG) Log.d(TAG, "screen off, instance " + Integer.toHexString(hashCode()));
+        if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
+                Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
+        // Once the screen turns off, we no longer consider this to be first boot and we want the
+        // biometric unlock to start next time keyguard is shown.
+        KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
         saveStickyWidgetIndex();
         showPrimarySecurityScreen(true);
         getSecurityView(mCurrentSecuritySelection).onPause();
+        CameraWidgetFrame cameraPage = findCameraPage();
+        if (cameraPage != null) {
+            cameraPage.onScreenTurnedOff();
+        }
     }
 
     @Override
@@ -824,7 +830,7 @@
             public void onLaunchingCamera() {
                 SlidingChallengeLayout slider = locateSlider();
                 if (slider != null) {
-                    slider.showHandle(false);
+                    slider.setHandleAlpha(0);
                 }
             }
 
@@ -835,7 +841,7 @@
                 }
                 SlidingChallengeLayout slider = locateSlider();
                 if (slider != null) {
-                    slider.showHandle(true);
+                    slider.setHandleAlpha(1);
                     slider.showChallenge(true);
                 }
             }
@@ -1140,6 +1146,15 @@
         mAppWidgetContainer.setCurrentPage(pageToShow);
     }
 
+    private CameraWidgetFrame findCameraPage() {
+        for (int i = mAppWidgetContainer.getChildCount() - 1; i >= 0; i--) {
+            if (isCameraPage(i)) {
+                return (CameraWidgetFrame) mAppWidgetContainer.getChildAt(i);
+            }
+        }
+        return null;
+    }
+
     private boolean isCameraPage(int pageIndex) {
         View v = mAppWidgetContainer.getChildAt(pageIndex);
         return v != null && v instanceof CameraWidgetFrame;
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java
index b35450c..64bbdd3 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java
@@ -72,7 +72,9 @@
     @Override
     public void onResume() {
         super.onResume();
-        mImm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
+        // XXX this is still not right because onResume is being called every time the page changes
+        mPasswordEntry.requestFocus();
+        mImm.showSoftInput(mPasswordEntry, InputMethodManager.SHOW_IMPLICIT);
     }
 
     @Override
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
index 316825a2..5fb8cf0 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
@@ -92,6 +92,7 @@
     private CharSequence mTelephonySpn;
     private int mRingMode;
     private int mPhoneState;
+    private boolean mKeyguardIsVisible;
 
     // Device provisioning state
     private boolean mDeviceProvisioned;
@@ -200,7 +201,6 @@
             }
         }
     };
-    private boolean mIsFirstBoot;
 
     /**
      * When we receive a
@@ -567,14 +567,20 @@
      */
     private void handleKeyguardVisibilityChanged(int showing) {
         if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
+        boolean isShowing = (showing == 1);
+        mKeyguardIsVisible = isShowing;
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
-                cb.onKeyguardVisibilityChanged(showing == 1);
+                cb.onKeyguardVisibilityChanged(isShowing);
             }
         }
     }
 
+    public boolean isKeyguardVisible() {
+        return mKeyguardIsVisible;
+    }
+
     private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
         final boolean nowPluggedIn = current.isPluggedIn();
         final boolean wasPluggedIn = old.isPluggedIn();
@@ -778,12 +784,4 @@
                 || simState == IccCardConstants.State.PUK_REQUIRED
                 || simState == IccCardConstants.State.PERM_DISABLED);
     }
-
-    public void setIsFirstBoot(boolean b) {
-        mIsFirstBoot = b;
-    }
-    
-    public boolean getIsFirstBoot() {
-        return mIsFirstBoot;
-    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
index 53cbb39..fe4ac5b 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
@@ -522,7 +522,6 @@
 
             // Disable alternate unlock right after boot until things have settled.
             mUpdateMonitor.setAlternateUnlockEnabled(false);
-            mUpdateMonitor.setIsFirstBoot(true);
 
             doKeyguardLocked();
         }
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 667b2d6..b023573 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
@@ -21,7 +21,6 @@
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.TimeInterpolator;
-import android.appwidget.AppWidgetHostView;
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Handler;
@@ -32,6 +31,8 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnLongClickListener;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
@@ -134,6 +135,14 @@
             KeyguardWidgetFrame newWidgetPage = getWidgetPageAt(newPageIndex);
             if (newWidgetPage != null) {
                 newWidgetPage.onActive(true);
+                newWidgetPage.requestAccessibilityFocus();
+            }
+            if (mParent != null && AccessibilityManager.getInstance(mContext).isEnabled()) {
+                AccessibilityEvent event = AccessibilityEvent.obtain(
+                        AccessibilityEvent.TYPE_VIEW_SCROLLED);
+                onInitializeAccessibilityEvent(event);
+                onPopulateAccessibilityEvent(event);
+                mParent.requestSendAccessibilityEvent(this, event);
             }
         }
         if (mViewStateManager != null) {
@@ -141,6 +150,13 @@
         }
     }
 
+    @Override
+    public void sendAccessibilityEvent(int eventType) {
+        if (eventType != AccessibilityEvent.TYPE_VIEW_SCROLLED || isPageMoving()) {
+            super.sendAccessibilityEvent(eventType);
+        }
+    }
+
     private void userActivity() {
         if (mCallbacks != null) {
             mCallbacks.onUserActivityTimeoutChanged();
@@ -227,10 +243,6 @@
             // The framework adds a default padding to AppWidgetHostView. We don't need this padding
             // for the Keyguard, so we override it to be 0.
             widget.setPadding(0,  0, 0, 0);
-            if (widget instanceof AppWidgetHostView) {
-                AppWidgetHostView awhv = (AppWidgetHostView) widget;
-                widget.setContentDescription(awhv.getAppWidgetInfo().label);
-            }
             frame.addView(widget, lp);
         } else {
             frame = (KeyguardWidgetFrame) widget;
@@ -245,6 +257,15 @@
         } else {
             addView(frame, pageIndex, pageLp);
         }
+
+        // Update the frame content description.
+        View content = (widget == frame) ?  frame.getContent() : widget;
+        if (content != null) {
+            String contentDescription = mContext.getString(
+                com.android.internal.R.string.keyguard_accessibility_widget,
+                content.getContentDescription());
+            frame.setContentDescription(contentDescription);
+        }
     }
 
     /**
@@ -361,22 +382,6 @@
     }
 
     @Override
-    public String getCurrentPageDescription() {
-        final int nextPageIndex = getNextPage();
-        if (nextPageIndex >= 0 && nextPageIndex < getChildCount()) {
-            KeyguardWidgetFrame frame = getWidgetPageAt(nextPageIndex);
-            CharSequence title = frame.getChildAt(0).getContentDescription();
-            if (title == null) {
-                title = "";
-            }
-            return mContext.getString(
-                    com.android.internal.R.string.keyguard_accessibility_widget_changed,
-                    title, nextPageIndex + 1, getChildCount());
-        }
-        return super.getCurrentPageDescription();
-    }
-
-    @Override
     protected void overScroll(float amount) {
         acceleratedOverScroll(amount);
     }
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 c93b11a..6eeada5 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
@@ -539,27 +539,12 @@
             if (mTouchState == TOUCH_STATE_REST) {
                 pageEndMoving();
             }
-
             onPostReorderingAnimationCompleted();
-
-            // Notify the user when the page changes
-            AccessibilityManager accessibilityManager = (AccessibilityManager)
-                    getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
-            if (accessibilityManager.isEnabled()) {
-                AccessibilityEvent ev =
-                    AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
-                ev.getText().add(getCurrentPageDescription());
-                sendAccessibilityEventUnchecked(ev);
-            }
             return true;
         }
         return false;
     }
 
-    public String getCurrentPageDescription() {
-        return "";
-    }
-
     @Override
     public void computeScroll() {
         computeScrollHelper();
@@ -2013,6 +1998,11 @@
     }
 
     protected void onStartReordering() {
+        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+            announceForAccessibility(mContext.getString(
+                    R.string.keyguard_accessibility_widget_reorder_start));
+        }
+
         // Set the touch state to reordering (allows snapping to pages, dragging a child, etc.)
         mTouchState = TOUCH_STATE_REORDERING;
         mIsReordering = true;
@@ -2033,6 +2023,10 @@
     }
 
     protected void onEndReordering() {
+        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+            announceForAccessibility(mContext.getString(
+                    R.string.keyguard_accessibility_widget_reorder_end));
+        }
         mIsReordering = false;
     }
 
@@ -2298,6 +2292,7 @@
     }
 
     /* Accessibility */
+
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
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 2e735a0..9079341 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
@@ -29,12 +29,14 @@
 import android.util.AttributeSet;
 import android.util.FloatProperty;
 import android.util.Log;
+import android.util.MathUtils;
 import android.util.Property;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
 import android.view.animation.Interpolator;
 import android.widget.Scroller;
 
@@ -56,18 +58,15 @@
     private static final int DRAG_HANDLE_OPEN_ABOVE = 8; // dp
     private static final int DRAG_HANDLE_OPEN_BELOW = 0; // dp
 
-    private static final boolean OPEN_ON_CLICK = true;
-
     private static final int HANDLE_ANIMATE_DURATION = 200; // ms
 
     // Drawn to show the drag handle in closed state; crossfades to the challenge view
     // when challenge is fully visible
-    private Drawable mHandleDrawable;
     private Drawable mFrameDrawable;
-    private Drawable mDragIconDrawable;
     private boolean mEdgeCaptured;
 
     // Initialized during measurement from child layoutparams
+    private View mExpandChallengeView;
     private View mChallengeView;
     private View mScrimView;
     private View mWidgetsView;
@@ -113,6 +112,7 @@
                                        // that should remain on-screen
 
     private int mTouchSlop;
+    private int mTouchSlopSquare;
 
     float mHandleAlpha;
     float mFrameAlpha;
@@ -184,6 +184,15 @@
         }
     };
 
+    private final OnClickListener mExpandChallengeClickListener = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            if (!isChallengeShowing()) {
+                showChallenge(true);
+            }
+        }
+    };
+
     /**
      * Listener interface that reports changes in scroll state of the challenge area.
      */
@@ -235,13 +244,6 @@
     public SlidingChallengeLayout(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        final TypedArray a = context.obtainStyledAttributes(attrs,
-                R.styleable.SlidingChallengeLayout, defStyle, 0);
-        setDragDrawables(a.getDrawable(R.styleable.SlidingChallengeLayout_dragHandle),
-                a.getDrawable(R.styleable.SlidingChallengeLayout_dragIcon));
-
-        a.recycle();
-
         mScroller = new Scroller(context, sMotionInterpolator);
 
         final ViewConfiguration vc = ViewConfiguration.get(context);
@@ -252,6 +254,7 @@
         mDragHandleEdgeSlop = res.getDimensionPixelSize(R.dimen.kg_edge_swipe_region_size);
 
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+        mTouchSlopSquare = mTouchSlop * mTouchSlop;
 
         final float density = res.getDisplayMetrics().density;
 
@@ -267,25 +270,9 @@
         setWillNotDraw(false);
     }
 
-    public void setDragDrawables(Drawable handle, Drawable icon) {
-        mHandleDrawable = handle;
-        mDragIconDrawable = icon;
-    }
-
-    public void setDragIconDrawable(Drawable d) {
-        mDragIconDrawable = d;
-    }
-
-    public void showHandle(boolean visible) {
-        if (visible) {
-            if (mHandleAnimation != null) {
-                mHandleAnimation.cancel();
-                mHandleAnimation = null;
-            }
-            mHandleAlpha = 1.f;
-            invalidate();
-        } else {
-            animateHandle(false);
+    public void setHandleAlpha(float alpha) {
+        if (mExpandChallengeView != null) {
+            mExpandChallengeView.setAlpha(alpha);
         }
     }
 
@@ -469,7 +456,27 @@
     }
 
     private void setChallengeShowing(boolean showChallenge) {
+        if (mChallengeShowing == showChallenge) {
+            return;
+        }
         mChallengeShowing = showChallenge;
+        if (mChallengeShowing) {
+            mExpandChallengeView.setVisibility(View.INVISIBLE);
+            mChallengeView.setVisibility(View.VISIBLE);
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                mChallengeView.requestAccessibilityFocus();
+                mChallengeView.announceForAccessibility(mContext.getString(
+                        R.string.keyguard_accessibility_unlock_area_expanded));
+            }
+        } else {
+            mExpandChallengeView.setVisibility(View.VISIBLE);
+            mChallengeView.setVisibility(View.INVISIBLE);
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                mExpandChallengeView.requestAccessibilityFocus();
+                mChallengeView.announceForAccessibility(mContext.getString(
+                        R.string.keyguard_accessibility_unlock_area_collapsed));
+            }
+        }
     }
 
     /**
@@ -573,12 +580,12 @@
                 for (int i = 0; i < count; i++) {
                     final float x = ev.getX(i);
                     final float y = ev.getY(i);
-
-                    if (!mIsBouncing &&
-                            (isInDragHandle(x, y) || crossedDragHandle(x, y, mGestureStartY) ||
-                            (isInChallengeView(x, y) &&
-                                (mScrollState == SCROLL_STATE_SETTLING || !mChallengeShowing))) &&
-                            mActivePointerId == INVALID_POINTER) {
+                    if (!mIsBouncing && mActivePointerId == INVALID_POINTER
+                            && ((isInDragHandle(x, y) && MathUtils.sq(x - mGestureStartX)
+                                    + MathUtils.sq(y - mGestureStartY) > mTouchSlopSquare)
+                               || crossedDragHandle(x, y, mGestureStartY)
+                               || (isInChallengeView(x, y) && (mScrollState == SCROLL_STATE_SETTLING
+                                       || !mChallengeShowing)))) {
                         mActivePointerId = ev.getPointerId(i);
                         mGestureStartX = x;
                         mGestureStartY = y;
@@ -634,12 +641,7 @@
                     break;
                 }
             case MotionEvent.ACTION_UP:
-                if (OPEN_ON_CLICK
-                        && isInDragHandle(mGestureStartX, mGestureStartY)
-                        && Math.abs(ev.getX() - mGestureStartX) <= mTouchSlop
-                        && Math.abs(ev.getY() - mGestureStartY) <= mTouchSlop) {
-                    showChallenge(true);
-                } else if (mDragging) {
+                if (mDragging) {
                     mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity);
                     showChallenge((int) mVelocityTracker.getYVelocity(mActivePointerId));
                 }
@@ -749,19 +751,19 @@
     }
 
     private boolean isInChallengeView(float x, float y) {
-        if (mChallengeView == null) return false;
-
-        return x >= mChallengeView.getLeft() && y >= mChallengeView.getTop() &&
-                x < mChallengeView.getRight() && y < mChallengeView.getBottom();
+        return isPointInView(x, y, mChallengeView);
     }
 
     private boolean isInDragHandle(float x, float y) {
-        if (mChallengeView == null) return false;
+        return isPointInView(x, y, mExpandChallengeView);
+    }
 
-        return x >= mDragHandleEdgeSlop &&
-                y >= mChallengeView.getTop() - getDragHandleSizeAbove() &&
-                x < getWidth() - mDragHandleEdgeSlop &&
-                y < mChallengeView.getTop() + getDragHandleSizeBelow();
+    private boolean isPointInView(float x, float y, View view) {
+        if (view == null) {
+            return false;
+        }
+        return x >= view.getLeft() && y >= view.getTop()
+                && x < view.getRight() && y < view.getBottom();
     }
 
     private boolean crossedDragHandle(float x, float y, float initialY) {
@@ -786,7 +788,9 @@
 
         // Find one and only one challenge view.
         final View oldChallengeView = mChallengeView;
+        final View oldExpandChallengeView = mChallengeView;
         mChallengeView = null;
+        mExpandChallengeView = null;
         final int count = getChildCount();
 
         // First iteration through the children finds special children and sets any associated
@@ -794,7 +798,6 @@
         for (int i = 0; i < count; i++) {
             final View child = getChildAt(i);
             final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
             if (lp.childType == LayoutParams.CHILD_TYPE_CHALLENGE) {
                 if (mChallengeView != null) {
                     throw new IllegalStateException(
@@ -806,31 +809,42 @@
                 }
                 // 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_EXPAND_CHALLENGE_HANDLE) {
+                if (mExpandChallengeView != null) {
+                    throw new IllegalStateException(
+                            "There may only be one child with layout_childType"
+                            + "=\"expandChallengeHandle\"");
+                }
+                mExpandChallengeView = child;
+                if (mExpandChallengeView != oldExpandChallengeView) {
+                    mExpandChallengeView.setVisibility(mChallengeShowing ? INVISIBLE : VISIBLE);
+                    mExpandChallengeView.setOnClickListener(mExpandChallengeClickListener);
+                }
             } 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;
         }
 
         // We want to measure the challenge view first, since the KeyguardWidgetPager
         // needs to do things its measure pass that are dependent on the challenge view
         // having been measured.
-        if (mChallengeView != null) {
+        if (mChallengeView != null && mChallengeView.getVisibility() != View.GONE) {
             measureChildWithMargins(mChallengeView, widthSpec, 0, heightSpec, 0);
         }
 
         // Measure the rest of the children
         for (int i = 0; i < count; i++) {
             final View child = getChildAt(i);
+            if (child.getVisibility() == GONE) {
+                continue;
+            }
             // Don't measure the challenge view twice!
             if (child != mChallengeView) {
                 measureChildWithMargins(child, widthSpec, 0, heightSpec, 0);
@@ -869,6 +883,13 @@
                         * (1 - mChallengeOffset));
                 child.setAlpha(getChallengeAlpha());
                 child.layout(left, bottom - childHeight, left + childWidth, bottom);
+            } else if (lp.childType == LayoutParams.CHILD_TYPE_EXPAND_CHALLENGE_HANDLE) {
+                final int center = (paddingLeft + width - paddingRight) / 2;
+                final int left = center - child.getMeasuredWidth() / 2;
+                final int right = left + child.getMeasuredWidth();
+                final int bottom = height - paddingBottom - lp.bottomMargin;
+                final int top = bottom - child.getMeasuredHeight();
+                child.layout(left, top, right, bottom);
             } else {
                 // Non-challenge views lay out from the upper left, layered.
                 child.layout(paddingLeft + lp.leftMargin,
@@ -886,6 +907,21 @@
         }
     }
 
+    @Override
+    public void draw(Canvas c) {
+        super.draw(c);
+        if (DEBUG) {
+            final Paint debugPaint = new Paint();
+            debugPaint.setColor(0x40FF00CC);
+            // show the isInDragHandle() rect
+            c.drawRect(mDragHandleEdgeSlop,
+                    mChallengeView.getTop() - getDragHandleSizeAbove(),
+                    getWidth() - mDragHandleEdgeSlop,
+                    mChallengeView.getTop() + getDragHandleSizeBelow(),
+                    debugPaint);
+        }
+    }
+
     public void computeScroll() {
         super.computeScroll();
 
@@ -906,65 +942,6 @@
         }
     }
 
-    @Override
-    public void draw(Canvas c) {
-        super.draw(c);
-
-        final Paint debugPaint;
-        if (DEBUG) {
-            debugPaint = new Paint();
-            debugPaint.setColor(0x40FF00CC);
-            // show the isInDragHandle() rect
-            c.drawRect(mDragHandleEdgeSlop,
-                    mChallengeView.getTop() - getDragHandleSizeAbove(),
-                    getWidth() - mDragHandleEdgeSlop,
-                    mChallengeView.getTop() + getDragHandleSizeBelow(),
-                    debugPaint);
-        }
-
-        if (mChallengeView != null && mHandleAlpha > 0) {
-            final int top = mChallengeView.getTop();
-            final int handleHeight;
-            final int challengeLeft = mChallengeView.getLeft();
-            final int challengeRight = mChallengeView.getRight();
-            if (mHandleDrawable != null) {
-                handleHeight = mHandleDrawable.getIntrinsicHeight();
-                mHandleDrawable.setBounds(challengeLeft, top, challengeRight, top + handleHeight);
-                mHandleDrawable.setAlpha((int) (mHandleAlpha * 0xFF));
-                mHandleDrawable.draw(c);
-            } else {
-                handleHeight = 0;
-            }
-
-            if (DEBUG) {
-                // now show the actual drag handle
-                debugPaint.setStyle(Paint.Style.STROKE);
-                debugPaint.setStrokeWidth(1);
-                debugPaint.setColor(0xFF80FF00);
-                c.drawRect(challengeLeft, top, challengeRight, top + handleHeight, debugPaint);
-            }
-
-            if (mDragIconDrawable != null) {
-                final int closedTop = getLayoutBottom() - mDragHandleClosedBelow;
-                final int iconWidth = mDragIconDrawable.getIntrinsicWidth();
-                final int iconHeight = mDragIconDrawable.getIntrinsicHeight();
-                final int iconLeft = (challengeLeft + challengeRight - iconWidth) / 2;
-                final int iconTop = closedTop +
-                        (mDragHandleClosedBelow - mDragHandleClosedAbove - iconHeight) / 2;
-                mDragIconDrawable.setBounds(iconLeft, iconTop, iconLeft + iconWidth,
-                        iconTop + iconHeight);
-                mDragIconDrawable.setAlpha((int) (mHandleAlpha * 0xFF));
-                mDragIconDrawable.draw(c);
-
-                if (DEBUG) {
-                    debugPaint.setColor(0xFF00FF00);
-                    c.drawRect(iconLeft, iconTop, iconLeft + iconWidth,
-                        iconTop + iconHeight, debugPaint);
-                }
-            }
-        }
-    }
-
     public int getMaxChallengeTop() {
         if (mChallengeView == null) return 0;
 
@@ -1096,6 +1073,7 @@
         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 static final int CHILD_TYPE_EXPAND_CHALLENGE_HANDLE = 6;
 
         public LayoutParams() {
             this(MATCH_PARENT, WRAP_CONTENT);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/FaceUnlock.java
index e4d9215..e4768e2 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/FaceUnlock.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/FaceUnlock.java
@@ -61,7 +61,7 @@
     private final int MSG_UNLOCK = 4;
     private final int MSG_CANCEL = 5;
     private final int MSG_REPORT_FAILED_ATTEMPT = 6;
-    private final int MSG_EXPOSE_FALLBACK = 7;
+    //private final int MSG_EXPOSE_FALLBACK = 7;
     private final int MSG_POKE_WAKELOCK = 8;
 
     // TODO: This was added for the purpose of adhering to what the biometric interface expects
@@ -258,9 +258,9 @@
             case MSG_REPORT_FAILED_ATTEMPT:
                 handleReportFailedAttempt();
                 break;
-            case MSG_EXPOSE_FALLBACK:
-                handleExposeFallback();
-                break;
+                //case MSG_EXPOSE_FALLBACK:
+                //handleExposeFallback();
+                //break;
             case MSG_POKE_WAKELOCK:
                 handlePokeWakelock(msg.arg1);
                 break;
@@ -401,14 +401,14 @@
      * is started, indicating there is no need to continue displaying the underlying view because
      * the service UI is now covering the backup lock.
      */
-    void handleExposeFallback() {
-        if (DEBUG) Log.d(TAG, "handleExposeFallback()");
-        if (mFaceUnlockView != null) {
-            mFaceUnlockView.setVisibility(View.INVISIBLE);
-        } else {
-            Log.e(TAG, "mFaceUnlockView is null in handleExposeFallback()");
-        }
-    }
+    //void handleExposeFallback() {
+    //    if (DEBUG) Log.d(TAG, "handleExposeFallback()");
+    //    if (mFaceUnlockView != null) {
+    //        mFaceUnlockView.setVisibility(View.INVISIBLE);
+    //    } else {
+    //        Log.e(TAG, "mFaceUnlockView is null in handleExposeFallback()");
+    //    }
+    //}
 
     /**
      * Pokes the wakelock to keep the screen alive and active for a specific amount of time.
@@ -534,11 +534,11 @@
          * unlock can be exposed because the Face Unlock service is now covering the backup with its
          * UI.
          **/
-        @Override
-        public void exposeFallback() {
-            if (DEBUG) Log.d(TAG, "exposeFallback()");
-            mHandler.sendEmptyMessage(MSG_EXPOSE_FALLBACK);
-        }
+        //@Override
+        //public void exposeFallback() {
+        //    if (DEBUG) Log.d(TAG, "exposeFallback()");
+        //    mHandler.sendEmptyMessage(MSG_EXPOSE_FALLBACK);
+        //}
 
         /**
          * Called when Face Unlock wants to keep the screen alive and active for a specific amount
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index 6a313a0..d0dd9cf 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -326,7 +326,6 @@
                 pw.print(" resizeMode=");
                 pw.print(info.resizeMode);
                 pw.print(info.widgetCategory);
-                pw.print(info.widgetFeatures);
                 pw.print(" autoAdvanceViewId=");
                 pw.print(info.autoAdvanceViewId);
                 pw.print(" initialLayout=#");
@@ -1412,9 +1411,6 @@
             info.widgetCategory = sa.getInt(
                     com.android.internal.R.styleable.AppWidgetProviderInfo_widgetCategory,
                     AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
-            info.widgetFeatures = sa.getInt(
-                    com.android.internal.R.styleable.AppWidgetProviderInfo_widgetFeatures,
-                    AppWidgetProviderInfo.WIDGET_FEATURES_NONE);
 
             sa.recycle();
         } catch (Exception e) {
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index dcf87350..18b46fb 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -584,6 +584,7 @@
                             // a given distance perform a drag.
                             mCurrentState = STATE_DRAGGING;
                             mDraggingPointerId = pointerId;
+                            event.setEdgeFlags(receivedTracker.getLastReceivedDownEdgeFlags());
                             sendMotionEvent(event, MotionEvent.ACTION_DOWN, pointerIdBits,
                                     policyFlags);
                         } else {
@@ -1752,6 +1753,9 @@
         // Which pointers are down.
         private int mReceivedPointersDown;
 
+        // The edge flags of the last received down event.
+        private int mLastReceivedDownEdgeFlags;
+
         // Which down pointers are active.
         private int mActivePointers;
 
@@ -1947,6 +1951,13 @@
         }
 
         /**
+         * @return The edge flags of the last received down event.
+         */
+        public int getLastReceivedDownEdgeFlags() {
+            return mLastReceivedDownEdgeFlags;
+        }
+
+        /**
          * @return Whether the last received pointer that went up was active.
          */
         public boolean wasLastReceivedUpPointerActive() {
@@ -1995,6 +2006,8 @@
             mLastReceivedUpPointerDownX = 0;
             mLastReceivedUpPointerDownX = 0;
 
+            mLastReceivedDownEdgeFlags = event.getEdgeFlags();
+
             mReceivedPointersDown |= pointerFlag;
             mReceivedPointerDownX[pointerId] = event.getX(pointerIndex);
             mReceivedPointerDownY[pointerId] = event.getY(pointerIndex);