Loading tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java +231 −3 Original line number Diff line number Diff line Loading @@ -26,20 +26,34 @@ import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.when; import android.app.AppOpsManager; import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.provider.DeviceConfig; import android.provider.Settings; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.test.mock.MockContentProvider; import android.test.mock.MockContentResolver; import android.test.suitebuilder.annotation.SmallTest; import com.android.internal.util.test.FakeSettingsProvider; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.lang.reflect.Field; @SmallTest public class TelephonyPermissionsTest { private static final int SUB_ID = 55555; private static final int SUB_ID_2 = 22222; private static final int PID = 12345; private static final int UID = 54321; private static final String PACKAGE = "com.example"; Loading @@ -50,17 +64,28 @@ public class TelephonyPermissionsTest { @Mock private AppOpsManager mMockAppOps; @Mock private SubscriptionManager mMockSubscriptionMananger; private SubscriptionManager mMockSubscriptionManager; @Mock private ITelephony mMockTelephony; @Mock private PackageManager mMockPackageManager; @Mock private ApplicationInfo mMockApplicationInfo; @Mock private DevicePolicyManager mMockDevicePolicyManager; private MockContentResolver mMockContentResolver; private FakeSettingsConfigProvider mFakeSettingsConfigProvider; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mMockAppOps); when(mMockContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)).thenReturn( mMockSubscriptionMananger); when(mMockSubscriptionMananger.getActiveSubscriptionIdList()).thenReturn(new int[]{SUB_ID}); mMockSubscriptionManager); when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn( mMockDevicePolicyManager); when(mMockSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[]{SUB_ID}); // By default, assume we have no permissions or app-ops bits. doThrow(new SecurityException()).when(mMockContext) Loading @@ -69,8 +94,14 @@ public class TelephonyPermissionsTest { .enforcePermission(anyString(), eq(PID), eq(UID), eq(MSG)); when(mMockAppOps.noteOp(anyInt(), eq(UID), eq(PACKAGE))) .thenReturn(AppOpsManager.MODE_ERRORED); when(mMockAppOps.noteOpNoThrow(anyString(), eq(UID), eq(PACKAGE))).thenReturn( AppOpsManager.MODE_ERRORED); when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID), eq(UID))) .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS); when(mMockContext.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, PID, UID)).thenReturn(PackageManager.PERMISSION_DENIED); when(mMockDevicePolicyManager.checkDeviceIdentifierAccess(eq(PACKAGE), eq(PID), eq(UID))).thenReturn(false); } @Test Loading Loading @@ -204,4 +235,201 @@ public class TelephonyPermissionsTest { assertTrue(TelephonyPermissions.checkReadPhoneNumber( mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_noPermissions() throws Exception { setupMocksForDeviceIdentifiersErrorPath(); try { TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG); fail("Should have thrown SecurityException"); } catch (SecurityException e) { // expected } } @Test public void testCheckReadDeviceIdentifiers_hasPrivilegedPermission() { when(mMockContext.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, PID, UID)).thenReturn(PackageManager.PERMISSION_GRANTED); assertTrue( TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_hasCarrierPrivileges() throws Exception { when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID), eq(UID))) .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS); assertTrue( TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_hasAppOp() { when(mMockAppOps.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, UID, PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED); assertTrue( TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_hasDPMDeviceIDAccess() { when(mMockDevicePolicyManager.checkDeviceIdentifierAccess(eq(PACKAGE), eq(PID), eq(UID))).thenReturn(true); assertTrue( TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_hasReadPhoneStateTargetQ() throws Exception { // if an app is targeting Q and does not meet the new requirements for device identifier // access then a SecurityException should be thrown even if the app has been granted the // READ_PHONE_STATE permission. when(mMockContext.checkPermission(android.Manifest.permission.READ_PHONE_STATE, PID, UID)).thenReturn(PackageManager.PERMISSION_GRANTED); setupMocksForDeviceIdentifiersErrorPath(); try { TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG); fail("Should have thrown SecurityException"); } catch (SecurityException e) { // expected } } @Test public void testCheckReadDeviceIdentifiers_hasReadPhoneStateTargetPreQ() throws Exception { // To prevent breaking existing apps if an app is targeting pre-Q and has been granted the // READ_PHONE_STATE permission then checkReadDeviceIdentifiers should return false to // indicate the caller should return null / placeholder data. when(mMockContext.checkPermission(android.Manifest.permission.READ_PHONE_STATE, PID, UID)).thenReturn(PackageManager.PERMISSION_GRANTED); setupMocksForDeviceIdentifiersErrorPath(); mMockApplicationInfo.targetSdkVersion = Build.VERSION_CODES.P; assertFalse( TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_hasCarrierPrivilegesOnOtherSubscription() throws Exception { when(mMockSubscriptionManager.getActiveSubscriptionIdList()).thenReturn( new int[]{SUB_ID, SUB_ID_2}); when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID_2), eq(UID))).thenReturn( TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS); assertTrue( TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_hasAppOpNullSubscription() { // The appop check comes after the carrier privilege check; this test verifies if the // SubscriptionManager returns a null array for the active subscription IDs this check can // still proceed to check if the calling package has the appop and any subsequent checks // without a NullPointerException. when(mMockSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(null); when(mMockAppOps.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, UID, PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED); assertTrue( TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_nullPackageName() throws Exception { // If a null package name is passed in then the AppOp and DevicePolicyManager checks cannot // be performed, but an app targeting Q should still receive a SecurityException in this // case. setupMocksForDeviceIdentifiersErrorPath(); try { TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, null, MSG); fail("Should have thrown SecurityException"); } catch (SecurityException e) { // expected } } public static class FakeSettingsConfigProvider extends FakeSettingsProvider { private static final String PROPERTY_DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_DISABLED = DeviceConfig.NAMESPACE_PRIVACY + "/" + "device_identifier_access_restrictions_disabled"; @Override public Bundle call(String method, String arg, Bundle extras) { switch (method) { case Settings.CALL_METHOD_GET_CONFIG: { switch (arg) { case PROPERTY_DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_DISABLED: { Bundle bundle = new Bundle(); bundle.putString( PROPERTY_DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_DISABLED, "0"); return bundle; } default: { fail("arg not expected: " + arg); } } break; } // If this is not a get call for Settings.Config then use the FakeSettingsProvider's // call method. default: return super.call(method, arg, extras); } return null; } } protected void setupMocksForDeviceIdentifiersErrorPath() throws Exception { // If the calling package does not meet the new requirements for device identifier access // TelephonyPermissions will query the PackageManager for the ApplicationInfo of the package // to determine the target SDK. For apps targeting Q a SecurityException is thrown // regardless of if the package satisfies the previous requirements for device ID access. mMockApplicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); when(mMockPackageManager.getApplicationInfoAsUser(eq(PACKAGE), anyInt(), anyInt())).thenReturn(mMockApplicationInfo); when(mMockContext.checkCallingOrSelfPermission( android.Manifest.permission.READ_DEVICE_CONFIG)).thenReturn( PackageManager.PERMISSION_GRANTED); // TelephonyPermissions queries DeviceConfig to determine if the identifier access // restrictions should be enabled; since DeviceConfig uses // Activity.currentActivity.getContentResolver as the resolver for Settings.Config.getString // the READ_DEVICE_CONFIG permission check cannot be mocked, so replace the IContentProvider // in the NameValueCache's provider holder with that from the fake provider. mFakeSettingsConfigProvider = new FakeSettingsConfigProvider(); mMockContentResolver = new MockContentResolver(); mMockContentResolver.addProvider(Settings.AUTHORITY, mFakeSettingsConfigProvider); when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver); Class c = Class.forName("android.provider.Settings$Config"); Field field = c.getDeclaredField("sNameValueCache"); field.setAccessible(true); Object cache = field.get(null); c = Class.forName("android.provider.Settings$NameValueCache"); field = c.getDeclaredField("mProviderHolder"); field.setAccessible(true); Object providerHolder = field.get(cache); field = MockContentProvider.class.getDeclaredField("mIContentProvider"); field.setAccessible(true); Object iContentProvider = field.get(mFakeSettingsConfigProvider); c = Class.forName("android.provider.Settings$ContentProviderHolder"); field = c.getDeclaredField("mContentProvider"); field.setAccessible(true); field.set(providerHolder, iContentProvider); } } Loading
tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java +231 −3 Original line number Diff line number Diff line Loading @@ -26,20 +26,34 @@ import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.when; import android.app.AppOpsManager; import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.provider.DeviceConfig; import android.provider.Settings; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.test.mock.MockContentProvider; import android.test.mock.MockContentResolver; import android.test.suitebuilder.annotation.SmallTest; import com.android.internal.util.test.FakeSettingsProvider; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.lang.reflect.Field; @SmallTest public class TelephonyPermissionsTest { private static final int SUB_ID = 55555; private static final int SUB_ID_2 = 22222; private static final int PID = 12345; private static final int UID = 54321; private static final String PACKAGE = "com.example"; Loading @@ -50,17 +64,28 @@ public class TelephonyPermissionsTest { @Mock private AppOpsManager mMockAppOps; @Mock private SubscriptionManager mMockSubscriptionMananger; private SubscriptionManager mMockSubscriptionManager; @Mock private ITelephony mMockTelephony; @Mock private PackageManager mMockPackageManager; @Mock private ApplicationInfo mMockApplicationInfo; @Mock private DevicePolicyManager mMockDevicePolicyManager; private MockContentResolver mMockContentResolver; private FakeSettingsConfigProvider mFakeSettingsConfigProvider; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mMockAppOps); when(mMockContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)).thenReturn( mMockSubscriptionMananger); when(mMockSubscriptionMananger.getActiveSubscriptionIdList()).thenReturn(new int[]{SUB_ID}); mMockSubscriptionManager); when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn( mMockDevicePolicyManager); when(mMockSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[]{SUB_ID}); // By default, assume we have no permissions or app-ops bits. doThrow(new SecurityException()).when(mMockContext) Loading @@ -69,8 +94,14 @@ public class TelephonyPermissionsTest { .enforcePermission(anyString(), eq(PID), eq(UID), eq(MSG)); when(mMockAppOps.noteOp(anyInt(), eq(UID), eq(PACKAGE))) .thenReturn(AppOpsManager.MODE_ERRORED); when(mMockAppOps.noteOpNoThrow(anyString(), eq(UID), eq(PACKAGE))).thenReturn( AppOpsManager.MODE_ERRORED); when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID), eq(UID))) .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS); when(mMockContext.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, PID, UID)).thenReturn(PackageManager.PERMISSION_DENIED); when(mMockDevicePolicyManager.checkDeviceIdentifierAccess(eq(PACKAGE), eq(PID), eq(UID))).thenReturn(false); } @Test Loading Loading @@ -204,4 +235,201 @@ public class TelephonyPermissionsTest { assertTrue(TelephonyPermissions.checkReadPhoneNumber( mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_noPermissions() throws Exception { setupMocksForDeviceIdentifiersErrorPath(); try { TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG); fail("Should have thrown SecurityException"); } catch (SecurityException e) { // expected } } @Test public void testCheckReadDeviceIdentifiers_hasPrivilegedPermission() { when(mMockContext.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, PID, UID)).thenReturn(PackageManager.PERMISSION_GRANTED); assertTrue( TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_hasCarrierPrivileges() throws Exception { when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID), eq(UID))) .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS); assertTrue( TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_hasAppOp() { when(mMockAppOps.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, UID, PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED); assertTrue( TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_hasDPMDeviceIDAccess() { when(mMockDevicePolicyManager.checkDeviceIdentifierAccess(eq(PACKAGE), eq(PID), eq(UID))).thenReturn(true); assertTrue( TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_hasReadPhoneStateTargetQ() throws Exception { // if an app is targeting Q and does not meet the new requirements for device identifier // access then a SecurityException should be thrown even if the app has been granted the // READ_PHONE_STATE permission. when(mMockContext.checkPermission(android.Manifest.permission.READ_PHONE_STATE, PID, UID)).thenReturn(PackageManager.PERMISSION_GRANTED); setupMocksForDeviceIdentifiersErrorPath(); try { TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG); fail("Should have thrown SecurityException"); } catch (SecurityException e) { // expected } } @Test public void testCheckReadDeviceIdentifiers_hasReadPhoneStateTargetPreQ() throws Exception { // To prevent breaking existing apps if an app is targeting pre-Q and has been granted the // READ_PHONE_STATE permission then checkReadDeviceIdentifiers should return false to // indicate the caller should return null / placeholder data. when(mMockContext.checkPermission(android.Manifest.permission.READ_PHONE_STATE, PID, UID)).thenReturn(PackageManager.PERMISSION_GRANTED); setupMocksForDeviceIdentifiersErrorPath(); mMockApplicationInfo.targetSdkVersion = Build.VERSION_CODES.P; assertFalse( TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_hasCarrierPrivilegesOnOtherSubscription() throws Exception { when(mMockSubscriptionManager.getActiveSubscriptionIdList()).thenReturn( new int[]{SUB_ID, SUB_ID_2}); when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID_2), eq(UID))).thenReturn( TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS); assertTrue( TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_hasAppOpNullSubscription() { // The appop check comes after the carrier privilege check; this test verifies if the // SubscriptionManager returns a null array for the active subscription IDs this check can // still proceed to check if the calling package has the appop and any subsequent checks // without a NullPointerException. when(mMockSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(null); when(mMockAppOps.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, UID, PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED); assertTrue( TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, PACKAGE, MSG)); } @Test public void testCheckReadDeviceIdentifiers_nullPackageName() throws Exception { // If a null package name is passed in then the AppOp and DevicePolicyManager checks cannot // be performed, but an app targeting Q should still receive a SecurityException in this // case. setupMocksForDeviceIdentifiersErrorPath(); try { TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony, SUB_ID, PID, UID, null, MSG); fail("Should have thrown SecurityException"); } catch (SecurityException e) { // expected } } public static class FakeSettingsConfigProvider extends FakeSettingsProvider { private static final String PROPERTY_DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_DISABLED = DeviceConfig.NAMESPACE_PRIVACY + "/" + "device_identifier_access_restrictions_disabled"; @Override public Bundle call(String method, String arg, Bundle extras) { switch (method) { case Settings.CALL_METHOD_GET_CONFIG: { switch (arg) { case PROPERTY_DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_DISABLED: { Bundle bundle = new Bundle(); bundle.putString( PROPERTY_DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_DISABLED, "0"); return bundle; } default: { fail("arg not expected: " + arg); } } break; } // If this is not a get call for Settings.Config then use the FakeSettingsProvider's // call method. default: return super.call(method, arg, extras); } return null; } } protected void setupMocksForDeviceIdentifiersErrorPath() throws Exception { // If the calling package does not meet the new requirements for device identifier access // TelephonyPermissions will query the PackageManager for the ApplicationInfo of the package // to determine the target SDK. For apps targeting Q a SecurityException is thrown // regardless of if the package satisfies the previous requirements for device ID access. mMockApplicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); when(mMockPackageManager.getApplicationInfoAsUser(eq(PACKAGE), anyInt(), anyInt())).thenReturn(mMockApplicationInfo); when(mMockContext.checkCallingOrSelfPermission( android.Manifest.permission.READ_DEVICE_CONFIG)).thenReturn( PackageManager.PERMISSION_GRANTED); // TelephonyPermissions queries DeviceConfig to determine if the identifier access // restrictions should be enabled; since DeviceConfig uses // Activity.currentActivity.getContentResolver as the resolver for Settings.Config.getString // the READ_DEVICE_CONFIG permission check cannot be mocked, so replace the IContentProvider // in the NameValueCache's provider holder with that from the fake provider. mFakeSettingsConfigProvider = new FakeSettingsConfigProvider(); mMockContentResolver = new MockContentResolver(); mMockContentResolver.addProvider(Settings.AUTHORITY, mFakeSettingsConfigProvider); when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver); Class c = Class.forName("android.provider.Settings$Config"); Field field = c.getDeclaredField("sNameValueCache"); field.setAccessible(true); Object cache = field.get(null); c = Class.forName("android.provider.Settings$NameValueCache"); field = c.getDeclaredField("mProviderHolder"); field.setAccessible(true); Object providerHolder = field.get(cache); field = MockContentProvider.class.getDeclaredField("mIContentProvider"); field.setAccessible(true); Object iContentProvider = field.get(mFakeSettingsConfigProvider); c = Class.forName("android.provider.Settings$ContentProviderHolder"); field = c.getDeclaredField("mContentProvider"); field.setAccessible(true); field.set(providerHolder, iContentProvider); } }