1 /* 2 * Copyright (C) 2020 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.view.CrossWindowBlurListeners.CROSS_WINDOW_BLUR_SUPPORTED 20 21 import android.app.ActivityManager 22 import android.content.res.Resources 23 import android.os.SystemProperties 24 import android.util.IndentingPrintWriter 25 import android.util.MathUtils 26 import android.view.CrossWindowBlurListeners 27 import android.view.SurfaceControl 28 import android.view.ViewRootImpl 29 import androidx.annotation.VisibleForTesting 30 import com.android.systemui.Dumpable 31 import com.android.systemui.R 32 import com.android.systemui.dagger.SysUISingleton 33 import com.android.systemui.dagger.qualifiers.Main 34 import com.android.systemui.dump.DumpManager 35 import java.io.FileDescriptor 36 import java.io.PrintWriter 37 import javax.inject.Inject 38 39 @SysUISingleton 40 open class BlurUtils @Inject constructor( 41 @Main private val resources: Resources, 42 private val crossWindowBlurListeners: CrossWindowBlurListeners, 43 dumpManager: DumpManager 44 ) : Dumpable { 45 val minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius) 46 val maxBlurRadius = resources.getDimensionPixelSize(R.dimen.max_window_blur_radius) 47 48 private var lastAppliedBlur = 0 49 50 init { 51 dumpManager.registerDumpable(javaClass.name, this) 52 } 53 54 /** 55 * Translates a ratio from 0 to 1 to a blur radius in pixels. 56 */ blurRadiusOfRationull57 fun blurRadiusOfRatio(ratio: Float): Int { 58 if (ratio == 0f) { 59 return 0 60 } 61 return MathUtils.lerp(minBlurRadius.toFloat(), maxBlurRadius.toFloat(), ratio).toInt() 62 } 63 64 /** 65 * Translates a blur radius in pixels to a ratio between 0 to 1. 66 */ ratioOfBlurRadiusnull67 fun ratioOfBlurRadius(blur: Int): Float { 68 if (blur == 0) { 69 return 0f 70 } 71 return MathUtils.map(minBlurRadius.toFloat(), maxBlurRadius.toFloat(), 72 0f /* maxStart */, 1f /* maxStop */, blur.toFloat()) 73 } 74 75 /** 76 * Applies background blurs to a {@link ViewRootImpl}. 77 * 78 * @param viewRootImpl The window root. 79 * @param radius blur radius in pixels. 80 * @param opaque if surface is opaque, regardless or having blurs or no. 81 */ applyBlurnull82 fun applyBlur(viewRootImpl: ViewRootImpl?, radius: Int, opaque: Boolean) { 83 if (viewRootImpl == null || !viewRootImpl.surfaceControl.isValid || 84 !supportsBlursOnWindows()) { 85 return 86 } 87 createTransaction().use { 88 it.setBackgroundBlurRadius(viewRootImpl.surfaceControl, radius) 89 it.setOpaque(viewRootImpl.surfaceControl, opaque) 90 if (lastAppliedBlur == 0 && radius != 0) { 91 it.setEarlyWakeupStart() 92 } 93 if (lastAppliedBlur != 0 && radius == 0) { 94 it.setEarlyWakeupEnd() 95 } 96 it.apply() 97 } 98 lastAppliedBlur = radius 99 } 100 101 @VisibleForTesting createTransactionnull102 open fun createTransaction(): SurfaceControl.Transaction { 103 return SurfaceControl.Transaction() 104 } 105 106 /** 107 * If this device can render blurs. 108 * 109 * @see android.view.SurfaceControl.Transaction#setBackgroundBlurRadius(SurfaceControl, int) 110 * @return {@code true} when supported. 111 */ supportsBlursOnWindowsnull112 open fun supportsBlursOnWindows(): Boolean { 113 return CROSS_WINDOW_BLUR_SUPPORTED && ActivityManager.isHighEndGfx() && 114 crossWindowBlurListeners.isCrossWindowBlurEnabled() && 115 !SystemProperties.getBoolean("persist.sysui.disableBlur", false) 116 } 117 dumpnull118 override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) { 119 IndentingPrintWriter(pw, " ").let { 120 it.println("BlurUtils:") 121 it.increaseIndent() 122 it.println("minBlurRadius: $minBlurRadius") 123 it.println("maxBlurRadius: $maxBlurRadius") 124 it.println("supportsBlursOnWindows: ${supportsBlursOnWindows()}") 125 it.println("CROSS_WINDOW_BLUR_SUPPORTED: $CROSS_WINDOW_BLUR_SUPPORTED") 126 it.println("isHighEndGfx: ${ActivityManager.isHighEndGfx()}") 127 } 128 } 129 } 130