Merge "Removing callbacks in onDetachedFromWindow, fixes b/7465673" into jb-mr1-lockscreen-dev
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index f3c6566..bcb35d5 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -28,6 +28,8 @@
 import android.os.RemoteException;
 import android.os.Parcelable;
 import android.os.Build;
+import android.os.Process;
+import android.os.UserHandle;
 import android.util.Log;
 import android.text.TextUtils;
 
@@ -42,7 +44,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
 /**
@@ -396,8 +397,13 @@
      *     (never null) if no accounts of the specified type have been added.
      */
     public Account[] getAccountsByType(String type) {
+        return getAccountsByTypeAsUser(type, Process.myUserHandle());
+    }
+
+    /** @hide Same as {@link #getAccountsByType(String)} but for a specific user. */
+    public Account[] getAccountsByTypeAsUser(String type, UserHandle userHandle) {
         try {
-            return mService.getAccounts(type);
+            return mService.getAccountsAsUser(type, userHandle.getIdentifier());
         } catch (RemoteException e) {
             // won't ever happen
             throw new RuntimeException(e);
@@ -1175,10 +1181,26 @@
             final Activity activity,
             final AccountManagerCallback<Bundle> callback,
             final Handler handler) {
+        return confirmCredentialsAsUser(account, options, activity, callback, handler,
+                Process.myUserHandle());
+    }
+
+    /**
+     * @hide
+     * Same as {@link #confirmCredentials(Account, Bundle, Activity, AccountManagerCallback, Handler)}
+     * but for the specified user.
+     */
+    public AccountManagerFuture<Bundle> confirmCredentialsAsUser(final Account account,
+            final Bundle options,
+            final Activity activity,
+            final AccountManagerCallback<Bundle> callback,
+            final Handler handler, UserHandle userHandle) {
         if (account == null) throw new IllegalArgumentException("account is null");
+        final int userId = userHandle.getIdentifier();
         return new AmsTask(activity, handler, callback) {
             public void doWork() throws RemoteException {
-                mService.confirmCredentials(mResponse, account, options, activity != null);
+                mService.confirmCredentialsAsUser(mResponse, account, options, activity != null,
+                        userId);
             }
         }.start();
     }
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 03e0c0f..2b1a2b2 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -1297,8 +1297,17 @@
         }
     }
 
