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 package com.android.systemui.statusbar.phone 18 19 import android.testing.TestableLooper 20 import android.view.View 21 import androidx.test.filters.SmallTest 22 import com.android.systemui.res.R 23 import com.android.systemui.SysuiTestCase 24 import com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT 25 import com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT 26 import com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE 27 import com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT 28 import com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT 29 import com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT 30 import com.android.systemui.util.mockito.argumentCaptor 31 import com.android.systemui.util.mockito.mock 32 import com.android.systemui.util.mockito.whenever 33 import com.google.common.truth.Truth.assertThat 34 import org.junit.Before 35 import org.junit.Test 36 import org.mockito.Mockito.reset 37 import org.mockito.Mockito.verify 38 39 @SmallTest 40 @TestableLooper.RunWithLooper(setAsMainLooper = true) 41 class PhoneStatusBarTransitionsTest : SysuiTestCase() { 42 43 // PhoneStatusBarView does a lot of non-standard things when inflating, so just use mocks. 44 private val batteryView = mock<View>() 45 private val statusIcons = mock<View>() 46 private val startIcons = mock<View>() 47 private val statusBarView = <lambda>null48 mock<PhoneStatusBarView>().apply { 49 whenever(this.context).thenReturn(mContext) 50 whenever(this.findViewById<View>(R.id.battery)).thenReturn(batteryView) 51 whenever(this.findViewById<View>(R.id.statusIcons)).thenReturn(statusIcons) 52 whenever(this.findViewById<View>(R.id.status_bar_start_side_except_heads_up)) 53 .thenReturn(startIcons) 54 } <lambda>null55 private val backgroundView = mock<View>().apply { whenever(this.context).thenReturn(mContext) } 56 <lambda>null57 private val underTest: PhoneStatusBarTransitions by lazy { 58 PhoneStatusBarTransitions(statusBarView, backgroundView).also { 59 // The views' alphas will be set when PhoneStatusBarTransitions is created and we want 60 // to ignore those in the tests, so clear those verifications here. 61 reset(batteryView) 62 reset(statusIcons) 63 reset(startIcons) 64 } 65 } 66 67 @Before setUpnull68 fun setUp() { 69 context.orCreateTestableResources.addOverride( 70 R.dimen.status_bar_icon_drawing_alpha, 71 RESOURCE_ALPHA, 72 ) 73 } 74 75 @Test transitionTo_lightsOutMode_batteryTranslucentnull76 fun transitionTo_lightsOutMode_batteryTranslucent() { 77 underTest.transitionTo(/* mode= */ MODE_LIGHTS_OUT, /* animate= */ false) 78 79 val alpha = batteryView.capturedAlpha() 80 assertThat(alpha).isGreaterThan(0) 81 assertThat(alpha).isLessThan(1) 82 } 83 84 @Test transitionTo_lightsOutMode_statusIconsHiddennull85 fun transitionTo_lightsOutMode_statusIconsHidden() { 86 underTest.transitionTo(/* mode= */ MODE_LIGHTS_OUT, /* animate= */ false) 87 88 assertThat(statusIcons.capturedAlpha()).isEqualTo(0) 89 } 90 91 @Test transitionTo_lightsOutMode_startIconsHiddennull92 fun transitionTo_lightsOutMode_startIconsHidden() { 93 underTest.transitionTo(/* mode= */ MODE_LIGHTS_OUT, /* animate= */ false) 94 95 assertThat(startIcons.capturedAlpha()).isEqualTo(0) 96 } 97 98 @Test transitionTo_lightsOutTransparentMode_batteryTranslucentnull99 fun transitionTo_lightsOutTransparentMode_batteryTranslucent() { 100 underTest.transitionTo(/* mode= */ MODE_LIGHTS_OUT_TRANSPARENT, /* animate= */ false) 101 102 val alpha = batteryView.capturedAlpha() 103 assertThat(alpha).isGreaterThan(0) 104 assertThat(alpha).isLessThan(1) 105 } 106 107 @Test transitionTo_lightsOutTransparentMode_statusIconsHiddennull108 fun transitionTo_lightsOutTransparentMode_statusIconsHidden() { 109 underTest.transitionTo(/* mode= */ MODE_LIGHTS_OUT_TRANSPARENT, /* animate= */ false) 110 111 assertThat(statusIcons.capturedAlpha()).isEqualTo(0) 112 } 113 114 @Test transitionTo_lightsOutTransparentMode_startIconsHiddennull115 fun transitionTo_lightsOutTransparentMode_startIconsHidden() { 116 underTest.transitionTo(/* mode= */ MODE_LIGHTS_OUT_TRANSPARENT, /* animate= */ false) 117 118 assertThat(startIcons.capturedAlpha()).isEqualTo(0) 119 } 120 121 @Test transitionTo_translucentMode_batteryIconShownnull122 fun transitionTo_translucentMode_batteryIconShown() { 123 underTest.transitionTo(/* mode= */ MODE_TRANSLUCENT, /* animate= */ false) 124 125 assertThat(batteryView.capturedAlpha()).isEqualTo(1) 126 } 127 128 @Test transitionTo_semiTransparentMode_statusIconsShownnull129 fun transitionTo_semiTransparentMode_statusIconsShown() { 130 underTest.transitionTo(/* mode= */ MODE_SEMI_TRANSPARENT, /* animate= */ false) 131 132 assertThat(statusIcons.capturedAlpha()).isEqualTo(1) 133 } 134 135 @Test transitionTo_transparentMode_startIconsShownnull136 fun transitionTo_transparentMode_startIconsShown() { 137 // Transparent is the default, so we need to switch to a different mode first 138 underTest.transitionTo(/* mode= */ MODE_OPAQUE, /* animate= */ false) 139 reset(startIcons) 140 141 underTest.transitionTo(/* mode= */ MODE_TRANSPARENT, /* animate= */ false) 142 143 assertThat(startIcons.capturedAlpha()).isEqualTo(1) 144 } 145 146 @Test transitionTo_opaqueMode_batteryIconUsesResourceAlphanull147 fun transitionTo_opaqueMode_batteryIconUsesResourceAlpha() { 148 underTest.transitionTo(/* mode= */ MODE_OPAQUE, /* animate= */ false) 149 150 assertThat(batteryView.capturedAlpha()).isEqualTo(RESOURCE_ALPHA) 151 } 152 153 @Test transitionTo_opaqueMode_statusIconsUseResourceAlphanull154 fun transitionTo_opaqueMode_statusIconsUseResourceAlpha() { 155 underTest.transitionTo(/* mode= */ MODE_OPAQUE, /* animate= */ false) 156 157 assertThat(statusIcons.capturedAlpha()).isEqualTo(RESOURCE_ALPHA) 158 } 159 160 @Test transitionTo_opaqueMode_startIconsUseResourceAlphanull161 fun transitionTo_opaqueMode_startIconsUseResourceAlpha() { 162 underTest.transitionTo(/* mode= */ MODE_OPAQUE, /* animate= */ false) 163 164 assertThat(startIcons.capturedAlpha()).isEqualTo(RESOURCE_ALPHA) 165 } 166 167 @Test onHeadsUpStateChanged_true_semiTransparentMode_startIconsShownnull168 fun onHeadsUpStateChanged_true_semiTransparentMode_startIconsShown() { 169 underTest.transitionTo(/* mode= */ MODE_SEMI_TRANSPARENT, /* animate= */ false) 170 reset(startIcons) 171 172 underTest.onHeadsUpStateChanged(true) 173 174 assertThat(startIcons.capturedAlpha()).isEqualTo(1) 175 } 176 177 @Test onHeadsUpStateChanged_true_opaqueMode_startIconsUseResourceAlphanull178 fun onHeadsUpStateChanged_true_opaqueMode_startIconsUseResourceAlpha() { 179 underTest.transitionTo(/* mode= */ MODE_OPAQUE, /* animate= */ false) 180 reset(startIcons) 181 182 underTest.onHeadsUpStateChanged(true) 183 184 assertThat(startIcons.capturedAlpha()).isEqualTo(RESOURCE_ALPHA) 185 } 186 187 /** Regression test for b/291173113. */ 188 @Test onHeadsUpStateChanged_true_lightsOutMode_startIconsUseResourceAlphanull189 fun onHeadsUpStateChanged_true_lightsOutMode_startIconsUseResourceAlpha() { 190 underTest.transitionTo(/* mode= */ MODE_LIGHTS_OUT, /* animate= */ false) 191 reset(startIcons) 192 193 underTest.onHeadsUpStateChanged(true) 194 195 assertThat(startIcons.capturedAlpha()).isEqualTo(RESOURCE_ALPHA) 196 } 197 198 @Test onHeadsUpStateChanged_false_semiTransparentMode_startIconsShownnull199 fun onHeadsUpStateChanged_false_semiTransparentMode_startIconsShown() { 200 underTest.transitionTo(/* mode= */ MODE_SEMI_TRANSPARENT, /* animate= */ false) 201 reset(startIcons) 202 203 underTest.onHeadsUpStateChanged(false) 204 205 assertThat(startIcons.capturedAlpha()).isEqualTo(1) 206 } 207 208 @Test onHeadsUpStateChanged_false_opaqueMode_startIconsUseResourceAlphanull209 fun onHeadsUpStateChanged_false_opaqueMode_startIconsUseResourceAlpha() { 210 underTest.transitionTo(/* mode= */ MODE_OPAQUE, /* animate= */ false) 211 reset(startIcons) 212 213 underTest.onHeadsUpStateChanged(false) 214 215 assertThat(startIcons.capturedAlpha()).isEqualTo(RESOURCE_ALPHA) 216 } 217 218 @Test onHeadsUpStateChanged_false_lightsOutMode_startIconsHiddennull219 fun onHeadsUpStateChanged_false_lightsOutMode_startIconsHidden() { 220 underTest.transitionTo(/* mode= */ MODE_LIGHTS_OUT, /* animate= */ false) 221 reset(startIcons) 222 223 underTest.onHeadsUpStateChanged(false) 224 225 assertThat(startIcons.capturedAlpha()).isEqualTo(0) 226 } 227 Viewnull228 private fun View.capturedAlpha(): Float { 229 val captor = argumentCaptor<Float>() 230 verify(this).alpha = captor.capture() 231 return captor.value 232 } 233 234 private companion object { 235 const val RESOURCE_ALPHA = 0.34f 236 } 237 } 238