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