Merge changes Id51293db,Ib7586997 into sc-dev

* changes:
  Tests for media player on the left side on lockscreen in split shade mode
  Moving media player in split shade mode on the lockscreen to the left side
This commit is contained in:
TreeHugger Robot
2021-04-27 18:41:29 +00:00
committed by Android (Google) Code Review
13 changed files with 266 additions and 95 deletions

View File

@@ -20,12 +20,14 @@
<!-- This is a view that shows general status information in Keyguard. -->
<com.android.keyguard.KeyguardStatusView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/res-auto"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_status_view"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal|top">
systemui:layout_constraintStart_toStartOf="parent"
systemui:layout_constraintEnd_toEndOf="parent"
systemui:layout_constraintTop_toTopOf="parent"
android:layout_width="0dp"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/status_view_container"
android:layout_width="match_parent"
@@ -70,5 +72,11 @@
android:letterSpacing="0.05"
android:ellipsize="marquee"
android:singleLine="true" />
<FrameLayout
android:id="@+id/status_view_media_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/qs_media_padding"
/>
</LinearLayout>
</com.android.keyguard.KeyguardStatusView>

View File

@@ -37,10 +37,6 @@
android:layout_height="match_parent"
android:layout_width="match_parent" />
<include
layout="@layout/keyguard_status_view"
android:visibility="gone" />
<com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -49,6 +45,10 @@
android:clipToPadding="false"
android:clipChildren="false">
<include
layout="@layout/keyguard_status_view"
android:visibility="gone"/>
<include layout="@layout/dock_info_overlay" />
<FrameLayout

View File

@@ -35,6 +35,7 @@ import androidx.core.graphics.ColorUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -44,6 +45,7 @@ import java.io.PrintWriter;
* - keyguard clock
* - logout button (on certain managed devices)
* - owner information (if set)
* - media player (split shade mode only)
*/
public class KeyguardStatusView extends GridLayout {
private static final boolean DEBUG = KeyguardConstants.DEBUG;
@@ -60,6 +62,7 @@ public class KeyguardStatusView extends GridLayout {
private KeyguardSliceView mKeyguardSlice;
private Runnable mPendingMarqueeStart;
private Handler mHandler;
private View mMediaHostContainer;
private float mDarkAmount = 0;
private int mTextColor;
@@ -148,6 +151,8 @@ public class KeyguardStatusView extends GridLayout {
mKeyguardSlice.setContentChangeListener(this::onSliceContentChanged);
onSliceContentChanged();
mMediaHostContainer = findViewById(R.id.status_view_media_container);
updateOwnerInfo();
updateDark();
}
@@ -223,6 +228,9 @@ public class KeyguardStatusView extends GridLayout {
}
mDarkAmount = darkAmount;
mClockView.setDarkAmount(darkAmount);
if (mMediaHostContainer.getVisibility() != View.GONE) {
CrossFadeHelper.fadeOut(mMediaHostContainer, darkAmount);
}
updateDark();
}

View File

@@ -17,6 +17,7 @@
package com.android.systemui.media
import android.view.View
import android.view.ViewGroup
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.media.dagger.MediaModule.KEYGUARD
import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -29,8 +30,8 @@ import javax.inject.Inject
import javax.inject.Named
/**
* A class that controls the media notifications on the lock screen, handles its visibility and
* is responsible for the embedding of he media experience.
* Controls the media notifications on the lock screen, handles its visibility and placement -
* switches media player positioning between split pane container vs single pane container
*/
@SysUISingleton
class KeyguardMediaController @Inject constructor(
@@ -43,46 +44,114 @@ class KeyguardMediaController @Inject constructor(
init {
statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
override fun onStateChanged(newState: Int) {
updateVisibility()
refreshMediaPosition()
}
override fun onDozingChanged(isDozing: Boolean) {
if (!isDozing) {
mediaHost.visible = true
refreshMediaPosition()
}
}
})
}
var visibilityChangedListener: ((Boolean) -> 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)
}
}
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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 =

View File

@@ -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;

View File

@@ -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);

View File

@@ -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,

View File

@@ -19,26 +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.mockito.capture
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.ArgumentCaptor
import org.mockito.Captor
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)
@@ -52,51 +49,81 @@ class KeyguardMediaControllerTest : SysuiTestCase() {
private lateinit var statusBarStateController: SysuiStatusBarStateController
@Mock
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 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)
keyguardMediaController.attachSinglePaneContainer(mediaHeaderView)
}
@Test
fun testAttach_hiddenWhenHostIsHidden() {
`when`(mediaHost.visible).thenReturn(false)
triggerVisibilityListener()
fun testHiddenWhenHostIsHidden() {
whenever(mediaHost.visible).thenReturn(false)
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)
triggerVisibilityListener()
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)
triggerVisibilityListener()
verify(mediaHeaderView, atLeastOnce()).visibility = eq(GONE)
keyguardMediaController.refreshMediaPosition()
assertThat(mediaHeaderView.visibility).isEqualTo(GONE)
}
private fun triggerVisibilityListener() {
keyguardMediaController.attach(mediaHeaderView)
verify(mediaHost).addVisibilityChangeListener(capture(visibilityListener))
visibilityListener.value.invoke(true)
@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)
}
}

View File

@@ -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() {
@@ -264,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
@@ -397,7 +411,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);
}
}

View File

@@ -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;
@@ -282,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(
@@ -346,6 +350,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mLockIconViewController,
mFeatureFlags,
mQuickAccessWalletClient,
mKeyguardMediaController,
new FakeExecutor(new FakeSystemClock()));
mNotificationPanelViewController.initDependencies(
mStatusBar,
@@ -475,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();