From 4e0bac824362c0ad43f4d6666522d4ad31697069 Mon Sep 17 00:00:00 2001 From: Michal Brzezinski Date: Thu, 4 Mar 2021 16:31:57 +0000 Subject: [PATCH 1/2] Moving media player in split shade mode on the lockscreen to the left side Bug: 181882240 Test: manual Change-Id: Ib75869971168b3a514b961262ee8a02659f8ae74 --- .../layout/keyguard_status_view.xml | 16 ++- .../res/layout/status_bar_expanded.xml | 8 +- .../android/keyguard/KeyguardStatusView.java | 8 ++ .../systemui/media/KeyguardMediaController.kt | 105 +++++++++++++++--- .../com/android/systemui/media/MediaHost.kt | 11 +- .../notification/stack/MediaHeaderView.java | 8 -- .../stack/NotificationSectionsManager.kt | 2 +- ...tificationStackScrollLayoutController.java | 5 +- .../phone/KeyguardClockPositionAlgorithm.java | 26 +++-- .../NotificationPanelViewController.java | 40 +++++-- .../media/KeyguardMediaControllerTest.kt | 20 +--- .../KeyguardClockPositionAlgorithmTest.java | 3 +- .../phone/NotificationPanelViewTest.java | 4 + 13 files changed, 182 insertions(+), 74 deletions(-) diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml index c5ba3d2a36cf4..7f645ba816647 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml @@ -20,12 +20,14 @@ + systemui:layout_constraintStart_toStartOf="parent" + systemui:layout_constraintEnd_toEndOf="parent" + systemui:layout_constraintTop_toTopOf="parent" + android:layout_width="0dp" + android:layout_height="wrap_content"> + diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml index 46a698a092e38..52995ea41b030 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded.xml @@ -37,10 +37,6 @@ android:layout_height="match_parent" android:layout_width="match_parent" /> - - + + Unit)? = null - var view: MediaHeaderView? = null - private set /** - * Attach this controller to a media view, initializing its state + * single pane media container placed at the top of the notifications list */ - fun attach(mediaView: MediaHeaderView) { - view = mediaView + var singlePaneContainer: MediaHeaderView? = null + private set + private var splitShadeContainer: ViewGroup? = null + private var useSplitShadeContainer: () -> Boolean = { false } + + /** + * Attaches media container in single pane mode, situated at the top of the notifications list + */ + fun attachSinglePaneContainer(mediaView: MediaHeaderView?) { + singlePaneContainer = mediaView // First let's set the desired state that we want for this host - mediaHost.addVisibilityChangeListener { updateVisibility() } - mediaHost.expansion = 0.0f + mediaHost.expansion = MediaHostState.COLLAPSED mediaHost.showsOnlyActiveMedia = true mediaHost.falsingProtectionNeeded = true // Let's now initialize this view, which also creates the host view for us. mediaHost.init(MediaHierarchyManager.LOCATION_LOCKSCREEN) - mediaView.setContentView(mediaHost.hostView) - - // Ensure the visibility is correct - updateVisibility() + // Required to show it for the first time, afterwards visibility is managed automatically + mediaHost.visible = true + mediaHost.addVisibilityChangeListener { visible -> + refreshMediaPosition() + if (visible) { + mediaHost.hostView.layoutParams.apply { + height = ViewGroup.LayoutParams.WRAP_CONTENT + width = ViewGroup.LayoutParams.MATCH_PARENT + } + } + } + refreshMediaPosition() } - private fun updateVisibility() { + /** + * Attaches media container in split shade mode, situated to the left of notifications + */ + fun attachSplitShadeContainer(container: ViewGroup, useContainer: () -> Boolean) { + splitShadeContainer = container + useSplitShadeContainer = useContainer + } + + fun refreshMediaPosition() { val keyguardOrUserSwitcher = (statusBarStateController.state == StatusBarState.KEYGUARD || statusBarStateController.state == StatusBarState.FULLSCREEN_USER_SWITCHER) + // mediaHost.visible required for proper animations handling val shouldBeVisible = mediaHost.visible && !bypassController.bypassEnabled && keyguardOrUserSwitcher && notifLockscreenUserManager.shouldShowLockscreenNotifications() - val previousVisibility = view?.visibility ?: View.GONE - val newVisibility = if (shouldBeVisible) View.VISIBLE else View.GONE + if (shouldBeVisible) { + showMediaPlayer() + } else { + hideMediaPlayer() + } + } + + private fun showMediaPlayer() { + if (useSplitShadeContainer()) { + showMediaPlayer( + activeContainer = splitShadeContainer, + inactiveContainer = singlePaneContainer) + } else { + showMediaPlayer( + activeContainer = singlePaneContainer, + inactiveContainer = splitShadeContainer) + } + } + + private fun showMediaPlayer(activeContainer: ViewGroup?, inactiveContainer: ViewGroup?) { + if (inactiveContainer?.childCount == 1) { + inactiveContainer.removeAllViews() + } + // might be called a few times for the same view, no need to add hostView again + if (activeContainer?.childCount == 0) { + activeContainer.addView(mediaHost.hostView) + } + setVisibility(activeContainer, View.VISIBLE) + setVisibility(inactiveContainer, View.GONE) + } + + private fun hideMediaPlayer() { + if (useSplitShadeContainer()) { + setVisibility(splitShadeContainer, View.GONE) + } else { + setVisibility(singlePaneContainer, View.GONE) + } + } + + private fun setVisibility(view: ViewGroup?, newVisibility: Int) { + val previousVisibility = view?.visibility view?.visibility = newVisibility if (previousVisibility != newVisibility) { - visibilityChangedListener?.invoke(shouldBeVisible) + visibilityChangedListener?.invoke(newVisibility == View.VISIBLE) } } } \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt index 8c12a305992e3..2347481d1c3de 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt @@ -264,15 +264,20 @@ class MediaHost constructor( */ interface MediaHostState { + companion object { + const val EXPANDED: Float = 1.0f + const val COLLAPSED: Float = 0.0f + } + /** - * The last measurement input that this state was measured with. Infers with and height of + * The last measurement input that this state was measured with. Infers width and height of * the players. */ var measurementInput: MeasurementInput? /** - * The expansion of the player, 0 for fully collapsed (up to 3 actions), 1 for fully expanded - * (up to 5 actions.) + * The expansion of the player, [COLLAPSED] for fully collapsed (up to 3 actions), + * [EXPANDED] for fully expanded (up to 5 actions). */ var expansion: Float diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java index 040f707e12f10..0247a99bc6c0d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java @@ -19,7 +19,6 @@ package com.android.systemui.statusbar.notification.stack; import android.animation.AnimatorListenerAdapter; import android.content.Context; import android.util.AttributeSet; -import android.view.ViewGroup; import com.android.systemui.statusbar.notification.row.ExpandableView; @@ -43,11 +42,4 @@ public class MediaHeaderView extends ExpandableView { public void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear) { // No animation, it doesn't need it, this would be local } - - public void setContentView(ViewGroup contentView) { - addView(contentView); - ViewGroup.LayoutParams layoutParams = contentView.getLayoutParams(); - layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; - layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT; - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt index b06f7d25db163..45ce20a1f08fd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt @@ -138,7 +138,7 @@ class NotificationSectionsManager @Inject internal constructor( incomingHeaderController.reinflateView(parent) mediaControlsView = reinflateView(mediaControlsView, layoutInflater, R.layout.keyguard_media_header) - .also(keyguardMediaController::attach) + keyguardMediaController.attachSinglePaneContainer(mediaControlsView) } override fun beginsSection(view: View, previous: View?): Boolean = diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 36a370c712166..527443eff1687 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -708,9 +708,10 @@ public class NotificationStackScrollLayoutController { mView.setKeyguardMediaControllorVisible(visible); if (visible) { mView.generateAddAnimation( - mKeyguardMediaController.getView(), false /*fromMoreCard */); + mKeyguardMediaController.getSinglePaneContainer(), + false /*fromMoreCard */); } else { - mView.generateRemoveAnimation(mKeyguardMediaController.getView()); + mView.generateRemoveAnimation(mKeyguardMediaController.getSinglePaneContainer()); } mView.requestChildrenUpdate(); return Unit.INSTANCE; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java index 481b2db16964e..069c19770aef1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java @@ -155,6 +155,8 @@ public class KeyguardClockPositionAlgorithm { private int mLockScreenMode; + private boolean mIsSplitShade; + /** * Refreshes the dimension values. */ @@ -180,7 +182,7 @@ public class KeyguardClockPositionAlgorithm { int keyguardStatusHeight, int userSwitchHeight, int clockPreferredY, int userSwitchPreferredY, boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float emptyDragAmount, boolean bypassEnabled, int unlockedStackScrollerPadding, - float qsExpansion, int cutoutTopInset) { + float qsExpansion, int cutoutTopInset, boolean isSplitShade) { mMinTopMargin = keyguardStatusBarHeaderHeight + Math.max(mContainerTopPadding, userSwitchHeight); mMaxShadeBottom = maxShadeBottom; @@ -199,6 +201,7 @@ public class KeyguardClockPositionAlgorithm { mUnlockedStackScrollerPadding = unlockedStackScrollerPadding; mQsExpansion = qsExpansion; mCutoutTopInset = cutoutTopInset; + mIsSplitShade = isSplitShade; } public void run(Result result) { @@ -208,14 +211,23 @@ public class KeyguardClockPositionAlgorithm { result.clockYFullyDozing = getClockY( 1.0f /* panelExpansion */, 1.0f /* darkAmount */); result.clockAlpha = getClockAlpha(y); - result.stackScrollerPadding = mBypassEnabled ? mUnlockedStackScrollerPadding - : y + mKeyguardStatusHeight; + result.stackScrollerPadding = getStackScrollerPadding(y); result.stackScrollerPaddingExpanded = mBypassEnabled ? mUnlockedStackScrollerPadding : getClockY(1.0f, mDarkAmount) + mKeyguardStatusHeight; result.clockX = (int) interpolate(0, burnInPreventionOffsetX(), mDarkAmount); result.clockScale = interpolate(getBurnInScale(), 1.0f, 1.0f - mDarkAmount); } + private int getStackScrollerPadding(int clockYPosition) { + if (mBypassEnabled) { + return mUnlockedStackScrollerPadding; + } else if (mIsSplitShade) { + return clockYPosition; + } else { + return clockYPosition + mKeyguardStatusHeight; + } + } + /** * Update lock screen mode for testing different layouts */ @@ -232,15 +244,11 @@ public class KeyguardClockPositionAlgorithm { return mHeight / 2 - mKeyguardStatusHeight - mClockNotificationsMargin; } - private int getPreferredClockY() { - return mClockPreferredY; - } - private int getExpandedPreferredClockY() { if (mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) { return mMinTopMargin + mUserSwitchHeight; } - return (mHasCustomClock && (!mHasVisibleNotifs || mBypassEnabled)) ? getPreferredClockY() + return (mHasCustomClock && (!mHasVisibleNotifs || mBypassEnabled)) ? mClockPreferredY : getExpandedClockPosition(); } @@ -271,7 +279,7 @@ public class KeyguardClockPositionAlgorithm { private int getClockY(float panelExpansion, float darkAmount) { // Dark: Align the bottom edge of the clock at about half of the screen: - float clockYDark = (mHasCustomClock ? getPreferredClockY() : getMaxClockY()) + float clockYDark = (mHasCustomClock ? mClockPreferredY : getMaxClockY()) + burnInPreventionOffsetY(); clockYDark = MathUtils.max(0, clockYDark); 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 d85be1df1b999..8574830e642ce 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -28,6 +28,7 @@ import static com.android.systemui.classifier.Classifier.QS_COLLAPSE; import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL; +import static com.android.systemui.util.Utils.shouldUseSplitNotificationShade; import static java.lang.Float.isNaN; @@ -99,6 +100,7 @@ import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.doze.DozeLog; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.fragments.FragmentHostManager.FragmentListener; +import com.android.systemui.media.KeyguardMediaController; import com.android.systemui.media.MediaDataManager; import com.android.systemui.media.MediaHierarchyManager; import com.android.systemui.plugins.FalsingManager; @@ -527,6 +529,7 @@ public class NotificationPanelViewController extends PanelViewController { private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL; private int mScrimCornerRadius; + private KeyguardMediaController mKeyguardMediaController; private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() { @Override @@ -597,6 +600,7 @@ public class NotificationPanelViewController extends PanelViewController { LockIconViewController lockIconViewController, FeatureFlags featureFlags, QuickAccessWalletClient quickAccessWalletClient, + KeyguardMediaController keyguardMediaController, @Main Executor uiExecutor) { super(view, falsingManager, dozeLog, keyguardStateController, (SysuiStatusBarStateController) statusBarStateController, vibratorHelper, @@ -604,6 +608,7 @@ public class NotificationPanelViewController extends PanelViewController { statusBarTouchableRegionManager, ambientState); mView = view; mVibratorHelper = vibratorHelper; + mKeyguardMediaController = keyguardMediaController; mMetricsLogger = metricsLogger; mActivityManager = activityManager; mConfigurationController = configurationController; @@ -771,7 +776,6 @@ public class NotificationPanelViewController extends PanelViewController { }); mView.setAccessibilityDelegate(mAccessibilityDelegate); - // dynamically apply the split shade value overrides. if (mShouldUseSplitNotificationShade) { updateResources(); } @@ -889,13 +893,17 @@ public class NotificationPanelViewController extends PanelViewController { constraintSet.connect( R.id.notification_stack_scroller, START, R.id.qs_edge_guideline, START); + constraintSet.connect(R.id.keyguard_status_view, END, R.id.qs_edge_guideline, END); } else { constraintSet.connect(R.id.qs_frame, END, PARENT_ID, END); constraintSet.connect(R.id.notification_stack_scroller, START, PARENT_ID, START); + constraintSet.connect(R.id.keyguard_status_view, END, PARENT_ID, END); } constraintSet.getConstraint(R.id.notification_stack_scroller).layout.mWidth = panelWidth; constraintSet.getConstraint(R.id.qs_frame).layout.mWidth = qsWidth; constraintSet.applyTo(mNotificationContainerParent); + + mKeyguardMediaController.refreshMediaPosition(); } private static void ensureAllViewsHaveIds(ViewGroup parentView) { @@ -929,12 +937,18 @@ public class NotificationPanelViewController extends PanelViewController { private void reInflateViews() { if (DEBUG) Log.d(TAG, "reInflateViews"); // Re-inflate the status view group. - KeyguardStatusView keyguardStatusView = mView.findViewById(R.id.keyguard_status_view); - int index = mView.indexOfChild(keyguardStatusView); - mView.removeView(keyguardStatusView); + KeyguardStatusView keyguardStatusView = + mNotificationContainerParent.findViewById(R.id.keyguard_status_view); + int statusIndex = mNotificationContainerParent.indexOfChild(keyguardStatusView); + mNotificationContainerParent.removeView(keyguardStatusView); keyguardStatusView = (KeyguardStatusView) mLayoutInflater.inflate( - R.layout.keyguard_status_view, mView, false); - mView.addView(keyguardStatusView, index); + R.layout.keyguard_status_view, mNotificationContainerParent, false); + mNotificationContainerParent.addView(keyguardStatusView, statusIndex); + attachSplitShadeMediaPlayerContainer( + keyguardStatusView.findViewById(R.id.status_view_media_container)); + + // we need to update KeyguardStatusView constraints after reinflating it + updateResources(); // Re-inflate the keyguard user switcher group. boolean isUserSwitcherEnabled = mUserManager.isUserSwitcherEnabled(); @@ -956,11 +970,11 @@ public class NotificationPanelViewController extends PanelViewController { showKeyguardUserSwitcher /* enabled */); mBigClockContainer.removeAllViews(); - updateViewControllers( - keyguardStatusView, userAvatarView, mKeyguardStatusBar, keyguardUserSwitcherView); + updateViewControllers(mView.findViewById(R.id.keyguard_status_view), userAvatarView, + mKeyguardStatusBar, keyguardUserSwitcherView); // Update keyguard bottom area - index = mView.indexOfChild(mKeyguardBottomArea); + int index = mView.indexOfChild(mKeyguardBottomArea); mView.removeView(mKeyguardBottomArea); KeyguardBottomAreaView oldBottomArea = mKeyguardBottomArea; mKeyguardBottomArea = (KeyguardBottomAreaView) mLayoutInflater.inflate( @@ -998,6 +1012,11 @@ public class NotificationPanelViewController extends PanelViewController { setKeyguardBottomAreaVisibility(mBarState, false); } + private void attachSplitShadeMediaPlayerContainer(FrameLayout container) { + mKeyguardMediaController.attachSplitShadeContainer(container, + () -> mShouldUseSplitNotificationShade); + } + private void initBottomArea() { mAffordanceHelper = new KeyguardAffordanceHelper( mKeyguardAffordanceHelperCallback, mView.getContext(), mFalsingManager); @@ -1110,7 +1129,8 @@ public class NotificationPanelViewController extends PanelViewController { hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount, bypassEnabled, getUnlockedStackScrollerPadding(), getQsExpansionFraction(), - mDisplayCutoutTopInset); + mDisplayCutoutTopInset, + shouldUseSplitNotificationShade(mFeatureFlags, mResources)); mClockPositionAlgorithm.run(mClockPositionResult); mKeyguardStatusViewController.updatePosition( mClockPositionResult.clockX, mClockPositionResult.clockY, diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt index 730c941cc4140..1403b7674d097 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt @@ -27,13 +27,10 @@ import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.notification.stack.MediaHeaderView import com.android.systemui.statusbar.phone.KeyguardBypassController -import com.android.systemui.util.mockito.capture import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import org.mockito.ArgumentCaptor -import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.atLeastOnce @@ -54,8 +51,6 @@ class KeyguardMediaControllerTest : SysuiTestCase() { private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager @Mock private lateinit var mediaHeaderView: MediaHeaderView - @Captor - private lateinit var visibilityListener: ArgumentCaptor<((Boolean) -> Unit)> @JvmField @Rule val mockito = MockitoJUnit.rule() private lateinit var keyguardMediaController: KeyguardMediaController @@ -69,7 +64,8 @@ class KeyguardMediaControllerTest : SysuiTestCase() { @Test fun testAttach_hiddenWhenHostIsHidden() { `when`(mediaHost.visible).thenReturn(false) - triggerVisibilityListener() + + keyguardMediaController.attachSinglePaneContainer(mediaHeaderView) verify(mediaHeaderView, atLeastOnce()).visibility = eq(GONE) } @@ -79,7 +75,8 @@ class KeyguardMediaControllerTest : SysuiTestCase() { `when`(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD) `when`(notificationLockscreenUserManager.shouldShowLockscreenNotifications()) .thenReturn(true) - triggerVisibilityListener() + + keyguardMediaController.attachSinglePaneContainer(mediaHeaderView) verify(mediaHeaderView, atLeastOnce()).visibility = eq(VISIBLE) } @@ -89,14 +86,9 @@ class KeyguardMediaControllerTest : SysuiTestCase() { `when`(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD) `when`(notificationLockscreenUserManager.shouldShowLockscreenNotifications()) .thenReturn(false) - triggerVisibilityListener() + + keyguardMediaController.attachSinglePaneContainer(mediaHeaderView) verify(mediaHeaderView, atLeastOnce()).visibility = eq(GONE) } - - private fun triggerVisibilityListener() { - keyguardMediaController.attach(mediaHeaderView) - verify(mediaHost).addVisibilityChangeListener(capture(visibilityListener)) - visibilityListener.value.invoke(true) - } } \ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java index 02e2e4c793bcc..71519ce03a422 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java @@ -53,6 +53,7 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { private boolean mHasVisibleNotifs; private float mQsExpansion; private int mCutoutTopInset = 0; // in pixels + private boolean mIsSplitShade = false; @Before public void setUp() { @@ -397,7 +398,7 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { 0 /* userSwitchHeight */, mPreferredClockY, 0 /* userSwitchPreferredY */, mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG, false /* bypassEnabled */, 0 /* unlockedStackScrollerPadding */, mQsExpansion, - mCutoutTopInset); + mCutoutTopInset, mIsSplitShade); mClockPositionAlgorithm.run(mClockPosition); } } 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 2e4d253fad56d..63086e4d9e94d 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 @@ -75,6 +75,7 @@ import com.android.systemui.biometrics.AuthController; import com.android.systemui.classifier.FalsingCollectorFake; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.doze.DozeLog; +import com.android.systemui.media.KeyguardMediaController; import com.android.systemui.media.MediaDataManager; import com.android.systemui.media.MediaHierarchyManager; import com.android.systemui.qs.QSDetailDisplayer; @@ -240,6 +241,8 @@ public class NotificationPanelViewTest extends SysuiTestCase { private LockIconViewController mLockIconViewController; @Mock private QuickAccessWalletClient mQuickAccessWalletClient; + @Mock + private KeyguardMediaController mKeyguardMediaController; private SysuiStatusBarStateController mStatusBarStateController; private NotificationPanelViewController mNotificationPanelViewController; @@ -346,6 +349,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { mLockIconViewController, mFeatureFlags, mQuickAccessWalletClient, + mKeyguardMediaController, new FakeExecutor(new FakeSystemClock())); mNotificationPanelViewController.initDependencies( mStatusBar, From 89bd618dcb4d031e5a52fe6afa6a0620372608f5 Mon Sep 17 00:00:00 2001 From: Michal Brzezinski Date: Fri, 23 Apr 2021 11:48:45 +0000 Subject: [PATCH 2/2] Tests for media player on the left side on lockscreen in split shade mode Bug: 181882240 Test: atest KeyguardMediaControllerTest KeyguardClockPositionAlgorithmTest NotificationPanelViewTest Change-Id: Id51293dbd134ea45ed0084a89f2da48136599168 --- .../media/KeyguardMediaControllerTest.kt | 91 +++++++++++++------ .../KeyguardClockPositionAlgorithmTest.java | 13 +++ .../phone/NotificationPanelViewTest.java | 15 +++ 3 files changed, 91 insertions(+), 28 deletions(-) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt index 1403b7674d097..0d67d664c0789 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt @@ -19,23 +19,23 @@ package com.android.systemui.media import android.testing.AndroidTestingRunner import android.view.View.GONE import android.view.View.VISIBLE +import android.widget.FrameLayout import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase -import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.notification.stack.MediaHeaderView import com.android.systemui.statusbar.phone.KeyguardBypassController +import com.android.systemui.util.animation.UniqueObjectHostView +import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock -import org.mockito.Mockito.`when` -import org.mockito.Mockito.atLeastOnce -import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit +import org.mockito.Mockito.`when` as whenever @SmallTest @RunWith(AndroidTestingRunner::class) @@ -49,46 +49,81 @@ class KeyguardMediaControllerTest : SysuiTestCase() { private lateinit var statusBarStateController: SysuiStatusBarStateController @Mock private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager - @Mock - private lateinit var mediaHeaderView: MediaHeaderView @JvmField @Rule val mockito = MockitoJUnit.rule() + + private val mediaHeaderView: MediaHeaderView = MediaHeaderView(context, null) private lateinit var keyguardMediaController: KeyguardMediaController @Before fun setup() { + // default state is positive, media should show up + whenever(mediaHost.visible).thenReturn(true) + whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD) + whenever(notificationLockscreenUserManager.shouldShowLockscreenNotifications()) + .thenReturn(true) + whenever(mediaHost.hostView).thenReturn(UniqueObjectHostView(context)) + keyguardMediaController = KeyguardMediaController(mediaHost, bypassController, statusBarStateController, notificationLockscreenUserManager) - } - - @Test - fun testAttach_hiddenWhenHostIsHidden() { - `when`(mediaHost.visible).thenReturn(false) - keyguardMediaController.attachSinglePaneContainer(mediaHeaderView) - - verify(mediaHeaderView, atLeastOnce()).visibility = eq(GONE) } + @Test - fun testAttach_visibleOnKeyguard() { - `when`(mediaHost.visible).thenReturn(true) - `when`(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD) - `when`(notificationLockscreenUserManager.shouldShowLockscreenNotifications()) - .thenReturn(true) + fun testHiddenWhenHostIsHidden() { + whenever(mediaHost.visible).thenReturn(false) - keyguardMediaController.attachSinglePaneContainer(mediaHeaderView) + keyguardMediaController.refreshMediaPosition() - verify(mediaHeaderView, atLeastOnce()).visibility = eq(VISIBLE) + assertThat(mediaHeaderView.visibility).isEqualTo(GONE) } + @Test - fun testAttach_hiddenOnKeyguard_whenNotificationsAreHidden() { - `when`(mediaHost.visible).thenReturn(true) - `when`(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD) - `when`(notificationLockscreenUserManager.shouldShowLockscreenNotifications()) + fun testVisibleOnKeyguardOrFullScreenUserSwitcher() { + testStateVisibility(StatusBarState.SHADE, GONE) + testStateVisibility(StatusBarState.SHADE_LOCKED, GONE) + testStateVisibility(StatusBarState.FULLSCREEN_USER_SWITCHER, VISIBLE) + testStateVisibility(StatusBarState.KEYGUARD, VISIBLE) + } + + private fun testStateVisibility(state: Int, visibility: Int) { + whenever(statusBarStateController.state).thenReturn(state) + keyguardMediaController.refreshMediaPosition() + assertThat(mediaHeaderView.visibility).isEqualTo(visibility) + } + + @Test + fun testHiddenOnKeyguard_whenNotificationsAreHidden() { + whenever(notificationLockscreenUserManager.shouldShowLockscreenNotifications()) .thenReturn(false) - keyguardMediaController.attachSinglePaneContainer(mediaHeaderView) + keyguardMediaController.refreshMediaPosition() - verify(mediaHeaderView, atLeastOnce()).visibility = eq(GONE) + assertThat(mediaHeaderView.visibility).isEqualTo(GONE) } -} \ No newline at end of file + + @Test + fun testActivatesSplitShadeContainerInSplitShadeMode() { + val splitShadeContainer = FrameLayout(context) + keyguardMediaController.attachSplitShadeContainer( + splitShadeContainer, + useContainer = { true }) + + keyguardMediaController.refreshMediaPosition() + + assertThat(splitShadeContainer.visibility).isEqualTo(VISIBLE) + } + + @Test + fun testActivatesSinglePaneContainerInSinglePaneMode() { + val splitShadeContainer = FrameLayout(context) + keyguardMediaController.attachSplitShadeContainer( + splitShadeContainer, + useContainer = { false }) + + keyguardMediaController.refreshMediaPosition() + + assertThat(splitShadeContainer.visibility).isEqualTo(GONE) + assertThat(mediaHeaderView.visibility).isEqualTo(VISIBLE) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java index 71519ce03a422..152ba90858d61 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java @@ -265,6 +265,19 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { assertThat(mClockPosition.stackScrollerPadding).isEqualTo(810); } + @Test + public void notifPositionAlignedWithClockInSplitShadeMode() { + // GIVEN on lock screen and split shade mode + givenLockScreen(); + mIsSplitShade = true; + mPreferredClockY = 100; + mHasCustomClock = true; + // WHEN the position algorithm is run + positionClock(); + // THEN the notif padding DOESN'T adjust for keyguard status height. + assertThat(mClockPosition.stackScrollerPadding).isEqualTo(mPreferredClockY); + } + @Test public void notifPositionWithLargeClockOnLockScreen() { // GIVEN on lock screen and clock has a nonzero height 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 63086e4d9e94d..4bac7625cfed2 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 @@ -285,6 +285,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null); mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame)); mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller)); + mNotificationContainerParent.addView(newViewWithId(R.id.keyguard_status_view)); when(mView.findViewById(R.id.notification_container_parent)) .thenReturn(mNotificationContainerParent); FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder( @@ -479,6 +480,20 @@ public class NotificationPanelViewTest extends SysuiTestCase { .isEqualTo(ConstraintSet.PARENT_ID); } + @Test + public void testKeyguardStatusView_isAlignedToGuidelineInSplitShadeMode() { + mNotificationPanelViewController.updateResources(); + + assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd) + .isEqualTo(ConstraintSet.PARENT_ID); + + enableSplitShade(); + mNotificationPanelViewController.updateResources(); + + assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd) + .isEqualTo(R.id.qs_edge_guideline); + } + @Test public void testSplitShadeLayout_isAlignedToGuideline() { enableSplitShade();