Merge "Use new keyguard appwidget picker" into jb-mr1-lockscreen-dev
diff --git a/core/res/res/layout-port/keyguard_widget_pager.xml b/core/res/res/layout-port/keyguard_widget_pager.xml
index 3b29db8..7fd370b 100644
--- a/core/res/res/layout-port/keyguard_widget_pager.xml
+++ b/core/res/res/layout-port/keyguard_widget_pager.xml
@@ -25,7 +25,7 @@
     android:paddingLeft="25dp"
     android:paddingRight="25dp"
     android:paddingTop="25dp"
-    android:paddingBottom="64dp"
+    android:paddingBottom="@dimen/kg_widget_pager_bottom_padding"
     android:clipChildren="false"
     android:clipToPadding="false"
     androidprv:pageSpacing="10dp">
diff --git a/core/res/res/layout/keyguard_pin_view.xml b/core/res/res/layout/keyguard_pin_view.xml
index 19e0a27..2529196 100644
--- a/core/res/res/layout/keyguard_pin_view.xml
+++ b/core/res/res/layout/keyguard_pin_view.xml
@@ -59,6 +59,7 @@
             android:paddingLeft="24dp"
             android:paddingRight="24dp"
             android:background="?android:attr/selectableItemBackground"
+            android:contentDescription="@string/keyboardview_keycode_delete"
             />
     </LinearLayout>
     <View
@@ -196,6 +197,7 @@
             android:layout_height="match_parent"
             android:layout_weight="1"
             android:src="@drawable/sym_keyboard_return_holo"
+            android:contentDescription="@string/keyboardview_keycode_enter"
             />
     </LinearLayout>
 
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index 07f62ed..36f2628 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -50,4 +50,10 @@
     <!-- Space reserved at the bottom of secure views (pin/pattern/password/SIM pin/SIM puk) -->
     <dimen name="kg_secure_padding_height">0dp</dimen>
 
+    <!-- Top padding for the widget pager -->
+    <dimen name="kg_widget_pager_top_padding">0dp</dimen>
+
+    <!-- Bottom padding for the widget pager -->
+    <dimen name="kg_widget_pager_bottom_padding">0dp</dimen>
+
 </resources>
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 0d01df4..52c230b 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -98,10 +98,10 @@
     <dimen name="kg_widget_pager_horizontal_padding">24dp</dimen>
 
     <!-- Top padding for the widget pager -->
-    <dimen name="kg_widget_pager_top_padding">24dp</dimen>
+    <dimen name="kg_widget_pager_top_padding">0dp</dimen>
 
     <!-- Bottom padding for the widget pager -->
-    <dimen name="kg_widget_pager_bottom_padding">16dp</dimen>
+    <dimen name="kg_widget_pager_bottom_padding">0dp</dimen>
 
     <!-- Top margin for the runway lights. We add a negative margin in large
         devices to account for the widget pager padding -->
diff --git a/core/res/res/values-sw720dp/dimens.xml b/core/res/res/values-sw720dp/dimens.xml
index ffb4e11..ccdb4be 100644
--- a/core/res/res/values-sw720dp/dimens.xml
+++ b/core/res/res/values-sw720dp/dimens.xml
@@ -91,10 +91,10 @@
     <dimen name="kg_widget_pager_horizontal_padding">80dp</dimen>
 
     <!-- Top padding for the widget pager -->
-    <dimen name="kg_widget_pager_top_padding">32dp</dimen>
+    <dimen name="kg_widget_pager_top_padding">0dp</dimen>
 
     <!-- Bottom padding for the widget pager -->
-    <dimen name="kg_widget_pager_bottom_padding">36dp</dimen>
+    <dimen name="kg_widget_pager_bottom_padding">0dp</dimen>
 
     <!-- Top margin for the runway lights. We add a negative margin in large
         devices to account for the widget pager padding -->
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index c0b2b1f..4966b97 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -294,7 +294,7 @@
     <dimen name="kg_widget_pager_top_padding">0dp</dimen>
 
     <!-- Bottom padding for the widget pager -->
