diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalHostViewController.java b/packages/SystemUI/src/com/android/systemui/communal/CommunalHostViewController.java index b84d9ce147d62..b06f4430d0e9e 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/CommunalHostViewController.java +++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalHostViewController.java @@ -28,6 +28,10 @@ import com.android.keyguard.KeyguardVisibilityHelper; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.notification.AnimatableProperty; +import com.android.systemui.statusbar.notification.PropertyAnimator; +import com.android.systemui.statusbar.notification.stack.AnimationProperties; +import com.android.systemui.statusbar.notification.stack.StackStateAnimator; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -51,6 +55,8 @@ public class CommunalHostViewController extends ViewController private static final String TAG = "CommunalController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final String STATE_LIST_FORMAT = "[%s]"; + private static final AnimationProperties COMMUNAL_ANIMATION_PROPERTIES = + new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); private final Executor mMainExecutor; private final CommunalStateController mCommunalStateController; @@ -354,6 +360,14 @@ public class CommunalHostViewController extends ViewController showSource(); } + /** + * Update position of the view with an optional animation + */ + public void updatePosition(int y, boolean animate) { + PropertyAnimator.setProperty(mView, AnimatableProperty.Y, y, COMMUNAL_ANIMATION_PROPERTIES, + animate); + } + /** * Invoked when the quick settings is expanded. * @param expansionFraction the percentage the QS shade has been expanded. diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalHostViewPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/communal/CommunalHostViewPositionAlgorithm.java new file mode 100644 index 0000000000000..424da0b111c5a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalHostViewPositionAlgorithm.java @@ -0,0 +1,74 @@ +/* + * 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.communal; + +import android.util.Log; + +import com.android.systemui.statusbar.phone.NotificationPanelViewController; + +/** + * {@link CommunalHostViewPositionAlgorithm} calculates the position of the communal view given + * input such as the notification panel position. + */ +public class CommunalHostViewPositionAlgorithm { + private static final String TAG = "CommunalPositionAlg"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + /** + * @see NotificationPanelViewController#getExpandedFraction() + */ + private float mPanelExpansion; + + /** + * Height of {@link CommunalHostView}. + */ + private int mCommunalHeight; + + /** + * A data container for the result of the position algorithm. + */ + public static class Result { + /** + * The y translation of the clock. + */ + public int communalY; + } + + /** + * Sets the conditions under which the result should be calculated from. + * @param panelExpansion The percentage the keyguard panel has been moved upwards. + * @param communalHeight The height of the communal panel. + */ + public void setup(float panelExpansion, int communalHeight) { + if (DEBUG) { + Log.d(TAG, "setup. panelExpansion:" + panelExpansion); + } + mPanelExpansion = panelExpansion; + mCommunalHeight = communalHeight; + } + + /** + * Calculates the position based on factors input through {link {@link #setup(float, int)}}. + * @param result The resulting calculations. + */ + public void run(Result result) { + // The panel expansion relates to the keyguard expansion. At full expansion, the communal + // view should be aligned at the top (0). Otherwise, it should be shifted offscreen by the + // unexpanded amount. + result.communalY = (int) ((1 - mPanelExpansion) * -mCommunalHeight); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 4ab6e92ca1be3..d0c9962ba5b4f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -108,6 +108,7 @@ import com.android.systemui.classifier.Classifier; import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.communal.CommunalHostView; import com.android.systemui.communal.CommunalHostViewController; +import com.android.systemui.communal.CommunalHostViewPositionAlgorithm; import com.android.systemui.communal.CommunalSource; import com.android.systemui.communal.CommunalSourceMonitor; import com.android.systemui.communal.CommunalStateController; @@ -381,6 +382,12 @@ public class NotificationPanelViewController extends PanelViewController { private final KeyguardClockPositionAlgorithm.Result mClockPositionResult = new KeyguardClockPositionAlgorithm.Result(); + private final CommunalHostViewPositionAlgorithm + mCommunalPositionAlgorithm = + new CommunalHostViewPositionAlgorithm(); + private final CommunalHostViewPositionAlgorithm.Result + mCommunalPositionResult = + new CommunalHostViewPositionAlgorithm.Result(); private boolean mIsExpanding; private boolean mBlockTouches; @@ -1307,6 +1314,11 @@ public class NotificationPanelViewController extends PanelViewController { boolean animate = mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending(); int stackScrollerPadding; boolean onKeyguard = isOnKeyguard(); + + if (onKeyguard) { + updateCommunalViewAppearance(); + } + if (onKeyguard || forceClockUpdate) { updateClockAppearance(); } @@ -1332,6 +1344,22 @@ public class NotificationPanelViewController extends PanelViewController { mAnimateNextPositionUpdate = false; } + private void updateCommunalViewAppearance() { + if (mCommunalViewController == null) { + return; + } + + float expandedFraction = + mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying() + ? 1.0f : getExpandedFraction(); + mCommunalPositionAlgorithm.setup(expandedFraction, mCommunalView.getHeight()); + mCommunalPositionAlgorithm.run(mCommunalPositionResult); + boolean animate = + mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending() + || mAnimateNextPositionUpdate; + mCommunalViewController.updatePosition(mCommunalPositionResult.communalY, animate); + } + private void updateClockAppearance() { int userSwitcherPreferredY = mStatusBarHeaderHeightKeyguard; boolean bypassEnabled = mKeyguardBypassController.getBypassEnabled(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalHostViewPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalHostViewPositionAlgorithmTest.java new file mode 100644 index 0000000000000..0a0266bc19554 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalHostViewPositionAlgorithmTest.java @@ -0,0 +1,44 @@ +/* + * 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.communal; + +import static com.google.common.truth.Truth.assertThat; + +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.communal.CommunalHostViewPositionAlgorithm.Result; + +import org.junit.Test; + + +@SmallTest +public class CommunalHostViewPositionAlgorithmTest extends SysuiTestCase { + @Test + public void testOutput() { + final float expansion = 0.25f; + final int height = 120; + + final CommunalHostViewPositionAlgorithm algorithm = new CommunalHostViewPositionAlgorithm(); + algorithm.setup(expansion, height); + final Result result = new Result(); + algorithm.run(result); + + // Verify the communal view is shifted offscreen vertically by the correct amount. + assertThat((1 - expansion) * -height).isEqualTo(result.communalY); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java index f6e06cc6a59b9..99f6354b27cee 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java @@ -908,6 +908,20 @@ public class NotificationPanelViewTest extends SysuiTestCase { verify(mCommunalHostViewController).setAlpha(anyFloat()); } + @Test + public void testCommunalPositionUpdate() { + // Verify that the communal position is updated on interaction with the + // NotificationPanelViewController. Note that there a number of paths where the position + // might be updated and therefore the check isn't strictly on a single invocation. + clearInvocations(mCommunalHostViewController); + final View.OnLayoutChangeListener layoutChangeListener = + mNotificationPanelViewController.createLayoutChangeListener(); + mNotificationPanelViewController.mStatusBarStateController.setState(KEYGUARD); + layoutChangeListener.onLayoutChange(mView, 0, 0, 200, 200, 0, 0, 200, 200); + verify(mCommunalHostViewController, atLeast(1)) + .updatePosition(anyInt(), anyBoolean()); + } + private void triggerPositionClockAndNotifications() { mNotificationPanelViewController.closeQs(); }