Remove user switcher callback when exiting user switcher mode

It was previously not possible to exit user switcher mode in the
bouncer. Now with SIM support on large screens, it is.

Fixes: 369996464
Test: atest KeyguardSecurityContainerTest
Flag: EXEMPT bugfix
Change-Id: I9bcd24d15b823591c11b2c568311f0a3a6478eec
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 94d3b2c..176824f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -61,6 +61,7 @@
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.res.R;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.UserSwitcherController.UserSwitchCallback;
 import com.android.systemui.user.data.source.UserRecord;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.settings.GlobalSettings;
@@ -70,6 +71,8 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
@@ -96,6 +99,9 @@
     private UserSwitcherController mUserSwitcherController;
     @Mock
     private FalsingA11yDelegate mFalsingA11yDelegate;
+    @Captor
+    private ArgumentCaptor<UserSwitchCallback> mUserSwitchCallbackCaptor =
+            ArgumentCaptor.forClass(UserSwitchCallback.class);
 
     private KeyguardSecurityContainer mKeyguardSecurityContainer;
     private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
@@ -360,6 +366,18 @@
     }
 
     @Test
+    public void goingOutOfUserSwitcherRemovesCallback() {
+        // WHEN UserSwitcherViewMode is initialized
+        setupUserSwitcher();
+        verify(mUserSwitcherController).addUserSwitchCallback(mUserSwitchCallbackCaptor.capture());
+
+        // Back to default mode, as SIM PIN would be
+        initMode(MODE_DEFAULT);
+        verify(mUserSwitcherController).removeUserSwitchCallback(
+                mUserSwitchCallbackCaptor.getValue());
+    }
+
+    @Test
     public void testOnDensityOrFontScaleChanged() {
         setupUserSwitcher();
         View oldUserSwitcher = mKeyguardSecurityContainer.findViewById(
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index f05cbf4..2d27f1c0 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -1067,6 +1067,8 @@
 
         @Override
         public void onDestroy() {
+            mUserSwitcherController.removeUserSwitchCallback(mUserSwitchCallback);
+
             ConstraintSet constraintSet = new ConstraintSet();
             constraintSet.clone(mView);
             constraintSet.clear(mUserSwitcherViewGroup.getId());
@@ -1075,6 +1077,8 @@
 
             mView.removeView(mUserSwitcherViewGroup);
             mView.removeView(mUserSwitcher);
+            mUserSwitcher = null;
+            mUserSwitcherViewGroup = null;
         }
 
         private void findLargeUserIcon(int userId, Consumer<Drawable> consumer) {
@@ -1102,6 +1106,10 @@
                 return;
             }
 
+            if (mUserSwitcherViewGroup == null) {
+                return;
+            }
+
             mUserSwitcherViewGroup.setAlpha(0f);
             ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
             int yTrans = mView.getResources().getDimensionPixelSize(R.dimen.pin_view_trans_y_entry);
@@ -1110,14 +1118,18 @@
             animator.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animation) {
-                    mUserSwitcherViewGroup.setAlpha(1f);
-                    mUserSwitcherViewGroup.setTranslationY(0f);
+                    if (mUserSwitcherViewGroup != null) {
+                        mUserSwitcherViewGroup.setAlpha(1f);
+                        mUserSwitcherViewGroup.setTranslationY(0f);
+                    }
                 }
             });
             animator.addUpdateListener(animation -> {
-                float value = (float) animation.getAnimatedValue();
-                mUserSwitcherViewGroup.setAlpha(value);
-                mUserSwitcherViewGroup.setTranslationY(yTrans - yTrans * value);
+                if (mUserSwitcherViewGroup != null) {
+                    float value = (float) animation.getAnimatedValue();
+                    mUserSwitcherViewGroup.setAlpha(value);
+                    mUserSwitcherViewGroup.setTranslationY(yTrans - yTrans * value);
+                }
             });
             animator.start();
         }
@@ -1148,6 +1160,10 @@
                 Log.e(TAG, "Current user in user switcher is null.");
                 return;
             }
+            if (mUserSwitcher == null) {
+                Log.w(TAG, "User switcher is not inflated, cannot setupUserSwitcher");
+                return;
+            }
             final String currentUserName = mUserSwitcherController.getCurrentUserName();
             findLargeUserIcon(currentUser.info.id,
                     (Drawable userIcon) -> {