DpmMockContext.java revision 7f5c91c6bce6a8ff2414549219a321a98a98ab31
1/*
2 * Copyright (C) 2015 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.devicepolicy;
18
19import android.accounts.Account;
20import android.accounts.AccountManager;
21import android.app.AlarmManager;
22import android.app.IActivityManager;
23import android.app.NotificationManager;
24import android.app.backup.IBackupManager;
25import android.content.BroadcastReceiver;
26import android.content.ContentResolver;
27import android.content.Context;
28import android.content.Intent;
29import android.content.IntentFilter;
30import android.content.pm.ApplicationInfo;
31import android.content.pm.IPackageManager;
32import android.content.pm.PackageManager;
33import android.content.pm.PackageManagerInternal;
34import android.content.pm.UserInfo;
35import android.content.res.Resources;
36import android.media.IAudioService;
37import android.net.IIpConnectivityMetrics;
38import android.net.wifi.WifiManager;
39import android.os.Bundle;
40import android.os.Handler;
41import android.os.PowerManager.WakeLock;
42import android.os.PowerManagerInternal;
43import android.os.UserHandle;
44import android.os.UserManager;
45import android.os.UserManagerInternal;
46import android.security.KeyChain;
47import android.telephony.TelephonyManager;
48import android.test.mock.MockContentResolver;
49import android.test.mock.MockContext;
50import android.util.ArrayMap;
51import android.view.IWindowManager;
52
53import com.android.internal.widget.LockPatternUtils;
54
55import org.junit.Assert;
56import org.mockito.invocation.InvocationOnMock;
57import org.mockito.stubbing.Answer;
58
59import java.io.File;
60import java.io.IOException;
61import java.util.ArrayList;
62import java.util.List;
63import java.util.Map;
64
65import static org.mockito.Matchers.anyBoolean;
66import static org.mockito.Matchers.anyInt;
67import static org.mockito.Matchers.eq;
68import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
69import static org.mockito.Mockito.mock;
70import static org.mockito.Mockito.spy;
71import static org.mockito.Mockito.when;
72
73/**
74 * Context used throughout DPMS tests.
75 */
76public class DpmMockContext extends MockContext {
77    /**
78     * User-id of a non-system user we use throughout unit tests.
79     */
80    public static final int CALLER_USER_HANDLE = 20;
81
82    /**
83     * UID corresponding to {@link #CALLER_USER_HANDLE}.
84     */
85    public static final int CALLER_UID = UserHandle.getUid(CALLER_USER_HANDLE, 20123);
86
87    /**
88     * UID used when a caller is on the system user.
89     */
90    public static final int CALLER_SYSTEM_USER_UID = 20321;
91
92    /**
93     * PID of the caller.
94     */
95    public static final int CALLER_PID = 22222;
96
97    /**
98     * UID of the system server.
99     */
100    public static final int SYSTEM_UID = android.os.Process.SYSTEM_UID;
101
102    /**
103     * PID of the system server.
104     */
105    public static final int SYSTEM_PID = 11111;
106
107    public static final String ANOTHER_PACKAGE_NAME = "com.another.package.name";
108
109    public static final int ANOTHER_UID = UserHandle.getUid(UserHandle.USER_SYSTEM, 18434);
110
111    public static class MockBinder {
112        public int callingUid = CALLER_UID;
113        public int callingPid = CALLER_PID;
114
115        public long clearCallingIdentity() {
116            final long token = (((long) callingUid) << 32) | (callingPid);
117            callingUid = SYSTEM_UID;
118            callingPid = SYSTEM_PID;
119            return token;
120        }
121
122        public void restoreCallingIdentity(long token) {
123            callingUid = (int) (token >> 32);
124            callingPid = (int) token;
125        }
126
127        public int getCallingUid() {
128            return callingUid;
129        }
130
131        public int getCallingPid() {
132            return callingPid;
133        }
134
135        public UserHandle getCallingUserHandle() {
136            return new UserHandle(UserHandle.getUserId(getCallingUid()));
137        }
138
139        public boolean isCallerUidMyUid() {
140            return callingUid == SYSTEM_UID;
141        }
142    }
143
144    public static class EnvironmentForMock {
145        public File getUserSystemDirectory(int userId) {
146            return null;
147        }
148    }
149
150    public static class BuildMock {
151        public boolean isDebuggable = true;
152    }
153
154    public static class PowerManagerForMock {
155        public WakeLock newWakeLock(int levelAndFlags, String tag) {
156            return null;
157        }
158
159        public void goToSleep(long time, int reason, int flags) {
160        }
161
162        public void reboot(String reason) {
163        }
164    }
165
166    public static class RecoverySystemForMock {
167        public void rebootWipeUserData(
168                boolean shutdown, String reason, boolean force) throws IOException {
169        }
170    }
171
172    public static class SystemPropertiesForMock {
173        public boolean getBoolean(String key, boolean def) {
174            return false;
175        }
176
177        public long getLong(String key, long def) {
178            return 0;
179        }
180
181        public String get(String key, String def) {
182            return null;
183        }
184
185        public String get(String key) {
186            return null;
187        }
188
189        public void set(String key, String value) {
190        }
191    }
192
193    public static class UserManagerForMock {
194        public boolean isSplitSystemUser() {
195            return false;
196        }
197    }
198
199    public static class SettingsForMock {
200        public int settingsSecureGetIntForUser(String name, int def, int userHandle) {
201            return 0;
202        }
203
204        public void settingsSecurePutIntForUser(String name, int value, int userHandle) {
205        }
206
207        public void settingsSecurePutStringForUser(String name, String value, int userHandle) {
208        }
209
210        public void settingsGlobalPutStringForUser(String name, String value, int userHandle) {
211        }
212
213        public void settingsSecurePutInt(String name, int value) {
214        }
215
216        public void settingsGlobalPutInt(String name, int value) {
217        }
218
219        public void settingsSecurePutString(String name, String value) {
220        }
221
222        public void settingsGlobalPutString(String name, String value) {
223        }
224
225        public int settingsGlobalGetInt(String name, int value) {
226            return 0;
227        }
228
229        public void securityLogSetLoggingEnabledProperty(boolean enabled) {
230        }
231
232        public boolean securityLogGetLoggingEnabledProperty() {
233            return false;
234        }
235
236        public boolean securityLogIsLoggingEnabled() {
237            return false;
238        }
239    }
240
241    public static class StorageManagerForMock {
242        public boolean isFileBasedEncryptionEnabled() {
243            return false;
244        }
245
246        public boolean isNonDefaultBlockEncrypted() {
247            return false;
248        }
249
250        public boolean isEncrypted() {
251            return false;
252        }
253
254        public boolean isEncryptable() {
255            return false;
256        }
257    }
258
259    public final Context realTestContext;
260
261    /**
262     * Use this instance to verify unimplemented methods such as {@link #sendBroadcast}.
263     * (Spying on {@code this} instance will confuse mockito somehow and I got weired "wrong number
264     * of arguments" exceptions.)
265     */
266    public final Context spiedContext;
267
268    public final File dataDir;
269    public final File systemUserDataDir;
270
271    public final MockBinder binder;
272    public final EnvironmentForMock environment;
273    public final Resources resources;
274    public final SystemPropertiesForMock systemProperties;
275    public final UserManager userManager;
276    public final UserManagerInternal userManagerInternal;
277    public final PackageManagerInternal packageManagerInternal;
278    public final UserManagerForMock userManagerForMock;
279    public final PowerManagerForMock powerManager;
280    public final PowerManagerInternal powerManagerInternal;
281    public final RecoverySystemForMock recoverySystem;
282    public final NotificationManager notificationManager;
283    public final IIpConnectivityMetrics iipConnectivityMetrics;
284    public final IWindowManager iwindowManager;
285    public final IActivityManager iactivityManager;
286    public final IPackageManager ipackageManager;
287    public final IBackupManager ibackupManager;
288    public final IAudioService iaudioService;
289    public final LockPatternUtils lockPatternUtils;
290    public final StorageManagerForMock storageManager;
291    public final WifiManager wifiManager;
292    public final SettingsForMock settings;
293    public final MockContentResolver contentResolver;
294    public final TelephonyManager telephonyManager;
295    public final AccountManager accountManager;
296    public final AlarmManager alarmManager;
297    public final KeyChain.KeyChainConnection keyChainConnection;
298
299    /** Note this is a partial mock, not a real mock. */
300    public final PackageManager packageManager;
301
302    public final List<String> callerPermissions = new ArrayList<>();
303
304    private final ArrayList<UserInfo> mUserInfos = new ArrayList<>();
305
306    public final BuildMock buildMock = new BuildMock();
307
308    /** Optional mapping of other user contexts for {@link #createPackageContextAsUser} to return */
309    public final Map<UserHandle, Context> userContexts = new ArrayMap<>();
310
311    public String packageName = null;
312
313    public ApplicationInfo applicationInfo = null;
314
315    public DpmMockContext(Context context, File dataDir) {
316        realTestContext = context;
317
318        this.dataDir = dataDir;
319        DpmTestUtils.clearDir(dataDir);
320
321        binder = new MockBinder();
322        environment = mock(EnvironmentForMock.class);
323        resources = mock(Resources.class);
324        systemProperties = mock(SystemPropertiesForMock.class);
325        userManager = mock(UserManager.class);
326        userManagerInternal = mock(UserManagerInternal.class);
327        userManagerForMock = mock(UserManagerForMock.class);
328        packageManagerInternal = mock(PackageManagerInternal.class);
329        powerManager = mock(PowerManagerForMock.class);
330        powerManagerInternal = mock(PowerManagerInternal.class);
331        recoverySystem = mock(RecoverySystemForMock.class);
332        notificationManager = mock(NotificationManager.class);
333        iipConnectivityMetrics = mock(IIpConnectivityMetrics.class);
334        iwindowManager = mock(IWindowManager.class);
335        iactivityManager = mock(IActivityManager.class);
336        ipackageManager = mock(IPackageManager.class);
337        ibackupManager = mock(IBackupManager.class);
338        iaudioService = mock(IAudioService.class);
339        lockPatternUtils = mock(LockPatternUtils.class);
340        storageManager = mock(StorageManagerForMock.class);
341        wifiManager = mock(WifiManager.class);
342        settings = mock(SettingsForMock.class);
343        telephonyManager = mock(TelephonyManager.class);
344        accountManager = mock(AccountManager.class);
345        alarmManager = mock(AlarmManager.class);
346        keyChainConnection = mock(KeyChain.KeyChainConnection.class, RETURNS_DEEP_STUBS);
347
348        // Package manager is huge, so we use a partial mock instead.
349        packageManager = spy(context.getPackageManager());
350
351        spiedContext = mock(Context.class);
352
353        contentResolver = new MockContentResolver();
354
355        // Add the system user with a fake profile group already set up (this can happen in the real
356        // world if a managed profile is added and then removed).
357        systemUserDataDir =
358                addUser(UserHandle.USER_SYSTEM, UserInfo.FLAG_PRIMARY, UserHandle.USER_SYSTEM);
359
360        // System user is always running.
361        setUserRunning(UserHandle.USER_SYSTEM, true);
362    }
363
364    public File addUser(int userId, int flags) {
365        return addUser(userId, flags, UserInfo.NO_PROFILE_GROUP_ID);
366    }
367
368    public File addUser(int userId, int flags, int profileGroupId) {
369        // Set up (default) UserInfo for CALLER_USER_HANDLE.
370        final UserInfo uh = new UserInfo(userId, "user" + userId, flags);
371        uh.profileGroupId = profileGroupId;
372        when(userManager.getUserInfo(eq(userId))).thenReturn(uh);
373
374        mUserInfos.add(uh);
375        when(userManager.getUsers()).thenReturn(mUserInfos);
376        when(userManager.getUsers(anyBoolean())).thenReturn(mUserInfos);
377        when(userManager.isUserRunning(eq(new UserHandle(userId)))).thenReturn(true);
378        when(userManager.getUserInfo(anyInt())).thenAnswer(
379                new Answer<UserInfo>() {
380                    @Override
381                    public UserInfo answer(InvocationOnMock invocation) throws Throwable {
382                        final int userId = (int) invocation.getArguments()[0];
383                        return getUserInfo(userId);
384                    }
385                }
386        );
387        when(userManager.getProfiles(anyInt())).thenAnswer(
388                new Answer<List<UserInfo>>() {
389                    @Override
390                    public List<UserInfo> answer(InvocationOnMock invocation) throws Throwable {
391                        final int userId = (int) invocation.getArguments()[0];
392                        return getProfiles(userId);
393                    }
394                }
395        );
396        when(userManager.getProfileIdsWithDisabled(anyInt())).thenAnswer(
397                new Answer<int[]>() {
398                    @Override
399                    public int[] answer(InvocationOnMock invocation) throws Throwable {
400                        final int userId = (int) invocation.getArguments()[0];
401                        List<UserInfo> profiles = getProfiles(userId);
402                        return profiles.stream()
403                                .mapToInt(profile -> profile.id)
404                                .toArray();
405                    }
406                }
407        );
408        when(accountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]);
409
410        // Create a data directory.
411        final File dir = new File(dataDir, "user" + userId);
412        DpmTestUtils.clearDir(dir);
413
414        when(environment.getUserSystemDirectory(eq(userId))).thenReturn(dir);
415        return dir;
416    }
417
418    public void removeUser(int userId) {
419        for (int i = 0; i < mUserInfos.size(); i++) {
420            if (mUserInfos.get(i).id == userId) {
421                mUserInfos.remove(i);
422                break;
423            }
424        }
425        when(userManager.getUserInfo(eq(userId))).thenReturn(null);
426
427        when(userManager.isUserRunning(eq(new UserHandle(userId)))).thenReturn(false);
428    }
429
430    private UserInfo getUserInfo(int userId) {
431        for (UserInfo ui : mUserInfos) {
432            if (ui.id == userId) {
433                return ui;
434            }
435        }
436        return null;
437    }
438
439    private List<UserInfo> getProfiles(int userId) {
440        final ArrayList<UserInfo> ret = new ArrayList<UserInfo>();
441        UserInfo parent = null;
442        for (UserInfo ui : mUserInfos) {
443            if (ui.id == userId) {
444                parent = ui;
445                break;
446            }
447        }
448        if (parent == null) {
449            return ret;
450        }
451        for (UserInfo ui : mUserInfos) {
452            if (ui == parent
453                    || ui.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
454                    && ui.profileGroupId == parent.profileGroupId) {
455                ret.add(ui);
456            }
457        }
458        return ret;
459    }
460
461    /**
462     * Add multiple users at once.  They'll all have flag 0.
463     */
464    public void addUsers(int... userIds) {
465        for (int userId : userIds) {
466            addUser(userId, 0);
467        }
468    }
469
470    public void setUserRunning(int userId, boolean isRunning) {
471        when(userManager.isUserRunning(MockUtils.checkUserHandle(userId)))
472                .thenReturn(isRunning);
473    }
474
475    @Override
476    public Resources getResources() {
477        return resources;
478    }
479
480    @Override
481    public Resources.Theme getTheme() {
482        return spiedContext.getTheme();
483    }
484
485    @Override
486    public String getPackageName() {
487        if (packageName != null) {
488            return packageName;
489        }
490        return super.getPackageName();
491    }
492
493    @Override
494    public ApplicationInfo getApplicationInfo() {
495        if (applicationInfo != null) {
496            return applicationInfo;
497        }
498        return super.getApplicationInfo();
499    }
500
501    @Override
502    public Object getSystemService(String name) {
503        switch (name) {
504            case Context.ALARM_SERVICE:
505                return alarmManager;
506            case Context.USER_SERVICE:
507                return userManager;
508            case Context.POWER_SERVICE:
509                return powerManager;
510            case Context.WIFI_SERVICE:
511                return wifiManager;
512            case Context.ACCOUNT_SERVICE:
513                return accountManager;
514        }
515        throw new UnsupportedOperationException();
516    }
517
518    @Override
519    public String getSystemServiceName(Class<?> serviceClass) {
520        return realTestContext.getSystemServiceName(serviceClass);
521    }
522
523    @Override
524    public PackageManager getPackageManager() {
525        return packageManager;
526    }
527
528    @Override
529    public void enforceCallingOrSelfPermission(String permission, String message) {
530        if (binder.getCallingUid() == SYSTEM_UID) {
531            return; // Assume system has all permissions.
532        }
533        if (!callerPermissions.contains(permission)) {
534            throw new SecurityException("Caller doesn't have " + permission + " : " + message);
535        }
536    }
537
538    @Override
539    public void sendBroadcast(Intent intent) {
540        spiedContext.sendBroadcast(intent);
541    }
542
543    @Override
544    public void sendBroadcast(Intent intent, String receiverPermission) {
545        spiedContext.sendBroadcast(intent, receiverPermission);
546    }
547
548    @Override
549    public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) {
550        spiedContext.sendBroadcastMultiplePermissions(intent, receiverPermissions);
551    }
552
553    @Override
554    public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
555        spiedContext.sendBroadcast(intent, receiverPermission, options);
556    }
557
558    @Override
559    public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
560        spiedContext.sendBroadcast(intent, receiverPermission, appOp);
561    }
562
563    @Override
564    public void sendOrderedBroadcast(Intent intent, String receiverPermission) {
565        spiedContext.sendOrderedBroadcast(intent, receiverPermission);
566    }
567
568    @Override
569    public void sendOrderedBroadcast(Intent intent, String receiverPermission,
570            BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
571            String initialData, Bundle initialExtras) {
572        spiedContext.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler,
573                initialCode, initialData, initialExtras);
574    }
575
576    @Override
577    public void sendOrderedBroadcast(Intent intent, String receiverPermission, Bundle options,
578            BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
579            String initialData, Bundle initialExtras) {
580        spiedContext.sendOrderedBroadcast(intent, receiverPermission, options, resultReceiver,
581                scheduler,
582                initialCode, initialData, initialExtras);
583    }
584
585    @Override
586    public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp,
587            BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
588            String initialData, Bundle initialExtras) {
589        spiedContext.sendOrderedBroadcast(intent, receiverPermission, appOp, resultReceiver,
590                scheduler,
591                initialCode, initialData, initialExtras);
592    }
593
594    @Override
595    public void sendBroadcastAsUser(Intent intent, UserHandle user) {
596        if (binder.callingPid != SYSTEM_PID) {
597            // Unless called as the system process, can only call if the target user is the
598            // calling user.
599            // (The actual check is more complex; we may need to change it later.)
600            Assert.assertEquals(UserHandle.getUserId(binder.getCallingUid()), user.getIdentifier());
601        }
602
603        spiedContext.sendBroadcastAsUser(intent, user);
604    }
605
606    @Override
607    public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission) {
608        spiedContext.sendBroadcastAsUser(intent, user, receiverPermission);
609    }
610
611    @Override
612    public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission,
613            int appOp) {
614        spiedContext.sendBroadcastAsUser(intent, user, receiverPermission, appOp);
615    }
616
617    @Override
618    public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
619            String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
620            int initialCode, String initialData, Bundle initialExtras) {
621        spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, resultReceiver,
622                scheduler, initialCode, initialData, initialExtras);
623        resultReceiver.onReceive(spiedContext, intent);
624    }
625
626    @Override
627    public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
628            String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
629            Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
630        spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp,
631                resultReceiver,
632                scheduler, initialCode, initialData, initialExtras);
633    }
634
635    @Override
636    public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
637            String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
638            Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
639        spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, options,
640                resultReceiver, scheduler, initialCode, initialData, initialExtras);
641    }
642
643    @Override
644    public void sendStickyBroadcast(Intent intent) {
645        spiedContext.sendStickyBroadcast(intent);
646    }
647
648    @Override
649    public void sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver,
650            Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
651        spiedContext.sendStickyOrderedBroadcast(intent, resultReceiver, scheduler, initialCode,
652                initialData, initialExtras);
653    }
654
655    @Override
656    public void removeStickyBroadcast(Intent intent) {
657        spiedContext.removeStickyBroadcast(intent);
658    }
659
660    @Override
661    public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
662        spiedContext.sendStickyBroadcastAsUser(intent, user);
663    }
664
665    @Override
666    public void sendStickyOrderedBroadcastAsUser(Intent intent, UserHandle user,
667            BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
668            String initialData, Bundle initialExtras) {
669        spiedContext.sendStickyOrderedBroadcastAsUser(intent, user, resultReceiver, scheduler, initialCode,
670                initialData, initialExtras);
671    }
672
673    @Override
674    public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
675        spiedContext.removeStickyBroadcastAsUser(intent, user);
676    }
677
678    @Override
679    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
680        return spiedContext.registerReceiver(receiver, filter);
681    }
682
683    @Override
684    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
685            String broadcastPermission, Handler scheduler) {
686        return spiedContext.registerReceiver(receiver, filter, broadcastPermission, scheduler);
687    }
688
689    @Override
690    public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
691            IntentFilter filter, String broadcastPermission, Handler scheduler) {
692        return spiedContext.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
693                scheduler);
694    }
695
696    @Override
697    public void unregisterReceiver(BroadcastReceiver receiver) {
698        spiedContext.unregisterReceiver(receiver);
699    }
700
701    @Override
702    public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
703            throws PackageManager.NameNotFoundException {
704        if (!userContexts.containsKey(user)) {
705            return super.createPackageContextAsUser(packageName, flags, user);
706        }
707        if (!getPackageName().equals(packageName)) {
708            throw new UnsupportedOperationException(
709                    "Creating a context as another package is not implemented");
710        }
711        return userContexts.get(user);
712    }
713
714    @Override
715    public ContentResolver getContentResolver() {
716        return contentResolver;
717    }
718
719    @Override
720    public int getUserId() {
721        return UserHandle.getUserId(binder.getCallingUid());
722    }
723}
724