private Object proceed(final Object proxy, final Method method, final Object[] args) throws Throwable {
			final String method_name = method.getName();
			OutboundType outbound_type = null;
			switch (method_name) {
			case "queryIntentServices":
				outbound_type = OutboundType.QUERY_SERVICES;
				if (IPackageManager_queryIntentServices == null) IPackageManager_queryIntentServices = method;
				if (args[0] == DUMMY_INTENT) return null;	// Short-circuit for capturing IPackageManager_queryIntentServices.
			case "queryIntentReceivers":
				if (outbound_type == null) outbound_type = OutboundType.QUERY_RECEIVERS;

				final Object receivers = super.invoke(proxy, method, args);

				final List<ResolveInfo> list = mCondom.proceedQuery(outbound_type, (Intent) args[0], () -> asList(receivers),
						outbound_type == OutboundType.QUERY_SERVICES ? CondomCore.SERVICE_PACKAGE_GETTER : CondomCore.RECEIVER_PACKAGE_GETTER);	// Both "queryIntentServices" and "queryIntentReceivers" reach here.
				if (list.isEmpty()) asList(receivers).clear();	// In case Collections.emptyList() is returned due to targeted query being rejected by outbound judge.
				return receivers;

			case "resolveService":
				// Intent flags could only filter background receivers, we have to deal with services by ourselves.
				final Intent intent = (Intent) args[0];
				final int original_intent_flags = intent.getFlags();
				return mCondom.proceed(OutboundType.QUERY_SERVICES, intent, null, () -> {
					if (! mCondom.mExcludeBackgroundServices && mCondom.mOutboundJudge == null)
						return (ResolveInfo) CondomProcessPackageManager.super.invoke(proxy, method, args);

					if (IPackageManager_queryIntentServices == null) {
						mCondom.mBase.getPackageManager().queryIntentServices(DUMMY_INTENT, 0);
						if (IPackageManager_queryIntentServices == null)
							throw new IllegalStateException("Failed to capture IPackageManager.queryIntentServices()");
					}
					final List<ResolveInfo> candidates = asList(CondomProcessPackageManager.super.invoke(proxy, IPackageManager_queryIntentServices, args));
					return mCondom.filterCandidates(OutboundType.QUERY_SERVICES, intent.setFlags(original_intent_flags), candidates, FULL_TAG, false);
				});

			case "resolveContentProvider":
				final ProviderInfo provider = (ProviderInfo) super.invoke(proxy, method, args);
				final int flags = (int) args[1];
				if ((flags & PackageManager.MATCH_ALL) != 0) return provider;	// MATCH_ALL will be used by the hooked IActivityManager.getContentProvider().
				return mCondom.shouldAllowProvider(provider) ? provider : null;

			case "getInstalledApplications":
			case "getInstalledPackages":
				mCondom.logConcern(FULL_TAG, "IPackageManager." + method_name);
				break;
			case "getPackageInfo":
				return mCondom.proceed(OutboundType.GET_PACKAGE_INFO, (String) args[0], null, () ->
						(PackageInfo) CondomProcessPackageManager.super.invoke(proxy, method, args));
			case "getPackageUid":
				final String pkg = (String) args[0];
				final Integer result = mCondom.proceed(OutboundType.GET_PACKAGE_INFO, pkg, null, () ->
						(Integer) com.oasisfeng.condom.CondomProcess.CondomProcessPackageManager.super.invoke(proxy, method, args));
				if (result == null) throw new PackageManager.NameNotFoundException(pkg);    // TODO: Add test case
				return result;
			}
			return super.invoke(proxy, method, args);
		}
Install the condom protection for current process. This method should generally never be called in the main process of app.

<p>It is suggested to use {@link android.content.ContentProvider ContentProvider} with "android:process", to install it in specified process.
library/src/main/java/com/oasisfeng/condom/CondomProcess.java