• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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.keyguard.ui.view.layout.sections
18 
19 import android.content.Context
20 import androidx.compose.ui.platform.ComposeView
21 import androidx.constraintlayout.widget.ConstraintLayout
22 import androidx.constraintlayout.widget.ConstraintSet
23 import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
24 import androidx.constraintlayout.widget.ConstraintSet.END
25 import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
26 import androidx.constraintlayout.widget.ConstraintSet.START
27 import androidx.constraintlayout.widget.ConstraintSet.TOP
28 import com.android.systemui.keyguard.shared.model.KeyguardSection
29 import com.android.systemui.res.R
30 import com.android.systemui.shade.ShadeDisplayAware
31 import com.android.systemui.shade.domain.interactor.ShadeModeInteractor
32 import com.android.systemui.statusbar.notification.promoted.AODPromotedNotification
33 import com.android.systemui.statusbar.notification.promoted.PromotedNotificationLogger
34 import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUi
35 import com.android.systemui.statusbar.notification.promoted.ui.viewmodel.AODPromotedNotificationViewModel
36 import javax.inject.Inject
37 
38 class AodPromotedNotificationSection
39 @Inject
40 constructor(
41     @ShadeDisplayAware private val context: Context,
42     private val viewModelFactory: AODPromotedNotificationViewModel.Factory,
43     private val shadeModeInteractor: ShadeModeInteractor,
44     private val logger: PromotedNotificationLogger,
45 ) : KeyguardSection() {
46     var view: ComposeView? = null
47 
48     init {
49         logger.logSectionCreated(this)
50     }
51 
addViewsnull52     override fun addViews(constraintLayout: ConstraintLayout) {
53         if (!PromotedNotificationUi.isEnabled) {
54             return
55         }
56 
57         check(view == null)
58 
59         view =
60             ComposeView(constraintLayout.context).apply {
61                 setContent { AODPromotedNotification(viewModelFactory) }
62                 id = viewId
63                 constraintLayout.addView(this)
64             }
65 
66         logger.logSectionAddedViews(this)
67     }
68 
bindDatanull69     override fun bindData(constraintLayout: ConstraintLayout) {
70         if (!PromotedNotificationUi.isEnabled) {
71             return
72         }
73 
74         checkNotNull(view)
75 
76         // Do nothing; the binding happens in the AODPromotedNotification Composable.
77 
78         logger.logSectionBoundData(this)
79     }
80 
applyConstraintsnull81     override fun applyConstraints(constraintSet: ConstraintSet) {
82         if (!PromotedNotificationUi.isEnabled) {
83             return
84         }
85 
86         // view may have been created by a different instance of the section (!), and we don't
87         // actually *need* it to set constraints, so don't check for it here.
88 
89         val topPadding =
90             context.resources.getDimensionPixelSize(R.dimen.below_clock_padding_start_icons)
91 
92         constraintSet.apply {
93             val isShadeLayoutWide = shadeModeInteractor.isShadeLayoutWide.value
94 
95             if (isShadeLayoutWide) {
96                 // When in split shade, align with top of smart space:
97                 connect(viewId, TOP, R.id.smart_space_barrier_top, TOP, 0)
98 
99                 // and occupy the right half of the screen:
100                 connect(viewId, START, R.id.split_shade_guideline, START, 0)
101                 connect(viewId, END, PARENT_ID, END, 0)
102 
103                 // TODO(b/369151941): Calculate proper right padding here (when in split shade, it's
104                 // bigger than what the Composable applies!)
105             } else {
106                 // When not in split shade, place below smart space:
107                 connect(viewId, TOP, R.id.smart_space_barrier_bottom, BOTTOM, topPadding)
108 
109                 // and occupy the full width of the screen:
110                 connect(viewId, START, PARENT_ID, START, 0)
111                 connect(viewId, END, PARENT_ID, END, 0)
112             }
113 
114             constrainWidth(viewId, ConstraintSet.MATCH_CONSTRAINT)
115             constrainHeight(viewId, ConstraintSet.WRAP_CONTENT)
116         }
117 
118         logger.logSectionAppliedConstraints(this)
119     }
120 
removeViewsnull121     override fun removeViews(constraintLayout: ConstraintLayout) {
122         if (!PromotedNotificationUi.isEnabled) {
123             return
124         }
125 
126         constraintLayout.removeView(checkNotNull(view))
127 
128         view = null
129 
130         logger.logSectionRemovedViews(this)
131     }
132 
133     companion object {
134         val viewId = R.id.aod_promoted_notification_frame
135     }
136 }
137