-    public void confirmCredentials(IAccountManagerResponse response,
-            final Account account, final Bundle options, final boolean expectActivityLaunch) {
+    @Override
+    public void confirmCredentialsAsUser(IAccountManagerResponse response,
+            final Account account, final Bundle options, final boolean expectActivityLaunch,
+            int userId) {
+        // Only allow the system process to read accounts of other users
+        if (userId != UserHandle.getCallingUserId()
+                && Binder.getCallingUid() != android.os.Process.myUid()) {
+            throw new SecurityException("User " + UserHandle.getCallingUserId()
+                    + " trying to confirm account credentials for " + userId);
+        }
+
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "confirmCredentials: " + account
                     + ", response " + response
@@ -1309,7 +1318,7 @@
         if (response == null) throw new IllegalArgumentException("response is null");
         if (account == null) throw new IllegalArgumentException("account is null");
         checkManageAccountsPermission();
-        UserAccounts accounts = getUserAccountsForCaller();
+        UserAccounts accounts = getUserAccounts(userId);
         long identityToken = clearCallingIdentity();
         try {
             new Session(accounts, response, account.type, expectActivityLaunch,
@@ -1548,14 +1557,22 @@
         return runningAccounts.toArray(accountsArray);
     }
 
-    public Account[] getAccounts(String type) {
+    @Override
+    public Account[] getAccountsAsUser(String type, int userId) {
+        // Only allow the system process to read accounts of other users
+        if (userId != UserHandle.getCallingUserId()
+                && Binder.getCallingUid() != android.os.Process.myUid()) {
+            throw new SecurityException("User " + UserHandle.getCallingUserId()
+                    + " trying to get account for " + userId);
+        }
+
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "getAccounts: accountType " + type
                     + ", caller's uid " + Binder.getCallingUid()
                     + ", pid " + Binder.getCallingPid());
         }
         checkReadAccountsPermission();
-        UserAccounts accounts = getUserAccountsForCaller();
+        UserAccounts accounts = getUserAccounts(userId);
         long identityToken = clearCallingIdentity();
         try {
             synchronized (accounts.cacheLock) {
@@ -1566,6 +1583,11 @@
         }
     }
 
+    @Override
+    public Account[] getAccounts(String type) {
+        return getAccountsAsUser(type, UserHandle.getCallingUserId());
+    }
+
     public void getAccountsByFeatures(IAccountManagerResponse response,
             String type, String[] features) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index 6007321..dbb4924 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -31,6 +31,7 @@
     String getUserData(in Account account, String key);
     AuthenticatorDescription[] getAuthenticatorTypes();
     Account[] getAccounts(String accountType);
+    Account[] getAccountsAsUser(String accountType, int userId);
     void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features);
     void getAccountsByFeatures(in IAccountManagerResponse response, String accountType, in String[] features);
     boolean addAccount(in Account account, String password, in Bundle extras);
@@ -53,8 +54,8 @@
         String authTokenType, boolean expectActivityLaunch, in Bundle options);
     void editProperties(in IAccountManagerResponse response, String accountType,
         boolean expectActivityLaunch);
-    void confirmCredentials(in IAccountManagerResponse response, in Account account,
-        in Bundle options, boolean expectActivityLaunch);
+    void confirmCredentialsAsUser(in IAccountManagerResponse response, in Account account,
+        in Bundle options, boolean expectActivityLaunch, int userId);
     void getAuthTokenLabel(in IAccountManagerResponse response, String accountType,
         String authTokenType);
 }
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 8d83774..8d1be53 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -351,12 +351,12 @@
                     public void onClick(View v) {
                         // Insure that this view is a child of an AdapterView
                         View parent = (View) v.getParent();
-                        while (!(parent instanceof AdapterView<?>)
+                        while (parent != null && !(parent instanceof AdapterView<?>)
                                 && !(parent instanceof AppWidgetHostView)) {
                             parent = (View) parent.getParent();
                         }
 
-                        if (parent instanceof AppWidgetHostView) {
+                        if (parent instanceof AppWidgetHostView || parent == null) {
                             // Somehow they've managed to get this far without having
                             // and AdapterView as a parent.
                             Log.e("RemoteViews", "Collection item doesn't have AdapterView parent");
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
index 3ce61d9..d552b35 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
@@ -27,6 +27,7 @@
 import android.content.Intent;
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.text.Editable;
 import android.text.InputFilter;
 import android.text.LoginFilter;
@@ -175,7 +176,8 @@
                     Intent intent = new Intent();
                     intent.setClassName(LOCK_PATTERN_PACKAGE, LOCK_PATTERN_CLASS);
                     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                    mContext.startActivity(intent);
+                    mContext.startActivityAsUser(intent,
+                            new UserHandle(mLockPatternUtils.getCurrentUser()));
                     mCallback.reportSuccessfulUnlockAttempt();
 
                     // dismiss keyguard
@@ -220,7 +222,8 @@
      * find a single best match.
      */
     private Account findIntendedAccount(String username) {
-        Account[] accounts = AccountManager.get(mContext).getAccountsByType("com.google");
+        Account[] accounts = AccountManager.get(mContext).getAccountsByTypeAsUser("com.google",
+                new UserHandle(mLockPatternUtils.getCurrentUser()));
 
         // Try to figure out which account they meant if they
         // typed only the username (and not the domain), or got
@@ -267,7 +270,7 @@
         getProgressDialog().show();
         Bundle options = new Bundle();
         options.putString(AccountManager.KEY_PASSWORD, password);
-        AccountManager.get(mContext).confirmCredentials(account, options, null /* activity */,
+        AccountManager.get(mContext).confirmCredentialsAsUser(account, options, null /* activity */,
                 new AccountManagerCallback<Bundle>() {
             public void run(AccountManagerFuture<Bundle> future) {
                 try {
@@ -289,7 +292,7 @@
                     });
                 }
             }
-        }, null /* handler */);
+        }, null /* handler */, new UserHandle(mLockPatternUtils.getCurrentUser()));
     }
 
     private Dialog getProgressDialog() {
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 fabab75..51407fe 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java
@@ -19,6 +19,8 @@
 import android.app.ActivityManagerNative;
 import android.app.ActivityOptions;
 import android.app.IActivityManager.WaitResult;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
@@ -112,6 +114,27 @@
         }
     }
 
