1 /*
2  * Copyright (C) 2019 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.statusbar
18 
19 import android.content.Context
20 import android.graphics.Bitmap
21 import android.graphics.Canvas
22 import android.graphics.Point
23 import android.graphics.Rect
24 import android.renderscript.Allocation
25 import android.renderscript.Element
26 import android.renderscript.RenderScript
27 import android.renderscript.ScriptIntrinsicBlur
28 import android.util.Log
29 import android.util.MathUtils
30 import com.android.internal.graphics.ColorUtils
31 import com.android.systemui.statusbar.notification.MediaNotificationProcessor
32 
33 import javax.inject.Inject
34 import javax.inject.Singleton
35 
36 private const val TAG = "MediaArtworkProcessor"
37 private const val COLOR_ALPHA = (255 * 0.7f).toInt()
38 private const val BLUR_RADIUS = 25f
39 private const val DOWNSAMPLE = 6
40 
41 @Singleton
42 class MediaArtworkProcessor @Inject constructor() {
43 
44     private val mTmpSize = Point()
45     private var mArtworkCache: Bitmap? = null
46 
processArtworknull47     fun processArtwork(context: Context, artwork: Bitmap): Bitmap? {
48         if (mArtworkCache != null) {
49             return mArtworkCache
50         }
51         val renderScript = RenderScript.create(context)
52         val blur = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript))
53         var input: Allocation? = null
54         var output: Allocation? = null
55         var inBitmap: Bitmap? = null
56         try {
57             context.display.getSize(mTmpSize)
58             val rect = Rect(0, 0, artwork.width, artwork.height)
59             MathUtils.fitRect(rect, Math.max(mTmpSize.x / DOWNSAMPLE, mTmpSize.y / DOWNSAMPLE))
60             inBitmap = Bitmap.createScaledBitmap(artwork, rect.width(), rect.height(),
61                     true /* filter */)
62             // Render script blurs only support ARGB_8888, we need a conversion if we got a
63             // different bitmap config.
64             if (inBitmap.config != Bitmap.Config.ARGB_8888) {
65                 val oldIn = inBitmap
66                 inBitmap = oldIn.copy(Bitmap.Config.ARGB_8888, false /* isMutable */)
67                 oldIn.recycle()
68             }
69             val outBitmap = Bitmap.createBitmap(inBitmap.width, inBitmap.height,
70                     Bitmap.Config.ARGB_8888)
71 
72             input = Allocation.createFromBitmap(renderScript, inBitmap,
73                     Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_GRAPHICS_TEXTURE)
74             output = Allocation.createFromBitmap(renderScript, outBitmap)
75 
76             blur.setRadius(BLUR_RADIUS)
77             blur.setInput(input)
78             blur.forEach(output)
79             output.copyTo(outBitmap)
80 
81             val swatch = MediaNotificationProcessor.findBackgroundSwatch(artwork)
82 
83             val canvas = Canvas(outBitmap)
84             canvas.drawColor(ColorUtils.setAlphaComponent(swatch.rgb, COLOR_ALPHA))
85             return outBitmap
86         } catch (ex: IllegalArgumentException) {
87             Log.e(TAG, "error while processing artwork", ex)
88             return null
89         } finally {
90             input?.destroy()
91             output?.destroy()
92             blur.destroy()
93             inBitmap?.recycle()
94         }
95     }
96 
clearCachenull97     fun clearCache() {
98         mArtworkCache?.recycle()
99         mArtworkCache = null
100     }
101 }