Merge "Show a small toast when a double tap is needed." into sc-dev
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user