+    public void launchWidgetPicker(int appWidgetId) {
+        Intent pickIntent = new Intent(AppWidgetManager.ACTION_KEYGUARD_APPWIDGET_PICK);
+
+        pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+        pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_SORT, false);
+        pickIntent.putExtra(AppWidgetManager.EXTRA_CATEGORY_FILTER,
+                AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
+
+        Bundle options = new Bundle();
+        options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
+                AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
+        pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
+        pickIntent.addFlags(
+                Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_SINGLE_TOP
+                | Intent.FLAG_ACTIVITY_CLEAR_TOP
+                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+
+        launchActivity(pickIntent, false, false, null, null);
+    }
+
     /**
      * Launches the said intent for the current foreground user.
      *
@@ -128,7 +151,8 @@
             final Handler worker,
             final Runnable onStarted) {
         final Context context = getContext();
-        final Bundle animation = ActivityOptions.makeCustomAnimation(context, 0, 0).toBundle();
+        final Bundle animation = useDefaultAnimations ? null
+                : ActivityOptions.makeCustomAnimation(context, 0, 0).toBundle();
         LockPatternUtils lockPatternUtils = getLockPatternUtils();
         intent.addFlags(
                 Intent.FLAG_ACTIVITY_NEW_TASK
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 11e600e..7d84a45 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -33,12 +33,10 @@
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Rect;
-import android.os.Bundle;
 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;
 import android.util.Log;
@@ -84,6 +82,9 @@
     private KeyguardSecurityModel mSecurityModel;
     private KeyguardViewStateManager mViewStateManager;
 
+    int mLocalStickyWidget = -1;
+    boolean mPersitentStickyWidgetLoaded = false;
+
     private Rect mTempRect = new Rect();
 
     /*package*/ interface TransportCallback {
@@ -111,7 +112,7 @@
         mAppWidgetManager = AppWidgetManager.getInstance(mContext);
         mSecurityModel = new KeyguardSecurityModel(context);
 
-        mViewStateManager = new KeyguardViewStateManager();
+        mViewStateManager = new KeyguardViewStateManager(this);
     }
 
     @Override
@@ -898,14 +899,12 @@
         addWidgetButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                mCallback.setOnDismissRunnable(new Runnable() {
-
-                    @Override
-                    public void run() {
-                        launchPickActivityIntent();
-                    }
-                });
-                mCallback.dismiss(false);
+                int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
+                if (appWidgetId != -1) {
+                    mActivityLauncher.launchWidgetPicker(appWidgetId);
+                } else {
+                    Log.e(TAG, "Unable to allocate an AppWidget id in lock screen");
+                }
             }
         });
 
@@ -913,33 +912,6 @@
         initializeTransportControl();
     }
 
