RetailDemoModeServiceTest.java revision e25dbaa619bab4291e1013582a0b59e7b82d4db8
1/* 2 * Copyright (C) 2016 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 17package com.android.server.retaildemo; 18 19import static com.android.server.retaildemo.RetailDemoModeService.SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED; 20 21import static org.junit.Assert.assertEquals; 22import static org.junit.Assert.assertTrue; 23import static org.mockito.Matchers.any; 24import static org.mockito.Matchers.anyInt; 25import static org.mockito.Matchers.anyString; 26import static org.mockito.Matchers.argThat; 27import static org.mockito.Matchers.eq; 28import static org.mockito.Mockito.verify; 29import static org.mockito.Mockito.when; 30 31import android.Manifest; 32import android.app.ActivityManagerInternal; 33import android.app.Notification; 34import android.app.NotificationManager; 35import android.app.RetailDemoModeServiceInternal; 36import android.app.job.JobInfo; 37import android.app.job.JobScheduler; 38import android.content.BroadcastReceiver; 39import android.content.ContentResolver; 40import android.content.Context; 41import android.content.ContextWrapper; 42import android.content.Intent; 43import android.content.IntentFilter; 44import android.content.pm.ActivityInfo; 45import android.content.pm.IPackageManager; 46import android.content.pm.PackageManager; 47import android.content.pm.ResolveInfo; 48import android.content.pm.UserInfo; 49import android.content.res.Configuration; 50import android.media.AudioManager; 51import android.net.Uri; 52import android.net.wifi.WifiManager; 53import android.os.FileUtils; 54import android.os.Handler; 55import android.os.Looper; 56import android.os.UserHandle; 57import android.os.UserManager; 58import android.provider.CallLog; 59import android.provider.MediaStore; 60import android.provider.Settings; 61import android.support.test.InstrumentationRegistry; 62import android.support.test.filters.SmallTest; 63import android.support.test.runner.AndroidJUnit4; 64import android.test.mock.MockContentProvider; 65import android.test.mock.MockContentResolver; 66import android.util.ArrayMap; 67 68import com.android.internal.util.test.FakeSettingsProvider; 69import com.android.internal.widget.LockPatternUtils; 70import com.android.server.SystemService; 71import com.android.server.retaildemo.RetailDemoModeService.Injector; 72 73import org.junit.After; 74import org.junit.Before; 75import org.junit.Test; 76import org.junit.runner.RunWith; 77import org.mockito.ArgumentCaptor; 78import org.mockito.Mock; 79import org.mockito.Mockito; 80import org.mockito.MockitoAnnotations; 81import org.mockito.compat.ArgumentMatcher; 82 83import java.io.File; 84import java.util.concurrent.CountDownLatch; 85import java.util.concurrent.TimeUnit; 86 87@RunWith(AndroidJUnit4.class) 88@SmallTest 89public class RetailDemoModeServiceTest { 90 private static final int TEST_DEMO_USER = 111; 91 private static final long SETUP_COMPLETE_TIMEOUT_MS = 2000; // 2 sec 92 private static final String TEST_CAMERA_PKG = "test.cameraapp"; 93 private static final String TEST_PRELOADS_DIR_NAME = "test_preloads"; 94 95 private Context mContext; 96 private @Mock UserManager mUm; 97 private @Mock PackageManager mPm; 98 private @Mock IPackageManager mIpm; 99 private @Mock NotificationManager mNm; 100 private @Mock ActivityManagerInternal mAmi; 101 private @Mock AudioManager mAudioManager; 102 private @Mock WifiManager mWifiManager; 103 private @Mock LockPatternUtils mLockPatternUtils; 104 private @Mock JobScheduler mJobScheduler; 105 private MockPreloadAppsInstaller mPreloadAppsInstaller; 106 private MockContentResolver mContentResolver; 107 private MockContactsProvider mContactsProvider; 108 private Configuration mConfiguration; 109 private File mTestPreloadsDir; 110 private CountDownLatch mLatch; 111 112 private RetailDemoModeService mService; 113 private TestInjector mInjector; 114 115 @Before 116 public void setUp() throws Exception { 117 MockitoAnnotations.initMocks(this); 118 mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); 119 when(mContext.getSystemServiceName(eq(JobScheduler.class))).thenReturn( 120 Context.JOB_SCHEDULER_SERVICE); 121 when(mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE)).thenReturn(mJobScheduler); 122 when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUm); 123 mContentResolver = new MockContentResolver(mContext); 124 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); 125 mContactsProvider = new MockContactsProvider(mContext); 126 mContentResolver.addProvider(CallLog.AUTHORITY, mContactsProvider); 127 when(mContext.getContentResolver()).thenReturn(mContentResolver); 128 mPreloadAppsInstaller = new MockPreloadAppsInstaller(mContext); 129 mConfiguration = new Configuration(); 130 mTestPreloadsDir = new File(InstrumentationRegistry.getContext().getFilesDir(), 131 TEST_PRELOADS_DIR_NAME); 132 133 Settings.Global.putString(mContentResolver, Settings.Global.RETAIL_DEMO_MODE_CONSTANTS, ""); 134 Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED, 1); 135 Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_DEMO_MODE, 1); 136 137 // Initialize RetailDemoModeService 138 mInjector = new TestInjector(); 139 mService = new RetailDemoModeService(mInjector); 140 mService.onStart(); 141 } 142 143 @After 144 public void tearDown() { 145 if (mTestPreloadsDir != null) { 146 FileUtils.deleteContentsAndDir(mTestPreloadsDir); 147 } 148 } 149 150 @Test 151 public void testDemoUserSetup() throws Exception { 152 mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); 153 154 mLatch = new CountDownLatch(1); 155 final UserInfo userInfo = new UserInfo(); 156 userInfo.id = TEST_DEMO_USER; 157 when(mUm.createUser(anyString(), anyInt())).thenReturn(userInfo); 158 159 setCameraPackage(TEST_CAMERA_PKG); 160 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 161 assertEquals(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED + " property not set", 162 "1", mInjector.systemPropertiesGet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED)); 163 164 final ArgumentCaptor<IntentFilter> intentFilter = 165 ArgumentCaptor.forClass(IntentFilter.class); 166 verify(mContext).registerReceiver(any(BroadcastReceiver.class), intentFilter.capture()); 167 assertTrue("Not registered for " + Intent.ACTION_SCREEN_OFF, 168 intentFilter.getValue().hasAction(Intent.ACTION_SCREEN_OFF)); 169 170 // Wait for the setup to complete. 171 mLatch.await(SETUP_COMPLETE_TIMEOUT_MS, TimeUnit.MILLISECONDS); 172 ArgumentCaptor<Integer> flags = ArgumentCaptor.forClass(Integer.class); 173 verify(mUm).createUser(anyString(), flags.capture()); 174 assertTrue("FLAG_DEMO not set during user creation", 175 (flags.getValue() & UserInfo.FLAG_DEMO) != 0); 176 assertTrue("FLAG_EPHEMERAL not set during user creation", 177 (flags.getValue() & UserInfo.FLAG_EPHEMERAL) != 0); 178 // Verify if necessary restrictions are being set. 179 final UserHandle user = UserHandle.of(TEST_DEMO_USER); 180 verify(mUm).setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, user); 181 verify(mUm).setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true, user); 182 verify(mUm).setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, true, user); 183 verify(mUm).setUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER, true, user); 184 verify(mUm).setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user); 185 verify(mUm).setUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, true, user); 186 verify(mUm).setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, false, user); 187 verify(mUm).setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, true, UserHandle.SYSTEM); 188 // Verify if necessary settings are updated. 189 assertEquals("SKIP_FIRST_USE_HINTS setting is not set for demo user", 190 Settings.Secure.getIntForUser(mContentResolver, 191 Settings.Secure.SKIP_FIRST_USE_HINTS, TEST_DEMO_USER), 192 1); 193 assertEquals("PACKAGE_VERIFIER_ENABLE settings should be set to 0 for demo user", 194 Settings.Global.getInt(mContentResolver, 195 Settings.Global.PACKAGE_VERIFIER_ENABLE), 196 0); 197 // Verify if camera is granted location permission. 198 verify(mPm).grantRuntimePermission(TEST_CAMERA_PKG, 199 Manifest.permission.ACCESS_FINE_LOCATION, user); 200 // Verify call logs are cleared. 201 assertTrue("Call logs should be deleted", mContactsProvider.isCallLogDeleted()); 202 } 203 204 @Test 205 public void testSettingsObserver_disableDemoMode() throws Exception { 206 final RetailDemoModeService.SettingsObserver observer = 207 mService.new SettingsObserver(new Handler(Looper.getMainLooper())); 208 final Uri deviceDemoModeUri = Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE); 209 when(mUm.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT, UserHandle.SYSTEM)) 210 .thenReturn(false); 211 Settings.Global.putInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_ENABLE, 1); 212 // Settings.Global.DEVICE_DEMO_MODE has been set to 1 initially. 213 observer.onChange(false, deviceDemoModeUri); 214 final ArgumentCaptor<BroadcastReceiver> receiver = 215 ArgumentCaptor.forClass(BroadcastReceiver.class); 216 verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class)); 217 218 Settings.Global.putInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_ENABLE, 0); 219 new File(mTestPreloadsDir, "dir1").mkdirs(); 220 new File(mTestPreloadsDir, "file1").createNewFile(); 221 Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_DEMO_MODE, 0); 222 observer.onChange(false, deviceDemoModeUri); 223 verify(mContext).unregisterReceiver(receiver.getValue()); 224 verify(mUm).setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, false, UserHandle.SYSTEM); 225 assertEquals("Package verifier enable value has not been reset", 1, 226 Settings.Global.getInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_ENABLE)); 227 Thread.sleep(20); // Wait for the deletion to complete. 228 // verify that the preloaded directory is emptied. 229 assertEquals("Preloads directory is not emptied", 230 0, mTestPreloadsDir.list().length); 231 // Verify that the expiration job was scheduled 232 verify(mJobScheduler).schedule(any(JobInfo.class)); 233 } 234 235 @Test 236 public void testSettingsObserver_enableDemoMode() throws Exception { 237 final RetailDemoModeService.SettingsObserver observer = 238 mService.new SettingsObserver(new Handler(Looper.getMainLooper())); 239 final Uri deviceDemoModeUri = Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE); 240 // Settings.Global.DEVICE_DEMO_MODE has been set to 1 initially. 241 observer.onChange(false, deviceDemoModeUri); 242 assertEquals(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED + " property not set", 243 "1", mInjector.systemPropertiesGet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED)); 244 245 final ArgumentCaptor<IntentFilter> intentFilter = 246 ArgumentCaptor.forClass(IntentFilter.class); 247 verify(mContext).registerReceiver(any(BroadcastReceiver.class), intentFilter.capture()); 248 assertTrue("Not registered for " + Intent.ACTION_SCREEN_OFF, 249 intentFilter.getValue().hasAction(Intent.ACTION_SCREEN_OFF)); 250 } 251 252 @Test 253 public void testSwitchToDemoUser() { 254 // To make the RetailDemoModeService update it's internal state. 255 mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); 256 final RetailDemoModeService.SettingsObserver observer = 257 mService.new SettingsObserver(new Handler(Looper.getMainLooper())); 258 observer.onChange(false, Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE)); 259 260 final UserInfo userInfo = new UserInfo(TEST_DEMO_USER, "demo_user", 261 UserInfo.FLAG_DEMO | UserInfo.FLAG_EPHEMERAL); 262 when(mUm.getUserInfo(TEST_DEMO_USER)).thenReturn(userInfo); 263 when(mWifiManager.isWifiEnabled()).thenReturn(false); 264 final int minVolume = -111; 265 for (int stream : RetailDemoModeService.VOLUME_STREAMS_TO_MUTE) { 266 when(mAudioManager.getStreamMinVolume(stream)).thenReturn(minVolume); 267 } 268 269 mService.onSwitchUser(TEST_DEMO_USER); 270 verify(mAmi).updatePersistentConfigurationForUser(mConfiguration, TEST_DEMO_USER); 271 for (int stream : RetailDemoModeService.VOLUME_STREAMS_TO_MUTE) { 272 verify(mAudioManager).setStreamVolume(stream, minVolume, 0); 273 } 274 verify(mLockPatternUtils).setLockScreenDisabled(true, TEST_DEMO_USER); 275 verify(mWifiManager).setWifiEnabled(true); 276 } 277 278 private void setCameraPackage(String pkgName) { 279 final ResolveInfo ri = new ResolveInfo(); 280 final ActivityInfo ai = new ActivityInfo(); 281 ai.packageName = pkgName; 282 ri.activityInfo = ai; 283 when(mPm.resolveActivityAsUser( 284 argThat(new IntentMatcher(MediaStore.ACTION_IMAGE_CAPTURE)), 285 anyInt(), 286 eq(TEST_DEMO_USER))).thenReturn(ri); 287 } 288 289 private class IntentMatcher extends ArgumentMatcher<Intent> { 290 private final Intent mIntent; 291 292 IntentMatcher(String action) { 293 mIntent = new Intent(action); 294 } 295 296 @Override 297 public boolean matchesObject(Object argument) { 298 if (argument instanceof Intent) { 299 return ((Intent) argument).filterEquals(mIntent); 300 } 301 return false; 302 } 303 304 @Override 305 public String toString() { 306 return "Expected: " + mIntent; 307 } 308 } 309 310 private class MockContactsProvider extends MockContentProvider { 311 private boolean mCallLogDeleted; 312 313 MockContactsProvider(Context context) { 314 super(context); 315 } 316 317 @Override 318 public int delete(Uri uri, String selection, String[] selectionArgs) { 319 if (CallLog.Calls.CONTENT_URI.equals(uri)) { 320 mCallLogDeleted = true; 321 } 322 return 0; 323 } 324 325 public boolean isCallLogDeleted() { 326 return mCallLogDeleted; 327 } 328 } 329 330 private class MockPreloadAppsInstaller extends PreloadAppsInstaller { 331 MockPreloadAppsInstaller(Context context) { 332 super(context); 333 } 334 335 @Override 336 public void installApps(int userId) { 337 } 338 } 339 340 private class TestInjector extends Injector { 341 private ArrayMap<String, String> mSystemProperties = new ArrayMap<>(); 342 343 TestInjector() { 344 super(mContext); 345 } 346 347 @Override 348 Context getContext() { 349 return mContext; 350 } 351 352 @Override 353 UserManager getUserManager() { 354 return mUm; 355 } 356 357 @Override 358 WifiManager getWifiManager() { 359 return mWifiManager; 360 } 361 362 @Override 363 void switchUser(int userId) { 364 if (mLatch != null) { 365 mLatch.countDown(); 366 } 367 } 368 369 @Override 370 AudioManager getAudioManager() { 371 return mAudioManager; 372 } 373 374 @Override 375 NotificationManager getNotificationManager() { 376 return mNm; 377 } 378 379 @Override 380 ActivityManagerInternal getActivityManagerInternal() { 381 return mAmi; 382 } 383 384 @Override 385 PackageManager getPackageManager() { 386 return mPm; 387 } 388 389 @Override 390 IPackageManager getIPackageManager() { 391 return mIpm; 392 } 393 394 @Override 395 ContentResolver getContentResolver() { 396 return mContentResolver; 397 } 398 399 @Override 400 PreloadAppsInstaller getPreloadAppsInstaller() { 401 return mPreloadAppsInstaller; 402 } 403 404 @Override 405 void systemPropertiesSet(String key, String value) { 406 mSystemProperties.put(key, value); 407 } 408 409 @Override 410 void turnOffAllFlashLights(String[] cameraIdsWithFlash) { 411 } 412 413 @Override 414 void initializeWakeLock() { 415 } 416 417 @Override 418 void destroyWakeLock() { 419 } 420 421 @Override 422 boolean isWakeLockHeld() { 423 return false; 424 } 425 426 @Override 427 void acquireWakeLock() { 428 } 429 430 @Override 431 void releaseWakeLock() { 432 } 433 434 @Override 435 void logSessionDuration(int duration) { 436 } 437 438 @Override 439 void logSessionCount(int count) { 440 } 441 442 @Override 443 Configuration getSystemUsersConfiguration() { 444 return mConfiguration; 445 } 446 447 @Override 448 LockPatternUtils getLockPatternUtils() { 449 return mLockPatternUtils; 450 } 451 452 @Override 453 Notification createResetNotification() { 454 return null; 455 } 456 457 @Override 458 File getDataPreloadsDirectory() { 459 return mTestPreloadsDir; 460 } 461 462 @Override 463 File getDataPreloadsFileCacheDirectory() { 464 return new File(mTestPreloadsDir, "file_cache"); 465 } 466 467 @Override 468 void publishLocalService(RetailDemoModeService service, 469 RetailDemoModeServiceInternal localService) { 470 } 471 472 String systemPropertiesGet(String key) { 473 return mSystemProperties.get(key); 474 } 475 } 476} 477