• 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.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