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