Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.layout
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
Expand Down Expand Up @@ -62,6 +63,8 @@ internal fun BoxScope.UnifiedPlayerMiniAndFullLayers(
currentPositionProvider: () -> Long,
isFavorite: Boolean,
shouldRenderFullPlayer: Boolean = true,
currentHorizontalPaddingStartPxProvider: () -> Float,
currentHorizontalPaddingEndPxProvider: () -> Float,
onShowQueueClicked: () -> Unit,
onQueueDragStart: () -> Unit,
onQueueDrag: (Float) -> Unit,
Expand Down Expand Up @@ -89,6 +92,27 @@ internal fun BoxScope.UnifiedPlayerMiniAndFullLayers(
alpha = (1f - playerContentExpansionFraction.value * 2f)
.coerceIn(0f, 1f)
}
.layout { measurable, constraints ->
val fraction = playerContentExpansionFraction.value
val startPaddingPx = currentHorizontalPaddingStartPxProvider().toInt().coerceAtLeast(0)
val endPaddingPx = currentHorizontalPaddingEndPxProvider().toInt().coerceAtLeast(0)

val targetWidth = if (fraction > 0f) {
(constraints.maxWidth - startPaddingPx - endPaddingPx).coerceAtLeast(0)
} else {
constraints.maxWidth
}
val placeable = measurable.measure(
constraints.copy(
minWidth = targetWidth,
maxWidth = targetWidth
)
)
layout(constraints.maxWidth, constraints.maxHeight) {
val xOffset = if (fraction > 0f) startPaddingPx else 0
placeable.placeRelative(xOffset, 0)
}
}
.zIndex(miniPlayerZIndex)
) {
val isMiniPlayerVisible by remember {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -688,16 +688,27 @@ fun UnifiedPlayerSheetV2(
// Measures the actual player content with full screen height targetContentHeightPx
// so that it can render correctly, while reporting targetHeightPx to the outer
// clip/background/shadow so that they are perfectly constrained to the miniplayer card bounds.
// During drag/animation, we measure at stable full-screen constraints to prevent jank.
.layout { measurable, constraints ->
val targetContentHeightPx = containerHeight.roundToPx()
val fraction = playerContentExpansionFraction.value
val startPaddingPx = currentHorizontalPaddingStartPxProvider().toInt()
val measureWidth = if (fraction > 0f) {
screenWidthPx.roundToInt()
} else {
constraints.maxWidth
}
val placeable = measurable.measure(
constraints.copy(
minWidth = measureWidth,
maxWidth = measureWidth,
minHeight = targetContentHeightPx,
maxHeight = targetContentHeightPx
)
)
layout(constraints.maxWidth, constraints.maxHeight) {
placeable.placeRelative(0, 0)
val xOffset = if (fraction > 0f) -startPaddingPx else 0
placeable.placeRelative(xOffset, 0)
}
}
.miniPlayerDismissHorizontalGesture(
Expand Down Expand Up @@ -740,6 +751,8 @@ fun UnifiedPlayerSheetV2(
currentPositionProvider = positionToDisplayProvider,
isFavorite = isFavorite,
shouldRenderFullPlayer = shouldRenderFullPlayer,
currentHorizontalPaddingStartPxProvider = currentHorizontalPaddingStartPxProvider,
currentHorizontalPaddingEndPxProvider = currentHorizontalPaddingEndPxProvider,
onShowQueueClicked = sheetActionHandlers.openQueueSheet,
onQueueDragStart = sheetActionHandlers.beginQueueDrag,
onQueueDrag = sheetActionHandlers.dragQueueBy,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,13 +374,8 @@ class BaselineProfileGenerator {
return
}
waitForUi(EXTRA_UI_WAIT_MS)
val openedBackStackSurface = hasTextOrDescription(pattern(BACK_NAV_ALTERNATIVES))
body()
if (openedBackStackSurface || hasTextOrDescription(pattern(BACK_NAV_ALTERNATIVES))) {
pressBackAndWait()
} else {
Log.d(TAG, "Optional surface '$labelPattern' did not navigate; staying on current app surface.")
}
pressBackAndWait()
}

private fun MacrobenchmarkScope.openSettingsFromHome(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import androidx.test.uiautomator.UiObject2
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import java.util.Locale
import java.util.regex.Pattern

@RunWith(AndroidJUnit4::class)
Expand All @@ -25,6 +26,30 @@ class PlayerSheetAnimationBenchmarks {

@Test
fun playerSheetOpenCloseGestures() {
runPlayerSheetBenchmarkForPlaylist(null)
}

@Test
fun playerSheetOpenCloseGestures_FLAC() {
runPlayerSheetBenchmarkForPlaylist("FLAC")
}

@Test
fun playerSheetOpenCloseGestures_MP3() {
runPlayerSheetBenchmarkForPlaylist("MP3")
}

@Test
fun playerSheetOpenCloseGestures_M4A() {
runPlayerSheetBenchmarkForPlaylist("M4A")
}

@Test
fun playerSheetOpenCloseGestures_OPUS() {
runPlayerSheetBenchmarkForPlaylist("OPUS")
}

private fun runPlayerSheetBenchmarkForPlaylist(playlistName: String?) {
val packageName = benchmarkTargetPackageName()

benchmarkRule.measureRepeated(
Expand Down Expand Up @@ -54,7 +79,11 @@ class PlayerSheetAnimationBenchmarks {
Thread.sleep(BENCHMARK_REBUILD_WAIT_MS)
dismissBenchmarkBlockingDialogs()
}
ensureSongIsReady()
if (playlistName != null) {
playFromPlaylist(playlistName)
} else {
ensureSongIsReady()
}
libraryRebuiltForThisRun = true
openHomeTab()
waitForSheetState(SHEET_COLLAPSED_PATTERN, "setup after opening Home")
Expand Down Expand Up @@ -85,6 +114,71 @@ class PlayerSheetAnimationBenchmarks {
}
}

private fun androidx.benchmark.macro.MacrobenchmarkScope.playFromPlaylist(playlistName: String) {
if (isExpandedSheetVisible()) {
collapseExpandedPlayer()
waitForSheetState(SHEET_COLLAPSED_PATTERN, "collapsing existing player during setup")
}

openLibraryTab()
waitForLibraryContent()

openLibraryTabDropdown()
selectPlaylistsTabInSheet()

Thread.sleep(DEFAULT_WAIT_MS)

val playlistButton = findByTextOrDescription(pattern(playlistName), SHORT_WAIT_MS)
if (playlistButton != null) {
click(playlistButton)
} else {
val y = when (playlistName.uppercase(Locale.US)) {
"FLAC" -> 300
"M4A" -> 410
"MP3" -> 520
"OPUS" -> 630
else -> 300
}
tap(device.displayWidth / 2, y)
}
Thread.sleep(DEFAULT_WAIT_MS)

tap(device.displayWidth / 2, (device.displayHeight * 0.30f).toInt())
waitForAnySheetState("after selecting first song in playlist $playlistName")

if (isExpandedSheetVisible()) {
collapseExpandedPlayer()
waitForSheetState(SHEET_COLLAPSED_PATTERN, "collapsing newly selected song")
}

if (!isCollapsedSheetVisible()) {
throw IllegalStateException(
"A playlist song was tapped, but the UnifiedPlayerSheetV2 mini-player did not appear. " +
"Visible UI: ${visibleUiSnapshot()}"
)
}
}

private fun androidx.benchmark.macro.MacrobenchmarkScope.openLibraryTabDropdown() {
findByTextOrDescription(EXPAND_MENU_PATTERN, SHORT_WAIT_MS)?.let {
click(it)
Thread.sleep(DEFAULT_WAIT_MS)
return
}
tap((device.displayWidth * 0.52f).toInt(), 100)
Thread.sleep(DEFAULT_WAIT_MS)
}

private fun androidx.benchmark.macro.MacrobenchmarkScope.selectPlaylistsTabInSheet() {
findByTextOrDescription(PLAYLISTS_TAB_GRID_PATTERN, SHORT_WAIT_MS)?.let {
click(it)
Thread.sleep(DEFAULT_WAIT_MS)
return
}
tap((device.displayWidth * 0.75f).toInt(), (device.displayHeight * 0.27f).toInt())
Thread.sleep(DEFAULT_WAIT_MS)
}

private fun androidx.benchmark.macro.MacrobenchmarkScope.ensureSongIsReady() {
if (isCollapsedSheetVisible()) return
if (isExpandedSheetVisible()) {
Expand Down Expand Up @@ -212,7 +306,6 @@ class PlayerSheetAnimationBenchmarks {
return
}
repeat(4) {
if (!hasTextOrDescription(BACK_PATTERN)) return@repeat
device.pressKeyCode(KeyEvent.KEYCODE_BACK)
Thread.sleep(DEFAULT_WAIT_MS)
findByTextOrDescription(HOME_TAB_PATTERN, TINY_WAIT_MS)?.let { home ->
Expand Down Expand Up @@ -393,6 +486,10 @@ class PlayerSheetAnimationBenchmarks {
private val EMPTY_LIBRARY_PATTERN = pattern(
"No songs|No valid songs|Sin canciones|No se encontraron canciones|Empty"
)
private val EXPAND_MENU_PATTERN = pattern(
"Expand menu|Expandir men[uú]|Men[uü] aufklappen|D[eé]velopper le menu|Perluas menu|Espandi menu|메뉴 확장|Utvid meny|Развернуть menu|展开菜单"
)
private val PLAYLISTS_TAB_GRID_PATTERN = pattern("PLAYLISTS|Playlists|Listas de reproducci[oó]n")

private fun pattern(alternatives: String): Pattern =
Pattern.compile(".*($alternatives).*", Pattern.CASE_INSENSITIVE or Pattern.UNICODE_CASE)
Expand Down
Loading