175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov/*
275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov * Copyright (C) 2017 The Android Open Source Project
375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov *
475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov * Licensed under the Apache License, Version 2.0 (the "License");
575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov * you may not use this file except in compliance with the License.
675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov * You may obtain a copy of the License at
775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov *
875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov *      http://www.apache.org/licenses/LICENSE-2.0
975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov *
1075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov * Unless required by applicable law or agreed to in writing, software
1175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov * distributed under the License is distributed on an "AS IS" BASIS,
1275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov * See the License for the specific language governing permissions and
1475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov * limitations under the License.
1575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov */
1675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovpackage com.android.server.devicepolicy;
1775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
1875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport static org.mockito.ArgumentMatchers.anyBoolean;
1975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport static org.mockito.ArgumentMatchers.anyInt;
2075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport static org.mockito.ArgumentMatchers.eq;
2175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport static org.mockito.Mockito.RETURNS_DEEP_STUBS;
2275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport static org.mockito.Mockito.mock;
2375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport static org.mockito.Mockito.spy;
2475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport static org.mockito.Mockito.when;
2575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
2675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.accounts.Account;
2775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.accounts.AccountManager;
2875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.app.AlarmManager;
2975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.app.IActivityManager;
3075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.app.NotificationManager;
3175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.app.backup.IBackupManager;
3275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.content.BroadcastReceiver;
3375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.content.Context;
3475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.content.Intent;
3575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.content.IntentFilter;
3675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.content.pm.IPackageManager;
3775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.content.pm.PackageManager;
3875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.content.pm.PackageManagerInternal;
3975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.content.pm.UserInfo;
4075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.media.IAudioService;
4175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.net.IIpConnectivityMetrics;
4275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.net.wifi.WifiManager;
4375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.os.Handler;
4475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.os.PowerManager;
4575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.os.PowerManagerInternal;
4675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.os.UserHandle;
4775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.os.UserManager;
4875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.os.UserManagerInternal;
499a18f5fa409d99e09bed57626d5a600142fd7009Christine Franksimport android.provider.Settings;
5075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.security.KeyChain;
5175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.telephony.TelephonyManager;
5275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.test.mock.MockContentResolver;
5375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.util.ArrayMap;
5475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.util.Pair;
5575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport android.view.IWindowManager;
5675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
579a18f5fa409d99e09bed57626d5a600142fd7009Christine Franksimport com.android.internal.util.test.FakeSettingsProvider;
5875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport com.android.internal.widget.LockPatternUtils;
5975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
6075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport java.io.File;
6175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport java.io.IOException;
6275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport java.util.ArrayList;
6375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport java.util.List;
6475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport java.util.Map;
6575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovimport java.util.concurrent.atomic.AtomicReference;
6675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
6775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov/**
6875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov * System services mocks and some other data that are shared by all contexts during the test.
6975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov */
7075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafovpublic class MockSystemServices {
7175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final File systemUserDataDir;
7275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final EnvironmentForMock environment;
7375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final SystemPropertiesForMock systemProperties;
7475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final UserManager userManager;
7575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final UserManagerInternal userManagerInternal;
7675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final PackageManagerInternal packageManagerInternal;
7775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final UserManagerForMock userManagerForMock;
7875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final PowerManagerForMock powerManager;
7975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final PowerManagerInternal powerManagerInternal;
8075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final RecoverySystemForMock recoverySystem;
8175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final NotificationManager notificationManager;
8275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final IIpConnectivityMetrics iipConnectivityMetrics;
8375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final IWindowManager iwindowManager;
8475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final IActivityManager iactivityManager;
8575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final IPackageManager ipackageManager;
8675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final IBackupManager ibackupManager;
8775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final IAudioService iaudioService;
8875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final LockPatternUtils lockPatternUtils;
8975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final StorageManagerForMock storageManager;
9075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final WifiManager wifiManager;
9175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final SettingsForMock settings;
9275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final MockContentResolver contentResolver;
9375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final TelephonyManager telephonyManager;
9475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final AccountManager accountManager;
9575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final AlarmManager alarmManager;
9675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final KeyChain.KeyChainConnection keyChainConnection;
9775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    /** Note this is a partial mock, not a real mock. */
9875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final PackageManager packageManager;
9975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final BuildMock buildMock = new BuildMock();
10075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public final File dataDir;
10175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
10275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public MockSystemServices(Context realContext, String name) {
10375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        dataDir = new File(realContext.getCacheDir(), name);
10475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        DpmTestUtils.clearDir(dataDir);
10575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
10675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        environment = mock(EnvironmentForMock.class);
10775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        systemProperties = mock(SystemPropertiesForMock.class);
10875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        userManager = mock(UserManager.class);
10975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        userManagerInternal = mock(UserManagerInternal.class);
11075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        userManagerForMock = mock(UserManagerForMock.class);
11175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        packageManagerInternal = mock(PackageManagerInternal.class);
11275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        powerManager = mock(PowerManagerForMock.class);
11375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        powerManagerInternal = mock(PowerManagerInternal.class);
11475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        recoverySystem = mock(RecoverySystemForMock.class);
11575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        notificationManager = mock(NotificationManager.class);
11675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        iipConnectivityMetrics = mock(IIpConnectivityMetrics.class);
11775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        iwindowManager = mock(IWindowManager.class);
11875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        iactivityManager = mock(IActivityManager.class);
11975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        ipackageManager = mock(IPackageManager.class);
12075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        ibackupManager = mock(IBackupManager.class);
12175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        iaudioService = mock(IAudioService.class);
12275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        lockPatternUtils = mock(LockPatternUtils.class);
12375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        storageManager = mock(StorageManagerForMock.class);
12475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        wifiManager = mock(WifiManager.class);
12575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        settings = mock(SettingsForMock.class);
12675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        telephonyManager = mock(TelephonyManager.class);
12775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        accountManager = mock(AccountManager.class);
12875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        alarmManager = mock(AlarmManager.class);
12975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        keyChainConnection = mock(KeyChain.KeyChainConnection.class, RETURNS_DEEP_STUBS);
13075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
13175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        // Package manager is huge, so we use a partial mock instead.
13275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        packageManager = spy(realContext.getPackageManager());
13375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
13475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        contentResolver = new MockContentResolver();
1359a18f5fa409d99e09bed57626d5a600142fd7009Christine Franks        contentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
13675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
13775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        // Add the system user with a fake profile group already set up (this can happen in the real
13875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        // world if a managed profile is added and then removed).
13975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        systemUserDataDir =
14075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                addUser(UserHandle.USER_SYSTEM, UserInfo.FLAG_PRIMARY, UserHandle.USER_SYSTEM);
14175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
14275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        // System user is always running.
14375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        setUserRunning(UserHandle.USER_SYSTEM, true);
14475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
14575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
14675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    /** Optional mapping of other user contexts for {@link #createPackageContextAsUser} to return */
14775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    private final Map<Pair<UserHandle, String>, Context> userPackageContexts = new ArrayMap<>();
14875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
14975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    private final ArrayList<UserInfo> mUserInfos = new ArrayList<>();
15075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
15175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    private final List<BroadcastReceiverRegistration> mBroadcastReceivers = new ArrayList<>();
15275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
15375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public void registerReceiver(
15475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            BroadcastReceiver receiver, IntentFilter filter, Handler scheduler) {
15575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        mBroadcastReceivers.add(new BroadcastReceiverRegistration(receiver, filter, scheduler));
15675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
15775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
15875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public void unregisterReceiver(BroadcastReceiver receiver) {
15975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        mBroadcastReceivers.removeIf(r -> r.receiver == receiver);
16075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
16175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
16275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public File addUser(int userId, int flags) {
16375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        return addUser(userId, flags, UserInfo.NO_PROFILE_GROUP_ID);
16475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
16575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
16675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public File addUser(int userId, int flags, int profileGroupId) {
16775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        // Set up (default) UserInfo for CALLER_USER_HANDLE.
16875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        final UserInfo uh = new UserInfo(userId, "user" + userId, flags);
16975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        uh.profileGroupId = profileGroupId;
17075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        when(userManager.getUserInfo(eq(userId))).thenReturn(uh);
17175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
17275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        mUserInfos.add(uh);
17375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        when(userManager.getUsers()).thenReturn(mUserInfos);
17475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        when(userManager.getUsers(anyBoolean())).thenReturn(mUserInfos);
17575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        when(userManager.isUserRunning(eq(new UserHandle(userId)))).thenReturn(true);
17675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        when(userManager.getUserInfo(anyInt())).thenAnswer(
17775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                invocation -> {
17875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    final int userId1 = (int) invocation.getArguments()[0];
17975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    return getUserInfo(userId1);
18075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                }
18175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        );
18275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        when(userManager.getProfiles(anyInt())).thenAnswer(
18375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                invocation -> {
18475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    final int userId12 = (int) invocation.getArguments()[0];
18575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    return getProfiles(userId12);
18675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                }
18775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        );
18875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        when(userManager.getProfileIdsWithDisabled(anyInt())).thenAnswer(
18975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                invocation -> {
19075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    final int userId13 = (int) invocation.getArguments()[0];
19175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    List<UserInfo> profiles = getProfiles(userId13);
19275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    return profiles.stream()
19375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                            .mapToInt(profile -> profile.id)
19475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                            .toArray();
19575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                }
19675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        );
19775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        when(accountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]);
19875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
19975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        // Create a data directory.
20075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        final File dir = new File(dataDir, "users/" + userId);
20175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        DpmTestUtils.clearDir(dir);
20275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
20375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        when(environment.getUserSystemDirectory(eq(userId))).thenReturn(dir);
20475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        return dir;
20575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
20675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
20775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public void removeUser(int userId) {
20875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        for (int i = 0; i < mUserInfos.size(); i++) {
20975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            if (mUserInfos.get(i).id == userId) {
21075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                mUserInfos.remove(i);
21175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                break;
21275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            }
21375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
21475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        when(userManager.getUserInfo(eq(userId))).thenReturn(null);
21575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
21675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        when(userManager.isUserRunning(eq(new UserHandle(userId)))).thenReturn(false);
21775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
21875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
21975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    private UserInfo getUserInfo(int userId) {
22075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        for (final UserInfo ui : mUserInfos) {
22175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            if (ui.id == userId) {
22275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                return ui;
22375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            }
22475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
22575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        return null;
22675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
22775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
22875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    private List<UserInfo> getProfiles(int userId) {
22975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        final ArrayList<UserInfo> ret = new ArrayList<>();
23075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        UserInfo parent = null;
23175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        for (final UserInfo ui : mUserInfos) {
23275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            if (ui.id == userId) {
23375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                parent = ui;
23475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                break;
23575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            }
23675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
23775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        if (parent == null) {
23875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return ret;
23975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
24075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        for (final UserInfo ui : mUserInfos) {
24175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            if (ui == parent
24275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    || ui.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
24375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    && ui.profileGroupId == parent.profileGroupId) {
24475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                ret.add(ui);
24575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            }
24675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
24775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        return ret;
24875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
24975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
25075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    /**
25175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov     * Add multiple users at once.  They'll all have flag 0.
25275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov     */
25375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public void addUsers(int... userIds) {
25475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        for (final int userId : userIds) {
25575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            addUser(userId, 0);
25675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
25775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
25875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
25975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public void setUserRunning(int userId, boolean isRunning) {
26075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        when(userManager.isUserRunning(MockUtils.checkUserHandle(userId)))
26175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                .thenReturn(isRunning);
26275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
26375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
26475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public void injectBroadcast(Context context, final Intent intent, int userId) {
26575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        //final int userId = UserHandle.getUserId(binder.getCallingUid());
26675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        for (final BroadcastReceiverRegistration receiver : mBroadcastReceivers) {
26775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            receiver.sendBroadcastIfApplicable(context, userId, intent);
26875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
26975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
27075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
27175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public void rethrowBackgroundBroadcastExceptions() throws Exception {
27275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        for (final BroadcastReceiverRegistration receiver : mBroadcastReceivers) {
27375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            final Exception e = receiver.backgroundException.getAndSet(null);
27475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            if (e != null) {
27575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                throw e;
27675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            }
27775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
27875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
27975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
28075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public void addPackageContext(UserHandle user, Context context) {
28175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        if (context.getPackageName() == null) {
28275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            throw new NullPointerException("getPackageName() == null");
28375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
28475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        userPackageContexts.put(new Pair<>(user, context.getPackageName()), context);
28575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
28675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
28775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
28875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            throws PackageManager.NameNotFoundException {
28975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        final Pair<UserHandle, String> key = new Pair<>(user, packageName);
29075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        if (userPackageContexts.containsKey(key)) {
29175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return userPackageContexts.get(key);
29275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
29375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        throw new UnsupportedOperationException("No package " + packageName + " for user " + user);
29475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
29575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
29675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
29775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public static class EnvironmentForMock {
29875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public File getUserSystemDirectory(int userId) {
29975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return null;
30075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
30175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
30275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
30375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public static class BuildMock {
30475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public boolean isDebuggable = true;
30575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
30675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
30775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public static class PowerManagerForMock {
30875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public PowerManager.WakeLock newWakeLock(int levelAndFlags, String tag) {
30975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return null;
31075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
31175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
31275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public void goToSleep(long time, int reason, int flags) {
31375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
31475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
31575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public void reboot(String reason) {
31675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
31775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
31875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
31975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public static class RecoverySystemForMock {
320f4f9cec234bf147f0067cef2791a26eaa2cde0a0yinxu        public void rebootWipeUserData(boolean shutdown, String reason, boolean force,
321f4f9cec234bf147f0067cef2791a26eaa2cde0a0yinxu                boolean wipeEuicc) throws IOException {
32275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
32375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
32475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
32575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public static class SystemPropertiesForMock {
32675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public boolean getBoolean(String key, boolean def) {
32775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return false;
32875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
32975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
33075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public long getLong(String key, long def) {
33175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return 0;
33275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
33375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
33475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public String get(String key, String def) {
33575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return null;
33675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
33775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
33875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public String get(String key) {
33975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return null;
34075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
34175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
34275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public void set(String key, String value) {
34375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
34475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
34575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
34675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public static class UserManagerForMock {
34775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public boolean isSplitSystemUser() {
34875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return false;
34975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
35075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
35175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
35275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public static class SettingsForMock {
35375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public int settingsSecureGetIntForUser(String name, int def, int userHandle) {
35475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return 0;
35575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
35675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
35775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public String settingsSecureGetStringForUser(String name, int userHandle) {
35875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return null;
35975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
36075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
36175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public void settingsSecurePutIntForUser(String name, int value, int userHandle) {
36275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
36375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
36475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public void settingsSecurePutStringForUser(String name, String value, int userHandle) {
36575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
36675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
36775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public void settingsGlobalPutStringForUser(String name, String value, int userHandle) {
36875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
36975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
37075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public void settingsSecurePutInt(String name, int value) {
37175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
37275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
37375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public void settingsGlobalPutInt(String name, int value) {
37475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
37575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
37675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public void settingsSecurePutString(String name, String value) {
37775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
37875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
37975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public void settingsGlobalPutString(String name, String value) {
38075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
38175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
38275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public int settingsGlobalGetInt(String name, int value) {
38375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return 0;
38475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
38575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
38675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public String settingsGlobalGetString(String name) {
38775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return "";
38875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
38975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
39075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public void securityLogSetLoggingEnabledProperty(boolean enabled) {
39175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
39275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
39375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public boolean securityLogGetLoggingEnabledProperty() {
39475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return false;
39575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
39675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
39775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public boolean securityLogIsLoggingEnabled() {
39875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return false;
39975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
40075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
40175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
40275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    public static class StorageManagerForMock {
40375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public boolean isFileBasedEncryptionEnabled() {
40475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return false;
40575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
40675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
40775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public boolean isNonDefaultBlockEncrypted() {
40875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return false;
40975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
41075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
41175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public boolean isEncrypted() {
41275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return false;
41375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
41475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
41575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public boolean isEncryptable() {
41675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            return false;
41775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
41875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
41975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
42075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    // We have to keep track of broadcast receivers registered for a given intent ourselves as the
42175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    // DPM unit tests mock out the package manager and PackageManager.queryBroadcastReceivers() does
42275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    // not work.
42375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    private static class BroadcastReceiverRegistration {
42475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public final BroadcastReceiver receiver;
42575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public final IntentFilter filter;
42675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public final Handler scheduler;
42775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
42875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        // Exceptions thrown in a background thread kill the whole test. Save them instead.
42975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public final AtomicReference<Exception> backgroundException = new AtomicReference<>();
43075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
43175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public BroadcastReceiverRegistration(BroadcastReceiver receiver, IntentFilter filter,
43275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                Handler scheduler) {
43375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            this.receiver = receiver;
43475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            this.filter = filter;
43575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            this.scheduler = scheduler;
43675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
43775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov
43875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        public void sendBroadcastIfApplicable(Context context, int userId, Intent intent) {
43975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            final BroadcastReceiver.PendingResult result = new BroadcastReceiver.PendingResult(
44075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    0 /* resultCode */, null /* resultData */, null /* resultExtras */,
44175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    0 /* type */, false /* ordered */, false /* sticky */, null /* token */, userId,
44275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    0 /* flags */);
44375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            if (filter.match(null, intent, false, "DpmMockContext") > 0) {
44475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                final Runnable send = () -> {
44575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    receiver.setPendingResult(result);
44675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    receiver.onReceive(context, intent);
44775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                };
44875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                if (scheduler != null) {
44975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    scheduler.post(() -> {
45075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                        try {
45175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                            send.run();
45275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                        } catch (Exception e) {
45375c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                            backgroundException.compareAndSet(null, e);
45475c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                        }
45575c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    });
45675c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                } else {
45775c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                    send.run();
45875c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov                }
45975c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov            }
46075c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov        }
46175c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov    }
46275c0a891ae2f1170d64b06baeca49908b6183b70Pavel Grafov}
463