1 /*
2  * Copyright (C) 2023 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 
18 package com.android.systemui.keyguard.ui.view.layout.sections
19 
20 import android.content.Context
21 import android.view.LayoutInflater
22 import android.view.View
23 import android.view.ViewGroup
24 import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
25 import androidx.constraintlayout.widget.ConstraintLayout
26 import androidx.constraintlayout.widget.ConstraintSet
27 import androidx.constraintlayout.widget.ConstraintSet.END
28 import androidx.constraintlayout.widget.ConstraintSet.MATCH_CONSTRAINT
29 import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
30 import androidx.constraintlayout.widget.ConstraintSet.START
31 import androidx.constraintlayout.widget.ConstraintSet.TOP
32 import com.android.keyguard.KeyguardStatusView
33 import com.android.keyguard.dagger.KeyguardStatusViewComponent
34 import com.android.systemui.keyguard.KeyguardViewConfigurator
35 import com.android.systemui.keyguard.MigrateClocksToBlueprint
36 import com.android.systemui.keyguard.shared.model.KeyguardSection
37 import com.android.systemui.media.controls.ui.controller.KeyguardMediaController
38 import com.android.systemui.res.R
39 import com.android.systemui.shade.NotificationPanelView
40 import com.android.systemui.shade.NotificationPanelViewController
41 import com.android.systemui.statusbar.policy.SplitShadeStateController
42 import com.android.systemui.util.Utils
43 import dagger.Lazy
44 import javax.inject.Inject
45 import kotlinx.coroutines.ExperimentalCoroutinesApi
46 
47 class DefaultStatusViewSection
48 @Inject
49 constructor(
50     private val context: Context,
51     private val notificationPanelView: NotificationPanelView,
52     private val keyguardStatusViewComponentFactory: KeyguardStatusViewComponent.Factory,
53     private val keyguardViewConfigurator: Lazy<KeyguardViewConfigurator>,
54     private val notificationPanelViewController: Lazy<NotificationPanelViewController>,
55     private val keyguardMediaController: KeyguardMediaController,
56     private val splitShadeStateController: SplitShadeStateController,
57 ) : KeyguardSection() {
58     private val statusViewId = R.id.keyguard_status_view
59 
addViewsnull60     override fun addViews(constraintLayout: ConstraintLayout) {
61         if (!MigrateClocksToBlueprint.isEnabled) {
62             return
63         }
64         // At startup, 2 views with the ID `R.id.keyguard_status_view` will be available.
65         // Disable one of them
66         notificationPanelView.findViewById<View>(statusViewId)?.let {
67             notificationPanelView.removeView(it)
68         }
69         val keyguardStatusView =
70             (LayoutInflater.from(context)
71                     .inflate(R.layout.keyguard_status_view, constraintLayout, false)
72                     as KeyguardStatusView)
73                 .apply { clipChildren = false }
74 
75         // This is diassembled and moved to [AodNotificationIconsSection]
76         keyguardStatusView.findViewById<View>(R.id.left_aligned_notification_icon_container)?.let {
77             it.setVisibility(View.GONE)
78         }
79         // Should keep this even if flag, migrating clocks to blueprint, is on
80         // cause some events in clockEventController rely on keyguardStatusViewController
81         // TODO(b/313499340): clean up
82         constraintLayout.addView(keyguardStatusView)
83     }
84 
bindDatanull85     override fun bindData(constraintLayout: ConstraintLayout) {
86         if (MigrateClocksToBlueprint.isEnabled) {
87             constraintLayout.findViewById<KeyguardStatusView?>(R.id.keyguard_status_view)?.let {
88                 val statusViewComponent =
89                     keyguardStatusViewComponentFactory.build(it, context.display)
90                 val controller = statusViewComponent.keyguardStatusViewController
91                 controller.init()
92                 keyguardMediaController.attachSplitShadeContainer(
93                     it.requireViewById<ViewGroup>(R.id.status_view_media_container)
94                 )
95                 keyguardViewConfigurator.get().keyguardStatusViewController = controller
96                 notificationPanelViewController.get().updateStatusViewController()
97             }
98         }
99     }
100 
applyConstraintsnull101     override fun applyConstraints(constraintSet: ConstraintSet) {
102         constraintSet.apply {
103             constrainWidth(statusViewId, MATCH_CONSTRAINT)
104             constrainHeight(statusViewId, WRAP_CONTENT)
105             // TODO(b/296122465): Constrain to the top of [DefaultStatusBarSection] and remove the
106             // extra margin below.
107             connect(statusViewId, TOP, PARENT_ID, TOP)
108             connect(statusViewId, START, PARENT_ID, START)
109             connect(statusViewId, END, PARENT_ID, END)
110 
111             val margin =
112                 if (splitShadeStateController.shouldUseSplitNotificationShade(context.resources)) {
113                     context.resources.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin)
114                 } else {
115                     context.resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) +
116                         Utils.getStatusBarHeaderHeightKeyguard(context)
117                 }
118             setMargin(statusViewId, TOP, margin)
119         }
120     }
121 
122     @OptIn(ExperimentalCoroutinesApi::class)
removeViewsnull123     override fun removeViews(constraintLayout: ConstraintLayout) {
124         constraintLayout.removeView(statusViewId)
125         keyguardViewConfigurator.get().keyguardStatusViewController = null
126     }
127 }
128