From 1a0b969d6a534627775f7f141ccf0a73b9b42aca Mon Sep 17 00:00:00 2001 From: Neil Fuller Date: Thu, 8 Jul 2021 20:05:34 +0100 Subject: [PATCH] Enable matching of non-system app services Change CurrentUserServiceSupplier to support attaching to services that are not "system" services (i.e. provided by apps from the system image). This is to support an upcoming test change in location time zone detection where a fake provider supplied by a CTS app can be bound. As part of this change constructors have been removed and replaced by factory methods, which makes the choice to allow non-system services more obvious. Bug: 184947690 Test: build / treehugger Change-Id: I629228c09ad1cf91c28c20d0b4b6227d1e4b1a00 --- .../server/location/GeocoderProxy.java | 2 +- .../HardwareActivityRecognitionProxy.java | 4 +- .../location/geofence/GeofenceProxy.java | 2 +- .../provider/proxy/ProxyLocationProvider.java | 2 +- .../CurrentUserServiceSupplier.java | 89 +++++++++++++------ .../RealLocationTimeZoneProviderProxy.java | 2 +- 6 files changed, 70 insertions(+), 31 deletions(-) diff --git a/services/core/java/com/android/server/location/GeocoderProxy.java b/services/core/java/com/android/server/location/GeocoderProxy.java index dc3596b6c2a70..57a7620a3b322 100644 --- a/services/core/java/com/android/server/location/GeocoderProxy.java +++ b/services/core/java/com/android/server/location/GeocoderProxy.java @@ -56,7 +56,7 @@ public class GeocoderProxy { private GeocoderProxy(Context context) { mServiceWatcher = ServiceWatcher.create(context, "GeocoderProxy", - new CurrentUserServiceSupplier(context, SERVICE_ACTION, + CurrentUserServiceSupplier.createFromConfig(context, SERVICE_ACTION, com.android.internal.R.bool.config_enableGeocoderOverlay, com.android.internal.R.string.config_geocoderProviderPackageName), null); diff --git a/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java b/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java index 6ac6e77342bea..f63ba583fdf0f 100644 --- a/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java +++ b/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java @@ -73,8 +73,8 @@ public class HardwareActivityRecognitionProxy implements ServiceListener { mGpsGeofenceHardware = Objects.requireNonNull(gpsGeofence); mServiceWatcher = ServiceWatcher.create(context, "GeofenceProxy", - new CurrentUserServiceSupplier(context, SERVICE_ACTION, + CurrentUserServiceSupplier.createFromConfig(context, SERVICE_ACTION, com.android.internal.R.bool.config_enableGeofenceOverlay, com.android.internal.R.string.config_geofenceProviderPackageName), this); diff --git a/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java b/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java index a9641f0f1c1b2..2b3f420749918 100644 --- a/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java +++ b/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java @@ -103,7 +103,7 @@ public class ProxyLocationProvider extends AbstractLocationProvider implements mContext = context; mServiceWatcher = ServiceWatcher.create(context, provider, - new CurrentUserServiceSupplier(context, action, enableOverlayResId, + CurrentUserServiceSupplier.createFromConfig(context, action, enableOverlayResId, nonOverlayPackageResId), this); mName = provider; diff --git a/services/core/java/com/android/server/servicewatcher/CurrentUserServiceSupplier.java b/services/core/java/com/android/server/servicewatcher/CurrentUserServiceSupplier.java index 3ca8a5a1f5544..87b28dbc905ec 100644 --- a/services/core/java/com/android/server/servicewatcher/CurrentUserServiceSupplier.java +++ b/services/core/java/com/android/server/servicewatcher/CurrentUserServiceSupplier.java @@ -62,7 +62,7 @@ import java.util.Objects; * not require callers to hold this permission is rejected (2) a service permission - any service * whose package does not hold this permission is rejected. */ -public class CurrentUserServiceSupplier extends BroadcastReceiver implements +public final class CurrentUserServiceSupplier extends BroadcastReceiver implements ServiceSupplier { private static final String TAG = "CurrentUserServiceSupplier"; @@ -144,6 +144,53 @@ public class CurrentUserServiceSupplier extends BroadcastReceiver implements } } + /** + * Creates an instance using package details retrieved from config. + * + * @see #create(Context, String, String, String, String) + */ + public static CurrentUserServiceSupplier createFromConfig(Context context, String action, + @BoolRes int enableOverlayResId, @StringRes int nonOverlayPackageResId) { + String explicitPackage = retrieveExplicitPackage(context, enableOverlayResId, + nonOverlayPackageResId); + return CurrentUserServiceSupplier.create(context, action, explicitPackage, + /*callerPermission=*/null, /*servicePermission=*/null); + } + + /** + * Creates an instance with the specific service details and permission requirements. + * + * @param context the context the supplier is to use + * @param action the action the service must declare in its intent-filter + * @param explicitPackage the package of the service, or {@code null} if the package of the + * service is not constrained + * @param callerPermission a permission that the service forces callers (i.e. + * ServiceWatcher/system server) to hold, or {@code null} if there isn't one + * @param servicePermission a permission that the service package should hold, or {@code null} + * if there isn't one + */ + public static CurrentUserServiceSupplier create(Context context, String action, + @Nullable String explicitPackage, @Nullable String callerPermission, + @Nullable String servicePermission) { + boolean matchSystemAppsOnly = true; + return new CurrentUserServiceSupplier(context, action, + explicitPackage, callerPermission, servicePermission, matchSystemAppsOnly); + } + + /** + * Creates an instance like {@link #create} except it allows connection to services that are not + * supplied by system packages. Only intended for use during tests. + * + * @see #create(Context, String, String, String, String) + */ + public static CurrentUserServiceSupplier createUnsafeForTestsOnly(Context context, + String action, @Nullable String explicitPackage, @Nullable String callerPermission, + @Nullable String servicePermission) { + boolean matchSystemAppsOnly = false; + return new CurrentUserServiceSupplier(context, action, + explicitPackage, callerPermission, servicePermission, matchSystemAppsOnly); + } + private static @Nullable String retrieveExplicitPackage(Context context, @BoolRes int enableOverlayResId, @StringRes int nonOverlayPackageResId) { Resources resources = context.getResources(); @@ -162,31 +209,14 @@ public class CurrentUserServiceSupplier extends BroadcastReceiver implements private final @Nullable String mCallerPermission; // a permission that the service package should hold private final @Nullable String mServicePermission; + // whether to use MATCH_SYSTEM_ONLY in queries + private final boolean mMatchSystemAppsOnly; private volatile ServiceChangedListener mListener; - public CurrentUserServiceSupplier(Context context, String action) { - this(context, action, null, null, null); - } - - public CurrentUserServiceSupplier(Context context, String action, - @BoolRes int enableOverlayResId, @StringRes int nonOverlayPackageResId) { - this(context, action, - retrieveExplicitPackage(context, enableOverlayResId, nonOverlayPackageResId), null, - null); - } - - public CurrentUserServiceSupplier(Context context, String action, - @BoolRes int enableOverlayResId, @StringRes int nonOverlayPackageResId, - @Nullable String callerPermission, @Nullable String servicePermission) { - this(context, action, - retrieveExplicitPackage(context, enableOverlayResId, nonOverlayPackageResId), - callerPermission, servicePermission); - } - - public CurrentUserServiceSupplier(Context context, String action, + private CurrentUserServiceSupplier(Context context, String action, @Nullable String explicitPackage, @Nullable String callerPermission, - @Nullable String servicePermission) { + @Nullable String servicePermission, boolean matchSystemAppsOnly) { mContext = context; mActivityManager = Objects.requireNonNull( LocalServices.getService(ActivityManagerInternal.class)); @@ -198,13 +228,18 @@ public class CurrentUserServiceSupplier extends BroadcastReceiver implements mCallerPermission = callerPermission; mServicePermission = servicePermission; + mMatchSystemAppsOnly = matchSystemAppsOnly; } @Override public boolean hasMatchingService() { + int intentQueryFlags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE; + if (mMatchSystemAppsOnly) { + intentQueryFlags |= MATCH_SYSTEM_ONLY; + } List resolveInfos = mContext.getPackageManager() .queryIntentServicesAsUser(mIntent, - MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE | MATCH_SYSTEM_ONLY, + intentQueryFlags, UserHandle.USER_SYSTEM); return !resolveInfos.isEmpty(); } @@ -234,11 +269,15 @@ public class CurrentUserServiceSupplier extends BroadcastReceiver implements public BoundServiceInfo getServiceInfo() { BoundServiceInfo bestServiceInfo = null; - // only allow privileged services in the correct direct boot state to match + // only allow services in the correct direct boot state to match + int intentQueryFlags = MATCH_DIRECT_BOOT_AUTO | GET_META_DATA; + if (mMatchSystemAppsOnly) { + intentQueryFlags |= MATCH_SYSTEM_ONLY; + } int currentUserId = mActivityManager.getCurrentUserId(); List resolveInfos = mContext.getPackageManager().queryIntentServicesAsUser( mIntent, - GET_META_DATA | MATCH_DIRECT_BOOT_AUTO | MATCH_SYSTEM_ONLY, + intentQueryFlags, currentUserId); for (ResolveInfo resolveInfo : resolveInfos) { ServiceInfo service = Objects.requireNonNull(resolveInfo.serviceInfo); diff --git a/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java b/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java index b5ac712a35229..b7ff733eabbc8 100644 --- a/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java +++ b/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java @@ -71,7 +71,7 @@ class RealLocationTimeZoneProviderProxy extends LocationTimeZoneProviderProxy im mServiceWatcher = ServiceWatcher.create(context, handler, "RealLocationTimeZoneProviderProxy", - new CurrentUserServiceSupplier(context, action, + CurrentUserServiceSupplier.create(context, action, providerPackageName, BIND_TIME_ZONE_PROVIDER_SERVICE, INSTALL_LOCATION_TIME_ZONE_PROVIDER_SERVICE), this);