-    private void launchPickActivityIntent() {
-        // Create intent to pick widget
-        Intent pickIntent = new Intent(AppWidgetManager.ACTION_KEYGUARD_APPWIDGET_PICK);
-
-        int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
-        if (appWidgetId != -1) {
-            pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
-            pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_SORT, false);
-            pickIntent.putExtra(AppWidgetManager.EXTRA_CATEGORY_FILTER,
-                    AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
-
-            Bundle options = new Bundle();
-            options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
-                    AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
-            pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
-            pickIntent.addFlags(
-                    Intent.FLAG_ACTIVITY_NEW_TASK
-                    | Intent.FLAG_ACTIVITY_SINGLE_TOP
-                    | Intent.FLAG_ACTIVITY_CLEAR_TOP
-                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-            mContext.startActivityAsUser(pickIntent,
-                    new UserHandle(UserHandle.USER_CURRENT));
-        } else {
-            Log.e(TAG, "Unable to allocate an AppWidget id in lock screen");
-        }
-    }
-
     private void removeTransportFromWidgetPager() {
         int page = getWidgetPosition(R.id.keyguard_transport_control);
         if (page != -1) {
@@ -1200,6 +1172,37 @@
         return v != null && v.getId() == R.id.keyguard_add_widget;
     }
 
+    private boolean isMusicPage(int pageIndex) {
+        return pageIndex >= 0 && pageIndex == getWidgetPosition(R.id.keyguard_transport_control);
+    }
+
+    private int getStickyWidget() {
+        // The first time we query the persistent state. From that point, we use a locally updated
+        // notion of the sticky widget page.
+        if (!mPersitentStickyWidgetLoaded) {
+            mLocalStickyWidget = mLockPatternUtils.getStickyAppWidgetIndex();
+            mPersitentStickyWidgetLoaded = true;
+        }
+        return mLocalStickyWidget;
+    }
+
+    public void updateStickyWidget(int index) {
+        if (index < 0 || index >= mAppWidgetContainer.getChildCount()) {
+            return;
+        }
+        if (isAddPage(index)) {
+            return;
+        }
+        if (isCameraPage(index)) {
+            return;
+        }
+        if (isMusicPage(index)) {
+            return;
+        }
+
+        mLocalStickyWidget = index;
+    }
+
     private int getAppropriateWidgetPage(boolean isMusicPlaying) {
         // assumes at least one widget (besides camera + add)
 
@@ -1210,7 +1213,7 @@
         }
 
         // if we have a valid sticky widget, show it
-        int stickyWidgetIndex = mLockPatternUtils.getStickyAppWidgetIndex();
+        int stickyWidgetIndex = getStickyWidget();
         if (stickyWidgetIndex > -1
                 && stickyWidgetIndex < mAppWidgetContainer.getChildCount()
                 && !isAddPage(stickyWidgetIndex)
@@ -1229,18 +1232,10 @@
     }
 
     private void saveStickyWidgetIndex() {
-        int stickyWidgetIndex = mAppWidgetContainer.getCurrentPage();
-        if (isAddPage(stickyWidgetIndex)) {
-            stickyWidgetIndex++;
+        if (DEBUG) Log.d(TAG, "saveStickyWidgetIndex: " + mLocalStickyWidget);
+        if (mPersitentStickyWidgetLoaded && mLocalStickyWidget >= 0) {
+            mLockPatternUtils.setStickyAppWidgetIndex(mLocalStickyWidget);
         }
-        if (isCameraPage(stickyWidgetIndex)) {
-            stickyWidgetIndex--;
-        }
-        if (stickyWidgetIndex < 0 || stickyWidgetIndex >= mAppWidgetContainer.getChildCount()) {
-            stickyWidgetIndex = -1;
-        }
-        if (DEBUG) Log.d(TAG, "saveStickyWidgetIndex: " + stickyWidgetIndex);
-        mLockPatternUtils.setStickyAppWidgetIndex(stickyWidgetIndex);
     }
 
     private void enableUserSelectorIfNecessary() {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java
index 3a82687..186d717 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java
@@ -27,6 +27,7 @@
 import android.os.Bundle;
 import android.os.CountDownTimer;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.MotionEvent;
@@ -295,7 +296,8 @@
 
         private AccountAnalyzer(AccountManager accountManager) {
             mAccountManager = accountManager;
-            mAccounts = accountManager.getAccountsByType("com.google");
+            mAccounts = accountManager.getAccountsByTypeAsUser("com.google",
+                    new UserHandle(mLockPatternUtils.getCurrentUser()));
         }
 
         private void next() {
@@ -306,7 +308,8 @@
             }
 
             // lookup the confirmCredentials intent for the current account
-            mAccountManager.confirmCredentials(mAccounts[mAccountIndex], null, null, this, null);
+            mAccountManager.confirmCredentialsAsUser(mAccounts[mAccountIndex], null, null, this,
+                    null, new UserHandle(mLockPatternUtils.getCurrentUser()));
         }
 
         public void start() {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewFlipper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewFlipper.java
index 3d4cb19..c92c791 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewFlipper.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewFlipper.java
@@ -128,22 +128,24 @@
 
     @Override
     public void showBouncer(int duration) {
+        KeyguardSecurityView active = getSecurityView();
         for (int i = 0; i < getChildCount(); i++) {
             View child = getChildAt(i);
             if (child instanceof KeyguardSecurityView) {
                 KeyguardSecurityView ksv = (KeyguardSecurityView) child;
-                ksv.showBouncer(child.getVisibility() == View.VISIBLE ? duration : 0);
+                ksv.showBouncer(ksv == active ? duration : 0);
             }
         }
     }
 
     @Override
     public void hideBouncer(int duration) {
+        KeyguardSecurityView active = getSecurityView();
         for (int i = 0; i < getChildCount(); i++) {
             View child = getChildAt(i);
             if (child instanceof KeyguardSecurityView) {
                 KeyguardSecurityView ksv = (KeyguardSecurityView) child;
-                ksv.hideBouncer(child.getVisibility() == View.VISIBLE ? duration : 0);
+                ksv.hideBouncer(ksv == active ? duration : 0);
             }
         }
     }
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewHelper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewHelper.java
index 2ccdc1d..294bc3d 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewHelper.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewHelper.java
@@ -42,7 +42,7 @@
         }
         if (bouncerFrame != null) {
             if (duration > 0) {
-                Animator anim = ObjectAnimator.ofInt(bouncerFrame, "alpha", 255);
+                Animator anim = ObjectAnimator.ofInt(bouncerFrame, "alpha", 0, 255);
                 anim.setDuration(duration);
                 anim.start();
             } else {
@@ -67,7 +67,7 @@
         }
         if (bouncerFrame != null) {
             if (duration > 0) {
-                Animator anim = ObjectAnimator.ofInt(bouncerFrame, "alpha", 0);
+                Animator anim = ObjectAnimator.ofInt(bouncerFrame, "alpha", 255, 0);
                 anim.setDuration(duration);
                 anim.start();
             } else {
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 e53358b..922ced2 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java
@@ -25,6 +25,7 @@
 
     private KeyguardWidgetPager mKeyguardWidgetPager;
     private ChallengeLayout mChallengeLayout;
+    private KeyguardHostView mKeyguardHostView;
     private int[] mTmpPoint = new int[2];
     private int[] mTmpLoc = new int[2];
 
@@ -49,7 +50,8 @@
 
     int mChallengeTop = 0;
 
-    public KeyguardViewStateManager() {
+    public KeyguardViewStateManager(KeyguardHostView hostView) {
+        mKeyguardHostView = hostView;
     }
 
     public void setPagedView(KeyguardWidgetPager pagedView) {
@@ -145,6 +147,10 @@
         // We only modify the page state if it is not currently under control by the slider.
         // This prevents conflicts.
 
+        if (mKeyguardHostView != null) {
+            mKeyguardHostView.updateStickyWidget(newPageIndex);
+        }
+
         // If the page hasn't switched, don't bother with any of this
         if (mCurrentPage == newPageIndex) return;
 
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 16ec8c5..8df3675 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
@@ -26,8 +26,6 @@
 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.DisplayMetrics;
 import android.util.FloatProperty;
@@ -62,7 +60,6 @@
 
     // Drawn to show the drag handle in closed state; crossfades to the challenge view
     // when challenge is fully visible
-    private Drawable mFrameDrawable;
     private boolean mEdgeCaptured;
 
     private DisplayMetrics mDisplayMetrics;
@@ -76,6 +73,7 @@
     // Range: 0 (fully hidden) to 1 (fully visible)
     private float mChallengeOffset = 1.f;
     private boolean mChallengeShowing = true;
+    private boolean mWasChallengeShowing = true;
     private boolean mIsBouncing = false;
 
     private final Scroller mScroller;
@@ -127,8 +125,6 @@
     private ObjectAnimator mHandleAnimation;
     private ObjectAnimator mFrameAnimation;
 
-    private final Rect mTempRect = new Rect();
-
     private boolean mHasGlowpad;
 
     // We have an internal and external version, and we and them together.
@@ -149,23 +145,6 @@
         }
     };
 
-    static final Property<SlidingChallengeLayout, Float> FRAME_ALPHA =
-            new FloatProperty<SlidingChallengeLayout>("frameAlpha") {
-        @Override
-        public void setValue(SlidingChallengeLayout view, float value) {
-            if (view.mFrameDrawable != null) {
-                view.mFrameAlpha = value;
-                view.mFrameDrawable.setAlpha((int) (value * 0xFF));
-                view.mFrameDrawable.invalidateSelf();
-            }
-        }
-
-        @Override
-        public Float get(SlidingChallengeLayout view) {
-            return view.mFrameAlpha;
-        }
-    };
-
     // True if at least one layout pass has happened since the view was attached.
     private boolean mHasLayout;
 
@@ -310,46 +289,6 @@
         mHandleAnimation.start();
     }
 
-    void animateFrame(final boolean visible, final boolean full) {
-        if (mFrameDrawable == null) return;
-
-        final float targetAlpha = visible ? (full ? 1.f : 0.5f) : 0.f;
-        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();
-    }
-
     private void sendInitialListenerUpdates() {
         if (mScrollListener != null) {
             int challengeTop = mChallengeView != null ? mChallengeView.getTop() : 0;
@@ -409,9 +348,6 @@
             mScrollState = state;
 
             animateHandle(state == SCROLL_STATE_IDLE && !mChallengeShowing);
-            if (!mIsBouncing) {
-                animateFrame(false, false);
-            }
             if (mScrollListener != null) {
                 mScrollListener.onScrollStateChanged(state);
             }
@@ -532,8 +468,9 @@
     @Override
     public void showBouncer() {
         if (mIsBouncing) return;
-        mIsBouncing = true;
+        mWasChallengeShowing = mChallengeShowing;
         showChallenge(true);
+        mIsBouncing = true;
         if (mScrimView != null) {
             mScrimView.setVisibility(VISIBLE);
         }
@@ -543,18 +480,11 @@
         // 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);
         }
@@ -563,7 +493,7 @@
     @Override
     public void hideBouncer() {
         if (!mIsBouncing) return;
-        showChallenge(false);
+        if (!mWasChallengeShowing) showChallenge(false);
         mIsBouncing = false;
         if (mScrimView != null) {
             mScrimView.setVisibility(GONE);
@@ -571,7 +501,6 @@
         if (mChallengeView != null) {
             mChallengeView.hideBouncer(HANDLE_ANIMATE_DURATION);
         }
-        animateFrame(false, true);
         if (mBouncerListener != null) {
             mBouncerListener.onBouncerStateChanged(false);
         }
@@ -861,7 +790,6 @@
                     mChallengeView.setVisibility(mChallengeShowing ? VISIBLE : INVISIBLE);
                 }
                 // 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;
@@ -971,9 +899,6 @@
         }
 
         if (!mHasLayout) {
-            if (mFrameDrawable != null) {
-                mFrameDrawable.setAlpha(0);
-            }
             mHasLayout = true;
         }
     }