-    <dimen name="kg_widget_pager_bottom_padding">0dp</dimen>
+    <dimen name="kg_widget_pager_bottom_padding">64dp</dimen>
 
     <!-- Top margin for the runway lights. We add a negative margin in large
         devices to account for the widget pager padding -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8f41a7a..51d6429 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2285,8 +2285,6 @@
     <string name="keyguard_accessibility_add_widget">Add widget.</string>
     <!-- Accessibility description of the empty sidget slot (place holder for a new widget). [CHAR_LIMIT=none] -->
     <string name="keyguard_accessibility_widget_empty_slot">Empty</string>
-    <!-- Accessibility description of the unlock area. [CHAR_LIMIT=none] -->
-    <string name="keyguard_accessibility_unlock_area">Unlock area.</string>
     <!-- Accessibility description of the event of expanding an unlock area. [CHAR_LIMIT=none] -->
     <string name="keyguard_accessibility_unlock_area_expanded">Unlock area expanded.</string>
     <!-- Accessibility description of the event of collapsing an unlock area. [CHAR_LIMIT=none] -->
@@ -2309,6 +2307,20 @@
     <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>
+    <!-- Accessibility description of the slide unlock. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_slide_unlock">Slide unlock.</string>
+    <!-- Accessibility description of the pattern unlock. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_pattern_unlock">Pattern unlock.</string>
+    <!-- Accessibility description of the face unlock. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_face_unlock">Face unlock.</string>
+    <!-- Accessibility description of the pin lock. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_pin_unlock">Pin unlock.</string>
+    <!-- Accessibility description of the password lock. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_password_unlock">Password unlock.</string>
+    <!-- Accessibility description of the unlock pattern area. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_pattern_area">Pattern area.</string>
+    <!-- Accessibility description of the unlock slide area. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_slide_area">Slide 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/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 8374b10..0623a9e 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -1191,6 +1191,11 @@
                 return;
             }
 
+            if (mRadius > 0 || mRadiusArray != null) {
+                mOpaque = false;
+                return;
+            }
+
             if (mStrokeWidth > 0 && !isOpaque(mStrokeColor)) {
                 mOpaque = false;
                 return;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 17256cf..de028a4 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2965,10 +2965,11 @@
             boolean applyWindow = attrs.type >= FIRST_APPLICATION_WINDOW
                     && attrs.type <= LAST_APPLICATION_WINDOW;
             if (attrs.type == TYPE_DREAM) {
-                mShowingDream = true;
-                if (!mDreamingLockscreen) {
-                    applyWindow = true;
-                } else if (win.isVisibleLw() && win.hasDrawnLw()) {
+                // If the lockscreen was showing when the dream started then wait
+                // for the dream to draw before hiding the lockscreen.
+                if (!mDreamingLockscreen
+                        || (win.isVisibleLw() && win.hasDrawnLw())) {
+                    mShowingDream = true;
                     applyWindow = true;
                 }
             }
@@ -3008,8 +3009,10 @@
                 ? mTopFullscreenOpaqueWindowState.getAttrs()
                 : null;
 
-        // If we are not currently showing a dream, then update the lockscreen
-        // state that will apply if a dream is shown next time.
+        // If we are not currently showing a dream then remember the current
+        // lockscreen state.  We will use this to determine whether the dream
+        // started while the lockscreen was showing and remember this state
+        // while the dream is showing.
         if (!mShowingDream) {
             mDreamingLockscreen = mShowingLockscreen;
         }
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java
index eabf5e0..db36bcc 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java
@@ -98,6 +98,9 @@
         mPasswordEntry.setOnEditorActionListener(this);
         mPasswordEntry.addTextChangedListener(this);
 
+        // Set selected property on so the view can send accessibility events.
+        mPasswordEntry.setSelected(true);
+
         // Poke the wakelock any time the text is selected or modified
         mPasswordEntry.setOnClickListener(new OnClickListener() {
             public void onClick(View v) {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java
index 8522401..1255712 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java
@@ -64,6 +64,7 @@
                     verifyPasswordAndUnlock();
                 }
             });
+            ok.setOnHoverListener(new NumPadKey.LiftToActivateListener(getContext()));
         }
 
         // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java b/policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java
index 060cc03..ca36007 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java
@@ -22,7 +22,9 @@
 import android.text.style.TextAppearanceSpan;
 import android.util.AttributeSet;
 import android.view.HapticFeedbackConstants;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.Button;
 import android.widget.TextView;
 
@@ -72,6 +74,7 @@
         setTextViewResId(a.getResourceId(R.styleable.NumPadKey_textView, 0));
 
         setOnClickListener(mListener);
+        setOnHoverListener(new LiftToActivateListener(context));
 
         mEnableHaptics = new LockPatternUtils(context).isTactileFeedbackEnabled();
 
@@ -113,4 +116,45 @@
                     | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
         }
     }
