1 /* 2 * Copyright (C) 2024 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.qs.tiles.impl.rotation.ui.mapper 18 19 import android.graphics.drawable.TestStubDrawable 20 import android.widget.Switch 21 import androidx.test.ext.junit.runners.AndroidJUnit4 22 import androidx.test.filters.SmallTest 23 import com.android.systemui.SysuiTestCase 24 import com.android.systemui.common.shared.model.Icon 25 import com.android.systemui.defaultDeviceState 26 import com.android.systemui.deviceStateManager 27 import com.android.systemui.foldedDeviceStateList 28 import com.android.systemui.kosmos.Kosmos 29 import com.android.systemui.qs.tiles.impl.custom.QSTileStateSubject 30 import com.android.systemui.qs.tiles.impl.rotation.domain.model.RotationLockTileModel 31 import com.android.systemui.qs.tiles.impl.rotation.qsRotationLockTileConfig 32 import com.android.systemui.qs.tiles.viewmodel.QSTileState 33 import com.android.systemui.res.R 34 import com.android.systemui.statusbar.policy.DevicePostureController 35 import com.android.systemui.statusbar.policy.devicePostureController 36 import com.google.common.truth.Truth.assertThat 37 import org.junit.Before 38 import org.junit.Test 39 import org.junit.runner.RunWith 40 import org.mockito.kotlin.whenever 41 42 @SmallTest 43 @RunWith(AndroidJUnit4::class) 44 class RotationLockTileMapperTest : SysuiTestCase() { 45 private val kosmos = Kosmos() 46 private val rotationLockTileConfig = kosmos.qsRotationLockTileConfig 47 private val devicePostureController = kosmos.devicePostureController 48 private val deviceStateManager = kosmos.deviceStateManager 49 50 private lateinit var mapper: RotationLockTileMapper 51 52 @Before setupnull53 fun setup() { 54 deviceStateManager 55 whenever(devicePostureController.devicePosture) 56 .thenReturn(DevicePostureController.DEVICE_POSTURE_CLOSED) 57 whenever(deviceStateManager.supportedDeviceStates) 58 .thenReturn(listOf(kosmos.defaultDeviceState)) 59 60 mapper = 61 RotationLockTileMapper( 62 context.orCreateTestableResources 63 .apply { 64 addOverride(R.drawable.qs_auto_rotate_icon_off, TestStubDrawable()) 65 addOverride(R.drawable.qs_auto_rotate_icon_on, TestStubDrawable()) 66 addOverride(com.android.internal.R.bool.config_allowRotationResolver, true) 67 addOverride( 68 com.android.internal.R.array.config_foldedDeviceStates, 69 intArrayOf(), // empty array <=> device is not foldable 70 ) 71 } 72 .resources, 73 context.theme, 74 devicePostureController, 75 deviceStateManager, 76 ) 77 } 78 79 @Test rotationNotLocked_cameraRotationDisablednull80 fun rotationNotLocked_cameraRotationDisabled() { 81 val inputModel = RotationLockTileModel(false, false) 82 83 val outputState = mapper.map(rotationLockTileConfig, inputModel) 84 85 val expectedState = 86 createRotationLockTileState( 87 QSTileState.ActivationState.ACTIVE, 88 EMPTY_SECONDARY_STRING, 89 R.drawable.qs_auto_rotate_icon_on, 90 ) 91 QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState) 92 } 93 94 @Test rotationNotLocked_cameraRotationEnablednull95 fun rotationNotLocked_cameraRotationEnabled() { 96 val inputModel = RotationLockTileModel(false, true) 97 98 val outputState = mapper.map(rotationLockTileConfig, inputModel) 99 100 val expectedState = 101 createRotationLockTileState( 102 QSTileState.ActivationState.ACTIVE, 103 context.getString(R.string.rotation_lock_camera_rotation_on), 104 R.drawable.qs_auto_rotate_icon_on, 105 ) 106 QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState) 107 } 108 109 @Test rotationLocked_cameraRotationNotEnablednull110 fun rotationLocked_cameraRotationNotEnabled() { 111 val inputModel = RotationLockTileModel(true, false) 112 113 val outputState = mapper.map(rotationLockTileConfig, inputModel) 114 115 val expectedState = 116 createRotationLockTileState( 117 QSTileState.ActivationState.INACTIVE, 118 EMPTY_SECONDARY_STRING, 119 R.drawable.qs_auto_rotate_icon_off, 120 ) 121 QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState) 122 } 123 124 @Test deviceFoldableAndClosed_secondaryLabelIsFoldableSpecificnull125 fun deviceFoldableAndClosed_secondaryLabelIsFoldableSpecific() { 126 setDeviceFoldable() 127 val inputModel = RotationLockTileModel(false, false) 128 129 val outputState = mapper.map(rotationLockTileConfig, inputModel) 130 131 val expectedSecondaryLabelEnding = 132 context.getString(R.string.quick_settings_rotation_posture_folded) 133 assertThat( 134 context.resources.getIntArray( 135 com.android.internal.R.array.config_foldedDeviceStates 136 ) 137 ) 138 .isNotEmpty() 139 val actualSecondaryLabel = outputState.secondaryLabel 140 assertThat(actualSecondaryLabel).isNotNull() 141 assertThat(actualSecondaryLabel!!.endsWith(expectedSecondaryLabelEnding)).isTrue() 142 } 143 144 @Test deviceFoldableAndNotClosed_secondaryLabelIsFoldableSpecificnull145 fun deviceFoldableAndNotClosed_secondaryLabelIsFoldableSpecific() { 146 setDeviceFoldable() 147 whenever(devicePostureController.devicePosture) 148 .thenReturn(DevicePostureController.DEVICE_POSTURE_OPENED) 149 val inputModel = RotationLockTileModel(false, false) 150 151 val outputState = mapper.map(rotationLockTileConfig, inputModel) 152 153 val expectedSecondaryLabelEnding = 154 context.getString(R.string.quick_settings_rotation_posture_unfolded) 155 assertThat( 156 context.orCreateTestableResources.resources.getIntArray( 157 com.android.internal.R.array.config_foldedDeviceStates 158 ) 159 ) 160 .isNotEmpty() 161 val actualSecondaryLabel = outputState.secondaryLabel 162 assertThat(actualSecondaryLabel).isNotNull() 163 assertThat(actualSecondaryLabel!!.endsWith(expectedSecondaryLabelEnding)).isTrue() 164 } 165 setDeviceFoldablenull166 private fun setDeviceFoldable() { 167 mapper.apply { 168 overrideResource( 169 com.android.internal.R.array.config_foldedDeviceStates, 170 intArrayOf(1, 2, 3), 171 ) 172 } 173 whenever(deviceStateManager.supportedDeviceStates).thenReturn(kosmos.foldedDeviceStateList) 174 } 175 createRotationLockTileStatenull176 private fun createRotationLockTileState( 177 activationState: QSTileState.ActivationState, 178 secondaryLabel: String, 179 iconRes: Int, 180 ): QSTileState { 181 val label = context.getString(R.string.quick_settings_rotation_unlocked_label) 182 return QSTileState( 183 Icon.Loaded(context.getDrawable(iconRes)!!, null), 184 iconRes, 185 label, 186 activationState, 187 secondaryLabel, 188 setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK), 189 context.getString(R.string.accessibility_quick_settings_rotation), 190 secondaryLabel, 191 QSTileState.SideViewIcon.None, 192 QSTileState.EnabledState.ENABLED, 193 Switch::class.qualifiedName, 194 ) 195 } 196 197 private companion object { 198 private const val EMPTY_SECONDARY_STRING = "" 199 } 200 } 201