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