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.server.app; 18 19 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.mockito.Mockito.any; 24 import static org.mockito.Mockito.spy; 25 import static org.mockito.Mockito.verify; 26 import static org.mockito.Mockito.verifyNoMoreInteractions; 27 import static org.mockito.Mockito.when; 28 29 import android.content.BroadcastReceiver; 30 import android.content.ComponentName; 31 import android.content.Context; 32 import android.content.Intent; 33 import android.content.pm.UserInfo; 34 import android.net.Uri; 35 import android.os.UserHandle; 36 import android.platform.test.annotations.Presubmit; 37 38 import androidx.test.filters.SmallTest; 39 import androidx.test.runner.AndroidJUnit4; 40 41 import com.android.internal.util.ConcurrentUtils; 42 import com.android.server.SystemService; 43 import com.android.server.app.GameServiceConfiguration.GameServiceComponentConfiguration; 44 45 import org.junit.After; 46 import org.junit.Before; 47 import org.junit.Test; 48 import org.junit.runner.RunWith; 49 import org.mockito.ArgumentCaptor; 50 import org.mockito.InOrder; 51 import org.mockito.Mock; 52 import org.mockito.Mockito; 53 import org.mockito.MockitoSession; 54 import org.mockito.quality.Strictness; 55 56 57 /** Unit tests for {@link GameServiceController}. */ 58 @RunWith(AndroidJUnit4.class) 59 @SmallTest 60 @Presubmit 61 public final class GameServiceControllerTest { 62 private static final UserHandle USER_HANDLE_10 = new UserHandle(10); 63 private static final UserHandle USER_HANDLE_11 = new UserHandle(11); 64 private static final SystemService.TargetUser USER_10 = user(10); 65 private static final SystemService.TargetUser USER_11 = user(11); 66 private static final String PROVIDER_A_PACKAGE_NAME = "com.provider.a"; 67 private static final ComponentName PROVIDER_A_SERVICE_A = 68 new ComponentName(PROVIDER_A_PACKAGE_NAME, "com.provider.a.ServiceA"); 69 private static final ComponentName PROVIDER_A_SERVICE_B = 70 new ComponentName(PROVIDER_A_PACKAGE_NAME, "com.provider.a.ServiceB"); 71 private static final ComponentName PROVIDER_A_SERVICE_C = 72 new ComponentName(PROVIDER_A_PACKAGE_NAME, "com.provider.a.ServiceC"); 73 74 private MockitoSession mMockingSession; 75 private GameServiceController mGameServiceManager; 76 @Mock 77 private Context mMockContext; 78 @Mock 79 private GameServiceProviderSelector mMockGameServiceProviderSelector; 80 @Mock 81 private GameServiceProviderInstanceFactory mMockGameServiceProviderInstanceFactory; 82 83 @Before setUp()84 public void setUp() throws Exception { 85 mMockingSession = mockitoSession() 86 .initMocks(this) 87 .strictness(Strictness.LENIENT) 88 .startMocking(); 89 90 mGameServiceManager = new GameServiceController( 91 mMockContext, ConcurrentUtils.DIRECT_EXECUTOR, 92 mMockGameServiceProviderSelector, 93 mMockGameServiceProviderInstanceFactory); 94 } 95 96 @After tearDown()97 public void tearDown() { 98 mMockingSession.finishMocking(); 99 } 100 101 @Test notifyUserStarted_hasNotCompletedBoot_doesNothing()102 public void notifyUserStarted_hasNotCompletedBoot_doesNothing() { 103 mGameServiceManager.notifyUserStarted(USER_10); 104 105 verifyNoMoreInteractions(mMockGameServiceProviderInstanceFactory); 106 } 107 108 @Test notifyUserStarted_createsAndStartsNewInstance()109 public void notifyUserStarted_createsAndStartsNewInstance() { 110 GameServiceConfiguration configurationA = 111 new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME, 112 new GameServiceComponentConfiguration(USER_HANDLE_10, 113 PROVIDER_A_SERVICE_A, 114 PROVIDER_A_SERVICE_B)); 115 FakeGameServiceProviderInstance instanceA = 116 seedConfigurationForUser(USER_10, configurationA); 117 118 mGameServiceManager.onBootComplete(); 119 mGameServiceManager.notifyUserStarted(USER_10); 120 121 verify(mMockGameServiceProviderInstanceFactory).create( 122 configurationA.getGameServiceComponentConfiguration()); 123 verifyNoMoreInteractions(mMockGameServiceProviderInstanceFactory); 124 assertThat(instanceA.getIsRunning()).isTrue(); 125 } 126 127 @Test notifyUserStarted_sameUser_doesNotCreateNewInstance()128 public void notifyUserStarted_sameUser_doesNotCreateNewInstance() { 129 GameServiceConfiguration configurationA = 130 new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME, 131 new GameServiceComponentConfiguration(USER_HANDLE_10, 132 PROVIDER_A_SERVICE_A, 133 PROVIDER_A_SERVICE_B)); 134 FakeGameServiceProviderInstance instanceA = 135 seedConfigurationForUser(USER_10, configurationA); 136 137 mGameServiceManager.onBootComplete(); 138 mGameServiceManager.notifyUserStarted(USER_10); 139 mGameServiceManager.notifyUserStarted(USER_10); 140 141 verify(mMockGameServiceProviderInstanceFactory).create( 142 configurationA.getGameServiceComponentConfiguration()); 143 verifyNoMoreInteractions(mMockGameServiceProviderInstanceFactory); 144 assertThat(instanceA.getIsRunning()).isTrue(); 145 } 146 147 @Test notifyUserUnlocking_noForegroundUser_ignores()148 public void notifyUserUnlocking_noForegroundUser_ignores() { 149 GameServiceConfiguration configurationA = 150 new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME, 151 new GameServiceComponentConfiguration(USER_HANDLE_10, 152 PROVIDER_A_SERVICE_A, 153 PROVIDER_A_SERVICE_B)); 154 FakeGameServiceProviderInstance instanceA = 155 seedConfigurationForUser(USER_10, configurationA); 156 157 mGameServiceManager.onBootComplete(); 158 mGameServiceManager.notifyUserUnlocking(USER_10); 159 160 verifyNoMoreInteractions(mMockGameServiceProviderInstanceFactory); 161 assertThat(instanceA.getIsRunning()).isFalse(); 162 } 163 164 @Test notifyUserUnlocking_sameAsForegroundUser_evaluatesProvider()165 public void notifyUserUnlocking_sameAsForegroundUser_evaluatesProvider() { 166 GameServiceConfiguration configurationA = 167 new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME, 168 new GameServiceComponentConfiguration(USER_HANDLE_10, 169 PROVIDER_A_SERVICE_A, 170 PROVIDER_A_SERVICE_B)); 171 seedNoConfigurationForUser(USER_10); 172 173 mGameServiceManager.onBootComplete(); 174 mGameServiceManager.notifyUserStarted(USER_10); 175 FakeGameServiceProviderInstance instanceA = 176 seedConfigurationForUser(USER_10, configurationA); 177 mGameServiceManager.notifyUserUnlocking(USER_10); 178 179 verify(mMockGameServiceProviderInstanceFactory).create( 180 configurationA.getGameServiceComponentConfiguration()); 181 verifyNoMoreInteractions(mMockGameServiceProviderInstanceFactory); 182 assertThat(instanceA.getIsRunning()).isTrue(); 183 } 184 185 @Test notifyUserUnlocking_differentFromForegroundUser_ignores()186 public void notifyUserUnlocking_differentFromForegroundUser_ignores() { 187 GameServiceConfiguration configurationA = 188 new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME, 189 new GameServiceComponentConfiguration(USER_HANDLE_10, 190 PROVIDER_A_SERVICE_A, 191 PROVIDER_A_SERVICE_B)); 192 seedNoConfigurationForUser(USER_10); 193 194 mGameServiceManager.onBootComplete(); 195 mGameServiceManager.notifyUserStarted(USER_10); 196 FakeGameServiceProviderInstance instanceA = 197 seedConfigurationForUser(USER_11, configurationA); 198 mGameServiceManager.notifyUserUnlocking(USER_11); 199 200 verifyNoMoreInteractions(mMockGameServiceProviderInstanceFactory); 201 assertThat(instanceA.getIsRunning()).isFalse(); 202 } 203 204 @Test 205 public void notifyNewForegroundUser_differentUser_stopsPreviousInstanceAndThenStartsNewInstance()206 notifyNewForegroundUser_differentUser_stopsPreviousInstanceAndThenStartsNewInstance() { 207 GameServiceConfiguration configurationA = 208 new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME, 209 new GameServiceComponentConfiguration(USER_HANDLE_10, 210 PROVIDER_A_SERVICE_A, 211 PROVIDER_A_SERVICE_B)); 212 FakeGameServiceProviderInstance instanceA = 213 seedConfigurationForUser(USER_10, configurationA); 214 GameServiceConfiguration configurationB = 215 new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME, 216 new GameServiceComponentConfiguration(USER_HANDLE_11, 217 PROVIDER_A_SERVICE_A, 218 PROVIDER_A_SERVICE_B)); 219 FakeGameServiceProviderInstance instanceB = seedConfigurationForUser(USER_11, 220 configurationB); 221 InOrder instancesInOrder = Mockito.inOrder(instanceA, instanceB); 222 223 mGameServiceManager.onBootComplete(); 224 mGameServiceManager.notifyUserStarted(USER_10); 225 mGameServiceManager.notifyNewForegroundUser(USER_11); 226 227 verify(mMockGameServiceProviderInstanceFactory).create( 228 configurationA.getGameServiceComponentConfiguration()); 229 verify(mMockGameServiceProviderInstanceFactory).create( 230 configurationB.getGameServiceComponentConfiguration()); 231 instancesInOrder.verify(instanceA).start(); 232 instancesInOrder.verify(instanceA).stop(); 233 instancesInOrder.verify(instanceB).start(); 234 verifyNoMoreInteractions(mMockGameServiceProviderInstanceFactory); 235 assertThat(instanceA.getIsRunning()).isFalse(); 236 assertThat(instanceB.getIsRunning()).isTrue(); 237 } 238 239 @Test packageChanges_reevaluatesGameServiceProvider()240 public void packageChanges_reevaluatesGameServiceProvider() { 241 GameServiceConfiguration configurationA = 242 new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME, 243 new GameServiceComponentConfiguration(USER_HANDLE_10, 244 PROVIDER_A_SERVICE_A, 245 PROVIDER_A_SERVICE_B)); 246 FakeGameServiceProviderInstance instanceA = 247 seedConfigurationForUser(USER_10, configurationA); 248 249 mGameServiceManager.onBootComplete(); 250 mGameServiceManager.notifyUserStarted(USER_10); 251 ArgumentCaptor<BroadcastReceiver> broadcastReceiverArgumentCaptor = 252 ArgumentCaptor.forClass(BroadcastReceiver.class); 253 verify(mMockContext).registerReceiver(broadcastReceiverArgumentCaptor.capture(), any()); 254 255 GameServiceConfiguration configurationB = 256 new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME, 257 new GameServiceComponentConfiguration(USER_HANDLE_10, 258 PROVIDER_A_SERVICE_A, 259 PROVIDER_A_SERVICE_C)); 260 FakeGameServiceProviderInstance instanceB = 261 seedConfigurationForUser(USER_10, configurationB); 262 Intent intent = new Intent(); 263 intent.setData(Uri.parse("package:" + PROVIDER_A_PACKAGE_NAME)); 264 broadcastReceiverArgumentCaptor.getValue().onReceive(mMockContext, intent); 265 266 InOrder instancesInOrder = Mockito.inOrder(instanceA, instanceB); 267 verify(mMockGameServiceProviderInstanceFactory).create( 268 configurationA.getGameServiceComponentConfiguration()); 269 verify(mMockGameServiceProviderInstanceFactory).create( 270 configurationB.getGameServiceComponentConfiguration()); 271 instancesInOrder.verify(instanceA).start(); 272 instancesInOrder.verify(instanceA).stop(); 273 instancesInOrder.verify(instanceB).start(); 274 verifyNoMoreInteractions(mMockGameServiceProviderInstanceFactory); 275 assertThat(instanceA.getIsRunning()).isFalse(); 276 assertThat(instanceB.getIsRunning()).isTrue(); 277 } 278 seedNoConfigurationForUser(SystemService.TargetUser user)279 private void seedNoConfigurationForUser(SystemService.TargetUser user) { 280 when(mMockGameServiceProviderSelector.get(user, null)).thenReturn(null); 281 } 282 seedConfigurationForUser(SystemService.TargetUser user, GameServiceConfiguration configuration)283 private FakeGameServiceProviderInstance seedConfigurationForUser(SystemService.TargetUser user, 284 GameServiceConfiguration configuration) { 285 when(mMockGameServiceProviderSelector.get(user, null)).thenReturn(configuration); 286 FakeGameServiceProviderInstance instanceForConfiguration = 287 spy(new FakeGameServiceProviderInstance()); 288 when(mMockGameServiceProviderInstanceFactory.create( 289 configuration.getGameServiceComponentConfiguration())) 290 .thenReturn(instanceForConfiguration); 291 292 return instanceForConfiguration; 293 } 294 user(int userId)295 private static SystemService.TargetUser user(int userId) { 296 UserInfo userInfo = new UserInfo(userId, "", "", UserInfo.FLAG_FULL); 297 return new SystemService.TargetUser(userInfo); 298 } 299 } 300