Merge "Revert "Make media squishy for portrait shade open and close"" into tm-dev am: 5bcfb4c3fd am: 0dd9f89200
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18566290 Change-Id: I89bdf35e00f0e1c822720b153619a8daa7b453f4 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -199,14 +199,6 @@ class MediaHost constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override var squishFraction: Float = 1.0f
|
|
||||||
set(value) {
|
|
||||||
if (!value.equals(field)) {
|
|
||||||
field = value
|
|
||||||
changedListener?.invoke()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override var showsOnlyActiveMedia: Boolean = false
|
override var showsOnlyActiveMedia: Boolean = false
|
||||||
set(value) {
|
set(value) {
|
||||||
if (!value.equals(field)) {
|
if (!value.equals(field)) {
|
||||||
@@ -257,7 +249,6 @@ class MediaHost constructor(
|
|||||||
override fun copy(): MediaHostState {
|
override fun copy(): MediaHostState {
|
||||||
val mediaHostState = MediaHostStateHolder()
|
val mediaHostState = MediaHostStateHolder()
|
||||||
mediaHostState.expansion = expansion
|
mediaHostState.expansion = expansion
|
||||||
mediaHostState.squishFraction = squishFraction
|
|
||||||
mediaHostState.showsOnlyActiveMedia = showsOnlyActiveMedia
|
mediaHostState.showsOnlyActiveMedia = showsOnlyActiveMedia
|
||||||
mediaHostState.measurementInput = measurementInput?.copy()
|
mediaHostState.measurementInput = measurementInput?.copy()
|
||||||
mediaHostState.visible = visible
|
mediaHostState.visible = visible
|
||||||
@@ -276,9 +267,6 @@ class MediaHost constructor(
|
|||||||
if (expansion != other.expansion) {
|
if (expansion != other.expansion) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (squishFraction != other.squishFraction) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (showsOnlyActiveMedia != other.showsOnlyActiveMedia) {
|
if (showsOnlyActiveMedia != other.showsOnlyActiveMedia) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -297,7 +285,6 @@ class MediaHost constructor(
|
|||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
var result = measurementInput?.hashCode() ?: 0
|
var result = measurementInput?.hashCode() ?: 0
|
||||||
result = 31 * result + expansion.hashCode()
|
result = 31 * result + expansion.hashCode()
|
||||||
result = 31 * result + squishFraction.hashCode()
|
|
||||||
result = 31 * result + falsingProtectionNeeded.hashCode()
|
result = 31 * result + falsingProtectionNeeded.hashCode()
|
||||||
result = 31 * result + showsOnlyActiveMedia.hashCode()
|
result = 31 * result + showsOnlyActiveMedia.hashCode()
|
||||||
result = 31 * result + if (visible) 1 else 2
|
result = 31 * result + if (visible) 1 else 2
|
||||||
@@ -337,11 +324,6 @@ interface MediaHostState {
|
|||||||
*/
|
*/
|
||||||
var expansion: Float
|
var expansion: Float
|
||||||
|
|
||||||
/**
|
|
||||||
* Fraction of the height animation.
|
|
||||||
*/
|
|
||||||
var squishFraction: Float
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this host only showing active media or is it showing all of them including resumption?
|
* Is this host only showing active media or is it showing all of them including resumption?
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ package com.android.systemui.media
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import androidx.annotation.VisibleForTesting
|
|
||||||
import androidx.constraintlayout.widget.ConstraintSet
|
import androidx.constraintlayout.widget.ConstraintSet
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||||
@@ -276,62 +275,38 @@ class MediaViewController @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply squishFraction to a copy of viewState such that the cached version is untouched.
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
internal fun squishViewState(
|
|
||||||
viewState: TransitionViewState,
|
|
||||||
squishFraction: Float
|
|
||||||
): TransitionViewState {
|
|
||||||
val squishedViewState = viewState.copy()
|
|
||||||
squishedViewState.height = (squishedViewState.height * squishFraction).toInt()
|
|
||||||
val albumArtViewState = squishedViewState.widgetStates.get(R.id.album_art)
|
|
||||||
if (albumArtViewState != null) {
|
|
||||||
albumArtViewState.height = squishedViewState.height
|
|
||||||
}
|
|
||||||
return squishedViewState
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain a new viewState for a given media state. This usually returns a cached state, but if
|
* Obtain a new viewState for a given media state. This usually returns a cached state, but if
|
||||||
* it's not available, it will recreate one by measuring, which may be expensive.
|
* it's not available, it will recreate one by measuring, which may be expensive.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
private fun obtainViewState(state: MediaHostState?): TransitionViewState? {
|
||||||
public fun obtainViewState(state: MediaHostState?): TransitionViewState? {
|
|
||||||
if (state == null || state.measurementInput == null) {
|
if (state == null || state.measurementInput == null) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
// Only a subset of the state is relevant to get a valid viewState. Let's get the cachekey
|
// Only a subset of the state is relevant to get a valid viewState. Let's get the cachekey
|
||||||
var cacheKey = getKey(state, isGutsVisible, tmpKey)
|
var cacheKey = getKey(state, isGutsVisible, tmpKey)
|
||||||
val viewState = viewStates[cacheKey]
|
val viewState = viewStates[cacheKey]
|
||||||
|
|
||||||
if (viewState != null) {
|
if (viewState != null) {
|
||||||
// we already have cached this measurement, let's continue
|
// we already have cached this measurement, let's continue
|
||||||
if (state.squishFraction < 1f) {
|
|
||||||
return squishViewState(viewState, state.squishFraction)
|
|
||||||
}
|
|
||||||
return viewState
|
return viewState
|
||||||
}
|
}
|
||||||
// Copy the key since this might call recursively into it and we're using tmpKey
|
// Copy the key since this might call recursively into it and we're using tmpKey
|
||||||
cacheKey = cacheKey.copy()
|
cacheKey = cacheKey.copy()
|
||||||
val result: TransitionViewState?
|
val result: TransitionViewState?
|
||||||
if (transitionLayout == null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not cached. Let's create a new measurement
|
if (transitionLayout != null) {
|
||||||
|
// Let's create a new measurement
|
||||||
if (state.expansion == 0.0f || state.expansion == 1.0f) {
|
if (state.expansion == 0.0f || state.expansion == 1.0f) {
|
||||||
result = transitionLayout!!.calculateViewState(
|
result = transitionLayout!!.calculateViewState(
|
||||||
state.measurementInput!!,
|
state.measurementInput!!,
|
||||||
constraintSetForExpansion(state.expansion),
|
constraintSetForExpansion(state.expansion),
|
||||||
TransitionViewState())
|
TransitionViewState())
|
||||||
|
|
||||||
|
setGutsViewState(result)
|
||||||
// We don't want to cache interpolated or null states as this could quickly fill up
|
// We don't want to cache interpolated or null states as this could quickly fill up
|
||||||
// our cache. We only cache the start and the end states since the interpolation
|
// our cache. We only cache the start and the end states since the interpolation
|
||||||
// is cheap
|
// is cheap
|
||||||
setGutsViewState(result)
|
|
||||||
viewStates[cacheKey] = result
|
viewStates[cacheKey] = result
|
||||||
logger.logMediaSize("measured new viewState", result.width, result.height)
|
|
||||||
} else {
|
} else {
|
||||||
// This is an interpolated state
|
// This is an interpolated state
|
||||||
val startState = state.copy().also { it.expansion = 0.0f }
|
val startState = state.copy().also { it.expansion = 0.0f }
|
||||||
@@ -340,16 +315,14 @@ class MediaViewController @Inject constructor(
|
|||||||
// from the start and end state and interpolate them
|
// from the start and end state and interpolate them
|
||||||
val startViewState = obtainViewState(startState) as TransitionViewState
|
val startViewState = obtainViewState(startState) as TransitionViewState
|
||||||
val endState = state.copy().also { it.expansion = 1.0f }
|
val endState = state.copy().also { it.expansion = 1.0f }
|
||||||
|
|
||||||
val endViewState = obtainViewState(endState) as TransitionViewState
|
val endViewState = obtainViewState(endState) as TransitionViewState
|
||||||
result = layoutController.getInterpolatedState(
|
result = layoutController.getInterpolatedState(
|
||||||
startViewState,
|
startViewState,
|
||||||
endViewState,
|
endViewState,
|
||||||
state.expansion)
|
state.expansion)
|
||||||
logger.logMediaSize("interpolated viewState", result.width, result.height)
|
|
||||||
}
|
}
|
||||||
if (state.squishFraction < 1f) {
|
} else {
|
||||||
return squishViewState(result, state.squishFraction)
|
result = null
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -624,7 +624,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
|||||||
if (mQSAnimator != null) {
|
if (mQSAnimator != null) {
|
||||||
mQSAnimator.setPosition(expansion);
|
mQSAnimator.setPosition(expansion);
|
||||||
}
|
}
|
||||||
mQqsMediaHost.setSquishFraction(mSquishinessFraction);
|
|
||||||
updateMediaPositions();
|
updateMediaPositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1371,7 +1371,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
*/
|
*/
|
||||||
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
|
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
|
||||||
public void setExpandedHeight(float height) {
|
public void setExpandedHeight(float height) {
|
||||||
|
final float shadeBottom = getHeight() - getEmptyBottomMargin();
|
||||||
final boolean skipHeightUpdate = shouldSkipHeightUpdate();
|
final boolean skipHeightUpdate = shouldSkipHeightUpdate();
|
||||||
|
if (!skipHeightUpdate) {
|
||||||
|
final float expansionFraction = MathUtils.saturate(height / shadeBottom);
|
||||||
|
mAmbientState.setExpansionFraction(expansionFraction);
|
||||||
|
}
|
||||||
updateStackPosition();
|
updateStackPosition();
|
||||||
|
|
||||||
if (!skipHeightUpdate) {
|
if (!skipHeightUpdate) {
|
||||||
|
|||||||
@@ -3058,7 +3058,9 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int calculatePanelHeightShade() {
|
private int calculatePanelHeightShade() {
|
||||||
final int maxHeight = mNotificationStackScrollLayoutController.getHeight();
|
int emptyBottomMargin = mNotificationStackScrollLayoutController.getEmptyBottomMargin();
|
||||||
|
int maxHeight = mNotificationStackScrollLayoutController.getHeight() - emptyBottomMargin;
|
||||||
|
|
||||||
if (mBarState == KEYGUARD) {
|
if (mBarState == KEYGUARD) {
|
||||||
int minKeyguardPanelBottom = mClockPositionAlgorithm.getLockscreenStatusViewHeight()
|
int minKeyguardPanelBottom = mClockPositionAlgorithm.getLockscreenStatusViewHeight()
|
||||||
+ mNotificationStackScrollLayoutController.getIntrinsicContentHeight();
|
+ mNotificationStackScrollLayoutController.getIntrinsicContentHeight();
|
||||||
|
|||||||
@@ -808,7 +808,6 @@ public abstract class PanelViewController {
|
|||||||
mExpansionDragDownAmountPx = h;
|
mExpansionDragDownAmountPx = h;
|
||||||
mExpandedFraction = Math.min(1f,
|
mExpandedFraction = Math.min(1f,
|
||||||
maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight);
|
maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight);
|
||||||
mAmbientState.setExpansionFraction(mExpandedFraction);
|
|
||||||
onHeightUpdated(mExpandedHeight);
|
onHeightUpdated(mExpandedHeight);
|
||||||
updatePanelExpansionAndVisibility();
|
updatePanelExpansionAndVisibility();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
package com.android.systemui.media
|
|
||||||
|
|
||||||
import android.testing.AndroidTestingRunner
|
|
||||||
import android.testing.TestableLooper
|
|
||||||
import android.view.View
|
|
||||||
import androidx.test.filters.SmallTest
|
|
||||||
import com.android.systemui.R
|
|
||||||
import com.android.systemui.SysuiTestCase
|
|
||||||
import com.android.systemui.util.animation.MeasurementInput
|
|
||||||
import com.android.systemui.util.animation.TransitionLayout
|
|
||||||
import com.android.systemui.util.animation.TransitionViewState
|
|
||||||
import com.android.systemui.util.animation.WidgetState
|
|
||||||
import junit.framework.Assert.assertTrue
|
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.mockito.Mock
|
|
||||||
import org.mockito.Mockito.times
|
|
||||||
import org.mockito.Mockito.verify
|
|
||||||
import org.mockito.Mockito.verifyNoMoreInteractions
|
|
||||||
import org.mockito.MockitoAnnotations
|
|
||||||
import org.mockito.Mockito.`when` as whenever
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link MediaViewController}.
|
|
||||||
*/
|
|
||||||
@SmallTest
|
|
||||||
@RunWith(AndroidTestingRunner::class)
|
|
||||||
@TestableLooper.RunWithLooper
|
|
||||||
class MediaViewControllerTest : SysuiTestCase() {
|
|
||||||
@Mock
|
|
||||||
private lateinit var logger: MediaViewLogger
|
|
||||||
|
|
||||||
private val configurationController =
|
|
||||||
com.android.systemui.statusbar.phone.ConfigurationControllerImpl(context)
|
|
||||||
private val mediaHostStatesManager = MediaHostStatesManager()
|
|
||||||
private lateinit var mediaViewController: MediaViewController
|
|
||||||
private val mediaHostStateHolder = MediaHost.MediaHostStateHolder()
|
|
||||||
private var transitionLayout = TransitionLayout(context, /* attrs */ null, /* defStyleAttr */ 0)
|
|
||||||
@Mock private lateinit var mockViewState: TransitionViewState
|
|
||||||
@Mock private lateinit var mockCopiedState: TransitionViewState
|
|
||||||
@Mock private lateinit var mockWidgetState: WidgetState
|
|
||||||
|
|
||||||
@Before
|
|
||||||
fun setUp() {
|
|
||||||
MockitoAnnotations.initMocks(this)
|
|
||||||
mediaViewController = MediaViewController(
|
|
||||||
context,
|
|
||||||
configurationController,
|
|
||||||
mediaHostStatesManager,
|
|
||||||
logger
|
|
||||||
)
|
|
||||||
mediaViewController.attach(transitionLayout, MediaViewController.TYPE.PLAYER)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testObtainViewState_applySquishFraction_toTransitionViewState_height() {
|
|
||||||
transitionLayout.measureState = TransitionViewState().apply {
|
|
||||||
this.height = 100
|
|
||||||
}
|
|
||||||
mediaHostStateHolder.expansion = 1f
|
|
||||||
val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY)
|
|
||||||
val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY)
|
|
||||||
mediaHostStateHolder.measurementInput =
|
|
||||||
MeasurementInput(widthMeasureSpec, heightMeasureSpec)
|
|
||||||
|
|
||||||
// Test no squish
|
|
||||||
mediaHostStateHolder.squishFraction = 1f
|
|
||||||
assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 100)
|
|
||||||
|
|
||||||
// Test half squish
|
|
||||||
mediaHostStateHolder.squishFraction = 0.5f
|
|
||||||
assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 50)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testSquish_DoesNotMutateViewState() {
|
|
||||||
whenever(mockViewState.copy()).thenReturn(mockCopiedState)
|
|
||||||
whenever(mockCopiedState.widgetStates)
|
|
||||||
.thenReturn(mutableMapOf(R.id.album_art to mockWidgetState))
|
|
||||||
|
|
||||||
mediaViewController.squishViewState(mockViewState, 0.5f)
|
|
||||||
verify(mockViewState, times(1)).copy()
|
|
||||||
verifyNoMoreInteractions(mockViewState)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user