1 /* 2 * Copyright (C) 2021 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; 18 19 import static android.hardware.SensorPrivacyManager.Sensors.CAMERA; 20 21 import static junit.framework.TestCase.assertEquals; 22 23 import static org.mockito.Mockito.doReturn; 24 import static org.mockito.Mockito.when; 25 26 import android.Manifest; 27 import android.content.pm.PackageManager; 28 import android.hardware.SensorPrivacyManager; 29 import android.os.Handler; 30 import android.test.suitebuilder.annotation.SmallTest; 31 import android.testing.AndroidTestingRunner; 32 import android.testing.TestableLooper; 33 import android.testing.TestableResources; 34 35 import com.android.internal.logging.MetricsLogger; 36 import com.android.systemui.R; 37 import com.android.systemui.SysuiTestCase; 38 import com.android.systemui.classifier.FalsingManagerFake; 39 import com.android.systemui.plugins.ActivityStarter; 40 import com.android.systemui.plugins.qs.QSTile; 41 import com.android.systemui.plugins.statusbar.StatusBarStateController; 42 import com.android.systemui.qs.QSHost; 43 import com.android.systemui.qs.QsEventLogger; 44 import com.android.systemui.qs.logging.QSLogger; 45 import com.android.systemui.qs.tileimpl.QSTileImpl; 46 import com.android.systemui.statusbar.policy.BatteryController; 47 import com.android.systemui.statusbar.policy.DeviceStateRotationLockSettingController; 48 import com.android.systemui.statusbar.policy.RotationLockController; 49 import com.android.systemui.statusbar.policy.RotationLockControllerImpl; 50 import com.android.systemui.util.settings.FakeSettings; 51 import com.android.systemui.util.wrapper.RotationPolicyWrapper; 52 53 import org.junit.After; 54 import org.junit.Before; 55 import org.junit.Test; 56 import org.junit.runner.RunWith; 57 import org.mockito.Mock; 58 import org.mockito.MockitoAnnotations; 59 60 61 @RunWith(AndroidTestingRunner.class) 62 @TestableLooper.RunWithLooper(setAsMainLooper = true) 63 @SmallTest 64 public class RotationLockTileTest extends SysuiTestCase { 65 66 private static final String PACKAGE_NAME = "package_name"; 67 private static final String[] DEFAULT_SETTINGS = new String[]{ 68 "0:0", 69 "1:2" 70 }; 71 72 @Mock 73 private PackageManager mPackageManager; 74 @Mock 75 private ActivityStarter mActivityStarter; 76 @Mock 77 private QSHost mHost; 78 @Mock 79 private MetricsLogger mMetricsLogger; 80 @Mock 81 private StatusBarStateController mStatusBarStateController; 82 @Mock 83 private QSLogger mQSLogger; 84 @Mock 85 private SensorPrivacyManager mPrivacyManager; 86 @Mock 87 private BatteryController mBatteryController; 88 @Mock 89 DeviceStateRotationLockSettingController mDeviceStateRotationLockSettingController; 90 @Mock 91 RotationPolicyWrapper mRotationPolicyWrapper; 92 @Mock 93 QsEventLogger mUiEventLogger; 94 95 private RotationLockController mController; 96 private TestableLooper mTestableLooper; 97 private RotationLockTile mLockTile; 98 private TestableResources mTestableResources; 99 100 @Before setUp()101 public void setUp() throws Exception { 102 MockitoAnnotations.initMocks(this); 103 mTestableLooper = TestableLooper.get(this); 104 mTestableResources = mContext.getOrCreateTestableResources(); 105 106 when(mHost.getContext()).thenReturn(mContext); 107 when(mHost.getUserContext()).thenReturn(mContext); 108 mTestableResources.addOverride(com.android.internal.R.bool.config_allowRotationResolver, 109 true); 110 111 mController = new RotationLockControllerImpl(mRotationPolicyWrapper, 112 mDeviceStateRotationLockSettingController, DEFAULT_SETTINGS); 113 114 mLockTile = new RotationLockTile( 115 mHost, 116 mUiEventLogger, 117 mTestableLooper.getLooper(), 118 new Handler(mTestableLooper.getLooper()), 119 new FalsingManagerFake(), 120 mMetricsLogger, 121 mStatusBarStateController, 122 mActivityStarter, 123 mQSLogger, 124 mController, 125 mPrivacyManager, 126 mBatteryController, 127 new FakeSettings() 128 ); 129 130 mLockTile.initialize(); 131 132 // We are not setting the mocks to listening, so we trigger a first refresh state to 133 // set the initial state 134 mLockTile.refreshState(); 135 136 mTestableLooper.processAllMessages(); 137 138 mContext.setMockPackageManager(mPackageManager); 139 doReturn(PACKAGE_NAME).when(mPackageManager).getRotationResolverPackageName(); 140 doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission( 141 Manifest.permission.CAMERA, PACKAGE_NAME); 142 143 when(mBatteryController.isPowerSave()).thenReturn(false); 144 when(mPrivacyManager.isSensorPrivacyEnabled(CAMERA)).thenReturn(false); 145 enableAutoRotation(); 146 enableCameraBasedRotation(); 147 148 mLockTile.refreshState(); 149 mTestableLooper.processAllMessages(); 150 } 151 152 @After tearDown()153 public void tearDown() { 154 mLockTile.destroy(); 155 mTestableLooper.processAllMessages(); 156 } 157 158 @Test testSecondaryString_cameraRotateOn_returnsFaceBased()159 public void testSecondaryString_cameraRotateOn_returnsFaceBased() { 160 assertEquals(mContext.getString(R.string.rotation_lock_camera_rotation_on), 161 mLockTile.getState().secondaryLabel.toString()); 162 } 163 164 @Test testSecondaryString_rotateOff_isEmpty()165 public void testSecondaryString_rotateOff_isEmpty() { 166 disableAutoRotation(); 167 168 mLockTile.refreshState(); 169 mTestableLooper.processAllMessages(); 170 171 assertEquals("", mLockTile.getState().secondaryLabel.toString()); 172 } 173 174 @Test testSecondaryString_cameraRotateOff_isEmpty()175 public void testSecondaryString_cameraRotateOff_isEmpty() { 176 disableCameraBasedRotation(); 177 178 mLockTile.refreshState(); 179 mTestableLooper.processAllMessages(); 180 181 assertEquals("", mLockTile.getState().secondaryLabel.toString()); 182 } 183 184 @Test testSecondaryString_powerSaveEnabled_isEmpty()185 public void testSecondaryString_powerSaveEnabled_isEmpty() { 186 when(mBatteryController.isPowerSave()).thenReturn(true); 187 188 mLockTile.refreshState(); 189 mTestableLooper.processAllMessages(); 190 191 assertEquals("", mLockTile.getState().secondaryLabel.toString()); 192 } 193 194 @Test testSecondaryString_cameraDisabled_isEmpty()195 public void testSecondaryString_cameraDisabled_isEmpty() { 196 when(mPrivacyManager.isSensorPrivacyEnabled(CAMERA)).thenReturn(true); 197 198 mLockTile.refreshState(); 199 mTestableLooper.processAllMessages(); 200 201 assertEquals("", mLockTile.getState().secondaryLabel.toString()); 202 } 203 204 @Test testSecondaryString_noCameraPermission_isEmpty()205 public void testSecondaryString_noCameraPermission_isEmpty() { 206 doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission( 207 Manifest.permission.CAMERA, PACKAGE_NAME); 208 209 mLockTile.refreshState(); 210 mTestableLooper.processAllMessages(); 211 212 assertEquals("", mLockTile.getState().secondaryLabel.toString()); 213 } 214 215 @Test testSecondaryString_rotationResolverDisabled_isEmpty()216 public void testSecondaryString_rotationResolverDisabled_isEmpty() { 217 mTestableResources.addOverride(com.android.internal.R.bool.config_allowRotationResolver, 218 false); 219 RotationLockTile otherTile = new RotationLockTile( 220 mHost, 221 mUiEventLogger, 222 mTestableLooper.getLooper(), 223 new Handler(mTestableLooper.getLooper()), 224 new FalsingManagerFake(), 225 mMetricsLogger, 226 mStatusBarStateController, 227 mActivityStarter, 228 mQSLogger, 229 mController, 230 mPrivacyManager, 231 mBatteryController, 232 new FakeSettings() 233 ); 234 235 otherTile.refreshState(); 236 mTestableLooper.processAllMessages(); 237 238 assertEquals("", otherTile.getState().secondaryLabel.toString()); 239 240 destroyTile(otherTile); 241 } 242 243 @Test testIcon_whenDisabled_isOffState()244 public void testIcon_whenDisabled_isOffState() { 245 QSTile.BooleanState state = new QSTile.BooleanState(); 246 disableAutoRotation(); 247 248 mLockTile.handleUpdateState(state, /* arg= */ null); 249 250 assertEquals(state.icon, QSTileImpl.ResourceIcon.get(R.drawable.qs_auto_rotate_icon_off)); 251 } 252 253 @Test testIcon_whenEnabled_isOnState()254 public void testIcon_whenEnabled_isOnState() { 255 QSTile.BooleanState state = new QSTile.BooleanState(); 256 enableAutoRotation(); 257 258 mLockTile.handleUpdateState(state, /* arg= */ null); 259 260 assertEquals(state.icon, QSTileImpl.ResourceIcon.get(R.drawable.qs_auto_rotate_icon_on)); 261 } 262 263 destroyTile(QSTileImpl<?> tile)264 private void destroyTile(QSTileImpl<?> tile) { 265 tile.destroy(); 266 mTestableLooper.processAllMessages(); 267 } 268 enableAutoRotation()269 private void enableAutoRotation() { 270 when(mRotationPolicyWrapper.isRotationLocked()).thenReturn(false); 271 } 272 disableAutoRotation()273 private void disableAutoRotation() { 274 when(mRotationPolicyWrapper.isRotationLocked()).thenReturn(true); 275 } 276 enableCameraBasedRotation()277 private void enableCameraBasedRotation() { 278 when(mRotationPolicyWrapper.isCameraRotationEnabled()).thenReturn(true); 279 } 280 disableCameraBasedRotation()281 private void disableCameraBasedRotation() { 282 when(mRotationPolicyWrapper.isCameraRotationEnabled()).thenReturn(false); 283 } 284 } 285