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.blueprints 19 20 import android.testing.TestableLooper.RunWithLooper 21 import androidx.constraintlayout.widget.ConstraintLayout 22 import androidx.constraintlayout.widget.ConstraintSet 23 import androidx.test.ext.junit.runners.AndroidJUnit4 24 import androidx.test.filters.SmallTest 25 import com.android.systemui.SysuiTestCase 26 import com.android.systemui.communal.ui.view.layout.sections.CommunalTutorialIndicatorSection 27 import com.android.systemui.keyguard.shared.model.KeyguardBlueprint 28 import com.android.systemui.keyguard.shared.model.KeyguardSection 29 import com.android.systemui.keyguard.ui.view.KeyguardRootView 30 import com.android.systemui.keyguard.ui.view.layout.sections.AccessibilityActionsSection 31 import com.android.systemui.keyguard.ui.view.layout.sections.AodBurnInSection 32 import com.android.systemui.keyguard.ui.view.layout.sections.AodNotificationIconsSection 33 import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection 34 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultDeviceEntrySection 35 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection 36 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultNotificationStackScrollLayoutSection 37 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultSettingsPopupMenuSection 38 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSection 39 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusBarSection 40 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusViewSection 41 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultUdfpsAccessibilityOverlaySection 42 import com.android.systemui.keyguard.ui.view.layout.sections.KeyguardSliceViewSection 43 import com.android.systemui.keyguard.ui.view.layout.sections.SmartspaceSection 44 import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeGuidelines 45 import com.android.systemui.util.mockito.whenever 46 import java.util.Optional 47 import kotlinx.coroutines.ExperimentalCoroutinesApi 48 import org.junit.Before 49 import org.junit.Test 50 import org.junit.runner.RunWith 51 import org.mockito.Mock 52 import org.mockito.Mockito.mock 53 import org.mockito.Mockito.never 54 import org.mockito.Mockito.verify 55 import org.mockito.MockitoAnnotations 56 57 @RunWith(AndroidJUnit4::class) 58 @RunWithLooper(setAsMainLooper = true) 59 @ExperimentalCoroutinesApi 60 @SmallTest 61 class DefaultKeyguardBlueprintTest : SysuiTestCase() { 62 private lateinit var underTest: DefaultKeyguardBlueprint 63 private lateinit var rootView: KeyguardRootView 64 @Mock private lateinit var accessibilityActionsSection: AccessibilityActionsSection 65 @Mock private lateinit var defaultIndicationAreaSection: DefaultIndicationAreaSection 66 @Mock private lateinit var mDefaultDeviceEntrySection: DefaultDeviceEntrySection 67 @Mock private lateinit var defaultShortcutsSection: DefaultShortcutsSection 68 @Mock private lateinit var defaultAmbientIndicationAreaSection: Optional<KeyguardSection> 69 @Mock private lateinit var defaultSettingsPopupMenuSection: DefaultSettingsPopupMenuSection 70 @Mock private lateinit var defaultStatusViewSection: DefaultStatusViewSection 71 @Mock private lateinit var defaultStatusBarViewSection: DefaultStatusBarSection 72 @Mock private lateinit var defaultNSSLSection: DefaultNotificationStackScrollLayoutSection 73 @Mock private lateinit var splitShadeGuidelines: SplitShadeGuidelines 74 @Mock private lateinit var aodNotificationIconsSection: AodNotificationIconsSection 75 @Mock private lateinit var aodBurnInSection: AodBurnInSection 76 @Mock private lateinit var communalTutorialIndicatorSection: CommunalTutorialIndicatorSection 77 @Mock private lateinit var clockSection: ClockSection 78 @Mock private lateinit var smartspaceSection: SmartspaceSection 79 @Mock private lateinit var keyguardSliceViewSection: KeyguardSliceViewSection 80 @Mock 81 private lateinit var udfpsAccessibilityOverlaySection: DefaultUdfpsAccessibilityOverlaySection 82 @Before setupnull83 fun setup() { 84 MockitoAnnotations.initMocks(this) 85 rootView = KeyguardRootView(context, null) 86 underTest = 87 DefaultKeyguardBlueprint( 88 accessibilityActionsSection, 89 defaultIndicationAreaSection, 90 mDefaultDeviceEntrySection, 91 defaultShortcutsSection, 92 defaultAmbientIndicationAreaSection, 93 defaultSettingsPopupMenuSection, 94 defaultStatusViewSection, 95 defaultStatusBarViewSection, 96 defaultNSSLSection, 97 aodNotificationIconsSection, 98 aodBurnInSection, 99 communalTutorialIndicatorSection, 100 clockSection, 101 smartspaceSection, 102 keyguardSliceViewSection, 103 udfpsAccessibilityOverlaySection, 104 ) 105 } 106 107 @Test replaceViewsnull108 fun replaceViews() { 109 val constraintLayout = ConstraintLayout(context, null) 110 underTest.replaceViews(constraintLayout) 111 underTest.sections.forEach { verify(it)?.addViews(constraintLayout) } 112 } 113 114 @Test replaceViews_withPrevBlueprintnull115 fun replaceViews_withPrevBlueprint() { 116 val prevBlueprint = mock(KeyguardBlueprint::class.java) 117 val removedSection = mock(KeyguardSection::class.java) 118 val addedSection = mDefaultDeviceEntrySection 119 val rebuildSection = clockSection 120 val prevSections = underTest.sections.minus(addedSection).plus(removedSection) 121 val unchangedSections = underTest.sections.subtract(listOf(addedSection, rebuildSection)) 122 whenever(prevBlueprint.sections).thenReturn(prevSections) 123 124 val constraintLayout = ConstraintLayout(context, null) 125 underTest.replaceViews(constraintLayout, prevBlueprint) 126 127 unchangedSections.forEach { 128 verify(it, never()).addViews(constraintLayout) 129 verify(it, never()).removeViews(constraintLayout) 130 } 131 132 verify(addedSection).addViews(constraintLayout) 133 verify(removedSection).removeViews(constraintLayout) 134 } 135 136 @Test replaceViews_withPrevBlueprint_withRebuildTargetsnull137 fun replaceViews_withPrevBlueprint_withRebuildTargets() { 138 val prevBlueprint = mock(KeyguardBlueprint::class.java) 139 val removedSection = mock(KeyguardSection::class.java) 140 val addedSection = mDefaultDeviceEntrySection 141 val rebuildSection = clockSection 142 val prevSections = underTest.sections.minus(addedSection).plus(removedSection) 143 val unchangedSections = underTest.sections.subtract(listOf(addedSection, rebuildSection)) 144 whenever(prevBlueprint.sections).thenReturn(prevSections) 145 146 val constraintLayout = ConstraintLayout(context, null) 147 underTest.replaceViews(constraintLayout, prevBlueprint, listOf(rebuildSection)) 148 149 unchangedSections.forEach { 150 verify(it, never()).addViews(constraintLayout) 151 verify(it, never()).removeViews(constraintLayout) 152 } 153 154 verify(addedSection).addViews(constraintLayout) 155 verify(rebuildSection).addViews(constraintLayout) 156 verify(rebuildSection).removeViews(constraintLayout) 157 verify(removedSection).removeViews(constraintLayout) 158 } 159 160 @Test rebuildViewsnull161 fun rebuildViews() { 162 val rebuildSections = listOf(mDefaultDeviceEntrySection, clockSection) 163 val unchangedSections = underTest.sections.subtract(rebuildSections) 164 165 val constraintLayout = ConstraintLayout(context, null) 166 underTest.rebuildViews(constraintLayout, rebuildSections) 167 168 unchangedSections.forEach { 169 verify(it, never()).addViews(constraintLayout) 170 verify(it, never()).removeViews(constraintLayout) 171 } 172 173 rebuildSections.forEach { 174 verify(it).addViews(constraintLayout) 175 verify(it).removeViews(constraintLayout) 176 } 177 } 178 179 @Test deviceEntryIconIsOnTopnull180 fun deviceEntryIconIsOnTop() { 181 val constraintLayout = ConstraintLayout(context, null) 182 underTest.replaceViews(constraintLayout) 183 underTest.sections.forEach { verify(it)?.addViews(constraintLayout) } 184 } 185 186 @Test applyConstraintsnull187 fun applyConstraints() { 188 val cs = ConstraintSet() 189 underTest.applyConstraints(cs) 190 underTest.sections.forEach { verify(it)?.applyConstraints(cs) } 191 } 192 } 193