1 /*
<lambda>null2  * Copyright (C) 2024 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.keyboard.docking.binder
18 
19 import android.content.Context
20 import android.graphics.Paint
21 import android.graphics.PixelFormat
22 import android.view.WindowManager
23 import com.android.app.viewcapture.ViewCaptureAwareWindowManager
24 import com.android.systemui.dagger.SysUISingleton
25 import com.android.systemui.dagger.qualifiers.Application
26 import com.android.systemui.keyboard.docking.ui.KeyboardDockingIndicationView
27 import com.android.systemui.keyboard.docking.ui.viewmodel.KeyboardDockingIndicationViewModel
28 import com.android.systemui.surfaceeffects.PaintDrawCallback
29 import com.android.systemui.surfaceeffects.glowboxeffect.GlowBoxEffect
30 import javax.inject.Inject
31 import kotlinx.coroutines.CoroutineScope
32 import com.android.app.tracing.coroutines.launchTraced as launch
33 
34 @SysUISingleton
35 class KeyboardDockingIndicationViewBinder
36 @Inject
37 constructor(
38     context: Context,
39     @Application private val applicationScope: CoroutineScope,
40     private val viewModel: KeyboardDockingIndicationViewModel,
41     private val windowManager: ViewCaptureAwareWindowManager,
42 ) {
43 
44     private val windowLayoutParams =
45         WindowManager.LayoutParams().apply {
46             width = WindowManager.LayoutParams.MATCH_PARENT
47             height = WindowManager.LayoutParams.MATCH_PARENT
48             format = PixelFormat.TRANSLUCENT
49             type = WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
50             fitInsetsTypes = 0 // Ignore insets from all system bars
51             title = "Edge glow effect"
52             flags =
53                 (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
54                     WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
55             setTrustedOverlay()
56         }
57 
58     private var glowEffect: GlowBoxEffect? = null
59     private val glowEffectView = KeyboardDockingIndicationView(context, null)
60 
61     private val drawCallback =
62         object : PaintDrawCallback {
63             override fun onDraw(paint: Paint) {
64                 glowEffectView.draw(paint)
65             }
66         }
67 
68     private val stateChangedCallback =
69         object : GlowBoxEffect.AnimationStateChangedCallback {
70             override fun onStart() {
71                 windowManager.addView(glowEffectView, windowLayoutParams)
72             }
73 
74             override fun onEnd() {
75                 windowManager.removeView(glowEffectView)
76             }
77         }
78 
79     fun startListening() {
80         applicationScope.launch {
81             viewModel.edgeGlow.collect { config ->
82                 if (glowEffect == null) {
83                     glowEffect = GlowBoxEffect(config, drawCallback, stateChangedCallback)
84                 } else {
85                     glowEffect?.finish(force = true)
86                     glowEffect!!.updateConfig(config)
87                 }
88             }
89         }
90 
91         applicationScope.launch {
92             viewModel.keyboardConnected.collect { connected ->
93                 if (connected) {
94                     glowEffect?.play()
95                 } else {
96                     glowEffect?.finish()
97                 }
98             }
99         }
100     }
101 }
102