• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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