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