+
+    /**
+     * Hover listener that implements lift-to-activate interaction for
+     * accessibility. May be added to multiple views.
+     */
+    static class LiftToActivateListener implements View.OnHoverListener {
+        /** Manager used to query accessibility enabled state. */
+        private final AccessibilityManager mAccessibilityManager;
+
+        public LiftToActivateListener(Context context) {
+            mAccessibilityManager = (AccessibilityManager) context.getSystemService(
+                    Context.ACCESSIBILITY_SERVICE);
+        }
+
+        @Override
+        public boolean onHover(View v, MotionEvent event) {
+            // When touch exploration is turned on, lifting a finger while
+            // inside the view bounds should perform a click action.
+            if (mAccessibilityManager.isEnabled()
+                    && mAccessibilityManager.isTouchExplorationEnabled()) {
+                switch (event.getActionMasked()) {
+                    case MotionEvent.ACTION_HOVER_ENTER:
+                        // Lift-to-type temporarily disables double-tap
+                        // activation.
+                        v.setClickable(false);
+                        break;
+                    case MotionEvent.ACTION_HOVER_EXIT:
+                        final int x = (int) event.getX();
+                        final int y = (int) event.getY();
+                        if ((x > v.getPaddingLeft()) && (y > v.getPaddingTop())
+                                && (x < v.getWidth() - v.getPaddingRight())
+                                && (y < v.getHeight() - v.getPaddingBottom())) {
+                            v.performClick();
+                        }
+                        v.setClickable(true);
+                        break;
+                }
+            }
+            return false;
+        }
+    }
 }
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 7cf995c..2e735a0 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
@@ -20,6 +20,7 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.content.Context;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -247,12 +248,12 @@
         mMinVelocity = vc.getScaledMinimumFlingVelocity();
         mMaxVelocity = vc.getScaledMaximumFlingVelocity();
 
-        mDragHandleEdgeSlop = getResources().getDimensionPixelSize(
-                R.dimen.kg_edge_swipe_region_size);
+        final Resources res = getResources();
+        mDragHandleEdgeSlop = res.getDimensionPixelSize(R.dimen.kg_edge_swipe_region_size);
 
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
 
-        final float density = getResources().getDisplayMetrics().density;
+        final float density = res.getDisplayMetrics().density;
 
         // top half of the lock icon, plus another 25% to be sure
         mDragHandleClosedAbove = (int) (DRAG_HANDLE_CLOSED_ABOVE * density + 0.5f);
@@ -261,7 +262,7 @@
         mDragHandleOpenBelow = (int) (DRAG_HANDLE_OPEN_BELOW * density + 0.5f);
 
         // how much space to account for in the handle when closed
-        mChallengeBottomBound = mDragHandleClosedBelow;
+        mChallengeBottomBound = res.getDimensionPixelSize(R.dimen.kg_widget_pager_bottom_padding);
 
         setWillNotDraw(false);
     }
