Home | History | Annotate | Download | only in devicepolicy
      1 /*
      2  * Copyright (C) 2017 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 package com.android.server.devicepolicy;
     17 
     18 import static org.mockito.ArgumentMatchers.anyBoolean;
     19 import static org.mockito.ArgumentMatchers.anyInt;
     20 import static org.mockito.ArgumentMatchers.eq;
     21 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
     22 import static org.mockito.Mockito.mock;
     23 import static org.mockito.Mockito.spy;
     24 import static org.mockito.Mockito.when;
     25 
     26 import android.accounts.Account;
     27 import android.accounts.AccountManager;
     28 import android.app.AlarmManager;
     29 import android.app.IActivityManager;
     30 import android.app.NotificationManager;
     31 import android.app.backup.IBackupManager;
     32 import android.content.BroadcastReceiver;
     33 import android.content.Context;
     34 import android.content.Intent;
     35 import android.content.IntentFilter;
     36 import android.content.pm.IPackageManager;
     37 import android.content.pm.PackageManager;
     38 import android.content.pm.PackageManagerInternal;
     39 import android.content.pm.UserInfo;
     40 import android.media.IAudioService;
     41 import android.net.IIpConnectivityMetrics;
     42 import android.net.wifi.WifiManager;
     43 import android.os.Handler;
     44 import android.os.PowerManager;
     45 import android.os.PowerManagerInternal;
     46 import android.os.UserHandle;
     47 import android.os.UserManager;
     48 import android.os.UserManagerInternal;
     49 import android.provider.Settings;
     50 import android.security.KeyChain;
     51 import android.telephony.TelephonyManager;
     52 import android.test.mock.MockContentResolver;
     53 import android.util.ArrayMap;
     54 import android.util.Pair;
     55 import android.view.IWindowManager;
     56 
     57 import com.android.internal.util.test.FakeSettingsProvider;
     58 import com.android.internal.widget.LockPatternUtils;
     59 
     60 import java.io.File;
     61 import java.io.IOException;
     62 import java.util.ArrayList;
     63 import java.util.List;
     64 import java.util.Map;
     65 import java.util.concurrent.atomic.AtomicReference;
     66 
     67 /**
     68  * System services mocks and some other data that are shared by all contexts during the test.
     69  */
     70 public class MockSystemServices {
     71     public final File systemUserDataDir;
     72     public final EnvironmentForMock environment;
     73     public final SystemPropertiesForMock systemProperties;
     74     public final UserManager userManager;
     75     public final UserManagerInternal userManagerInternal;
     76     public final PackageManagerInternal packageManagerInternal;
     77     public final UserManagerForMock userManagerForMock;
     78     public final PowerManagerForMock powerManager;
     79     public final PowerManagerInternal powerManagerInternal;
     80     public final RecoverySystemForMock recoverySystem;
     81     public final NotificationManager notificationManager;
     82     public final IIpConnectivityMetrics iipConnectivityMetrics;
     83     public final IWindowManager iwindowManager;
     84     public final IActivityManager iactivityManager;
     85     public final IPackageManager ipackageManager;
     86     public final IBackupManager ibackupManager;
     87     public final IAudioService iaudioService;
     88     public final LockPatternUtils lockPatternUtils;
     89     public final StorageManagerForMock storageManager;
     90     public final WifiManager wifiManager;
     91     public final SettingsForMock settings;
     92     public final MockContentResolver contentResolver;
     93     public final TelephonyManager telephonyManager;
     94     public final AccountManager accountManager;
     95     public final AlarmManager alarmManager;
     96     public final KeyChain.KeyChainConnection keyChainConnection;
     97     /** Note this is a partial mock, not a real mock. */
     98     public final PackageManager packageManager;
     99     public final BuildMock buildMock = new BuildMock();
    100     public final File dataDir;
    101 
    102     public MockSystemServices(Context realContext, String name) {
    103         dataDir = new File(realContext.getCacheDir(), name);
    104         DpmTestUtils.clearDir(dataDir);
    105 
    106         environment = mock(EnvironmentForMock.class);
    107         systemProperties = mock(SystemPropertiesForMock.class);
    108         userManager = mock(UserManager.class);
    109         userManagerInternal = mock(UserManagerInternal.class);
    110         userManagerForMock = mock(UserManagerForMock.class);
    111         packageManagerInternal = mock(PackageManagerInternal.class);
    112         powerManager = mock(PowerManagerForMock.class);
    113         powerManagerInternal = mock(PowerManagerInternal.class);
    114         recoverySystem = mock(RecoverySystemForMock.class);
    115         notificationManager = mock(NotificationManager.class);
    116         iipConnectivityMetrics = mock(IIpConnectivityMetrics.class);
    117         iwindowManager = mock(IWindowManager.class);
    118         iactivityManager = mock(IActivityManager.class);
    119         ipackageManager = mock(IPackageManager.class);
    120         ibackupManager = mock(IBackupManager.class);
    121         iaudioService = mock(IAudioService.class);
    122         lockPatternUtils = mock(LockPatternUtils.class);
    123         storageManager = mock(StorageManagerForMock.class);
    124         wifiManager = mock(WifiManager.class);
    125         settings = mock(SettingsForMock.class);
    126         telephonyManager = mock(TelephonyManager.class);
    127         accountManager = mock(AccountManager.class);
    128         alarmManager = mock(AlarmManager.class);
    129         keyChainConnection = mock(KeyChain.KeyChainConnection.class, RETURNS_DEEP_STUBS);
    130 
    131         // Package manager is huge, so we use a partial mock instead.
    132         packageManager = spy(realContext.getPackageManager());
    133 
    134         contentResolver = new MockContentResolver();
    135         contentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
    136 
    137         // Add the system user with a fake profile group already set up (this can happen in the real
    138         // world if a managed profile is added and then removed).
    139         systemUserDataDir =
    140                 addUser(UserHandle.USER_SYSTEM, UserInfo.FLAG_PRIMARY, UserHandle.USER_SYSTEM);
    141 
    142         // System user is always running.
    143         setUserRunning(UserHandle.USER_SYSTEM, true);
    144     }
    145 
    146     /** Optional mapping of other user contexts for {@link #createPackageContextAsUser} to return */
    147     private final Map<Pair<UserHandle, String>, Context> userPackageContexts = new ArrayMap<>();
    148 
    149     private final ArrayList<UserInfo> mUserInfos = new ArrayList<>();
    150 
    151     private final List<BroadcastReceiverRegistration> mBroadcastReceivers = new ArrayList<>();
    152 
    153     public void registerReceiver(
    154             BroadcastReceiver receiver, IntentFilter filter, Handler scheduler) {
    155         mBroadcastReceivers.add(new BroadcastReceiverRegistration(receiver, filter, scheduler));
    156     }
    157 
    158     public void unregisterReceiver(BroadcastReceiver receiver) {
    159         mBroadcastReceivers.removeIf(r -> r.receiver == receiver);
    160     }
    161 
    162     public File addUser(int userId, int flags) {
    163         return addUser(userId, flags, UserInfo.NO_PROFILE_GROUP_ID);
    164     }
    165 
    166     public File addUser(int userId, int flags, int profileGroupId) {
    167         // Set up (default) UserInfo for CALLER_USER_HANDLE.
    168         final UserInfo uh = new UserInfo(userId, "user" + userId, flags);
    169         uh.profileGroupId = profileGroupId;
    170         when(userManager.getUserInfo(eq(userId))).thenReturn(uh);
    171 
    172         mUserInfos.add(uh);
    173         when(userManager.getUsers()).thenReturn(mUserInfos);
    174         when(userManager.getUsers(anyBoolean())).thenReturn(mUserInfos);
    175         when(userManager.isUserRunning(eq(new UserHandle(userId)))).thenReturn(true);
    176         when(userManager.getUserInfo(anyInt())).thenAnswer(
    177                 invocation -> {
    178                     final int userId1 = (int) invocation.getArguments()[0];
    179                     return getUserInfo(userId1);
    180                 }
    181         );
    182         when(userManager.getProfiles(anyInt())).thenAnswer(
    183                 invocation -> {
    184                     final int userId12 = (int) invocation.getArguments()[0];
    185                     return getProfiles(userId12);
    186                 }
    187         );
    188         when(userManager.getProfileIdsWithDisabled(anyInt())).thenAnswer(
    189                 invocation -> {
    190                     final int userId13 = (int) invocation.getArguments()[0];
    191                     List<UserInfo> profiles = getProfiles(userId13);
    192                     return profiles.stream()
    193                             .mapToInt(profile -> profile.id)
    194                             .toArray();
    195                 }
    196         );
    197         when(accountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]);
    198 
    199         // Create a data directory.
    200         final File dir = new File(dataDir, "users/" + userId);
    201         DpmTestUtils.clearDir(dir);
    202 
    203         when(environment.getUserSystemDirectory(eq(userId))).thenReturn(dir);
    204         return dir;
    205     }
    206 
    207     public void removeUser(int userId) {
    208         for (int i = 0; i < mUserInfos.size(); i++) {
    209             if (mUserInfos.get(i).id == userId) {
    210                 mUserInfos.remove(i);
    211                 break;
    212             }
    213         }
    214         when(userManager.getUserInfo(eq(userId))).thenReturn(null);
    215 
    216         when(userManager.isUserRunning(eq(new UserHandle(userId)))).thenReturn(false);
    217     }
    218 
    219     private UserInfo getUserInfo(int userId) {
    220         for (final UserInfo ui : mUserInfos) {
    221             if (ui.id == userId) {
    222                 return ui;
    223             }
    224         }
    225         return null;
    226     }
    227 
    228     private List<UserInfo> getProfiles(int userId) {
    229         final ArrayList<UserInfo> ret = new ArrayList<>();
    230         UserInfo parent = null;
    231         for (final UserInfo ui : mUserInfos) {
    232             if (ui.id == userId) {
    233                 parent = ui;
    234                 break;
    235             }
    236         }
    237         if (parent == null) {
    238             return ret;
    239         }
    240         for (final UserInfo ui : mUserInfos) {
    241             if (ui == parent
    242                     || ui.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
    243                     && ui.profileGroupId == parent.profileGroupId) {
    244                 ret.add(ui);
    245             }
    246         }
    247         return ret;
    248     }
    249 
    250     /**
    251      * Add multiple users at once.  They'll all have flag 0.
    252      */
    253     public void addUsers(int... userIds) {
    254         for (final int userId : userIds) {
    255             addUser(userId, 0);
    256         }
    257     }
    258 
    259     public void setUserRunning(int userId, boolean isRunning) {
    260         when(userManager.isUserRunning(MockUtils.checkUserHandle(userId)))
    261                 .thenReturn(isRunning);
    262     }
    263 
    264     public void injectBroadcast(Context context, final Intent intent, int userId) {
    265         //final int userId = UserHandle.getUserId(binder.getCallingUid());
    266         for (final BroadcastReceiverRegistration receiver : mBroadcastReceivers) {
    267             receiver.sendBroadcastIfApplicable(context, userId, intent);
    268         }
    269     }
    270 
    271     public void rethrowBackgroundBroadcastExceptions() throws Exception {
    272         for (final BroadcastReceiverRegistration receiver : mBroadcastReceivers) {
    273             final Exception e = receiver.backgroundException.getAndSet(null);
    274             if (e != null) {
    275                 throw e;
    276             }
    277         }
    278     }
    279 
    280     public void addPackageContext(UserHandle user, Context context) {
    281         if (context.getPackageName() == null) {
    282             throw new NullPointerException("getPackageName() == null");
    283         }
    284         userPackageContexts.put(new Pair<>(user, context.getPackageName()), context);
    285     }
    286 
    287     public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
    288             throws PackageManager.NameNotFoundException {
    289         final Pair<UserHandle, String> key = new Pair<>(user, packageName);
    290         if (userPackageContexts.containsKey(key)) {
    291             return userPackageContexts.get(key);
    292         }
    293         throw new UnsupportedOperationException("No package " + packageName + " for user " + user);
    294     }
    295 
    296 
    297     public static class EnvironmentForMock {
    298         public File getUserSystemDirectory(int userId) {
    299             return null;
    300         }
    301     }
    302 
    303     public static class BuildMock {
    304         public boolean isDebuggable = true;
    305     }
    306 
    307     public static class PowerManagerForMock {
    308         public PowerManager.WakeLock newWakeLock(int levelAndFlags, String tag) {
    309             return null;
    310         }
    311 
    312         public void goToSleep(long time, int reason, int flags) {
    313         }
    314 
    315         public void reboot(String reason) {
    316         }
    317     }
    318 
    319     public static class RecoverySystemForMock {
    320         public void rebootWipeUserData(boolean shutdown, String reason, boolean force,
    321                 boolean wipeEuicc) throws IOException {
    322         }
    323     }
    324 
    325     public static class SystemPropertiesForMock {
    326         public boolean getBoolean(String key, boolean def) {
    327             return false;
    328         }
    329 
    330         public long getLong(String key, long def) {
    331             return 0;
    332         }
    333 
    334         public String get(String key, String def) {
    335             return null;
    336         }
    337 
    338         public String get(String key) {
    339             return null;
    340         }
    341 
    342         public void set(String key, String value) {
    343         }
    344     }
    345 
    346     public static class UserManagerForMock {
    347         public boolean isSplitSystemUser() {
    348             return false;
    349         }
    350     }
    351 
    352     public static class SettingsForMock {
    353         public int settingsSecureGetIntForUser(String name, int def, int userHandle) {
    354             return 0;
    355         }
    356 
    357         public String settingsSecureGetStringForUser(String name, int userHandle) {
    358             return null;
    359         }
    360 
    361         public void settingsSecurePutIntForUser(String name, int value, int userHandle) {
    362         }
    363 
    364         public void settingsSecurePutStringForUser(String name, String value, int userHandle) {
    365         }
    366 
    367         public void settingsGlobalPutStringForUser(String name, String value, int userHandle) {
    368         }
    369 
    370         public void settingsSecurePutInt(String name, int value) {
    371         }
    372 
    373         public void settingsGlobalPutInt(String name, int value) {
    374         }
    375 
    376         public void settingsSecurePutString(String name, String value) {
    377         }
    378 
    379         public void settingsGlobalPutString(String name, String value) {
    380         }
    381 
    382         public int settingsGlobalGetInt(String name, int value) {
    383             return 0;
    384         }
    385 
    386         public String settingsGlobalGetString(String name) {
    387             return "";
    388         }
    389 
    390         public void securityLogSetLoggingEnabledProperty(boolean enabled) {
    391         }
    392 
    393         public boolean securityLogGetLoggingEnabledProperty() {
    394             return false;
    395         }
    396 
    397         public boolean securityLogIsLoggingEnabled() {
    398             return false;
    399         }
    400     }
    401 
    402     public static class StorageManagerForMock {
    403         public boolean isFileBasedEncryptionEnabled() {
    404             return false;
    405         }
    406 
    407         public boolean isNonDefaultBlockEncrypted() {
    408             return false;
    409         }
    410 
    411         public boolean isEncrypted() {
    412             return false;
    413         }
    414 
    415         public boolean isEncryptable() {
    416             return false;
    417         }
    418     }
    419 
    420     // We have to keep track of broadcast receivers registered for a given intent ourselves as the
    421     // DPM unit tests mock out the package manager and PackageManager.queryBroadcastReceivers() does
    422     // not work.
    423     private static class BroadcastReceiverRegistration {
    424         public final BroadcastReceiver receiver;
    425         public final IntentFilter filter;
    426         public final Handler scheduler;
    427 
    428         // Exceptions thrown in a background thread kill the whole test. Save them instead.
    429         public final AtomicReference<Exception> backgroundException = new AtomicReference<>();
    430 
    431         public BroadcastReceiverRegistration(BroadcastReceiver receiver, IntentFilter filter,
    432                 Handler scheduler) {
    433             this.receiver = receiver;
    434             this.filter = filter;
    435             this.scheduler = scheduler;
    436         }
    437 
    438         public void sendBroadcastIfApplicable(Context context, int userId, Intent intent) {
    439             final BroadcastReceiver.PendingResult result = new BroadcastReceiver.PendingResult(
    440                     0 /* resultCode */, null /* resultData */, null /* resultExtras */,
    441                     0 /* type */, false /* ordered */, false /* sticky */, null /* token */, userId,
    442                     0 /* flags */);
    443             if (filter.match(null, intent, false, "DpmMockContext") > 0) {
    444                 final Runnable send = () -> {
    445                     receiver.setPendingResult(result);
    446                     receiver.onReceive(context, intent);
    447                 };
    448                 if (scheduler != null) {
    449                     scheduler.post(() -> {
    450                         try {
    451                             send.run();
    452                         } catch (Exception e) {
    453                             backgroundException.compareAndSet(null, e);
    454                         }
    455                     });
    456                 } else {
    457                     send.run();
    458                 }
    459             }
    460         }
    461     }
    462 }
    463