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