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