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.any;
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.annotation.NonNull;
29 import android.app.ActivityManagerInternal;
30 import android.app.AlarmManager;
31 import android.app.AppOpsManager;
32 import android.app.IActivityManager;
33 import android.app.IActivityTaskManager;
34 import android.app.NotificationManager;
35 import android.app.admin.DevicePolicyManager;
36 import android.app.backup.IBackupManager;
37 import android.app.role.RoleManager;
38 import android.app.usage.UsageStatsManagerInternal;
39 import android.content.BroadcastReceiver;
40 import android.content.ComponentName;
41 import android.content.ContentValues;
42 import android.content.Context;
43 import android.content.Intent;
44 import android.content.IntentFilter;
45 import android.content.pm.CrossProfileApps;
46 import android.content.pm.IPackageManager;
47 import android.content.pm.PackageManager;
48 import android.content.pm.PackageManagerInternal;
49 import android.content.pm.UserInfo;
50 import android.database.Cursor;
51 import android.hardware.usb.UsbManager;
52 import android.location.LocationManager;
53 import android.media.IAudioService;
54 import android.net.ConnectivityManager;
55 import android.net.IIpConnectivityMetrics;
56 import android.net.Uri;
57 import android.net.VpnManager;
58 import android.net.wifi.WifiManager;
59 import android.os.Binder;
60 import android.os.Handler;
61 import android.os.PowerManager;
62 import android.os.PowerManagerInternal;
63 import android.os.UserHandle;
64 import android.os.UserManager;
65 import android.permission.IPermissionManager;
66 import android.provider.Settings;
67 import android.security.KeyChain;
68 import android.telephony.SubscriptionManager;
69 import android.telephony.TelephonyManager;
70 import android.test.mock.MockContentProvider;
71 import android.test.mock.MockContentResolver;
72 import android.util.ArrayMap;
73 import android.util.Pair;
74 import android.view.IWindowManager;
75 
76 import com.android.internal.util.test.FakeSettingsProvider;
77 import com.android.internal.widget.LockPatternUtils;
78 import com.android.internal.widget.LockSettingsInternal;
79 import com.android.server.AlarmManagerInternal;
80 import com.android.server.pdb.PersistentDataBlockManagerInternal;
81 import com.android.server.net.NetworkPolicyManagerInternal;
82 import com.android.server.pm.PackageManagerLocal;
83 import com.android.server.pm.UserManagerInternal;
84 import com.android.server.pm.pkg.PackageState;
85 import com.android.server.pm.pkg.PackageUserState;
86 import com.android.server.wm.ActivityTaskManagerInternal;
87 
88 import java.io.File;
89 import java.io.IOException;
90 import java.util.ArrayList;
91 import java.util.List;
92 import java.util.Map;
93 import java.util.concurrent.Executor;
94 import java.util.concurrent.atomic.AtomicReference;
95 
96 /**
97  * System services mocks and some other data that are shared by all contexts during the test.
98  */
99 public class MockSystemServices {
100     public final File systemUserDataDir;
101     public final EnvironmentForMock environment;
102     public final SystemPropertiesForMock systemProperties;
103     public final Executor executor;
104     public final UserManager userManager;
105     public final UserManagerInternal userManagerInternal;
106     public final UsageStatsManagerInternal usageStatsManagerInternal;
107     public final NetworkPolicyManagerInternal networkPolicyManagerInternal;
108     public final PackageManagerInternal packageManagerInternal;
109     public final PackageManagerLocal packageManagerLocal;
110     public final UserManagerForMock userManagerForMock;
111     public final PowerManagerForMock powerManager;
112     public final PowerManagerInternal powerManagerInternal;
113     public final RecoverySystemForMock recoverySystem;
114     public final NotificationManager notificationManager;
115     public final IIpConnectivityMetrics iipConnectivityMetrics;
116     public final IWindowManager iwindowManager;
117     public final IActivityManager iactivityManager;
118     public final IActivityTaskManager iactivityTaskManager;
119     public ActivityManagerInternal activityManagerInternal;
120     public ActivityTaskManagerInternal activityTaskManagerInternal;
121     public final IPackageManager ipackageManager;
122     public final IPermissionManager ipermissionManager;
123     public final IBackupManager ibackupManager;
124     public final IAudioService iaudioService;
125     public final LockPatternUtils lockPatternUtils;
126     public final LockSettingsInternal lockSettingsInternal;
127     public final StorageManagerForMock storageManager;
128     public final WifiManager wifiManager;
129     public final SettingsForMock settings;
130     public final MockContentResolver contentResolver;
131     public final TelephonyManager telephonyManager;
132     public final ConnectivityManager connectivityManager;
133     public final AccountManager accountManager;
134     public final AlarmManager alarmManager;
135     public final AlarmManagerInternal alarmManagerInternal;
136     public final KeyChain.KeyChainConnection keyChainConnection;
137     public final CrossProfileApps crossProfileApps;
138     public final PersistentDataBlockManagerInternal persistentDataBlockManagerInternal;
139     public final AppOpsManager appOpsManager;
140     public final UsbManager usbManager;
141     public final VpnManager vpnManager;
142     public final DevicePolicyManager devicePolicyManager;
143     public final LocationManager locationManager;
144     public final RoleManager roleManager;
145     public final SubscriptionManager subscriptionManager;
146     /** Note this is a partial mock, not a real mock. */
147     public final PackageManager packageManager;
148     public final BuildMock buildMock = new BuildMock();
149     public final File dataDir;
150     public final PolicyPathProvider pathProvider;
151 
152     private final Map<String, PackageState> mTestPackageStates = new ArrayMap<>();
153 
MockSystemServices(Context realContext, String name, @NonNull DpmMockContext.MockBinder mockBinder)154     public MockSystemServices(Context realContext, String name,
155             @NonNull DpmMockContext.MockBinder mockBinder) {
156         dataDir = new File(realContext.getCacheDir(), name);
157         DpmTestUtils.clearDir(dataDir);
158 
159         environment = mock(EnvironmentForMock.class);
160         systemProperties = mock(SystemPropertiesForMock.class);
161         executor = mock(Executor.class);
162         userManager = mock(UserManager.class);
163         userManagerInternal = mock(UserManagerInternal.class);
164         usageStatsManagerInternal = mock(UsageStatsManagerInternal.class);
165         networkPolicyManagerInternal = mock(NetworkPolicyManagerInternal.class);
166 
167         userManagerForMock = mock(UserManagerForMock.class);
168         packageManagerInternal = mock(PackageManagerInternal.class);
169         packageManagerLocal = mock(PackageManagerLocal.class);
170         powerManager = mock(PowerManagerForMock.class);
171         powerManagerInternal = mock(PowerManagerInternal.class);
172         recoverySystem = mock(RecoverySystemForMock.class);
173         notificationManager = mock(NotificationManager.class);
174         iipConnectivityMetrics = mock(IIpConnectivityMetrics.class);
175         iwindowManager = mock(IWindowManager.class);
176         iactivityManager = mock(IActivityManager.class);
177         iactivityTaskManager = mock(IActivityTaskManager.class);
178         activityManagerInternal = mock(ActivityManagerInternal.class);
179         activityTaskManagerInternal = mock(ActivityTaskManagerInternal.class);
180         ipackageManager = mock(IPackageManager.class);
181         ipermissionManager = mock(IPermissionManager.class);
182         ibackupManager = mock(IBackupManager.class);
183         iaudioService = mock(IAudioService.class);
184         lockPatternUtils = mock(LockPatternUtils.class);
185         lockSettingsInternal = mock(LockSettingsInternal.class);
186         storageManager = mock(StorageManagerForMock.class);
187         wifiManager = mock(WifiManager.class);
188         settings = mock(SettingsForMock.class);
189         telephonyManager = mock(TelephonyManager.class);
190         connectivityManager = mock(ConnectivityManager.class);
191         accountManager = mock(AccountManager.class);
192         alarmManager = mock(AlarmManager.class);
193         alarmManagerInternal = mock(AlarmManagerInternal.class);
194         keyChainConnection = mock(KeyChain.KeyChainConnection.class, RETURNS_DEEP_STUBS);
195         crossProfileApps = mock(CrossProfileApps.class);
196         persistentDataBlockManagerInternal = mock(PersistentDataBlockManagerInternal.class);
197         appOpsManager = mock(AppOpsManager.class);
198         usbManager = mock(UsbManager.class);
199         vpnManager = mock(VpnManager.class);
200         devicePolicyManager = mock(DevicePolicyManager.class);
201         locationManager = mock(LocationManager.class);
202         roleManager = realContext.getSystemService(RoleManager.class);
203         subscriptionManager = mock(SubscriptionManager.class);
204 
205         // Package manager is huge, so we use a partial mock instead.
206         packageManager = spy(realContext.getPackageManager());
207         when(packageManagerInternal.getSystemUiServiceComponent()).thenReturn(
208                 new ComponentName("com.android.systemui", ".Service"));
209 
210         addTestPackageUid("android", DpmMockContext.SYSTEM_UID);
211         addTestPackageUid(realContext.getPackageName(), Binder.getCallingUid());
212         when(packageManagerLocal.withUnfilteredSnapshot()).thenAnswer(unused -> {
213             var snapshot = mock(PackageManagerLocal.UnfilteredSnapshot.class);
214             when(snapshot.getPackageStates()).thenAnswer(unused1 -> mTestPackageStates);
215             return snapshot;
216         });
217 
218         contentResolver = new MockContentResolver();
219         contentResolver.addProvider("telephony", new MockContentProvider(realContext) {
220             @Override
221             public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
222                 return 0;
223             }
224 
225             @Override
226             public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
227                     String sortOrder) {
228                 return null;
229             }
230 
231             @Override
232             public int delete(Uri uri, String selection, String[] selectionArgs) {
233                 return 0;
234             }
235         });
236         contentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
237 
238         // Add the system user with a fake profile group already set up (this can happen in the real
239         // world if a managed profile is added and then removed).
240         systemUserDataDir = addUser(UserHandle.USER_SYSTEM,
241                 UserInfo.FLAG_PRIMARY | UserInfo.FLAG_MAIN,
242                 UserManager.USER_TYPE_FULL_SYSTEM, UserHandle.USER_SYSTEM);
243         when(userManager.getMainUser()).thenReturn(UserHandle.SYSTEM);
244 
245         // System user is always running.
246         setUserRunning(UserHandle.USER_SYSTEM, true);
247         pathProvider = new PolicyPathProvider() {
248             @Override
249             public File getDataSystemDirectory() {
250                 return new File(systemUserDataDir.getAbsolutePath());
251             }
252 
253             @Override
254             public File getUserSystemDirectory(int userId) {
255                 return environment.getUserSystemDirectory(userId);
256             }
257         };
258     }
259 
260     /** Optional mapping of other user contexts for {@link #createPackageContextAsUser} to return */
261     private final Map<Pair<UserHandle, String>, Context> userPackageContexts = new ArrayMap<>();
262 
263     private final ArrayList<UserInfo> mUserInfos = new ArrayList<>();
264 
265     private final List<BroadcastReceiverRegistration> mBroadcastReceivers = new ArrayList<>();
266 
registerReceiver( BroadcastReceiver receiver, IntentFilter filter, Handler scheduler)267     public void registerReceiver(
268             BroadcastReceiver receiver, IntentFilter filter, Handler scheduler) {
269         mBroadcastReceivers.add(new BroadcastReceiverRegistration(receiver, filter, scheduler));
270     }
271 
unregisterReceiver(BroadcastReceiver receiver)272     public void unregisterReceiver(BroadcastReceiver receiver) {
273         mBroadcastReceivers.removeIf(r -> r.receiver == receiver);
274     }
275 
addUser(int userId, int flags, String type)276     public File addUser(int userId, int flags, String type) {
277         return addUser(userId, flags, type, UserInfo.NO_PROFILE_GROUP_ID);
278     }
279 
addUser(int userId, int flags, String type, int profileGroupId)280     public File addUser(int userId, int flags, String type, int profileGroupId) {
281         // Set up (default) UserInfo for CALLER_USER_HANDLE.
282         final UserInfo uh = new UserInfo(userId, "user" + userId, flags);
283 
284         uh.userType = type;
285         uh.profileGroupId = profileGroupId;
286         when(userManager.getUserInfo(eq(userId))).thenReturn(uh);
287         // Ensure there are no duplicate UserInfo records.
288         // TODO: fix tests so that this is not needed.
289         for (int i = 0; i < mUserInfos.size(); i++) {
290             if (mUserInfos.get(i).id == userId) {
291                 mUserInfos.remove(i);
292                 break;
293             }
294         }
295         mUserInfos.add(uh);
296         when(userManager.getUsers()).thenReturn(mUserInfos);
297         when(userManager.getAliveUsers()).thenReturn(mUserInfos);
298         when(userManager.isUserRunning(eq(new UserHandle(userId)))).thenReturn(true);
299         when(userManager.getProfileParent(anyInt())).thenAnswer(
300                 invocation -> {
301                     final int userId1 = (int) invocation.getArguments()[0];
302                     final UserInfo ui = getUserInfo(userId1);
303                     return ui == null ? null : getUserInfo(ui.profileGroupId);
304                 }
305         );
306         when(userManager.getProfileParent(any(UserHandle.class))).thenAnswer(
307                 invocation -> {
308                     final UserHandle userHandle = (UserHandle) invocation.getArguments()[0];
309                     final UserInfo ui = getUserInfo(userHandle.getIdentifier());
310                     return ui == null ? UserHandle.USER_NULL : UserHandle.of(ui.profileGroupId);
311                 }
312         );
313         when(userManager.getProfiles(anyInt())).thenAnswer(
314                 invocation -> {
315                     final int userId12 = (int) invocation.getArguments()[0];
316                     return getProfiles(userId12);
317                 }
318         );
319         when(userManager.getProfileIdsWithDisabled(anyInt())).thenAnswer(
320                 invocation -> {
321                     final int userId13 = (int) invocation.getArguments()[0];
322                     List<UserInfo> profiles = getProfiles(userId13);
323                     return profiles.stream()
324                             .mapToInt(profile -> profile.id)
325                             .toArray();
326                 }
327         );
328         when(userManagerInternal.getUserInfos()).thenReturn(
329                 mUserInfos.toArray(new UserInfo[mUserInfos.size()]));
330 
331         when(accountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]);
332 
333         // Create a data directory.
334         final File dir = new File(dataDir, "users/" + userId);
335         DpmTestUtils.clearDir(dir);
336 
337         when(environment.getUserSystemDirectory(eq(userId))).thenReturn(dir);
338         return dir;
339     }
340 
removeUser(int userId)341     public void removeUser(int userId) {
342         for (int i = 0; i < mUserInfos.size(); i++) {
343             if (mUserInfos.get(i).id == userId) {
344                 mUserInfos.remove(i);
345                 break;
346             }
347         }
348         when(userManager.getUserInfo(eq(userId))).thenReturn(null);
349 
350         when(userManager.isUserRunning(eq(new UserHandle(userId)))).thenReturn(false);
351     }
352 
getUserInfo(int userId)353     private UserInfo getUserInfo(int userId) {
354         for (final UserInfo ui : mUserInfos) {
355             if (ui.id == userId) {
356                 return ui;
357             }
358         }
359         return null;
360     }
361 
getProfiles(int userId)362     private List<UserInfo> getProfiles(int userId) {
363         final ArrayList<UserInfo> ret = new ArrayList<>();
364         UserInfo parent = null;
365         for (final UserInfo ui : mUserInfos) {
366             if (ui.id == userId) {
367                 parent = ui;
368                 break;
369             }
370         }
371         if (parent == null) {
372             return ret;
373         }
374         for (final UserInfo ui : mUserInfos) {
375             if (ui == parent
376                     || ui.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
377                     && ui.profileGroupId == parent.profileGroupId) {
378                 ret.add(ui);
379             }
380         }
381         return ret;
382     }
383 
384     /**
385      * Add multiple users at once.  They'll all have flag 0.
386      */
addUsers(int... userIds)387     public void addUsers(int... userIds) {
388         for (final int userId : userIds) {
389             addUser(userId, 0, "");
390         }
391     }
392 
setUserRunning(int userId, boolean isRunning)393     public void setUserRunning(int userId, boolean isRunning) {
394         when(userManager.isUserRunning(MockUtils.checkUserHandle(userId)))
395                 .thenReturn(isRunning);
396     }
397 
injectBroadcast(Context context, final Intent intent, int userId)398     public void injectBroadcast(Context context, final Intent intent, int userId) {
399         //final int userId = UserHandle.getUserId(binder.getCallingUid());
400         for (final BroadcastReceiverRegistration receiver : mBroadcastReceivers) {
401             receiver.sendBroadcastIfApplicable(context, userId, intent);
402         }
403     }
404 
rethrowBackgroundBroadcastExceptions()405     public void rethrowBackgroundBroadcastExceptions() throws Exception {
406         for (final BroadcastReceiverRegistration receiver : mBroadcastReceivers) {
407             final Exception e = receiver.backgroundException.getAndSet(null);
408             if (e != null) {
409                 throw e;
410             }
411         }
412     }
413 
addPackageContext(UserHandle user, Context context)414     public void addPackageContext(UserHandle user, Context context) {
415         if (context.getPackageName() == null) {
416             throw new NullPointerException("getPackageName() == null");
417         }
418         userPackageContexts.put(new Pair<>(user, context.getPackageName()), context);
419     }
420 
createPackageContextAsUser(String packageName, int flags, UserHandle user)421     public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
422             throws PackageManager.NameNotFoundException {
423         final Pair<UserHandle, String> key = new Pair<>(user, packageName);
424         if (userPackageContexts.containsKey(key)) {
425             return userPackageContexts.get(key);
426         }
427         throw new UnsupportedOperationException("No package " + packageName + " for user " + user);
428     }
429 
addTestPackageUid(@onNull String packageName, int uid)430     public void addTestPackageUid(@NonNull String packageName, int uid) {
431         var packageState = mock(PackageState.class);
432         when(packageState.getAppId()).thenReturn(UserHandle.getAppId(uid));
433         when(packageState.getUserStateOrDefault(anyInt())).thenAnswer(invocation -> {
434             var userState = mock(PackageUserState.class);
435             when(userState.isInstalled()).thenReturn(true);
436             return userState;
437         });
438         mTestPackageStates.put(packageName, packageState);
439     }
440 
441     public static class EnvironmentForMock {
getUserSystemDirectory(int userId)442         public File getUserSystemDirectory(int userId) {
443             return null;
444         }
445     }
446 
447     public static class BuildMock {
448         public boolean isDebuggable = true;
449     }
450 
451     public static class PowerManagerForMock {
newWakeLock(int levelAndFlags, String tag)452         public PowerManager.WakeLock newWakeLock(int levelAndFlags, String tag) {
453             return null;
454         }
455 
goToSleep(long time, int reason, int flags)456         public void goToSleep(long time, int reason, int flags) {
457         }
458 
reboot(String reason)459         public void reboot(String reason) {
460         }
461     }
462 
463     public static class RecoverySystemForMock {
rebootWipeUserData(boolean shutdown, String reason, boolean force, boolean wipeEuicc, boolean wipeExtRequested, boolean wipeResetProtectionData)464         public boolean rebootWipeUserData(boolean shutdown, String reason, boolean force,
465                 boolean wipeEuicc, boolean wipeExtRequested, boolean wipeResetProtectionData)
466                         throws IOException {
467             return false;
468         }
469     }
470 
471     public static class SystemPropertiesForMock {
getBoolean(String key, boolean def)472         public boolean getBoolean(String key, boolean def) {
473             return false;
474         }
475 
getLong(String key, long def)476         public long getLong(String key, long def) {
477             return 0;
478         }
479 
get(String key, String def)480         public String get(String key, String def) {
481             return null;
482         }
483 
get(String key)484         public String get(String key) {
485             return null;
486         }
487 
set(String key, String value)488         public void set(String key, String value) {
489         }
490     }
491 
492     public static class UserManagerForMock {
isHeadlessSystemUserMode()493         public boolean isHeadlessSystemUserMode() {
494             return false;
495         }
496     }
497 
498     public static class SettingsForMock {
settingsSecureGetIntForUser(String name, int def, int userHandle)499         public int settingsSecureGetIntForUser(String name, int def, int userHandle) {
500             return 0;
501         }
502 
settingsSecureGetStringForUser(String name, int userHandle)503         public String settingsSecureGetStringForUser(String name, int userHandle) {
504             return null;
505         }
506 
settingsSecurePutIntForUser(String name, int value, int userHandle)507         public void settingsSecurePutIntForUser(String name, int value, int userHandle) {
508         }
509 
settingsSecurePutStringForUser(String name, String value, int userHandle)510         public void settingsSecurePutStringForUser(String name, String value, int userHandle) {
511         }
512 
settingsGlobalPutStringForUser(String name, String value, int userHandle)513         public void settingsGlobalPutStringForUser(String name, String value, int userHandle) {
514         }
515 
settingsSecurePutInt(String name, int value)516         public void settingsSecurePutInt(String name, int value) {
517         }
518 
settingsGlobalPutInt(String name, int value)519         public void settingsGlobalPutInt(String name, int value) {
520         }
521 
settingsSecurePutString(String name, String value)522         public void settingsSecurePutString(String name, String value) {
523         }
524 
settingsGlobalPutString(String name, String value)525         public void settingsGlobalPutString(String name, String value) {
526         }
527 
settingsSystemPutStringForUser(String name, String value, int callingUserId)528         public void settingsSystemPutStringForUser(String name, String value, int callingUserId) {
529         }
530 
settingsGlobalGetInt(String name, int value)531         public int settingsGlobalGetInt(String name, int value) {
532             return 0;
533         }
534 
settingsGlobalGetString(String name)535         public String settingsGlobalGetString(String name) {
536             return "";
537         }
538 
securityLogSetLoggingEnabledProperty(boolean enabled)539         public void securityLogSetLoggingEnabledProperty(boolean enabled) {
540         }
541 
securityLogGetLoggingEnabledProperty()542         public boolean securityLogGetLoggingEnabledProperty() {
543             return false;
544         }
545 
securityLogIsLoggingEnabled()546         public boolean securityLogIsLoggingEnabled() {
547             return false;
548         }
549     }
550 
551     public static class StorageManagerForMock {
isFileBasedEncryptionEnabled()552         public boolean isFileBasedEncryptionEnabled() {
553             return false;
554         }
555     }
556 
557     // We have to keep track of broadcast receivers registered for a given intent ourselves as the
558     // DPM unit tests mock out the package manager and PackageManager.queryBroadcastReceivers() does
559     // not work.
560     private static class BroadcastReceiverRegistration {
561         public final BroadcastReceiver receiver;
562         public final IntentFilter filter;
563         public final Handler scheduler;
564 
565         // Exceptions thrown in a background thread kill the whole test. Save them instead.
566         public final AtomicReference<Exception> backgroundException = new AtomicReference<>();
567 
BroadcastReceiverRegistration(BroadcastReceiver receiver, IntentFilter filter, Handler scheduler)568         public BroadcastReceiverRegistration(BroadcastReceiver receiver, IntentFilter filter,
569                 Handler scheduler) {
570             this.receiver = receiver;
571             this.filter = filter;
572             this.scheduler = scheduler;
573         }
574 
sendBroadcastIfApplicable(Context context, int userId, Intent intent)575         public void sendBroadcastIfApplicable(Context context, int userId, Intent intent) {
576             final BroadcastReceiver.PendingResult result = new BroadcastReceiver.PendingResult(
577                     0 /* resultCode */, null /* resultData */, null /* resultExtras */,
578                     0 /* type */, false /* ordered */, false /* sticky */, null /* token */, userId,
579                     0 /* flags */);
580             if (filter.match(null, intent, false, "DpmMockContext") > 0) {
581                 final Runnable send = () -> {
582                     receiver.setPendingResult(result);
583                     receiver.onReceive(context, intent);
584                 };
585                 if (scheduler != null) {
586                     scheduler.post(() -> {
587                         try {
588                             send.run();
589                         } catch (Exception e) {
590                             backgroundException.compareAndSet(null, e);
591                         }
592                     });
593                 } else {
594                     send.run();
595                 }
596             }
597         }
598     }
599 }
600