1 /* 2 * Copyright (C) 2022 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 junit.framework.TestCase.assertEquals; 20 import static junit.framework.TestCase.assertFalse; 21 import static junit.framework.TestCase.assertTrue; 22 23 import static org.mockito.ArgumentMatchers.any; 24 import static org.mockito.Mockito.mock; 25 import static org.mockito.Mockito.spy; 26 import static org.mockito.Mockito.verify; 27 import static org.mockito.Mockito.when; 28 29 import android.content.BroadcastReceiver; 30 import android.content.ComponentName; 31 import android.content.Intent; 32 import android.content.pm.UserInfo; 33 import android.os.Handler; 34 import android.os.RemoteException; 35 import android.provider.Settings; 36 import android.service.dreams.IDreamManager; 37 import android.service.quicksettings.Tile; 38 import android.testing.TestableLooper; 39 40 import androidx.test.ext.junit.runners.AndroidJUnit4; 41 import androidx.test.filters.SmallTest; 42 43 import com.android.internal.logging.MetricsLogger; 44 import com.android.systemui.SysuiTestCase; 45 import com.android.systemui.broadcast.BroadcastDispatcher; 46 import com.android.systemui.classifier.FalsingManagerFake; 47 import com.android.systemui.plugins.ActivityStarter; 48 import com.android.systemui.plugins.statusbar.StatusBarStateController; 49 import com.android.systemui.qs.QSHost; 50 import com.android.systemui.qs.QsEventLogger; 51 import com.android.systemui.qs.logging.QSLogger; 52 import com.android.systemui.qs.tileimpl.QSTileImpl; 53 import com.android.systemui.res.R; 54 import com.android.systemui.settings.UserTracker; 55 import com.android.systemui.util.settings.FakeSettings; 56 import com.android.systemui.util.settings.SecureSettings; 57 58 import org.junit.After; 59 import org.junit.Before; 60 import org.junit.Test; 61 import org.junit.runner.RunWith; 62 import org.mockito.ArgumentCaptor; 63 import org.mockito.Mock; 64 import org.mockito.MockitoAnnotations; 65 66 @RunWith(AndroidJUnit4.class) 67 @TestableLooper.RunWithLooper(setAsMainLooper = true) 68 @SmallTest 69 public class DreamTileTest extends SysuiTestCase { 70 71 @Mock 72 private ActivityStarter mActivityStarter; 73 @Mock 74 private QSHost mHost; 75 @Mock 76 private MetricsLogger mMetricsLogger; 77 @Mock 78 private QSLogger mQSLogger; 79 @Mock 80 private StatusBarStateController mStatusBarStateController; 81 @Mock 82 private IDreamManager mDreamManager; 83 @Mock 84 private BroadcastDispatcher mBroadcastDispatcher; 85 @Mock 86 private UserTracker mUserTracker; 87 @Mock 88 private QsEventLogger mUiEventLogger; 89 90 private TestableLooper mTestableLooper; 91 92 private DreamTile mTile; 93 94 private SecureSettings mSecureSettings; 95 96 private static final ComponentName COLORS_DREAM_COMPONENT_NAME = new ComponentName( 97 "com.android.dreams", ".Colors"); 98 99 private static final int DEFAULT_USER = 0; 100 101 private final String mExpectedTileLabel = mContext.getResources().getString( 102 R.string.quick_settings_screensaver_label); 103 104 @Before setUp()105 public void setUp() throws Exception { 106 MockitoAnnotations.initMocks(this); 107 mSecureSettings = new FakeSettings(); 108 mTestableLooper = TestableLooper.get(this); 109 110 when(mHost.getUserId()).thenReturn(DEFAULT_USER); 111 when(mHost.getContext()).thenReturn(mContext); 112 113 mTile = spy(constructTileForTest(true, false)); 114 115 mTestableLooper.processAllMessages(); 116 mTile.initialize(); 117 } 118 119 @After tearDown()120 public void tearDown() { 121 mTile.destroy(); 122 mTestableLooper.processAllMessages(); 123 } 124 125 @Test testNotAvailable()126 public void testNotAvailable() throws RemoteException { 127 // Should not be available if screensaver is disabled 128 setScreensaverEnabled(false); 129 130 mTile.refreshState(); 131 mTestableLooper.processAllMessages(); 132 assertEquals(Tile.STATE_UNAVAILABLE, mTile.getState().state); 133 134 // Should not be available if component is not set 135 mSecureSettings.putInt(Settings.Secure.SCREENSAVER_ENABLED, 1); 136 when(mDreamManager.getDreamComponentsForUser(mUserTracker.getUserId())).thenReturn(null); 137 138 mTestableLooper.processAllMessages(); 139 assertEquals(Tile.STATE_UNAVAILABLE, mTile.getState().state); 140 assertEquals(mExpectedTileLabel, mTile.getState().contentDescription); 141 } 142 143 @Test testInactiveWhenDreaming()144 public void testInactiveWhenDreaming() throws RemoteException { 145 setScreensaverEnabled(true); 146 147 when(mDreamManager.getDreamComponentsForUser(mUserTracker.getUserId())) 148 .thenReturn(new ComponentName[]{COLORS_DREAM_COMPONENT_NAME}); 149 when(mDreamManager.isDreaming()).thenReturn(false); 150 151 mTile.refreshState(); 152 mTestableLooper.processAllMessages(); 153 assertEquals(Tile.STATE_INACTIVE, mTile.getState().state); 154 } 155 156 @Test testActive()157 public void testActive() throws RemoteException { 158 setScreensaverEnabled(true); 159 160 when(mDreamManager.getDreamComponentsForUser(mUserTracker.getUserId())) 161 .thenReturn(new ComponentName[]{COLORS_DREAM_COMPONENT_NAME}); 162 when(mDreamManager.isDreaming()).thenReturn(true); 163 164 mTile.refreshState(); 165 mTestableLooper.processAllMessages(); 166 assertEquals(Tile.STATE_ACTIVE, mTile.getState().state); 167 } 168 169 @Test testClick()170 public void testClick() throws RemoteException { 171 // Set the AOSP dream enabled as the base setup. 172 setScreensaverEnabled(true); 173 when(mDreamManager.getDreamComponentsForUser(mUserTracker.getUserId())) 174 .thenReturn(new ComponentName[]{COLORS_DREAM_COMPONENT_NAME}); 175 when(mDreamManager.isDreaming()).thenReturn(false); 176 177 mTile.refreshState(); 178 mTestableLooper.processAllMessages(); 179 assertEquals(Tile.STATE_INACTIVE, mTile.getState().state); 180 181 // Now click 182 mTile.handleClick(null /* view */); 183 184 verify(mDreamManager).dream(); 185 186 when(mDreamManager.isDreaming()).thenReturn(true); 187 mTile.refreshState(); 188 mTestableLooper.processAllMessages(); 189 assertEquals(Tile.STATE_ACTIVE, mTile.getState().state); 190 191 // Click again to see that other method is called 192 mTile.handleClick(null /* view */); 193 194 verify(mDreamManager).awaken(); 195 } 196 197 @Test testContentDescription()198 public void testContentDescription() { 199 assertEquals(mExpectedTileLabel, mTile.getContentDescription(null)); 200 201 final String testDreamName = "MyDream"; 202 assertEquals(mExpectedTileLabel + ", " + testDreamName, 203 mTile.getContentDescription(testDreamName)); 204 } 205 206 @Test testUserAvailability()207 public void testUserAvailability() { 208 DreamTile unsupportedTile = constructTileForTest(false, true); 209 assertFalse(unsupportedTile.isAvailable()); 210 211 DreamTile supportedTileAllUsers = constructTileForTest(true, false); 212 213 UserInfo mainUserInfo = mock(UserInfo.class); 214 when(mainUserInfo.isMain()).thenReturn(true); 215 216 UserInfo nonMainUserInfo = mock(UserInfo.class); 217 when(nonMainUserInfo.isMain()).thenReturn(false); 218 219 when(mUserTracker.getUserInfo()).thenReturn(mainUserInfo); 220 assertTrue(supportedTileAllUsers.isAvailable()); 221 when(mUserTracker.getUserInfo()).thenReturn(nonMainUserInfo); 222 assertTrue(supportedTileAllUsers.isAvailable()); 223 224 DreamTile supportedTileOnlySystemUser = constructTileForTest(true, true); 225 when(mUserTracker.getUserInfo()).thenReturn(mainUserInfo); 226 assertTrue(supportedTileOnlySystemUser.isAvailable()); 227 when(mUserTracker.getUserInfo()).thenReturn(nonMainUserInfo); 228 assertFalse(supportedTileOnlySystemUser.isAvailable()); 229 230 destroyTile(unsupportedTile); 231 destroyTile(supportedTileAllUsers); 232 destroyTile(supportedTileOnlySystemUser); 233 } 234 235 @Test testIconDockState()236 public void testIconDockState() { 237 final DreamTile dockedTile = constructTileForTest(true, false); 238 239 final ArgumentCaptor<BroadcastReceiver> receiverCaptor = ArgumentCaptor.forClass( 240 BroadcastReceiver.class); 241 dockedTile.handleSetListening(true); 242 verify(mBroadcastDispatcher).registerReceiver(receiverCaptor.capture(), any()); 243 final BroadcastReceiver receiver = receiverCaptor.getValue(); 244 245 Intent dockIntent = new Intent(Intent.ACTION_DOCK_EVENT); 246 dockIntent.putExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_DESK); 247 receiver.onReceive(mContext, dockIntent); 248 mTestableLooper.processAllMessages(); 249 assertEquals(QSTileImpl.ResourceIcon.get(R.drawable.ic_qs_screen_saver), 250 dockedTile.getState().icon); 251 252 dockIntent.putExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED); 253 receiver.onReceive(mContext, dockIntent); 254 mTestableLooper.processAllMessages(); 255 assertEquals(QSTileImpl.ResourceIcon.get(R.drawable.ic_qs_screen_saver_undocked), 256 dockedTile.getState().icon); 257 258 destroyTile(dockedTile); 259 } 260 setScreensaverEnabled(boolean enabled)261 private void setScreensaverEnabled(boolean enabled) { 262 mSecureSettings.putIntForUser(Settings.Secure.SCREENSAVER_ENABLED, enabled ? 1 : 0, 263 DEFAULT_USER); 264 } 265 destroyTile(QSTileImpl<?> tile)266 private void destroyTile(QSTileImpl<?> tile) { 267 tile.destroy(); 268 mTestableLooper.processAllMessages(); 269 } 270 constructTileForTest(boolean dreamSupported, boolean dreamOnlyEnabledForSystemUser)271 private DreamTile constructTileForTest(boolean dreamSupported, 272 boolean dreamOnlyEnabledForSystemUser) { 273 return new DreamTile( 274 mHost, 275 mUiEventLogger, 276 mTestableLooper.getLooper(), 277 new Handler(mTestableLooper.getLooper()), 278 new FalsingManagerFake(), 279 mMetricsLogger, 280 mStatusBarStateController, 281 mActivityStarter, 282 mQSLogger, 283 mDreamManager, 284 mSecureSettings, 285 mBroadcastDispatcher, 286 mUserTracker, 287 dreamSupported, dreamOnlyEnabledForSystemUser); 288 } 289 } 290