condom.getBaseContext(); Object[] data = readLastEvent(CondomCore.CondomEvent.CONCERN); assertEquals(condom.getPackageName(), data[0]); assertEquals(condom.TAG, data[1]); assertEquals("getBaseContext", data[2]); assertCallerMatch(data); ((Application) condom.getApplicationContext()).getBaseContext(); data = readLastEvent(CondomCore.CondomEvent.CONCERN); assertEquals("Application.getBaseContext", data[2]); assertCallerMatch(data); condom.getPackageManager().getInstalledApplications(0); data = readLastEvent(CondomCore.CondomEvent.CONCERN); assertEquals("PackageManager.getInstalledApplications", data[2]); assertCallerMatch(data); condom.getPackageManager().getInstalledPackages(0); data = readLastEvent(CondomCore.CondomEvent.CONCERN); assertEquals("PackageManager.getInstalledPackages", data[2]); condom.bindService(intent, SERVICE_CONNECTION, 0); data = readLastEvent(CondomCore.CondomEvent.BIND_PASS); assertEquals(condom.getPackageName(), data[0]); assertEquals("Condom." + TAG, data[1]); assertEquals(intent.getPackage(), data[2]); assertEquals(intent.toString(), data[3]); condom.startService(intent);
/** * This is the very first (probably only) API you need to wrap the naked {@link Context} under protection of <code>CondomContext</code> * * @param base the original context used before <code>CondomContext</code> is introduced. * @param tag the optional tag to distinguish between multiple instances of <code>CondomContext</code> used parallel. */ public static @CheckResult CondomContext wrap(final Context base, final @Nullable @Size(max=13) String tag, final CondomOptions options) { if (base instanceof CondomContext) { final CondomContext condom = ((CondomContext) base); Log.w("Condom", "The wrapped context is already a CondomContext (tag: " + condom.TAG + "), tag and options specified here will be ignore."); return condom; } final Context app_context = base.getApplicationContext(); final CondomCore condom = new CondomCore(base, options, CondomCore.buildLogTag("Condom", "Condom.", tag)); if (app_context instanceof Application) { // The application context is indeed an Application, this should be preserved semantically. final Application app = (Application) app_context; final CondomApplication condom_app = new CondomApplication(condom, app, tag); // TODO: Application instance should be unique across CondomContext. final CondomContext condom_context = new CondomContext(condom, condom_app, tag); condom_app.attachBaseContext(base == app_context ? condom_context : new CondomContext(condom, app, tag)); return condom_context; } else return new CondomContext(condom, base == app_context ? null : new CondomContext(condom, app_context, tag), tag); }
@Test public void testBasicKit() throws ReflectiveOperationException, NameNotFoundException { final ActivityManager am = createActivityManager(context); final CondomOptions option = new CondomOptions().addKit(new CondomKit() { @Override public void onRegister(final CondomKitRegistry registry) { registry.registerSystemService(Context.ACTIVITY_SERVICE, new SystemServiceSupplier() { @Override public Object getSystemService(final Context context, final String name) { return am; }}); registry.addPermissionSpoof(WRITE_SETTINGS); registry.addPermissionSpoof(ACCESS_COARSE_LOCATION); }}); final CondomContext condom = CondomContext.wrap(new ContextWrapper(context), "KitTest", option); assertEquals(am, condom.getSystemService(Context.ACTIVITY_SERVICE)); assertEquals(am, condom.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE)); Assert.assertNotNull(condom.getSystemService(Context.NOTIFICATION_SERVICE)); // Service not registered in kit assertPermission(condom, WRITE_SETTINGS, true); assertPermission(condom.getApplicationContext(), WRITE_SETTINGS, true); assertPermission(condom, ACCESS_COARSE_LOCATION, true); assertPermission(condom.getApplicationContext(), ACCESS_COARSE_LOCATION, true); assertPermission(condom, WRITE_SECURE_SETTINGS, false); // Permission not registered to spoof in kit assertPermission(condom.getApplicationContext(), WRITE_SECURE_SETTINGS, false); }
@Test public void testNonApplicationAsApplicationContextOfBaseContext() throws Exception { final Context context = InstrumentationRegistry.getTargetContext(); final ContextWrapper context_wo_app = new ContextWrapper(context) { @Override public Context getApplicationContext() { return new ContextWrapper(context); } }; final CondomContext condom_context = CondomContext.wrap(context_wo_app, TAG); final Context condom_app_context = condom_context.getApplicationContext(); assertFalse(condom_app_context instanceof Application); assertTrue(condom_app_context instanceof CondomContext); }
@Test public void testPreventNone() { final TestContext context = new TestContext(); final CondomOptions options = new CondomOptions().preventServiceInBackgroundPackages(false).preventBroadcastToBackgroundPackages(false); final CondomContext condom = CondomContext.wrap(context, TAG, options), dry_condom = CondomContext.wrap(context, TAG, options.setDryRun(true)); //noinspection deprecation, intentional test for deprecated method condom.preventWakingUpStoppedPackages(false); //noinspection deprecation dry_condom.preventWakingUpStoppedPackages(false); for (final Context context2test : new Context[] {condom, condom.getApplicationContext(), dry_condom, dry_condom.getApplicationContext()}) with(ALL_SORT_OF_INTENTS, allBroadcastAndServiceApis(context2test), context.EXPECT_BASE_CALLED, context.expectFlags(0)); }
@Test public void testSelfTargeted() { final TestContext context = new TestContext(); final CondomContext condom = CondomContext.wrap(context, TAG), dry_condom = CondomContext.wrap(context, TAG, new CondomOptions().setDryRun(true)); // Self-targeting test final String self_pkg = condom.getPackageName(); final Intent[] self_targeted_intents = new Intent[] { intent().setPackage(self_pkg), intent().setComponent(new ComponentName(self_pkg, "X")) }; for (final Context context2test : new Context[] {condom, condom.getApplicationContext(), dry_condom, dry_condom.getApplicationContext()}) with(self_targeted_intents, allBroadcastAndServiceApis(context2test), context.EXPECT_BASE_CALLED, context.expectFlags(0)); }
final CondomContext condom = CondomContext.wrap(context, TAG, options), dry_condom = CondomContext.wrap(context, TAG, options.setDryRun(true)); assertOutboundJudgeCalled(1); }}; for (final Context context2test : new Context[] {condom, condom.getApplicationContext()}) with(DISALLOWED_INTENTS, allBroadcastApis(context2test), EXPECT_OUTBOUND_JUDGE_REFUSAL); for (final Context context2test : new Context[] {dry_condom, dry_condom.getApplicationContext()}) with(DISALLOWED_INTENTS, allBroadcastApis(context2test), EXPECT_OUTBOUND_JUDGE_PASS); for (final Context context2test : new Context[] {condom, condom.getApplicationContext(), dry_condom, dry_condom.getApplicationContext()}) with(ALLOWED_INTENTS, allBroadcastApis(context2test), EXPECT_OUTBOUND_JUDGE_PASS); final PackageManager pm = condom.getPackageManager(), dry_pm = dry_condom.getPackageManager(); assertNull(pm.resolveService(intent().setPackage(DISALLOWED_PACKAGE), 0)); context.assertBaseNotCalled(); assertOutboundJudgeCalled(2); condom.sendBroadcast(intent()); context.assertBaseCalled(); assertOutboundJudgeCalled(0); dry_condom.sendBroadcast(intent()); context.assertBaseCalled(); assertOutboundJudgeCalled(0);
public static @CheckResult CondomContext wrap(final Context base, final @Nullable @Size(max=13) String tag) { return wrap(base, tag, new CondomOptions()); }
@Test public void testContentProviderOutboundJudge() { final TestContext context = new TestContext(); final CondomOptions options = new CondomOptions().setOutboundJudge(new OutboundJudge() { @Override public boolean shouldAllow(final OutboundType type, final @Nullable Intent intent, final String target_pkg) { final String settings_pkg = InstrumentationRegistry.getTargetContext().getPackageManager().resolveContentProvider(Settings.System.CONTENT_URI.getAuthority(), 0).packageName; return ! settings_pkg.equals(target_pkg); }}); final CondomContext condom = CondomContext.wrap(context, TAG, options), dry_condom = CondomContext.wrap(context, TAG, options.setDryRun(true)); assertNull(condom.getPackageManager().resolveContentProvider(Settings.AUTHORITY, 0)); assertNotNull(dry_condom.getPackageManager().resolveContentProvider(Settings.AUTHORITY, 0)); assertNull(condom.getContentResolver().acquireContentProviderClient(Settings.System.CONTENT_URI)); assertNotNull(dry_condom.getContentResolver().acquireContentProviderClient(Settings.System.CONTENT_URI)); }
final CondomContext condom = CondomContext.wrap(context, TAG, options), dry_condom = CondomContext.wrap(context, TAG, options.setDryRun(true)); final PackageManager pm = condom.getPackageManager(), dry_pm = dry_condom.getPackageManager(); assertOutboundJudgeCalled(2); condom.sendBroadcast(intent()); context.assertBaseCalled(); assertOutboundJudgeCalled(0); dry_condom.sendBroadcast(intent()); context.assertBaseCalled(); assertOutboundJudgeCalled(0);
@Test public void testSelfTargeted() { final TestContext context = new TestContext(); final CondomContext condom = CondomContext.wrap(context, TAG), dry_condom = CondomContext.wrap(context, TAG, new CondomOptions().setDryRun(true)); // Self-targeting test final String self_pkg = condom.getPackageName(); final Intent[] self_targeted_intents = new Intent[] { intent().setPackage(self_pkg), intent().setComponent(new ComponentName(self_pkg, "X")) }; with(self_targeted_intents, allBroadcastApis(condom), context.EXPECT_BASE_CALLED, context.expectFlags(0)); with(self_targeted_intents, allServiceApis(condom), context.EXPECT_BASE_CALLED, context.expectFlags(0)); with(self_targeted_intents, allBroadcastApis(dry_condom), context.EXPECT_BASE_CALLED, context.expectFlags(0)); with(self_targeted_intents, allServiceApis(dry_condom), context.EXPECT_BASE_CALLED, context.expectFlags(0)); }
@Test public void testPreventServiceInBackgroundPackages() { final TestContext context = new TestContext(); context.mTestingBackgroundUid = true; final CondomOptions options = new CondomOptions().preventServiceInBackgroundPackages(true).preventBroadcastToBackgroundPackages(false); final CondomContext condom = CondomContext.wrap(context, TAG, options), dry_condom = CondomContext.wrap(context, TAG, options.setDryRun(true)); assertEquals(3, condom.getPackageManager().queryIntentServices(intent(), 0).size()); context.assertBaseCalled(); assertEquals(4, dry_condom.getPackageManager().queryIntentServices(intent(), 0).size()); context.assertBaseCalled(); assertEquals("non.bg.service", condom.getPackageManager().resolveService(intent(), 0).serviceInfo.packageName); context.assertBaseCalled(); assertEquals(7777777, dry_condom.getPackageManager().resolveService(intent(), 0).serviceInfo.applicationInfo.uid); context.assertBaseCalled(); }
@Test public void testPreventNone() { final TestContext context = new TestContext(); final CondomOptions options = new CondomOptions().preventServiceInBackgroundPackages(false).preventBroadcastToBackgroundPackages(false); final CondomContext condom = CondomContext.wrap(context, TAG, options), dry_condom = CondomContext.wrap(context, TAG, options.setDryRun(true)); //noinspection deprecation, intentional test for deprecated method condom.preventWakingUpStoppedPackages(false); //noinspection deprecation dry_condom.preventWakingUpStoppedPackages(false); with(ALL_SORT_OF_INTENTS, allBroadcastApis(condom), context.EXPECT_BASE_CALLED, context.expectFlags(0)); with(ALL_SORT_OF_INTENTS, allServiceApis(condom), context.EXPECT_BASE_CALLED, context.expectFlags(0)); with(ALL_SORT_OF_INTENTS, allBroadcastApis(dry_condom), context.EXPECT_BASE_CALLED, context.expectFlags(0)); with(ALL_SORT_OF_INTENTS, allServiceApis(dry_condom), context.EXPECT_BASE_CALLED, context.expectFlags(0)); }
@Test public void testHiddenApi() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { final Object uid = PackageManager.class.getMethod("getUidForSharedUser", String.class).invoke(condom.getPackageManager(),"android.uid.system"); assertEquals(1000, (int) uid); // This hidden API is used by some 3rd-party libraries, as reported in issue #9 on GitHub. if (SDK_INT >= LOLLIPOP) PackageManager.class.getMethod("getUserBadgeForDensity", UserHandle.class, int.class) .invoke(condom.getPackageManager(), Process.myUserHandle(), DisplayMetrics.DENSITY_DEFAULT); }
@Override public PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException { PackageInfo info = super.getPackageInfo(applyRedirect(packageName) , flags); if (getPackageName().equals(packageName)) { return FakeManifestUtils.buildFakePackageInfo(info); } return info; }
tests.add(new Consumer<Intent>() { @Override public void accept(final Intent intent) { condom.sendBroadcast(intent); }}); tests.add(new Consumer<Intent>() { @Override public void accept(final Intent intent) { condom.sendBroadcast(intent, permission.DUMP); }});
}}, new Consumer<Intent>() { @Override public void accept(final Intent intent) { condom.bindService(intent, SERVICE_CONNECTION, 0); }} };
@Test public void testNonApplicationRootContextAsBaseContext() throws Exception { final Context context = InstrumentationRegistry.getTargetContext(); final ContextWrapper context_wo_app = new ContextWrapper(context) { @Override public Context getApplicationContext() { return this; } }; final CondomContext condom_context = CondomContext.wrap(context_wo_app, TAG); final Context condom_app_context = condom_context.getApplicationContext(); assertFalse(condom_app_context instanceof Application); assertEquals(condom_context, condom_app_context); }
public static @CheckResult CondomContext wrap(final Context base, final @Nullable @Size(max=13) String tag) { return wrap(base, tag, new CondomOptions()); }
@Test public void testContentProvider() { final TestContext context = new TestContext(); final CondomContext condom = CondomContext.wrap(context, TAG), dry_condom = CondomContext.wrap(context, TAG, new CondomOptions().setDryRun(true)); // Regular provider access final String android_id = Settings.System.getString(context.getContentResolver(), Settings.System.ANDROID_ID); assertNotNull(android_id); final String condom_android_id = Settings.System.getString(condom.getContentResolver(), Settings.System.ANDROID_ID); assertEquals(android_id, condom_android_id); final String dry_android_id = Settings.System.getString(dry_condom.getContentResolver(), Settings.System.ANDROID_ID); assertEquals(android_id, dry_android_id); context.mTestingStoppedProvider = true; // Prevent stopped packages, assertNull(condom.getPackageManager().resolveContentProvider(TEST_AUTHORITY, 0)); assertNotNull(dry_condom.getPackageManager().resolveContentProvider(TEST_AUTHORITY, 0)); assertNull(condom.getContentResolver().acquireContentProviderClient(TEST_CONTENT_URI)); assertNotNull(dry_condom.getContentResolver().acquireContentProviderClient(TEST_CONTENT_URI)); // Providers in system package should not be blocked. assertNotNull(condom.getPackageManager().resolveContentProvider(Settings.AUTHORITY, 0)); assertNotNull(dry_condom.getPackageManager().resolveContentProvider(Settings.AUTHORITY, 0)); assertNotNull(condom.getContentResolver().acquireContentProviderClient(Settings.System.CONTENT_URI)); assertNotNull(dry_condom.getContentResolver().acquireContentProviderClient(Settings.System.CONTENT_URI)); context.mTestingStoppedProvider = false; } private static final String TEST_AUTHORITY = "com.oasisfeng.condom.test";