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