1 /*
<lambda>null2  * Copyright (C) 2014 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 package com.android.systemui.statusbar.phone
17 
18 import android.content.Context
19 import android.content.res.Configuration
20 import android.util.AttributeSet
21 import android.view.View
22 import android.view.ViewGroup
23 import android.widget.FrameLayout
24 import androidx.annotation.StringRes
25 import com.android.keyguard.LockIconViewController
26 import com.android.systemui.keyguard.ui.binder.KeyguardBottomAreaViewBinder
27 import com.android.systemui.keyguard.ui.binder.KeyguardBottomAreaViewBinder.bind
28 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel
29 import com.android.systemui.plugins.ActivityStarter
30 import com.android.systemui.plugins.FalsingManager
31 import com.android.systemui.res.R
32 import com.android.systemui.statusbar.VibratorHelper
33 
34 /**
35  * Renders the bottom area of the lock-screen. Concerned primarily with the quick affordance UI
36  * elements. A secondary concern is the interaction of the quick affordance elements with the
37  * indication area between them, though the indication area is primarily controlled elsewhere.
38  */
39 @Deprecated("Deprecated as part of b/278057014")
40 class KeyguardBottomAreaView
41 @JvmOverloads
42 constructor(
43     context: Context,
44     attrs: AttributeSet? = null,
45     defStyleAttr: Int = 0,
46     defStyleRes: Int = 0,
47 ) :
48     FrameLayout(
49         context,
50         attrs,
51         defStyleAttr,
52         defStyleRes,
53     ) {
54 
55     @Deprecated("Deprecated as part of b/278057014")
56     interface MessageDisplayer {
57         fun display(@StringRes stringResourceId: Int)
58     }
59 
60     private var ambientIndicationArea: View? = null
61     private var keyguardIndicationArea: View? = null
62     private var binding: KeyguardBottomAreaViewBinder.Binding? = null
63     private var lockIconViewController: LockIconViewController? = null
64     private var isLockscreenLandscapeEnabled: Boolean = false
65 
66     /** Initializes the view. */
67     @Deprecated("Deprecated as part of b/278057014")
68     fun init(
69         viewModel: KeyguardBottomAreaViewModel,
70         falsingManager: FalsingManager? = null,
71         lockIconViewController: LockIconViewController? = null,
72         messageDisplayer: MessageDisplayer? = null,
73         vibratorHelper: VibratorHelper? = null,
74         activityStarter: ActivityStarter? = null,
75     ) {
76         binding?.destroy()
77         binding =
78             bind(
79                 this,
80                 viewModel,
81                 falsingManager,
82                 vibratorHelper,
83                 activityStarter,
84             ) {
85                 messageDisplayer?.display(it)
86             }
87         this.lockIconViewController = lockIconViewController
88     }
89 
90     /**
91      * Initializes this instance of [KeyguardBottomAreaView] based on the given instance of another
92      * [KeyguardBottomAreaView]
93      */
94     @Deprecated("Deprecated as part of b/278057014")
95     fun initFrom(oldBottomArea: KeyguardBottomAreaView) {
96         // if it exists, continue to use the original ambient indication container
97         // instead of the newly inflated one
98         ambientIndicationArea?.let { nonNullAmbientIndicationArea ->
99             // remove old ambient indication from its parent
100             val originalAmbientIndicationView =
101                 oldBottomArea.requireViewById<View>(R.id.ambient_indication_container)
102             (originalAmbientIndicationView.parent as ViewGroup).removeView(
103                 originalAmbientIndicationView
104             )
105 
106             // remove current ambient indication from its parent (discard)
107             val ambientIndicationParent = nonNullAmbientIndicationArea.parent as ViewGroup
108             val ambientIndicationIndex =
109                 ambientIndicationParent.indexOfChild(nonNullAmbientIndicationArea)
110             ambientIndicationParent.removeView(nonNullAmbientIndicationArea)
111 
112             // add the old ambient indication to this view
113             ambientIndicationParent.addView(originalAmbientIndicationView, ambientIndicationIndex)
114             ambientIndicationArea = originalAmbientIndicationView
115         }
116     }
117 
118     fun setIsLockscreenLandscapeEnabled(isLockscreenLandscapeEnabled: Boolean) {
119         this.isLockscreenLandscapeEnabled = isLockscreenLandscapeEnabled
120     }
121 
122     override fun onFinishInflate() {
123         super.onFinishInflate()
124         ambientIndicationArea = findViewById(R.id.ambient_indication_container)
125         keyguardIndicationArea = findViewById(R.id.keyguard_indication_area)
126     }
127 
128     override fun onConfigurationChanged(newConfig: Configuration) {
129         super.onConfigurationChanged(newConfig)
130         binding?.onConfigurationChanged()
131 
132         if (isLockscreenLandscapeEnabled) {
133             updateIndicationAreaBottomMargin()
134         }
135     }
136 
137     private fun updateIndicationAreaBottomMargin() {
138         keyguardIndicationArea?.let {
139             val params = it.layoutParams as FrameLayout.LayoutParams
140             params.bottomMargin =
141                 resources.getDimensionPixelSize(R.dimen.keyguard_indication_margin_bottom)
142             it.layoutParams = params
143         }
144     }
145 
146     override fun hasOverlappingRendering(): Boolean {
147         return false
148     }
149 
150     override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
151         super.onLayout(changed, left, top, right, bottom)
152         findViewById<View>(R.id.ambient_indication_container)?.let {
153             val (ambientLeft, ambientTop) = it.locationOnScreen
154             if (binding?.shouldConstrainToTopOfLockIcon() == true) {
155                 // make top of ambient indication view the bottom of the lock icon
156                 it.layout(
157                     ambientLeft,
158                     lockIconViewController?.getBottom()?.toInt() ?: 0,
159                     right - ambientLeft,
160                     ambientTop + it.measuredHeight
161                 )
162             } else {
163                 // make bottom of ambient indication view the top of the lock icon
164                 val lockLocationTop = lockIconViewController?.getTop() ?: 0
165                 it.layout(
166                     ambientLeft,
167                     lockLocationTop.toInt() - it.measuredHeight,
168                     right - ambientLeft,
169                     lockLocationTop.toInt()
170                 )
171             }
172         }
173     }
174 }
175