Merge "Show a small toast when a double tap is needed." into sc-dev

This commit is contained in:
Dave Mankoff
2021-05-26 16:03:52 +00:00
committed by Android (Google) Code Review
9 changed files with 319 additions and 13 deletions

View File

@@ -129,7 +129,21 @@
android:layout_marginTop="@dimen/status_bar_header_height_keyguard" android:layout_marginTop="@dimen/status_bar_header_height_keyguard"
android:text="@string/report_rejected_touch" android:text="@string/report_rejected_touch"
android:visibility="gone" /> android:visibility="gone" />
<com.android.systemui.statusbar.phone.TapAgainView
android:id="@+id/shade_falsing_tap_again"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
systemui:layout_constraintLeft_toLeftOf="parent"
systemui:layout_constraintRight_toRightOf="parent"
systemui:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="20dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:elevation="10dp"
android:visibility="gone"
/>
</com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer> </com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer>
<FrameLayout <FrameLayout

View File

@@ -40,6 +40,7 @@ public class FalsingManagerFake implements FalsingManager {
private boolean mIsFalseRobustTap; private boolean mIsFalseRobustTap;
private final List<FalsingBeliefListener> mFalsingBeliefListeners = new ArrayList<>(); private final List<FalsingBeliefListener> mFalsingBeliefListeners = new ArrayList<>();
private final List<FalsingTapListener> mTapListeners = new ArrayList<>();
@Override @Override
public void onSuccessfulUnlock() { public void onSuccessfulUnlock() {
@@ -148,11 +149,15 @@ public class FalsingManagerFake implements FalsingManager {
@Override @Override
public void addTapListener(FalsingTapListener falsingTapListener) { public void addTapListener(FalsingTapListener falsingTapListener) {
mTapListeners.add(falsingTapListener);
} }
@Override @Override
public void removeTapListener(FalsingTapListener falsingTapListener) { public void removeTapListener(FalsingTapListener falsingTapListener) {
mTapListeners.remove(falsingTapListener);
}
public List<FalsingTapListener> getTapListeners() {
return mTapListeners;
} }
} }

View File

@@ -142,7 +142,6 @@ public class KeyguardIndicationTextView extends TextView {
Animator yTranslate = Animator yTranslate =
ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, 0, -getYTranslationPixels()); ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, 0, -getYTranslationPixels());
yTranslate.setDuration(getFadeOutDuration()); yTranslate.setDuration(getFadeOutDuration());
fadeOut.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
animatorSet.playTogether(fadeOut, yTranslate); animatorSet.playTogether(fadeOut, yTranslate);
return animatorSet; return animatorSet;

View File

@@ -24,6 +24,8 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode; import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet; import android.util.AttributeSet;
import com.android.systemui.R;
public class NotificationPanelView extends PanelView { public class NotificationPanelView extends PanelView {
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
@@ -92,6 +94,10 @@ public class NotificationPanelView extends PanelView {
mRtlChangeListener = listener; mRtlChangeListener = listener;
} }
public TapAgainView getTapAgainView() {
return findViewById(R.id.shade_falsing_tap_again);
}
interface RtlChangeListener { interface RtlChangeListener {
void onRtlPropertielsChanged(int layoutDirection); void onRtlPropertielsChanged(int layoutDirection);
} }

View File

@@ -97,8 +97,8 @@ import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.dagger.qualifiers.DisplayId; import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeLog; import com.android.systemui.doze.DozeLog;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener; import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.media.KeyguardMediaController; import com.android.systemui.media.KeyguardMediaController;
import com.android.systemui.media.MediaDataManager; import com.android.systemui.media.MediaDataManager;
import com.android.systemui.media.MediaHierarchyManager; import com.android.systemui.media.MediaHierarchyManager;
@@ -306,6 +306,7 @@ public class NotificationPanelViewController extends PanelViewController {
private final KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory; private final KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
private final KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory; private final KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
private final QSDetailDisplayer mQSDetailDisplayer; private final QSDetailDisplayer mQSDetailDisplayer;
private final FragmentService mFragmentService;
private final FeatureFlags mFeatureFlags; private final FeatureFlags mFeatureFlags;
private final ScrimController mScrimController; private final ScrimController mScrimController;
private final PrivacyDotViewController mPrivacyDotViewController; private final PrivacyDotViewController mPrivacyDotViewController;
@@ -314,6 +315,7 @@ public class NotificationPanelViewController extends PanelViewController {
// If there are exactly 1 + mMaxKeyguardNotifications, then still shows all notifications // If there are exactly 1 + mMaxKeyguardNotifications, then still shows all notifications
private final int mMaxKeyguardNotifications; private final int mMaxKeyguardNotifications;
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController; private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
private final TapAgainViewController mTapAgainViewController;
private boolean mShouldUseSplitNotificationShade; private boolean mShouldUseSplitNotificationShade;
// Current max allowed keyguard notifications determined by measuring the panel // Current max allowed keyguard notifications determined by measuring the panel
private int mMaxAllowedKeyguardNotifications; private int mMaxAllowedKeyguardNotifications;
@@ -604,7 +606,12 @@ public class NotificationPanelViewController extends PanelViewController {
private final FalsingTapListener mFalsingTapListener = new FalsingTapListener() { private final FalsingTapListener mFalsingTapListener = new FalsingTapListener() {
@Override @Override
public void onDoubleTapRequired() { public void onDoubleTapRequired() {
showTransientIndication(R.string.notification_tap_again); if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED) {
mTapAgainViewController.show();
} else {
mKeyguardIndicationController.showTransientIndication(
R.string.notification_tap_again);
}
mVibratorHelper.vibrate(VibrationEffect.EFFECT_STRENGTH_MEDIUM); mVibratorHelper.vibrate(VibrationEffect.EFFECT_STRENGTH_MEDIUM);
} }
}; };
@@ -653,6 +660,8 @@ public class NotificationPanelViewController extends PanelViewController {
QuickAccessWalletClient quickAccessWalletClient, QuickAccessWalletClient quickAccessWalletClient,
KeyguardMediaController keyguardMediaController, KeyguardMediaController keyguardMediaController,
PrivacyDotViewController privacyDotViewController, PrivacyDotViewController privacyDotViewController,
TapAgainViewController tapAgainViewController,
FragmentService fragmentService,
@Main Executor uiExecutor, @Main Executor uiExecutor,
SecureSettings secureSettings) { SecureSettings secureSettings) {
super(view, falsingManager, dozeLog, keyguardStateController, super(view, falsingManager, dozeLog, keyguardStateController,
@@ -679,6 +688,7 @@ public class NotificationPanelViewController extends PanelViewController {
mKeyguardQsUserSwitchComponentFactory = keyguardQsUserSwitchComponentFactory; mKeyguardQsUserSwitchComponentFactory = keyguardQsUserSwitchComponentFactory;
mKeyguardUserSwitcherComponentFactory = keyguardUserSwitcherComponentFactory; mKeyguardUserSwitcherComponentFactory = keyguardUserSwitcherComponentFactory;
mQSDetailDisplayer = qsDetailDisplayer; mQSDetailDisplayer = qsDetailDisplayer;
mFragmentService = fragmentService;
mKeyguardUserSwitcherEnabled = mResources.getBoolean( mKeyguardUserSwitcherEnabled = mResources.getBoolean(
com.android.internal.R.bool.config_keyguardUserSwitcher); com.android.internal.R.bool.config_keyguardUserSwitcher);
mKeyguardQsUserSwitchEnabled = mKeyguardQsUserSwitchEnabled =
@@ -705,6 +715,7 @@ public class NotificationPanelViewController extends PanelViewController {
mUserManager = userManager; mUserManager = userManager;
mMediaDataManager = mediaDataManager; mMediaDataManager = mediaDataManager;
mQuickAccessWalletClient = quickAccessWalletClient; mQuickAccessWalletClient = quickAccessWalletClient;
mTapAgainViewController = tapAgainViewController;
mUiExecutor = uiExecutor; mUiExecutor = uiExecutor;
mSecureSettings = secureSettings; mSecureSettings = secureSettings;
pulseExpansionHandler.setPulseExpandAbortListener(() -> { pulseExpansionHandler.setPulseExpandAbortListener(() -> {
@@ -843,6 +854,8 @@ public class NotificationPanelViewController extends PanelViewController {
if (mShouldUseSplitNotificationShade) { if (mShouldUseSplitNotificationShade) {
updateResources(); updateResources();
} }
mTapAgainViewController.init();
} }
@Override @Override
@@ -3675,10 +3688,6 @@ public class NotificationPanelViewController extends PanelViewController {
updateMaxDisplayedNotifications(true); updateMaxDisplayedNotifications(true);
} }
public void showTransientIndication(int id) {
mKeyguardIndicationController.showTransientIndication(id);
}
public void setAlpha(float alpha) { public void setAlpha(float alpha) {
mView.setAlpha(alpha); mView.setAlpha(alpha);
} }
@@ -4264,7 +4273,8 @@ public class NotificationPanelViewController extends PanelViewController {
private class OnAttachStateChangeListener implements View.OnAttachStateChangeListener { private class OnAttachStateChangeListener implements View.OnAttachStateChangeListener {
@Override @Override
public void onViewAttachedToWindow(View v) { public void onViewAttachedToWindow(View v) {
FragmentHostManager.get(mView).addTagListener(QS.TAG, mFragmentListener); mFragmentService.getFragmentHostManager(mView)
.addTagListener(QS.TAG, mFragmentListener);
mStatusBarStateController.addCallback(mStatusBarStateListener); mStatusBarStateController.addCallback(mStatusBarStateListener);
mConfigurationController.addCallback(mConfigurationListener); mConfigurationController.addCallback(mConfigurationListener);
mUpdateMonitor.registerCallback(mKeyguardUpdateCallback); mUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
@@ -4278,7 +4288,8 @@ public class NotificationPanelViewController extends PanelViewController {
@Override @Override
public void onViewDetachedFromWindow(View v) { public void onViewDetachedFromWindow(View v) {
FragmentHostManager.get(mView).removeTagListener(QS.TAG, mFragmentListener); mFragmentService.getFragmentHostManager(mView)
.removeTagListener(QS.TAG, mFragmentListener);
mStatusBarStateController.removeCallback(mStatusBarStateListener); mStatusBarStateController.removeCallback(mStatusBarStateListener);
mConfigurationController.removeCallback(mConfigurationListener); mConfigurationController.removeCallback(mConfigurationListener);
mUpdateMonitor.removeCallback(mKeyguardUpdateCallback); mUpdateMonitor.removeCallback(mKeyguardUpdateCallback);

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2021 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.systemui.statusbar.phone;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.systemui.R;
import com.android.wm.shell.animation.Interpolators;
/**
* View to show a toast-like popup on the notification shade and quick settings.
*/
public class TapAgainView extends FrameLayout {
public TapAgainView(
@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
updateBgColor();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
TextView text = new TextView(mContext);
text.setText(R.string.notification_tap_again);
addView(text);
}
void updateBgColor() {
setBackgroundResource(R.drawable.rounded_bg_full);
}
/** Make the view visible. */
public void animateIn() {
int yTranslation = mContext.getResources().getDimensionPixelSize(
R.dimen.keyguard_indication_y_translation);
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator fadeIn = ObjectAnimator.ofFloat(this, View.ALPHA, 1f);
fadeIn.setStartDelay(150); // From KeyguardIndicationTextView#getFadeInDelay
fadeIn.setDuration(317); // From KeyguardIndicationTextView#getFadeInDuration
fadeIn.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
Animator yTranslate =
ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, yTranslation, 0);
yTranslate.setDuration(600); // From KeyguardIndicationTextView#getYInDuration
yTranslate.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
setTranslationY(0);
}
});
animatorSet.playTogether(yTranslate, fadeIn);
animatorSet.start();
setVisibility(View.VISIBLE);
}
/** Make the view gone. */
public void animateOut() {
long fadeOutDuration = 167L; // From KeyguardIndicationTextView#getFadeOutDuration
int yTranslation = mContext.getResources().getDimensionPixelSize(
com.android.systemui.R.dimen.keyguard_indication_y_translation);
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator fadeOut = ObjectAnimator.ofFloat(this, View.ALPHA, 0f);
fadeOut.setDuration(fadeOutDuration);
fadeOut.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
Animator yTranslate =
ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, 0, -yTranslation);
yTranslate.setDuration(fadeOutDuration);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(GONE);
}
@Override
public void onAnimationCancel(Animator animation) {
setVisibility(GONE);
}
});
animatorSet.playTogether(yTranslate, fadeOut);
animatorSet.start();
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (C) 2021 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.systemui.statusbar.phone;
import static com.android.systemui.classifier.FalsingModule.DOUBLE_TAP_TIMEOUT_MS;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.util.ViewController;
import com.android.systemui.util.concurrency.DelayableExecutor;
import javax.inject.Inject;
import javax.inject.Named;
/**
* Controller for {@link TapAgainView}.
*/
@StatusBarComponent.StatusBarScope
public class TapAgainViewController extends ViewController<TapAgainView> {
private final DelayableExecutor mDelayableExecutor;
private final ConfigurationController mConfigurationController;
private final long mDoubleTapTimeMs;
private Runnable mHideCanceler;
@VisibleForTesting
final ConfigurationListener mConfigurationListener = new ConfigurationListener() {
@Override
public void onOverlayChanged() {
mView.updateBgColor();
}
@Override
public void onUiModeChanged() {
mView.updateBgColor();
}
@Override
public void onThemeChanged() {
mView.updateBgColor();
}
};
@Inject
protected TapAgainViewController(TapAgainView view,
@Main DelayableExecutor delayableExecutor,
ConfigurationController configurationController,
@Named(DOUBLE_TAP_TIMEOUT_MS) long doubleTapTimeMs) {
super(view);
mDelayableExecutor = delayableExecutor;
mConfigurationController = configurationController;
mDoubleTapTimeMs = doubleTapTimeMs;
}
@Override
protected void onViewAttached() {
mConfigurationController.addCallback(mConfigurationListener);
}
@Override
protected void onViewDetached() {
mConfigurationController.removeCallback(mConfigurationListener);
}
/** Shows the associated view, possibly animating it. */
public void show() {
if (mHideCanceler != null) {
mHideCanceler.run();
}
mView.animateIn();
mHideCanceler = mDelayableExecutor.executeDelayed(this::hide, mDoubleTapTimeMs);
}
/** Hides the associated view, possibly animating it. */
public void hide() {
mHideCanceler = null;
mView.animateOut();
}
}

View File

@@ -23,6 +23,7 @@ import com.android.systemui.R;
import com.android.systemui.biometrics.AuthRippleView; import com.android.systemui.biometrics.AuthRippleView;
import com.android.systemui.statusbar.phone.NotificationPanelView; import com.android.systemui.statusbar.phone.NotificationPanelView;
import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
import com.android.systemui.statusbar.phone.TapAgainView;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
@@ -53,4 +54,11 @@ public abstract class StatusBarViewModule {
NotificationShadeWindowView notificationShadeWindowView) { NotificationShadeWindowView notificationShadeWindowView) {
return notificationShadeWindowView.findViewById(R.id.auth_ripple); return notificationShadeWindowView.findViewById(R.id.auth_ripple);
} }
/** */
@Provides
@StatusBarComponent.StatusBarScope
public static TapAgainView getTapAgainView(NotificationPanelView npv) {
return npv.getTapAgainView();
}
} }

View File

@@ -20,12 +20,15 @@ import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE; import static com.android.systemui.statusbar.StatusBarState.SHADE;
import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED;
import static com.android.systemui.statusbar.notification.ViewGroupFadeHelper.reset;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
@@ -75,13 +78,17 @@ import com.android.systemui.biometrics.AuthController;
import com.android.systemui.classifier.FalsingCollectorFake; import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.doze.DozeLog; import com.android.systemui.doze.DozeLog;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.media.KeyguardMediaController; import com.android.systemui.media.KeyguardMediaController;
import com.android.systemui.media.MediaDataManager; import com.android.systemui.media.MediaDataManager;
import com.android.systemui.media.MediaHierarchyManager; import com.android.systemui.media.MediaHierarchyManager;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.qs.QSDetailDisplayer; import com.android.systemui.qs.QSDetailDisplayer;
import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.KeyguardAffordanceView; import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShadeDepthController; import com.android.systemui.statusbar.NotificationShadeDepthController;
@@ -252,11 +259,21 @@ public class NotificationPanelViewTest extends SysuiTestCase {
private PrivacyDotViewController mPrivacyDotViewController; private PrivacyDotViewController mPrivacyDotViewController;
@Mock @Mock
private SecureSettings mSecureSettings; private SecureSettings mSecureSettings;
@Mock
private TapAgainViewController mTapAgainViewController;
@Mock
private KeyguardIndicationController mKeyguardIndicationController;
@Mock
private FragmentService mFragmentService;
@Mock
private FragmentHostManager mFragmentHostManager;
private SysuiStatusBarStateController mStatusBarStateController; private SysuiStatusBarStateController mStatusBarStateController;
private NotificationPanelViewController mNotificationPanelViewController; private NotificationPanelViewController mNotificationPanelViewController;
private View.AccessibilityDelegate mAccessibiltyDelegate; private View.AccessibilityDelegate mAccessibiltyDelegate;
private NotificationsQuickSettingsContainer mNotificationContainerParent; private NotificationsQuickSettingsContainer mNotificationContainerParent;
private List<View.OnAttachStateChangeListener> mOnAttachStateChangeListeners;
private FalsingManagerFake mFalsingManager = new FalsingManagerFake();
@Before @Before
public void setup() { public void setup() {
@@ -297,6 +314,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mNotificationContainerParent.addView(newViewWithId(R.id.keyguard_status_view)); mNotificationContainerParent.addView(newViewWithId(R.id.keyguard_status_view));
when(mView.findViewById(R.id.notification_container_parent)) when(mView.findViewById(R.id.notification_container_parent))
.thenReturn(mNotificationContainerParent); .thenReturn(mNotificationContainerParent);
when(mFragmentService.getFragmentHostManager(mView)).thenReturn(mFragmentHostManager);
FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder( FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(
mDisplayMetrics); mDisplayMetrics);
@@ -317,7 +335,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mKeyguardBypassController, mHeadsUpManager, mKeyguardBypassController, mHeadsUpManager,
mock(NotificationRoundnessManager.class), mock(NotificationRoundnessManager.class),
mStatusBarStateController, mStatusBarStateController,
new FalsingManagerFake(), mFalsingManager,
mLockscreenShadeTransitionController, mLockscreenShadeTransitionController,
new FalsingCollectorFake()); new FalsingCollectorFake());
when(mKeyguardStatusViewComponentFactory.build(any())) when(mKeyguardStatusViewComponentFactory.build(any()))
@@ -331,11 +349,12 @@ public class NotificationPanelViewTest extends SysuiTestCase {
when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController()) when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController())
.thenReturn(mKeyguardStatusBarViewController); .thenReturn(mKeyguardStatusBarViewController);
reset(mView);
mNotificationPanelViewController = new NotificationPanelViewController(mView, mNotificationPanelViewController = new NotificationPanelViewController(mView,
mResources, mResources,
mLayoutInflater, mLayoutInflater,
coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController, coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
new FalsingManagerFake(), new FalsingCollectorFake(), mFalsingManager, new FalsingCollectorFake(),
mNotificationLockscreenUserManager, mNotificationEntryManager, mNotificationLockscreenUserManager, mNotificationEntryManager,
mKeyguardStateController, mStatusBarStateController, mDozeLog, mKeyguardStateController, mStatusBarStateController, mDozeLog,
mDozeParameters, mCommandQueue, mVibratorHelper, mDozeParameters, mCommandQueue, mVibratorHelper,
@@ -364,6 +383,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mQuickAccessWalletClient, mQuickAccessWalletClient,
mKeyguardMediaController, mKeyguardMediaController,
mPrivacyDotViewController, mPrivacyDotViewController,
mTapAgainViewController,
mFragmentService,
new FakeExecutor(new FakeSystemClock()), new FakeExecutor(new FakeSystemClock()),
mSecureSettings); mSecureSettings);
mNotificationPanelViewController.initDependencies( mNotificationPanelViewController.initDependencies(
@@ -371,6 +392,13 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mNotificationShelfController); mNotificationShelfController);
mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager); mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
mNotificationPanelViewController.setBar(mPanelBar); mNotificationPanelViewController.setBar(mPanelBar);
mNotificationPanelViewController.setKeyguardIndicationController(
mKeyguardIndicationController);
ArgumentCaptor<View.OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor =
ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
verify(mView, atLeast(1)).addOnAttachStateChangeListener(
onAttachStateChangeListenerArgumentCaptor.capture());
mOnAttachStateChangeListeners = onAttachStateChangeListenerArgumentCaptor.getAllValues();
ArgumentCaptor<View.AccessibilityDelegate> accessibilityDelegateArgumentCaptor = ArgumentCaptor<View.AccessibilityDelegate> accessibilityDelegateArgumentCaptor =
ArgumentCaptor.forClass(View.AccessibilityDelegate.class); ArgumentCaptor.forClass(View.AccessibilityDelegate.class);
@@ -616,6 +644,34 @@ public class NotificationPanelViewTest extends SysuiTestCase {
verify(mKeyguardStateController).notifyPanelFlingEnd(); verify(mKeyguardStateController).notifyPanelFlingEnd();
} }
@Test
public void testDoubleTapRequired_Keyguard() {
FalsingManager.FalsingTapListener listener = getFalsingTapListener();
mStatusBarStateController.setState(KEYGUARD);
listener.onDoubleTapRequired();
verify(mKeyguardIndicationController).showTransientIndication(anyInt());
}
@Test
public void testDoubleTapRequired_ShadeLocked() {
FalsingManager.FalsingTapListener listener = getFalsingTapListener();
mStatusBarStateController.setState(SHADE_LOCKED);
listener.onDoubleTapRequired();
verify(mTapAgainViewController).show();
}
private FalsingManager.FalsingTapListener getFalsingTapListener() {
for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
listener.onViewAttachedToWindow(mView);
}
assertThat(mFalsingManager.getTapListeners().size()).isEqualTo(1);
return mFalsingManager.getTapListeners().get(0);
}
private View newViewWithId(int id) { private View newViewWithId(int id) {
View view = new View(mContext); View view = new View(mContext);
view.setId(id); view.setId(id);