From e3c687ce3f257e71d2c9ff02f15cb9d00995ea48 Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Mon, 6 Mar 2023 11:48:40 -0800 Subject: Asynchronously inflate the bouncer. As we are lazily inflating the bouncer every time we show it, we can get huge performance gains from AsyncInflater. From the class documentation "This is intended for parts of the UI that are created lazily or in response to user interactions. This allows the UI thread to continue to be responsive & animate while the relatively heavy inflate is being performed." it seems that this is the perfect use case. I've added the AsyncInflater in a dagger module for testing purposes. I also moved the handler constructrion in KeyguardMessageArea to its corresponding view controller to conform to the AsynInflater requirements. Interestingly this also fixes b/265384692 as it seemed like the bouncer was being inflated before the onclicklisteners were added. Fixes: 269522372 Fixes: 265384692 Test: Test for talk back to ensure that it announces the text view. Test: open scrimmed and non scrimmed bouncer. Test: Pin, Password, pattern, simpin, simpuk Test: modified unit tests. Change-Id: Ic65af22da9f6822e5137aae3cfee03a6e819ab94 --- .../com/android/keyguard/KeyguardMessageArea.java | 41 ---------------- .../keyguard/KeyguardMessageAreaController.java | 45 ++++++++++++++++++ .../KeyguardSecurityContainerController.java | 19 +++++--- .../KeyguardSecurityViewFlipperController.java | 54 ++++++++++++++++++++-- .../systemui/dagger/FrameworkServicesModule.java | 8 ++++ .../ui/binder/KeyguardBouncerViewBinder.kt | 23 ++++----- .../KeyguardMessageAreaControllerTest.java | 21 ++++++++- .../KeyguardSecurityContainerControllerTest.java | 16 ++++++- .../KeyguardSecurityViewFlipperControllerTest.java | 19 +++++++- 9 files changed, 178 insertions(+), 68 deletions(-) diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java index 0e5f8c1c7a26..553453d7f79d 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java @@ -18,13 +18,9 @@ package com.android.keyguard; import android.content.Context; import android.content.res.TypedArray; -import android.os.Handler; -import android.os.Looper; -import android.os.SystemClock; import android.text.TextUtils; import android.util.AttributeSet; import android.util.TypedValue; -import android.view.View; import android.view.ViewGroup; import android.widget.TextView; @@ -33,22 +29,10 @@ import androidx.annotation.Nullable; import com.android.internal.policy.SystemBarUtils; import com.android.systemui.R; -import java.lang.ref.WeakReference; - /*** * Manages a number of views inside of the given layout. See below for a list of widgets. */ public abstract class KeyguardMessageArea extends TextView implements SecurityMessageDisplay { - /** Handler token posted with accessibility announcement runnables. */ - private static final Object ANNOUNCE_TOKEN = new Object(); - - /** - * Delay before speaking an accessibility announcement. Used to prevent - * lift-to-type from interrupting itself. - */ - private static final long ANNOUNCEMENT_DELAY = 250; - - private final Handler mHandler; private CharSequence mMessage; private boolean mIsVisible; @@ -65,7 +49,6 @@ public abstract class KeyguardMessageArea extends TextView implements SecurityMe super(context, attrs); setLayerType(LAYER_TYPE_HARDWARE, null); // work around nested unclipped SaveLayer bug - mHandler = new Handler(Looper.myLooper()); onThemeChanged(); } @@ -127,9 +110,6 @@ public abstract class KeyguardMessageArea extends TextView implements SecurityMe private void securityMessageChanged(CharSequence message) { mMessage = message; update(); - mHandler.removeCallbacksAndMessages(ANNOUNCE_TOKEN); - mHandler.postAtTime(new AnnounceRunnable(this, getText()), ANNOUNCE_TOKEN, - (SystemClock.uptimeMillis() + ANNOUNCEMENT_DELAY)); } private void clearMessage() { @@ -156,25 +136,4 @@ public abstract class KeyguardMessageArea extends TextView implements SecurityMe /** Set the text color */ protected abstract void updateTextColor(); - - /** - * Runnable used to delay accessibility announcements. - */ - private static class AnnounceRunnable implements Runnable { - private final WeakReference mHost; - private final CharSequence mTextToAnnounce; - - AnnounceRunnable(View host, CharSequence textToAnnounce) { - mHost = new WeakReference(host); - mTextToAnnounce = textToAnnounce; - } - - @Override - public void run() { - final View host = mHost.get(); - if (host != null) { - host.announceForAccessibility(mTextToAnnounce); - } - } - } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java index 6a9216218d07..c1896fc641e0 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java @@ -18,11 +18,17 @@ package com.android.keyguard; import android.content.res.ColorStateList; import android.content.res.Configuration; +import android.text.TextUtils; +import android.view.View; + +import androidx.annotation.VisibleForTesting; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; import com.android.systemui.util.ViewController; +import java.lang.ref.WeakReference; + import javax.inject.Inject; /** @@ -31,8 +37,14 @@ import javax.inject.Inject; */ public class KeyguardMessageAreaController extends ViewController { + /** + * Delay before speaking an accessibility announcement. Used to prevent + * lift-to-type from interrupting itself. + */ + private static final long ANNOUNCEMENT_DELAY = 250; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final ConfigurationController mConfigurationController; + private final AnnounceRunnable mAnnounceRunnable; private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() { public void onFinishedGoingToSleep(int why) { @@ -68,6 +80,7 @@ public class KeyguardMessageAreaController mKeyguardUpdateMonitor = keyguardUpdateMonitor; mConfigurationController = configurationController; + mAnnounceRunnable = new AnnounceRunnable(mView); } @Override @@ -100,6 +113,12 @@ public class KeyguardMessageAreaController */ public void setMessage(CharSequence s, boolean animate) { mView.setMessage(s, animate); + CharSequence msg = mView.getText(); + if (!TextUtils.isEmpty(msg)) { + mView.removeCallbacks(mAnnounceRunnable); + mAnnounceRunnable.setTextToAnnounce(msg); + mView.postDelayed(mAnnounceRunnable, ANNOUNCEMENT_DELAY); + } } public void setMessage(int resId) { @@ -134,4 +153,30 @@ public class KeyguardMessageAreaController view, mKeyguardUpdateMonitor, mConfigurationController); } } + + /** + * Runnable used to delay accessibility announcements. + */ + @VisibleForTesting + public static class AnnounceRunnable implements Runnable { + private final WeakReference mHost; + private CharSequence mTextToAnnounce; + + AnnounceRunnable(View host) { + mHost = new WeakReference<>(host); + } + + /** Sets the text to announce. */ + public void setTextToAnnounce(CharSequence textToAnnounce) { + mTextToAnnounce = textToAnnounce; + } + + @Override + public void run() { + final View host = mHost.get(); + if (host != null) { + host.announceForAccessibility(mTextToAnnounce); + } + } + } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java index 2c2caea60f5a..c098d4ca286d 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java @@ -1065,23 +1065,28 @@ public class KeyguardSecurityContainerController extends ViewController mView.reloadColors()); } /** Handles density or font scale changes. */ private void onDensityOrFontScaleChanged() { - reinflateViewFlipper(); - mView.onDensityOrFontScaleChanged(); + reinflateViewFlipper(() -> mView.onDensityOrFontScaleChanged()); } /** * Reinflate the view flipper child view. */ - public void reinflateViewFlipper() { + public void reinflateViewFlipper( + KeyguardSecurityViewFlipperController.OnViewInflatedListener onViewInflatedListener) { mSecurityViewFlipperController.clearViews(); - mSecurityViewFlipperController.getSecurityView(mCurrentSecurityMode, - mKeyguardSecurityCallback); + if (mFeatureFlags.isEnabled(Flags.ASYNC_INFLATE_BOUNCER)) { + mSecurityViewFlipperController.asynchronouslyInflateView(mCurrentSecurityMode, + mKeyguardSecurityCallback, onViewInflatedListener); + } else { + mSecurityViewFlipperController.getSecurityView(mCurrentSecurityMode, + mKeyguardSecurityCallback); + onViewInflatedListener.onViewInflated(); + } } /** diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java index 39b567fd21b9..68e1dd7d8eab 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java @@ -19,11 +19,16 @@ package com.android.keyguard; import android.util.Log; import android.view.LayoutInflater; +import androidx.annotation.Nullable; +import androidx.asynclayoutinflater.view.AsyncLayoutInflater; + import com.android.internal.annotations.VisibleForTesting; import com.android.keyguard.KeyguardInputViewController.Factory; import com.android.keyguard.KeyguardSecurityModel.SecurityMode; import com.android.keyguard.dagger.KeyguardBouncerScope; import com.android.systemui.R; +import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.util.ViewController; import java.util.ArrayList; @@ -44,18 +49,24 @@ public class KeyguardSecurityViewFlipperController private final List> mChildren = new ArrayList<>(); private final LayoutInflater mLayoutInflater; + private final AsyncLayoutInflater mAsyncLayoutInflater; private final EmergencyButtonController.Factory mEmergencyButtonControllerFactory; private final Factory mKeyguardSecurityViewControllerFactory; + private final FeatureFlags mFeatureFlags; @Inject protected KeyguardSecurityViewFlipperController(KeyguardSecurityViewFlipper view, LayoutInflater layoutInflater, + AsyncLayoutInflater asyncLayoutInflater, KeyguardInputViewController.Factory keyguardSecurityViewControllerFactory, - EmergencyButtonController.Factory emergencyButtonControllerFactory) { + EmergencyButtonController.Factory emergencyButtonControllerFactory, + FeatureFlags featureFlags) { super(view); mKeyguardSecurityViewControllerFactory = keyguardSecurityViewControllerFactory; mLayoutInflater = layoutInflater; mEmergencyButtonControllerFactory = emergencyButtonControllerFactory; + mAsyncLayoutInflater = asyncLayoutInflater; + mFeatureFlags = featureFlags; } @Override @@ -92,13 +103,12 @@ public class KeyguardSecurityViewFlipperController } } - if (childController == null + if (!mFeatureFlags.isEnabled(Flags.ASYNC_INFLATE_BOUNCER) && 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); + if (DEBUG) Log.v(TAG, "inflating on main thread id = " + layoutId); view = (KeyguardInputView) mLayoutInflater.inflate( layoutId, mView, false); mView.addView(view); @@ -119,6 +129,36 @@ public class KeyguardSecurityViewFlipperController return childController; } + /** + * Asynchronously inflate view and then add it to view flipper on the main thread when complete. + * + * OnInflateFinishedListener will be called on the main thread. + * + * @param securityMode + * @param keyguardSecurityCallback + */ + public void asynchronouslyInflateView(SecurityMode securityMode, + KeyguardSecurityCallback keyguardSecurityCallback, + @Nullable OnViewInflatedListener onViewInflatedListener) { + int layoutId = getLayoutIdFor(securityMode); + if (layoutId != 0) { + if (DEBUG) Log.v(TAG, "inflating on bg thread id = " + layoutId); + mAsyncLayoutInflater.inflate(layoutId, mView, + (view, resId, parent) -> { + mView.addView(view); + KeyguardInputViewController childController = + mKeyguardSecurityViewControllerFactory.create( + (KeyguardInputView) view, securityMode, + keyguardSecurityCallback); + childController.init(); + mChildren.add(childController); + if (onViewInflatedListener != null) { + onViewInflatedListener.onViewInflated(); + } + }); + } + } + private int getLayoutIdFor(SecurityMode securityMode) { switch (securityMode) { case Pattern: return R.layout.keyguard_pattern_view; @@ -162,4 +202,10 @@ public class KeyguardSecurityViewFlipperController return 0; } } + + /** Listener to when view has finished inflation. */ + public interface OnViewInflatedListener { + /** Notifies that view has been inflated */ + void onViewInflated(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java index d1c34a8d0821..4fa40757612b 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java @@ -97,6 +97,7 @@ import android.view.accessibility.CaptioningManager; import android.view.inputmethod.InputMethodManager; import android.view.textclassifier.TextClassificationManager; +import androidx.asynclayoutinflater.view.AsyncLayoutInflater; import androidx.core.app.NotificationManagerCompat; import com.android.internal.app.IBatteryStats; @@ -388,6 +389,13 @@ public class FrameworkServicesModule { return LayoutInflater.from(context); } + /** */ + @Provides + @Singleton + public AsyncLayoutInflater provideAsyncLayoutInflater(Context context) { + return new AsyncLayoutInflater(context); + } + @Provides static MediaProjectionManager provideMediaProjectionManager(Context context) { return context.getSystemService(MediaProjectionManager.class); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt index d7167845419b..5fcf1052d949 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt @@ -34,7 +34,6 @@ import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransition import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.ActivityStarter import kotlinx.coroutines.awaitCancellation -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch @@ -112,16 +111,18 @@ object KeyguardBouncerViewBinder { launch { viewModel.show.collect { // Reset Security Container entirely. - view.visibility = View.VISIBLE - securityContainerController.onBouncerVisibilityChanged( - /* isVisible= */ true - ) - securityContainerController.reinflateViewFlipper() - securityContainerController.showPrimarySecurityScreen( - /* turningOff= */ false - ) - securityContainerController.appear() - securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON) + securityContainerController.reinflateViewFlipper { + // Reset Security Container entirely. + view.visibility = View.VISIBLE + securityContainerController.onBouncerVisibilityChanged( + /* isVisible= */ true + ) + securityContainerController.showPrimarySecurityScreen( + /* turningOff= */ false + ) + securityContainerController.appear() + securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON) + } } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java index 0e837d2976ba..a35e5b59f765 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java @@ -18,12 +18,15 @@ package com.android.keyguard; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -37,6 +40,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; @SmallTest +@TestableLooper.RunWithLooper @RunWith(AndroidTestingRunner.class) public class KeyguardMessageAreaControllerTest extends SysuiTestCase { @Mock @@ -45,14 +49,14 @@ public class KeyguardMessageAreaControllerTest extends SysuiTestCase { private KeyguardUpdateMonitor mKeyguardUpdateMonitor; @Mock private KeyguardMessageArea mKeyguardMessageArea; - private KeyguardMessageAreaController mMessageAreaController; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mMessageAreaController = new KeyguardMessageAreaController.Factory( - mKeyguardUpdateMonitor, mConfigurationController).create(mKeyguardMessageArea); + mKeyguardUpdateMonitor, mConfigurationController).create( + mKeyguardMessageArea); } @Test @@ -88,6 +92,19 @@ public class KeyguardMessageAreaControllerTest extends SysuiTestCase { verify(mKeyguardMessageArea).setMessage("", /* animate= */ true); } + @Test + public void testSetMessage_AnnounceForAccessibility() { + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Runnable.class); + when(mKeyguardMessageArea.getText()).thenReturn("abc"); + mMessageAreaController.setMessage("abc"); + + verify(mKeyguardMessageArea).setMessage("abc", /* animate= */ true); + verify(mKeyguardMessageArea).removeCallbacks(any(Runnable.class)); + verify(mKeyguardMessageArea).postDelayed(argumentCaptor.capture(), anyLong()); + argumentCaptor.getValue().run(); + verify(mKeyguardMessageArea).announceForAccessibility("abc"); + } + @Test public void testSetBouncerVisible() { mMessageAreaController.setIsVisible(true); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java index 4dc4c2cbf93c..26d20c24cb84 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java @@ -66,6 +66,7 @@ import com.android.systemui.biometrics.SideFpsUiRequestSource; import com.android.systemui.classifier.FalsingA11yDelegate; import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.log.SessionTracker; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; @@ -617,12 +618,25 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { @Test public void testReinflateViewFlipper() { - mKeyguardSecurityContainerController.reinflateViewFlipper(); + mKeyguardSecurityContainerController.reinflateViewFlipper(() -> {}); verify(mKeyguardSecurityViewFlipperController).clearViews(); verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class), any(KeyguardSecurityCallback.class)); } + @Test + public void testReinflateViewFlipper_asyncBouncerFlagOn() { + when(mFeatureFlags.isEnabled(Flags.ASYNC_INFLATE_BOUNCER)).thenReturn(true); + KeyguardSecurityViewFlipperController.OnViewInflatedListener onViewInflatedListener = + () -> { + }; + mKeyguardSecurityContainerController.reinflateViewFlipper(onViewInflatedListener); + verify(mKeyguardSecurityViewFlipperController).clearViews(); + verify(mKeyguardSecurityViewFlipperController).asynchronouslyInflateView( + any(SecurityMode.class), + any(KeyguardSecurityCallback.class), eq(onViewInflatedListener)); + } + @Test public void testSideFpsControllerShow() { mKeyguardSecurityContainerController.updateSideFpsVisibility(/* isVisible= */ true); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java index 1614b577a6cc..afb54d2df49f 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java @@ -31,10 +31,12 @@ import android.view.LayoutInflater; import android.view.ViewGroup; import android.view.WindowInsetsController; +import androidx.asynclayoutinflater.view.AsyncLayoutInflater; import androidx.test.filters.SmallTest; import com.android.keyguard.KeyguardSecurityModel.SecurityMode; import com.android.systemui.SysuiTestCase; +import com.android.systemui.flags.FeatureFlags; import org.junit.Before; import org.junit.Rule; @@ -57,6 +59,8 @@ public class KeyguardSecurityViewFlipperControllerTest extends SysuiTestCase { @Mock private LayoutInflater mLayoutInflater; @Mock + private AsyncLayoutInflater mAsyncLayoutInflater; + @Mock private KeyguardInputViewController.Factory mKeyguardSecurityViewControllerFactory; @Mock private EmergencyButtonController.Factory mEmergencyButtonControllerFactory; @@ -70,6 +74,8 @@ public class KeyguardSecurityViewFlipperControllerTest extends SysuiTestCase { private WindowInsetsController mWindowInsetsController; @Mock private KeyguardSecurityCallback mKeyguardSecurityCallback; + @Mock + private FeatureFlags mFeatureFlags; private KeyguardSecurityViewFlipperController mKeyguardSecurityViewFlipperController; @@ -82,10 +88,11 @@ public class KeyguardSecurityViewFlipperControllerTest extends SysuiTestCase { when(mView.getWindowInsetsController()).thenReturn(mWindowInsetsController); when(mEmergencyButtonControllerFactory.create(any(EmergencyButton.class))) .thenReturn(mEmergencyButtonController); + when(mView.getContext()).thenReturn(getContext()); mKeyguardSecurityViewFlipperController = new KeyguardSecurityViewFlipperController(mView, - mLayoutInflater, mKeyguardSecurityViewControllerFactory, - mEmergencyButtonControllerFactory); + mLayoutInflater, mAsyncLayoutInflater, mKeyguardSecurityViewControllerFactory, + mEmergencyButtonControllerFactory, mFeatureFlags); } @Test @@ -107,6 +114,14 @@ public class KeyguardSecurityViewFlipperControllerTest extends SysuiTestCase { } } + @Test + public void asynchronouslyInflateView() { + mKeyguardSecurityViewFlipperController.asynchronouslyInflateView(SecurityMode.PIN, + mKeyguardSecurityCallback, null); + verify(mAsyncLayoutInflater).inflate(anyInt(), eq(mView), any( + AsyncLayoutInflater.OnInflateFinishedListener.class)); + } + @Test public void onDensityOrFontScaleChanged() { mKeyguardSecurityViewFlipperController.clearViews(); -- cgit v1.2.3-59-g8ed1b