diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java index b0a5533b0745a..ad6ca8582bf08 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java @@ -336,7 +336,7 @@ public class KeyguardHostViewController extends ViewController } public SecurityMode getCurrentSecurityMode() { - return mKeyguardSecurityContainerController.getCurrentSecuritySelection(); + return mKeyguardSecurityContainerController.getCurrentSecurityMode(); } public int getTop() { @@ -350,7 +350,7 @@ public class KeyguardHostViewController extends ViewController } public boolean handleBackKey() { - if (mKeyguardSecurityContainerController.getCurrentSecuritySelection() + if (mKeyguardSecurityContainerController.getCurrentSecurityMode() != SecurityMode.None) { mKeyguardSecurityContainerController.dismiss( false, KeyguardUpdateMonitor.getCurrentUser()); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java index b0b2cd8c74d97..83fcac6579f26 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java @@ -136,9 +136,9 @@ public class KeyguardInputViewController extends ViewController implements KeyguardSecurityView { @@ -70,13 +70,11 @@ public class KeyguardSecurityContainerController extends ViewController mChildren = new ArrayList<>(); private SecurityCallback mSecurityCallback; - private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid; - private KeyguardSecurityView mCurrentSecurityView; + private SecurityMode mCurrentSecurityMode = SecurityMode.Invalid; private KeyguardSecurityCallback mKeyguardSecurityCallback = new KeyguardSecurityCallback() { public void userActivity() { @@ -182,9 +180,7 @@ public class KeyguardSecurityContainerController extends ViewController implements KeyguardSecurityView { + + private static final boolean DEBUG = KeyguardConstants.DEBUG; + private static final String TAG = "KeyguardSecurityView"; + + private final List mChildren = new ArrayList<>(); + private final LayoutInflater mLayoutInflater; + private final Factory mKeyguardSecurityViewControllerFactory; + + @Inject + protected KeyguardSecurityViewFlipperController(KeyguardSecurityViewFlipper view, + LayoutInflater layoutInflater, + InjectionInflationController injectionInflationController, + KeyguardInputViewController.Factory keyguardSecurityViewControllerFactory) { + super(view); + mKeyguardSecurityViewControllerFactory = keyguardSecurityViewControllerFactory; + mLayoutInflater = injectionInflationController.injectable(layoutInflater); + } + + @Override + protected void onViewAttached() { + + } + + @Override + protected void onViewDetached() { + + } + + @Override + public void setKeyguardCallback(KeyguardSecurityCallback callback) { + mView.setKeyguardCallback(callback); + } + + @Override + public void setLockPatternUtils(LockPatternUtils utils) { + mView.setLockPatternUtils(utils); + } + + @Override + public void reset() { + mView.reset(); + } + + @Override + public void onPause() { + mView.onPause(); + } + + @Override + public void onResume(int reason) { + mView.onResume(reason); + } + + @Override + public boolean needsInput() { + return mView.needsInput(); + } + + @Override + public KeyguardSecurityCallback getCallback() { + return mView.getCallback(); + } + + @Override + public void showPromptReason(int reason) { + mView.showPromptReason(reason); + } + + @Override + public void showMessage(CharSequence message, ColorStateList colorState) { + mView.showMessage(message, colorState); + } + + @Override + public void showUsabilityHint() { + mView.showUsabilityHint(); + } + + @Override + public void startAppearAnimation() { + mView.startAppearAnimation(); + } + + @Override + public boolean startDisappearAnimation(Runnable finishRunnable) { + return mView.startDisappearAnimation(finishRunnable); + } + + @Override + public CharSequence getTitle() { + return mView.getTitle(); + } + + @VisibleForTesting + KeyguardInputViewController getSecurityView(SecurityMode securityMode, + KeyguardSecurityCallback keyguardSecurityCallback) { + KeyguardInputViewController childController = null; + for (KeyguardInputViewController mChild : mChildren) { + if (mChild.getSecurityMode() == securityMode) { + childController = mChild; + break; + } + } + + if (childController == null + && securityMode != SecurityMode.None && securityMode != SecurityMode.Invalid) { + + int layoutId = getLayoutIdFor(securityMode); + KeyguardInputView view = null; + if (layoutId != 0) { + if (DEBUG) Log.v(TAG, "inflating id = " + layoutId); + view = (KeyguardInputView) mLayoutInflater.inflate( + layoutId, mView, false); + mView.addView(view); + childController = mKeyguardSecurityViewControllerFactory.create( + view, securityMode, keyguardSecurityCallback); + + mChildren.add(childController); + } + } + + return childController; + } + + private int getLayoutIdFor(SecurityMode securityMode) { + switch (securityMode) { + case Pattern: return com.android.systemui.R.layout.keyguard_pattern_view; + case PIN: return com.android.systemui.R.layout.keyguard_pin_view; + case Password: return com.android.systemui.R.layout.keyguard_password_view; + case SimPin: return com.android.systemui.R.layout.keyguard_sim_pin_view; + case SimPuk: return R.layout.keyguard_sim_puk_view; + default: + return 0; + } + } + + /** Makes the supplied child visible if it is contained win this view, */ + public void show(KeyguardInputViewController childController) { + int index = childController.getIndexIn(mView); + if (index != -1) { + mView.setDisplayedChild(index); + } + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java index b6010c8915e7c..881108858b517 100644 --- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java +++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java @@ -22,6 +22,7 @@ import android.view.ViewGroup; import com.android.keyguard.KeyguardHostView; import com.android.keyguard.KeyguardMessageArea; import com.android.keyguard.KeyguardSecurityContainer; +import com.android.keyguard.KeyguardSecurityViewFlipper; import com.android.systemui.R; import com.android.systemui.statusbar.phone.KeyguardBouncer; @@ -58,7 +59,15 @@ public interface KeyguardBouncerModule { /** */ @Provides @KeyguardBouncerScope - static KeyguardSecurityContainer preovidesKeyguardSecurityContainer(KeyguardHostView hostView) { + static KeyguardSecurityContainer providesKeyguardSecurityContainer(KeyguardHostView hostView) { return hostView.findViewById(R.id.keyguard_security_container); } + + /** */ + @Provides + @KeyguardBouncerScope + static KeyguardSecurityViewFlipper providesKeyguardSecurityViewFlipper( + KeyguardSecurityContainer containerView) { + return containerView.findViewById(R.id.view_flipper); + } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java index 560b159485914..cdb91ecfad899 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java @@ -17,18 +17,14 @@ package com.android.keyguard; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; -import android.view.LayoutInflater; -import android.view.ViewGroup; import android.view.WindowInsetsController; import androidx.test.filters.SmallTest; @@ -39,7 +35,6 @@ import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardSecurityModel.SecurityMode; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.util.InjectionInflationController; import org.junit.Before; import org.junit.Rule; @@ -76,21 +71,15 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { @Mock private KeyguardStateController mKeyguardStateController; @Mock - private LayoutInflater mLayoutInflater; - @Mock - private InjectionInflationController mInjectionInflationController; - @Mock - private KeyguardInputViewController.Factory mKeyguardSecurityViewControllerFactory; - @Mock - private KeyguardInputViewController mKeyguardInputViewController; - @Mock - private KeyguardInputView mInputView; + private KeyguardInputViewController mInputViewController; @Mock private KeyguardSecurityContainer.SecurityCallback mSecurityCallback; @Mock private WindowInsetsController mWindowInsetsController; @Mock private KeyguardSecurityViewFlipper mSecurityViewFlipper; + @Mock + private KeyguardSecurityViewFlipperController mKeyguardSecurityViewFlipperController; private KeyguardSecurityContainerController mKeyguardSecurityContainerController; @@ -98,39 +87,28 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { public void setup() { when(mAdminSecondaryLockScreenControllerFactory.create(any(KeyguardSecurityCallback.class))) .thenReturn(mAdminSecondaryLockScreenController); - when(mInjectionInflationController.injectable(mLayoutInflater)).thenReturn(mLayoutInflater); - when(mKeyguardSecurityViewControllerFactory.create( - any(KeyguardInputView.class), any(SecurityMode.class), - any(KeyguardSecurityCallback.class))) - .thenReturn(mKeyguardInputViewController); - when(mView.getSecurityViewFlipper()).thenReturn(mSecurityViewFlipper); when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController); mKeyguardSecurityContainerController = new KeyguardSecurityContainerController( mView, mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils, mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger, - mKeyguardStateController, mLayoutInflater, mInjectionInflationController, - mKeyguardSecurityViewControllerFactory - ); + mKeyguardStateController, mKeyguardSecurityViewFlipperController); mKeyguardSecurityContainerController.setSecurityCallback(mSecurityCallback); } @Test public void showSecurityScreen_canInflateAllModes() { - KeyguardSecurityModel.SecurityMode[] modes = - KeyguardSecurityModel.SecurityMode.values(); - for (KeyguardSecurityModel.SecurityMode mode : modes) { - reset(mLayoutInflater); - when(mLayoutInflater.inflate(anyInt(), eq(mSecurityViewFlipper), eq(false))) - .thenReturn(mInputView); - when(mKeyguardInputViewController.getSecurityMode()).thenReturn(mode); + SecurityMode[] modes = SecurityMode.values(); + for (SecurityMode mode : modes) { + when(mInputViewController.getSecurityMode()).thenReturn(mode); mKeyguardSecurityContainerController.showSecurityScreen(mode); - if (mode == SecurityMode.Invalid || mode == SecurityMode.None) { - verify(mLayoutInflater, never()).inflate( - anyInt(), any(ViewGroup.class), anyBoolean()); + if (mode == SecurityMode.Invalid) { + verify(mKeyguardSecurityViewFlipperController, never()).getSecurityView( + any(SecurityMode.class), any(KeyguardSecurityCallback.class)); } else { - verify(mLayoutInflater).inflate(anyInt(), eq(mSecurityViewFlipper), eq(false)); + verify(mKeyguardSecurityViewFlipperController).getSecurityView( + eq(mode), any(KeyguardSecurityCallback.class)); } } } @@ -138,14 +116,15 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { @Test public void startDisappearAnimation_animatesKeyboard() { when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn( - KeyguardSecurityModel.SecurityMode.Password); - when(mKeyguardInputViewController.getSecurityMode()).thenReturn( - KeyguardSecurityModel.SecurityMode.Password); - when(mLayoutInflater.inflate(anyInt(), eq(mSecurityViewFlipper), eq(false))) - .thenReturn(mInputView); + SecurityMode.Password); + when(mInputViewController.getSecurityMode()).thenReturn( + SecurityMode.Password); + when(mKeyguardSecurityViewFlipperController.getSecurityView( + eq(SecurityMode.Password), any(KeyguardSecurityCallback.class))) + .thenReturn(mInputViewController); mKeyguardSecurityContainerController.showPrimarySecurityScreen(false /* turningOff */); mKeyguardSecurityContainerController.startDisappearAnimation(null); - verify(mKeyguardInputViewController).startDisappearAnimation(eq(null)); + verify(mInputViewController).startDisappearAnimation(eq(null)); } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java new file mode 100644 index 0000000000000..5061eedf453a8 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2020 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. + */ + +package com.android.keyguard; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.view.LayoutInflater; +import android.view.ViewGroup; +import android.view.WindowInsetsController; + +import androidx.test.filters.SmallTest; + +import com.android.keyguard.KeyguardSecurityModel.SecurityMode; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.util.InjectionInflationController; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper() +public class KeyguardSecurityViewFlipperControllerTest extends SysuiTestCase { + + @Rule + public MockitoRule mRule = MockitoJUnit.rule(); + + @Mock + private KeyguardSecurityViewFlipper mView; + @Mock + private LayoutInflater mLayoutInflater; + @Mock + private InjectionInflationController mInjectionInflationController; + @Mock + private KeyguardInputViewController.Factory mKeyguardSecurityViewControllerFactory; + @Mock + private KeyguardInputViewController mKeyguardInputViewController; + @Mock + private KeyguardInputView mInputView; + @Mock + private WindowInsetsController mWindowInsetsController; + @Mock + private KeyguardSecurityCallback mKeyguardSecurityCallback; + + private KeyguardSecurityViewFlipperController mKeyguardSecurityViewFlipperController; + + @Before + public void setup() { + when(mInjectionInflationController.injectable(mLayoutInflater)).thenReturn(mLayoutInflater); + when(mKeyguardSecurityViewControllerFactory.create( + any(KeyguardInputView.class), any(SecurityMode.class), + any(KeyguardSecurityCallback.class))) + .thenReturn(mKeyguardInputViewController); + when(mView.getWindowInsetsController()).thenReturn(mWindowInsetsController); + + mKeyguardSecurityViewFlipperController = new KeyguardSecurityViewFlipperController(mView, + mLayoutInflater, mInjectionInflationController, + mKeyguardSecurityViewControllerFactory); + } + + @Test + public void showSecurityScreen_canInflateAllModes() { + SecurityMode[] modes = SecurityMode.values(); + // Always return an invalid controller so that we're always making a new one. + when(mKeyguardInputViewController.getSecurityMode()).thenReturn(SecurityMode.Invalid); + for (SecurityMode mode : modes) { + reset(mLayoutInflater); + when(mLayoutInflater.inflate(anyInt(), eq(mView), eq(false))) + .thenReturn(mInputView); + mKeyguardSecurityViewFlipperController.getSecurityView(mode, mKeyguardSecurityCallback); + if (mode == SecurityMode.Invalid || mode == SecurityMode.None) { + verify(mLayoutInflater, never()).inflate( + anyInt(), any(ViewGroup.class), anyBoolean()); + } else { + verify(mLayoutInflater).inflate(anyInt(), eq(mView), eq(false)); + } + } + } +}