1 /* <lambda>null2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.media.controls.ui.util 18 19 import android.app.WallpaperColors 20 import android.content.Context 21 import android.content.pm.PackageManager 22 import android.graphics.Rect 23 import android.graphics.drawable.Drawable 24 import android.graphics.drawable.GradientDrawable 25 import android.graphics.drawable.Icon 26 import android.graphics.drawable.LayerDrawable 27 import android.util.Log 28 import com.android.systemui.media.controls.ui.animation.backgroundEndFromScheme 29 import com.android.systemui.media.controls.ui.animation.backgroundStartFromScheme 30 import com.android.systemui.monet.ColorScheme 31 import com.android.systemui.monet.Style 32 import com.android.systemui.util.getColorWithAlpha 33 import kotlinx.coroutines.CoroutineDispatcher 34 import kotlinx.coroutines.withContext 35 36 object MediaArtworkHelper { 37 38 /** 39 * This method should be called from a background thread. WallpaperColors.fromBitmap takes a 40 * good amount of time. We do that work on the background executor to avoid stalling animations 41 * on the UI Thread. 42 */ 43 suspend fun getWallpaperColor( 44 applicationContext: Context, 45 backgroundDispatcher: CoroutineDispatcher, 46 artworkIcon: Icon?, 47 tag: String, 48 ): WallpaperColors? = 49 withContext(backgroundDispatcher) { 50 return@withContext artworkIcon?.let { 51 if (it.type == Icon.TYPE_BITMAP || it.type == Icon.TYPE_ADAPTIVE_BITMAP) { 52 // Avoids extra processing if this is already a valid bitmap 53 it.bitmap.let { artworkBitmap -> 54 if (artworkBitmap.isRecycled) { 55 Log.d(tag, "Cannot load wallpaper color from a recycled bitmap") 56 null 57 } else { 58 WallpaperColors.fromBitmap(artworkBitmap) 59 } 60 } 61 } else { 62 it.loadDrawable(applicationContext)?.let { artworkDrawable -> 63 WallpaperColors.fromDrawable(artworkDrawable) 64 } 65 } 66 } 67 } 68 69 /** 70 * Returns a scaled [Drawable] of a given [Icon] centered in [width]x[height] background size. 71 */ 72 fun getScaledBackground(context: Context, icon: Icon, width: Int, height: Int): Drawable? { 73 val drawable = icon.loadDrawable(context) 74 val bounds = Rect(0, 0, width, height) 75 if (bounds.width() > width || bounds.height() > height) { 76 val offsetX = (bounds.width() - width) / 2.0f 77 val offsetY = (bounds.height() - height) / 2.0f 78 bounds.offset(-offsetX.toInt(), -offsetY.toInt()) 79 } 80 drawable?.bounds = bounds 81 return drawable 82 } 83 84 /** Adds [gradient] on a given [albumArt] drawable using [colorScheme]. */ 85 fun setUpGradientColorOnDrawable( 86 albumArt: Drawable?, 87 gradient: GradientDrawable, 88 colorScheme: ColorScheme, 89 startAlpha: Float, 90 endAlpha: Float 91 ): LayerDrawable { 92 gradient.colors = 93 intArrayOf( 94 getColorWithAlpha(backgroundStartFromScheme(colorScheme), startAlpha), 95 getColorWithAlpha(backgroundEndFromScheme(colorScheme), endAlpha) 96 ) 97 return LayerDrawable(arrayOf(albumArt, gradient)) 98 } 99 100 /** Returns [ColorScheme] of media app given its [packageName]. */ 101 fun getColorScheme( 102 applicationContext: Context, 103 packageName: String, 104 tag: String, 105 style: Style = Style.TONAL_SPOT 106 ): ColorScheme? { 107 return try { 108 // Set up media source app's logo. 109 val icon = applicationContext.packageManager.getApplicationIcon(packageName) 110 ColorScheme(WallpaperColors.fromDrawable(icon), true, style) 111 } catch (e: PackageManager.NameNotFoundException) { 112 Log.w(tag, "Fail to get media app info", e) 113 null 114 } 115 } 116 } 117