Merge "Use system colors for media" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
e580944462
@@ -47,7 +47,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:tint="@color/media_primary_text"
|
||||
android:tint="?android:attr/textColorPrimary"
|
||||
android:forceHasOverlappingRendering="false"
|
||||
/>
|
||||
</FrameLayout>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:fontFamily="@*android:string/config_bodyFontFamily"
|
||||
android:textColor="@color/media_primary_text"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:gravity="start"
|
||||
android:textSize="14sp" />
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:fontFamily="@*android:string/config_bodyFontFamily"
|
||||
android:textColor="@color/media_primary_text"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:gravity="end"
|
||||
android:textSize="14sp" />
|
||||
</FrameLayout>
|
||||
@@ -120,13 +120,13 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical|end"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/qs_media_light_source"
|
||||
android:forceHasOverlappingRendering="false">
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:foreground="@drawable/qs_media_seamless_background"
|
||||
android:background="@drawable/qs_media_light_source"
|
||||
android:background="@drawable/qs_media_seamless_background"
|
||||
android:orientation="horizontal"
|
||||
android:padding="6dp"
|
||||
android:contentDescription="@string/quick_settings_media_device_label">
|
||||
@@ -135,7 +135,7 @@
|
||||
android:layout_width="@dimen/qs_seamless_icon_size"
|
||||
android:layout_height="@dimen/qs_seamless_icon_size"
|
||||
android:layout_gravity="center"
|
||||
android:tint="@color/media_primary_text"
|
||||
android:tint="?android:attr/colorPrimary"
|
||||
android:src="@*android:drawable/ic_media_seamless" />
|
||||
<TextView
|
||||
android:visibility="gone"
|
||||
@@ -147,7 +147,7 @@
|
||||
android:fontFamily="@*android:string/config_headlineFontFamily"
|
||||
android:singleLine="true"
|
||||
android:text="@*android:string/ext_media_seamless_action"
|
||||
android:textColor="@color/media_primary_text"
|
||||
android:textColor="?android:attr/colorPrimary"
|
||||
android:textDirection="locale"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
@@ -157,7 +157,7 @@
|
||||
android:id="@+id/media_seamless_fallback"
|
||||
android:layout_width="@dimen/qs_seamless_icon_size"
|
||||
android:layout_height="@dimen/qs_seamless_icon_size"
|
||||
android:tint="@color/media_primary_text"
|
||||
android:tint="?android:attr/textColorPrimary"
|
||||
android:src="@drawable/ic_cast_connected"
|
||||
android:forceHasOverlappingRendering="false" />
|
||||
|
||||
@@ -171,15 +171,15 @@
|
||||
android:clickable="true"
|
||||
android:maxHeight="@dimen/qs_media_enabled_seekbar_height"
|
||||
android:paddingVertical="@dimen/qs_media_enabled_seekbar_vertical_padding"
|
||||
android:thumbTint="@color/media_primary_text"
|
||||
android:progressTint="@color/media_seekbar_progress"
|
||||
android:progressBackgroundTint="@color/media_disabled"
|
||||
android:thumbTint="?android:attr/textColorPrimary"
|
||||
android:progressTint="?android:attr/textColorPrimary"
|
||||
android:progressBackgroundTint="?android:attr/colorBackground"
|
||||
android:splitTrack="false" />
|
||||
|
||||
<!-- App name -->
|
||||
<TextView
|
||||
android:id="@+id/app_name"
|
||||
android:textColor="@color/media_primary_text"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
@@ -194,7 +194,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/media_primary_text"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<!-- Artist name -->
|
||||
@@ -204,12 +204,12 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@*android:string/config_headlineFontFamily"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/media_secondary_text"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<com.android.internal.widget.CachingIconView
|
||||
android:id="@+id/icon"
|
||||
android:tint="@color/media_primary_text"
|
||||
android:tint="?android:attr/textColorPrimary"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_margin="6dp" />
|
||||
@@ -223,7 +223,7 @@
|
||||
android:layout_marginEnd="@dimen/qs_media_panel_outer_padding"
|
||||
android:id="@+id/media_text"
|
||||
android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
|
||||
android:textColor="@color/media_primary_text"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:text="@string/controls_media_title"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
@@ -238,7 +238,7 @@
|
||||
android:id="@+id/remove_text"
|
||||
android:fontFamily="@*android:string/config_headlineFontFamily"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/media_primary_text"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:text="@string/controls_media_close_session"
|
||||
app:layout_constraintTop_toBottomOf="@id/media_text"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
@@ -262,7 +262,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
|
||||
android:textColor="@android:color/white"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:text="@string/controls_media_settings_button" />
|
||||
</FrameLayout>
|
||||
|
||||
@@ -283,7 +283,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
|
||||
android:textColor="@android:color/white"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:text="@string/cancel" />
|
||||
</FrameLayout>
|
||||
|
||||
@@ -304,7 +304,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
|
||||
android:textColor="@android:color/white"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:text="@string/controls_media_dismiss_button"
|
||||
/>
|
||||
</FrameLayout>
|
||||
|
||||
@@ -244,11 +244,8 @@
|
||||
<color name="magnification_switch_button_color">#7F000000</color>
|
||||
|
||||
<!-- media -->
|
||||
<color name="media_primary_text">@android:color/white</color>
|
||||
<color name="media_secondary_text">#99ffffff</color> <!-- 60% -->
|
||||
<color name="media_seekbar_progress">#c0ffffff</color>
|
||||
<color name="media_disabled">#80ffffff</color>
|
||||
<color name="media_seamless_border">#26ffffff</color> <!-- 15% -->
|
||||
<color name="media_seamless_border">?android:attr/colorAccent</color>
|
||||
<color name="media_divider">#1d000000</color>
|
||||
|
||||
<!-- controls -->
|
||||
|
||||
@@ -582,7 +582,7 @@
|
||||
|
||||
<style name="MediaPlayer.Button" parent="@android:style/Widget.Material.Button.Borderless.Small">
|
||||
<item name="android:background">@drawable/qs_media_light_source</item>
|
||||
<item name="android:tint">@android:color/white</item>
|
||||
<item name="android:tint">?android:attr/textColorPrimary</item>
|
||||
<item name="android:stateListAnimator">@anim/media_button_state_list_animator</item>
|
||||
</style>
|
||||
|
||||
|
||||
@@ -36,25 +36,23 @@
|
||||
app:layout_constraintTop_toTopOf="@id/icon"
|
||||
app:layout_constraintBottom_toBottomOf="@id/icon"
|
||||
app:layout_constraintStart_toEndOf="@id/icon"
|
||||
app:layout_constraintEnd_toStartOf="@id/media_seamless"
|
||||
app:layout_constraintHorizontal_chainStyle="spread_inside"
|
||||
app:layout_constraintEnd_toStartOf="@id/center_vertical_guideline"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintHorizontal_bias="0"
|
||||
/>
|
||||
|
||||
<Constraint
|
||||
android:id="@+id/media_seamless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/app_name"
|
||||
app:layout_constraintStart_toEndOf="@id/center_vertical_guideline"
|
||||
app:layout_constraintHorizontal_chainStyle="spread_inside"
|
||||
app:layout_constraintHorizontal_bias="1"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintWidth_min="48dp"
|
||||
app:layout_constraintHeight_min="48dp"
|
||||
android:layout_marginEnd="@dimen/qs_center_guideline_padding"
|
||||
android:layout_marginStart="@dimen/qs_center_guideline_padding"
|
||||
/>
|
||||
|
||||
|
||||
@@ -36,25 +36,23 @@
|
||||
app:layout_constraintTop_toTopOf="@id/icon"
|
||||
app:layout_constraintBottom_toBottomOf="@id/icon"
|
||||
app:layout_constraintStart_toEndOf="@id/icon"
|
||||
app:layout_constraintEnd_toStartOf="@id/media_seamless"
|
||||
app:layout_constraintHorizontal_chainStyle="spread_inside"
|
||||
app:layout_constraintEnd_toStartOf="@id/center_vertical_guideline"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintHorizontal_bias="0"
|
||||
/>
|
||||
|
||||
<Constraint
|
||||
android:id="@+id/media_seamless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/app_name"
|
||||
app:layout_constraintStart_toEndOf="@id/center_vertical_guideline"
|
||||
app:layout_constraintHorizontal_chainStyle="spread_inside"
|
||||
app:layout_constraintHorizontal_bias="1"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintWidth_min="48dp"
|
||||
app:layout_constraintHeight_min="48dp"
|
||||
android:layout_marginEnd="@dimen/qs_center_guideline_padding"
|
||||
android:layout_marginStart="@dimen/qs_center_guideline_padding"
|
||||
/>
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.android.systemui.media
|
||||
|
||||
import android.animation.ArgbEvaluator
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.content.res.Configuration
|
||||
import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS
|
||||
import android.util.Log
|
||||
@@ -112,6 +114,9 @@ class MediaCarouselController @Inject constructor(
|
||||
private val visualStabilityCallback: VisualStabilityManager.Callback
|
||||
private var needsReordering: Boolean = false
|
||||
private var keysNeedRemoval = mutableSetOf<String>()
|
||||
private var bgColor = getBackgroundColor()
|
||||
private var fgColor = com.android.settingslib.Utils.getColorAttr(context,
|
||||
com.android.internal.R.attr.textColorPrimary).defaultColor
|
||||
private var isRtl: Boolean = false
|
||||
set(value) {
|
||||
if (value != field) {
|
||||
@@ -147,7 +152,7 @@ class MediaCarouselController @Inject constructor(
|
||||
}
|
||||
|
||||
override fun onUiModeChanged() {
|
||||
// Only settings button needs to update for dark theme
|
||||
recreatePlayers()
|
||||
inflateSettingsButton()
|
||||
}
|
||||
}
|
||||
@@ -249,6 +254,11 @@ class MediaCarouselController @Inject constructor(
|
||||
}
|
||||
|
||||
private fun addOrUpdatePlayer(key: String, oldKey: String?, data: MediaData) {
|
||||
data.actions.forEach {
|
||||
it.icon?.setTintList(ColorStateList.valueOf(fgColor))
|
||||
}
|
||||
data.appIcon?.setTintList(ColorStateList.valueOf(fgColor))
|
||||
val dataCopy = data.copy(backgroundColor = bgColor)
|
||||
val existingPlayer = MediaPlayerData.getMediaPlayer(key, oldKey)
|
||||
if (existingPlayer == null) {
|
||||
var newPlayer = mediaControlPanelFactory.get()
|
||||
@@ -257,14 +267,14 @@ class MediaCarouselController @Inject constructor(
|
||||
val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
newPlayer.view?.player?.setLayoutParams(lp)
|
||||
newPlayer.bind(data, key)
|
||||
newPlayer.bind(dataCopy, key)
|
||||
newPlayer.setListening(currentlyExpanded)
|
||||
MediaPlayerData.addMediaPlayer(key, data, newPlayer)
|
||||
MediaPlayerData.addMediaPlayer(key, dataCopy, newPlayer)
|
||||
updatePlayerToState(newPlayer, noAnimation = true)
|
||||
reorderAllPlayers()
|
||||
} else {
|
||||
existingPlayer.bind(data, key)
|
||||
MediaPlayerData.addMediaPlayer(key, data, existingPlayer)
|
||||
existingPlayer.bind(dataCopy, key)
|
||||
MediaPlayerData.addMediaPlayer(key, dataCopy, existingPlayer)
|
||||
if (visualStabilityManager.isReorderingAllowed) {
|
||||
reorderAllPlayers()
|
||||
} else {
|
||||
@@ -298,12 +308,27 @@ class MediaCarouselController @Inject constructor(
|
||||
}
|
||||
|
||||
private fun recreatePlayers() {
|
||||
bgColor = getBackgroundColor()
|
||||
|
||||
fgColor = com.android.settingslib.Utils.getColorAttr(context,
|
||||
com.android.internal.R.attr.textColorPrimary).defaultColor
|
||||
pageIndicator.tintList = ColorStateList.valueOf(fgColor)
|
||||
|
||||
MediaPlayerData.mediaData().forEach { (key, data) ->
|
||||
removePlayer(key, dismissMediaData = false)
|
||||
addOrUpdatePlayer(key = key, oldKey = null, data = data)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBackgroundColor(): Int {
|
||||
val themeAccent = com.android.settingslib.Utils.getColorAttr(context,
|
||||
com.android.internal.R.attr.colorAccent).defaultColor
|
||||
val themeBackground = com.android.settingslib.Utils.getColorAttr(context,
|
||||
com.android.internal.R.attr.colorBackground).defaultColor
|
||||
// Simulate transparency - cannot be actually transparent because of lockscreen
|
||||
return ArgbEvaluator().evaluate(0.25f, themeBackground, themeAccent) as Int
|
||||
}
|
||||
|
||||
private fun updatePageIndicator() {
|
||||
val numPages = mediaContent.getChildCount()
|
||||
pageIndicator.setNumPages(numPages)
|
||||
|
||||
@@ -25,7 +25,6 @@ import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.ImageDecoder
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.Icon
|
||||
@@ -38,7 +37,6 @@ import android.os.UserHandle
|
||||
import android.service.notification.StatusBarNotification
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import com.android.internal.graphics.ColorUtils
|
||||
import com.android.systemui.Dumpable
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||
@@ -48,7 +46,6 @@ import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.dump.DumpManager
|
||||
import com.android.systemui.plugins.ActivityStarter
|
||||
import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState
|
||||
import com.android.systemui.statusbar.notification.MediaNotificationProcessor
|
||||
import com.android.systemui.statusbar.notification.row.HybridGroupManager
|
||||
import com.android.systemui.util.Assert
|
||||
import com.android.systemui.util.Utils
|
||||
@@ -68,10 +65,6 @@ private val ART_URIS = arrayOf(
|
||||
|
||||
private const val TAG = "MediaDataManager"
|
||||
private const val DEBUG = true
|
||||
private const val DEFAULT_LUMINOSITY = 0.25f
|
||||
private const val LUMINOSITY_THRESHOLD = 0.05f
|
||||
private const val SATURATION_MULTIPLIER = 0.8f
|
||||
const val DEFAULT_COLOR = Color.DKGRAY
|
||||
|
||||
private val LOADING = MediaData(-1, false, 0, null, null, null, null, null,
|
||||
emptyList(), emptyList(), "INVALID", null, null, null, true, null)
|
||||
@@ -110,6 +103,11 @@ class MediaDataManager(
|
||||
private val useQsMediaPlayer: Boolean
|
||||
) : Dumpable {
|
||||
|
||||
private val themeText = com.android.settingslib.Utils.getColorAttr(context,
|
||||
com.android.internal.R.attr.textColorPrimary).defaultColor
|
||||
private val bgColor = com.android.settingslib.Utils.getColorAttr(context,
|
||||
com.android.internal.R.attr.colorBackground).defaultColor
|
||||
|
||||
// Internal listeners are part of the internal pipeline. External listeners (those registered
|
||||
// with [MediaDeviceManager.addListener]) receive events after they have propagated through
|
||||
// the internal pipeline.
|
||||
@@ -395,7 +393,6 @@ class MediaDataManager(
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val bgColor = artworkBitmap?.let { computeBackgroundColor(it) } ?: DEFAULT_COLOR
|
||||
|
||||
val mediaAction = getResumeMediaAction(resumeAction)
|
||||
foregroundExecutor.execute {
|
||||
@@ -449,7 +446,6 @@ class MediaDataManager(
|
||||
}
|
||||
}
|
||||
}
|
||||
val bgColor = computeBackgroundColor(artworkBitmap)
|
||||
|
||||
// App name
|
||||
val builder = Notification.Builder.recoverBuilder(context, notif)
|
||||
@@ -506,7 +502,7 @@ class MediaDataManager(
|
||||
Icon.createWithResource(packageContext, action.getIcon()!!.getResId())
|
||||
} else {
|
||||
action.getIcon()
|
||||
}
|
||||
}.setTint(themeText)
|
||||
val mediaAction = MediaAction(
|
||||
mediaActionIcon,
|
||||
runnable,
|
||||
@@ -589,38 +585,9 @@ class MediaDataManager(
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeBackgroundColor(artworkBitmap: Bitmap?): Int {
|
||||
var color = Color.WHITE
|
||||
if (artworkBitmap != null && artworkBitmap.width > 1 && artworkBitmap.height > 1) {
|
||||
// If we have valid art, get colors from that
|
||||
val p = MediaNotificationProcessor.generateArtworkPaletteBuilder(artworkBitmap)
|
||||
.generate()
|
||||
val swatch = MediaNotificationProcessor.findBackgroundSwatch(p)
|
||||
color = swatch.rgb
|
||||
} else {
|
||||
return DEFAULT_COLOR
|
||||
}
|
||||
// Adapt background color, so it's always subdued and text is legible
|
||||
val tmpHsl = floatArrayOf(0f, 0f, 0f)
|
||||
ColorUtils.colorToHSL(color, tmpHsl)
|
||||
|
||||
val l = tmpHsl[2]
|
||||
// Colors with very low luminosity can have any saturation. This means that changing the
|
||||
// luminosity can make a black become red. Let's remove the saturation of very light or
|
||||
// very dark colors to avoid this issue.
|
||||
if (l < LUMINOSITY_THRESHOLD || l > 1f - LUMINOSITY_THRESHOLD) {
|
||||
tmpHsl[1] = 0f
|
||||
}
|
||||
tmpHsl[1] *= SATURATION_MULTIPLIER
|
||||
tmpHsl[2] = DEFAULT_LUMINOSITY
|
||||
|
||||
color = ColorUtils.HSLToColor(tmpHsl)
|
||||
return color
|
||||
}
|
||||
|
||||
private fun getResumeMediaAction(action: Runnable): MediaAction {
|
||||
return MediaAction(
|
||||
Icon.createWithResource(context, R.drawable.lb_ic_play),
|
||||
Icon.createWithResource(context, R.drawable.lb_ic_play).setTint(themeText),
|
||||
action,
|
||||
context.getString(R.string.controls_media_resume)
|
||||
)
|
||||
|
||||
@@ -315,10 +315,9 @@ class MediaDataManagerTest : SysuiTestCase() {
|
||||
}
|
||||
mediaDataManager.onNotificationAdded(KEY, notif)
|
||||
|
||||
// THEN it loads and uses the default background color
|
||||
// THEN it still loads
|
||||
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
|
||||
assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
|
||||
verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor))
|
||||
assertThat(mediaDataCaptor.value!!.backgroundColor).isEqualTo(DEFAULT_COLOR)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user