@@ -535,6 +536,11 @@
         return expanded && mHasGlowpad ? 0 : mDragHandleEdgeSlop;
     }
 
+    private float getChallengeAlpha() {
+        float x = mChallengeOffset - 1;
+        return x * x * x + 1.f;
+    }
+
     @Override
     public void requestDisallowInterceptTouchEvent(boolean allowIntercept) {
         // We'll intercept whoever we feel like! ...as long as it isn't a challenge view.
@@ -570,7 +576,8 @@
 
                     if (!mIsBouncing &&
                             (isInDragHandle(x, y) || crossedDragHandle(x, y, mGestureStartY) ||
-                            (isInChallengeView(x, y) && mScrollState == SCROLL_STATE_SETTLING)) &&
+                            (isInChallengeView(x, y) &&
+                                (mScrollState == SCROLL_STATE_SETTLING || !mChallengeShowing))) &&
                             mActivePointerId == INVALID_POINTER) {
                         mActivePointerId = ev.getPointerId(i);
                         mGestureStartX = x;
@@ -860,7 +867,7 @@
                 // we never want less than the handle size showing at the bottom.
                 final int bottom = layoutBottom + (int) ((childHeight - mChallengeBottomBound)
                         * (1 - mChallengeOffset));
-                child.setAlpha(mChallengeOffset / 2 + 0.5f);
+                child.setAlpha(getChallengeAlpha());
                 child.layout(left, bottom - childHeight, left + childWidth, bottom);
             } else {
                 // Non-challenge views lay out from the upper left, layered.
@@ -938,7 +945,7 @@
             }
 
             if (mDragIconDrawable != null) {
-                final int closedTop = getLayoutBottom() - mChallengeBottomBound;
+                final int closedTop = getLayoutBottom() - mDragHandleClosedBelow;
                 final int iconWidth = mDragIconDrawable.getIntrinsicWidth();
                 final int iconHeight = mDragIconDrawable.getIntrinsicHeight();
                 final int iconLeft = (challengeLeft + challengeRight - iconWidth) / 2;
@@ -996,7 +1003,7 @@
         mChallengeView.layout(mChallengeView.getLeft(),
                 bottom - mChallengeView.getHeight(), mChallengeView.getRight(), bottom);
 
-        mChallengeView.setAlpha(offset / 2 + 0.5f);
+        mChallengeView.setAlpha(getChallengeAlpha());
         if (mScrollListener != null) {
             mScrollListener.onScrollPositionChanged(offset, mChallengeView.getTop());
         }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 3532c0c..7958f9a 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -2773,7 +2773,7 @@
                     // TODO: Remove once b/7094175 is fixed
                     || ((String)win.mAttrs.getTitle()).contains("Keyguard")
                 ) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
-                    + " " + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
+                    + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
 
             win.mEnforceSizeCompat = (win.mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
 
@@ -3003,6 +3003,10 @@
             }
 
             mInputMonitor.updateInputWindowsLw(true /*force*/);
+
+            if (DEBUG_LAYOUT) {
+                Slog.v(TAG, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
+            }
         }
 
         if (configChanged) {
@@ -8379,7 +8383,8 @@
             // windows, since that means "perform layout as normal,
             // just don't display").
             if (!gone || !win.mHaveFrame || win.mLayoutNeeded
-                    || (win.mAttrs.type == TYPE_KEYGUARD && win.isConfigChanged())
+                    || ((win.mAttrs.type == TYPE_KEYGUARD || win.mAttrs.type == TYPE_WALLPAPER) &&
+                        win.isConfigChanged())
                     || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
                 if (!win.mLayoutAttached) {
                     if (initial) {
@@ -9301,6 +9306,8 @@
             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
         } finally {
             Surface.closeTransaction();
+            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
         }
 
         final WindowList defaultWindows = defaultDisplay.getWindowList();