Merge "Fading away notification panel individually" into qt-r1-dev
am: b26223d9c1 Change-Id: I546633a9516a8d65fd17534e4f008042e5e2c78a
This commit is contained in:
commit
798c910075
@ -23,9 +23,11 @@
|
||||
android:fromAlpha="0.0" android:toAlpha="1.0"
|
||||
android:fillEnabled="true" android:fillBefore="true"
|
||||
android:interpolator="@interpolator/linear"
|
||||
android:startOffset="80"
|
||||
android:duration="233"/>
|
||||
<translate android:fromYDelta="5%p" android:toYDelta="0"
|
||||
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
|
||||
android:interpolator="@interpolator/fast_out_slow_in"
|
||||
android:startOffset="80"
|
||||
android:duration="233" />
|
||||
</set>
|
@ -98,6 +98,12 @@
|
||||
<item type="id" name="keyguard_hun_animator_start_tag"/>
|
||||
<item type="id" name="keyguard_hun_animator_end_tag"/>
|
||||
|
||||
<item type="id" name="view_group_fade_helper_modified_views"/>
|
||||
<item type="id" name="view_group_fade_helper_animator"/>
|
||||
<item type="id" name="view_group_fade_helper_previous_value_tag"/>
|
||||
<item type="id" name="view_group_fade_helper_restore_tag"/>
|
||||
<item type="id" name="view_group_fade_helper_hardware_layer"/>
|
||||
|
||||
<!-- Accessibility actions for the notification menu -->
|
||||
<item type="id" name="action_snooze_undo"/>
|
||||
<item type="id" name="action_snooze_shorter"/>
|
||||
|
@ -61,6 +61,7 @@ import android.util.EventLog;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManagerPolicyConstants;
|
||||
import android.view.animation.Animation;
|
||||
@ -85,6 +86,7 @@ import com.android.systemui.SystemUIFactory;
|
||||
import com.android.systemui.UiOffloadThread;
|
||||
import com.android.systemui.classifier.FalsingManagerFactory;
|
||||
import com.android.systemui.statusbar.phone.BiometricUnlockController;
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController;
|
||||
import com.android.systemui.statusbar.phone.NotificationPanelView;
|
||||
import com.android.systemui.statusbar.phone.StatusBar;
|
||||
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
|
||||
@ -2060,9 +2062,11 @@ public class KeyguardViewMediator extends SystemUI {
|
||||
|
||||
public StatusBarKeyguardViewManager registerStatusBar(StatusBar statusBar,
|
||||
ViewGroup container, NotificationPanelView panelView,
|
||||
BiometricUnlockController biometricUnlockController, ViewGroup lockIconContainer) {
|
||||
BiometricUnlockController biometricUnlockController, ViewGroup lockIconContainer,
|
||||
View notificationContainer, KeyguardBypassController bypassController) {
|
||||
mStatusBarKeyguardViewManager.registerStatusBar(statusBar, container, panelView,
|
||||
biometricUnlockController, mDismissCallbackRegistry, lockIconContainer);
|
||||
biometricUnlockController, mDismissCallbackRegistry, lockIconContainer,
|
||||
notificationContainer, bypassController);
|
||||
return mStatusBarKeyguardViewManager;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.notification
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorListenerAdapter
|
||||
import android.animation.ValueAnimator
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.android.systemui.Interpolators
|
||||
import com.android.systemui.R
|
||||
|
||||
/**
|
||||
* Class to help with fading of view groups without fading one subview
|
||||
*/
|
||||
class ViewGroupFadeHelper {
|
||||
companion object {
|
||||
private val visibilityIncluder = {
|
||||
view: View -> view.visibility == View.VISIBLE
|
||||
}
|
||||
|
||||
/**
|
||||
* Fade out all views of a root except a single child. This will iterate over all children
|
||||
* of the view and make sure that the animation works smoothly.
|
||||
* @param root the view root to fade the children away
|
||||
* @param excludedView which view should remain
|
||||
* @param duration the duration of the animation
|
||||
*/
|
||||
@JvmStatic
|
||||
fun fadeOutAllChildrenExcept(root: ViewGroup, excludedView: View, duration: Long,
|
||||
endRunnable: Runnable?) {
|
||||
// starting from the view going up, we are adding the siblings of the child to the set
|
||||
// of views that need to be faded.
|
||||
val viewsToFadeOut = gatherViews(root, excludedView, visibilityIncluder)
|
||||
|
||||
// Applying the right layertypes for the animation
|
||||
for (viewToFade in viewsToFadeOut) {
|
||||
if (viewToFade.hasOverlappingRendering
|
||||
&& viewToFade.layerType == View.LAYER_TYPE_NONE) {
|
||||
viewToFade.setLayerType(View.LAYER_TYPE_HARDWARE, null)
|
||||
viewToFade.setTag(R.id.view_group_fade_helper_hardware_layer, true)
|
||||
}
|
||||
}
|
||||
|
||||
val animator = ValueAnimator.ofFloat(1.0f, 0.0f).apply {
|
||||
this.duration = duration
|
||||
interpolator = Interpolators.ALPHA_OUT
|
||||
addUpdateListener { animation ->
|
||||
val previousSetAlpha = root.getTag(
|
||||
R.id.view_group_fade_helper_previous_value_tag) as Float?
|
||||
val newAlpha = animation.animatedValue as Float
|
||||
for (viewToFade in viewsToFadeOut) {
|
||||
if (viewToFade.alpha != previousSetAlpha) {
|
||||
// A value was set that wasn't set from our view, let's store it and restore
|
||||
// it at the end
|
||||
viewToFade.setTag(R.id.view_group_fade_helper_restore_tag, viewToFade.alpha)
|
||||
}
|
||||
viewToFade.alpha = newAlpha
|
||||
}
|
||||
root.setTag(R.id.view_group_fade_helper_previous_value_tag, newAlpha)
|
||||
}
|
||||
addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
endRunnable?.run()
|
||||
}
|
||||
})
|
||||
start()
|
||||
}
|
||||
root.setTag(R.id.view_group_fade_helper_modified_views, viewsToFadeOut)
|
||||
root.setTag(R.id.view_group_fade_helper_animator, animator)
|
||||
}
|
||||
|
||||
private fun gatherViews(root: ViewGroup, excludedView: View,
|
||||
shouldInclude: (View) -> Boolean): MutableSet<View> {
|
||||
val viewsToFadeOut = mutableSetOf<View>()
|
||||
var parent = excludedView.parent as ViewGroup?
|
||||
var viewContainingExcludedView = excludedView;
|
||||
while (parent != null) {
|
||||
for (i in 0 until parent.childCount) {
|
||||
val child = parent.getChildAt(i)
|
||||
if (shouldInclude.invoke(child) && viewContainingExcludedView != child) {
|
||||
viewsToFadeOut.add(child)
|
||||
}
|
||||
}
|
||||
if (parent == root) {
|
||||
break;
|
||||
}
|
||||
viewContainingExcludedView = parent
|
||||
parent = parent.parent as ViewGroup?
|
||||
}
|
||||
return viewsToFadeOut
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all view alphas for views previously transformed away.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun reset(root: ViewGroup) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val modifiedViews = root.getTag(R.id.view_group_fade_helper_modified_views)
|
||||
as MutableSet<View>?
|
||||
val animator = root.getTag(R.id.view_group_fade_helper_animator) as Animator?
|
||||
if (modifiedViews == null || animator == null) {
|
||||
// nothing to restore
|
||||
return
|
||||
}
|
||||
animator.cancel()
|
||||
val lastSetValue = root.getTag(
|
||||
R.id.view_group_fade_helper_previous_value_tag) as Float?
|
||||
for (viewToFade in modifiedViews) {
|
||||
val restoreAlpha = viewToFade.getTag(
|
||||
R.id.view_group_fade_helper_restore_tag) as Float?
|
||||
if (restoreAlpha == null) {
|
||||
continue
|
||||
}
|
||||
if (lastSetValue == viewToFade.alpha) {
|
||||
// it was modified after the transition!
|
||||
viewToFade.alpha = restoreAlpha
|
||||
}
|
||||
val needsLayerReset = viewToFade.getTag(
|
||||
R.id.view_group_fade_helper_hardware_layer) as Boolean?
|
||||
if (needsLayerReset == true) {
|
||||
viewToFade.setLayerType(View.LAYER_TYPE_NONE, null)
|
||||
viewToFade.setTag(R.id.view_group_fade_helper_hardware_layer, null)
|
||||
}
|
||||
viewToFade.setTag(R.id.view_group_fade_helper_restore_tag, null)
|
||||
}
|
||||
root.setTag(R.id.view_group_fade_helper_modified_views, null)
|
||||
root.setTag(R.id.view_group_fade_helper_previous_value_tag, null)
|
||||
root.setTag(R.id.view_group_fade_helper_animator, null)
|
||||
}
|
||||
}
|
||||
}
|
@ -202,6 +202,7 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
|
||||
import com.android.systemui.statusbar.notification.NotificationListController;
|
||||
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
|
||||
import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
|
||||
import com.android.systemui.statusbar.notification.VisualStabilityManager;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
|
||||
@ -1235,7 +1236,8 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
new Handler(), mKeyguardUpdateMonitor, mKeyguardBypassController);
|
||||
mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
|
||||
getBouncerContainer(), mNotificationPanel, mBiometricUnlockController,
|
||||
mStatusBarWindow.findViewById(R.id.lock_icon_container));
|
||||
mStatusBarWindow.findViewById(R.id.lock_icon_container), mStackScroller,
|
||||
mKeyguardBypassController);
|
||||
mKeyguardIndicationController
|
||||
.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
|
||||
mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
|
||||
@ -3172,6 +3174,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
mNotificationPanel.onAffordanceLaunchEnded();
|
||||
mNotificationPanel.animate().cancel();
|
||||
mNotificationPanel.setAlpha(1f);
|
||||
ViewGroupFadeHelper.reset(mNotificationPanel);
|
||||
updateScrimController();
|
||||
Trace.endSection();
|
||||
return staying;
|
||||
|
@ -17,6 +17,7 @@
|
||||
package com.android.systemui.statusbar.phone;
|
||||
|
||||
import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
|
||||
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_UNLOCK_FADING;
|
||||
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
|
||||
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
|
||||
|
||||
@ -51,6 +52,7 @@ import com.android.systemui.statusbar.NotificationMediaManager;
|
||||
import com.android.systemui.statusbar.RemoteInputController;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
|
||||
import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardMonitor;
|
||||
@ -82,6 +84,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
// make everything a bit slower to bridge a gap until the user is unlocked and home screen has
|
||||
// dranw its first frame.
|
||||
private static final long KEYGUARD_DISMISS_DURATION_LOCKED = 2000;
|
||||
private static final long BYPASS_PANEL_FADE_DURATION = 67;
|
||||
|
||||
private static String TAG = "StatusBarKeyguardViewManager";
|
||||
|
||||
@ -132,6 +135,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
|
||||
private ViewGroup mContainer;
|
||||
private ViewGroup mLockIconContainer;
|
||||
private View mNotificationContainer;
|
||||
|
||||
protected KeyguardBouncer mBouncer;
|
||||
protected boolean mShowing;
|
||||
@ -165,9 +169,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
(KeyguardMonitorImpl) Dependency.get(KeyguardMonitor.class);
|
||||
private final NotificationMediaManager mMediaManager =
|
||||
Dependency.get(NotificationMediaManager.class);
|
||||
private final StatusBarStateController mStatusBarStateController =
|
||||
Dependency.get(StatusBarStateController.class);
|
||||
private final SysuiStatusBarStateController mStatusBarStateController =
|
||||
(SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
|
||||
private final DockManager mDockManager;
|
||||
private KeyguardBypassController mBypassController;
|
||||
|
||||
private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
|
||||
new KeyguardUpdateMonitorCallback() {
|
||||
@ -205,7 +210,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
NotificationPanelView notificationPanelView,
|
||||
BiometricUnlockController biometricUnlockController,
|
||||
DismissCallbackRegistry dismissCallbackRegistry,
|
||||
ViewGroup lockIconContainer) {
|
||||
ViewGroup lockIconContainer, View notificationContainer,
|
||||
KeyguardBypassController bypassController) {
|
||||
mStatusBar = statusBar;
|
||||
mContainer = container;
|
||||
mLockIconContainer = lockIconContainer;
|
||||
@ -218,6 +224,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
mExpansionCallback);
|
||||
mNotificationPanelView = notificationPanelView;
|
||||
notificationPanelView.setExpansionListener(this);
|
||||
mBypassController = bypassController;
|
||||
mNotificationContainer = notificationContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -555,12 +563,32 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
mBiometricUnlockController.startKeyguardFadingAway();
|
||||
hideBouncer(true /* destroyView */);
|
||||
if (wakeUnlockPulsing) {
|
||||
mStatusBar.fadeKeyguardWhilePulsing();
|
||||
if (needsBypassFading()) {
|
||||
ViewGroupFadeHelper.fadeOutAllChildrenExcept(mNotificationPanelView,
|
||||
mNotificationContainer,
|
||||
BYPASS_PANEL_FADE_DURATION,
|
||||
() -> {
|
||||
mStatusBar.hideKeyguard();
|
||||
onKeyguardFadedAway();
|
||||
});
|
||||
} else {
|
||||
mStatusBar.fadeKeyguardWhilePulsing();
|
||||
}
|
||||
wakeAndUnlockDejank();
|
||||
} else {
|
||||
boolean staying = mStatusBar.hideKeyguard();
|
||||
boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide();
|
||||
if (!staying) {
|
||||
mStatusBarWindowController.setKeyguardFadingAway(true);
|
||||
if (needsBypassFading()) {
|
||||
ViewGroupFadeHelper.fadeOutAllChildrenExcept(mNotificationPanelView,
|
||||
mNotificationContainer,
|
||||
BYPASS_PANEL_FADE_DURATION,
|
||||
() -> {
|
||||
mStatusBar.hideKeyguard();
|
||||
});
|
||||
} else {
|
||||
mStatusBar.hideKeyguard();
|
||||
}
|
||||
// hide() will happen asynchronously and might arrive after the scrims
|
||||
// were already hidden, this means that the transition callback won't
|
||||
// be triggered anymore and StatusBarWindowController will be forever in
|
||||
@ -568,6 +596,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
mStatusBar.updateScrimController();
|
||||
wakeAndUnlockDejank();
|
||||
} else {
|
||||
mStatusBar.hideKeyguard();
|
||||
mStatusBar.finishKeyguardFadingAway();
|
||||
mBiometricUnlockController.finishKeyguardFadingAway();
|
||||
}
|
||||
@ -580,6 +609,13 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
StatsLog.KEYGUARD_STATE_CHANGED__STATE__HIDDEN);
|
||||
}
|
||||
|
||||
private boolean needsBypassFading() {
|
||||
return (mBiometricUnlockController.getMode() == MODE_UNLOCK_FADING
|
||||
|| mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING
|
||||
|| mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK)
|
||||
&& mBypassController.getBypassEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDensityOrFontScaleChanged() {
|
||||
hideBouncer(true /* destroyView */);
|
||||
@ -602,6 +638,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
public void onKeyguardFadedAway() {
|
||||
mContainer.postDelayed(() -> mStatusBarWindowController.setKeyguardFadingAway(false),
|
||||
100);
|
||||
ViewGroupFadeHelper.reset(mNotificationPanelView);
|
||||
mStatusBar.finishKeyguardFadingAway();
|
||||
mBiometricUnlockController.finishKeyguardFadingAway();
|
||||
WindowManagerGlobal.getInstance().trimMemory(
|
||||
@ -821,8 +858,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
* @return Whether subtle animation should be used for unlocking the device.
|
||||
*/
|
||||
public boolean shouldSubtleWindowAnimationsForUnlock() {
|
||||
return mStatusBar.mKeyguardBypassController.getBypassEnabled()
|
||||
&& mStatusBar.mState == StatusBarState.KEYGUARD && !mBouncer.isAnimatingAway();
|
||||
return needsBypassFading();
|
||||
}
|
||||
|
||||
public boolean isGoingToNotificationShade() {
|
||||
|
@ -29,6 +29,7 @@ import static org.mockito.Mockito.when;
|
||||
import android.content.Context;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
@ -39,6 +40,7 @@ import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.keyguard.DismissCallbackRegistry;
|
||||
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@ -70,7 +72,11 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private ViewGroup mLockIconContainer;
|
||||
@Mock
|
||||
private StatusBarStateController mStatusBarStateController;
|
||||
private SysuiStatusBarStateController mStatusBarStateController;
|
||||
@Mock
|
||||
private View mNotificationContainer;
|
||||
@Mock
|
||||
private KeyguardBypassController mBypassController;
|
||||
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||
|
||||
@Before
|
||||
@ -83,7 +89,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
|
||||
mViewMediatorCallback, mLockPatternUtils);
|
||||
mStatusBarKeyguardViewManager.registerStatusBar(mStatusBar, mContainer,
|
||||
mNotificationPanelView, mBiometrucUnlockController, mDismissCallbackRegistry,
|
||||
mLockIconContainer);
|
||||
mLockIconContainer, mNotificationContainer, mBypassController);
|
||||
mStatusBarKeyguardViewManager.show(null);
|
||||
}
|
||||
|
||||
@ -221,9 +227,11 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
|
||||
NotificationPanelView notificationPanelView,
|
||||
BiometricUnlockController fingerprintUnlockController,
|
||||
DismissCallbackRegistry dismissCallbackRegistry,
|
||||
ViewGroup lockIconContainer) {
|
||||
ViewGroup lockIconContainer, View notificationContainer,
|
||||
KeyguardBypassController bypassController) {
|
||||
super.registerStatusBar(statusBar, container, notificationPanelView,
|
||||
fingerprintUnlockController, dismissCallbackRegistry, lockIconContainer);
|
||||
fingerprintUnlockController, dismissCallbackRegistry, lockIconContainer,
|
||||
notificationContainer, bypassController);
|
||||
mBouncer = StatusBarKeyguardViewManagerTest.this.mBouncer;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user