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