diff options
| -rw-r--r-- | core/api/module-lib-current.txt | 5 | ||||
| -rw-r--r-- | core/java/android/app/SystemServiceRegistry.java | 107 | ||||
| -rw-r--r-- | core/java/android/webkit/flags.aconfig | 9 |
3 files changed, 116 insertions, 5 deletions
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 24b923326baa..55ed1f559f51 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -66,6 +66,11 @@ package android.app { method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setExpansionDisabledForSimNetworkLock(boolean); } + public final class SystemServiceRegistry { + method @FlaggedApi("android.webkit.update_service_ipc_wrapper") @Nullable public static Object getSystemServiceWithNoContext(@NonNull String); + method @FlaggedApi("android.webkit.update_service_ipc_wrapper") public static <TServiceClass> void registerForeverStaticService(@NonNull String, @NonNull Class<TServiceClass>, @NonNull android.app.SystemServiceRegistry.StaticServiceProducerWithBinder<TServiceClass>); + } + } package android.app.admin { diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 397b63fe6a30..b21b0f3bcca8 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -19,6 +19,7 @@ package android.app; import android.accounts.AccountManager; import android.accounts.IAccountManager; import android.adservices.AdServicesFrameworkInitializer; +import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -1668,11 +1669,7 @@ public final class SystemServiceRegistry { return new Object[sServiceCacheSize]; } - /** - * Gets a system service from a given context. - * @hide - */ - public static Object getSystemService(ContextImpl ctx, String name) { + private static ServiceFetcher<?> getSystemServiceFetcher(String name) { if (name == null) { return null; } @@ -1683,6 +1680,18 @@ public final class SystemServiceRegistry { } return null; } + return fetcher; + } + + /** + * Gets a system service from a given context. + * @hide + */ + public static Object getSystemService(@NonNull ContextImpl ctx, String name) { + final ServiceFetcher<?> fetcher = getSystemServiceFetcher(name); + if (fetcher == null) { + return null; + } final Object ret = fetcher.getService(ctx); if (sEnableServiceNotFoundWtf && ret == null) { @@ -1710,6 +1719,26 @@ public final class SystemServiceRegistry { } /** + * Gets a system service which has opted-in to being fetched without a context. + * @hide + */ + @FlaggedApi(android.webkit.Flags.FLAG_UPDATE_SERVICE_IPC_WRAPPER) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static @Nullable Object getSystemServiceWithNoContext(@NonNull String name) { + final ServiceFetcher<?> fetcher = getSystemServiceFetcher(name); + if (fetcher == null) { + return null; + } + + if (!fetcher.supportsFetchWithoutContext()) { + throw new IllegalArgumentException( + "Manager cannot be fetched without a context: " + name); + } + + return fetcher.getService(null); + } + + /** * Gets the name of the system-level service that is represented by the specified class. * @hide */ @@ -1863,6 +1892,50 @@ public final class SystemServiceRegistry { } /** + * Used by apex modules to register a "service wrapper" that is not tied to any {@link Context} + * and will never require a context in the future. + * + * Services registered in this way can be fetched via + * {@link #getSystemServiceWithNoContext(String)}, so cannot require a context in future without + * a breaking change. + * + * <p>This can only be called from the methods called by the static initializer of + * {@link SystemServiceRegistry}. (Otherwise it throws a {@link IllegalStateException}.) + * + * @param serviceName the name of the binder object, such as + * {@link Context#JOB_SCHEDULER_SERVICE}. + * @param serviceWrapperClass the wrapper class, such as the class of + * {@link android.app.job.JobScheduler}. + * @param serviceProducer Callback that takes the service binder object with the name + * {@code serviceName} and returns an actual service wrapper instance. + * + * @hide + */ + @FlaggedApi(android.webkit.Flags.FLAG_UPDATE_SERVICE_IPC_WRAPPER) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static <TServiceClass> void registerForeverStaticService( + @NonNull String serviceName, @NonNull Class<TServiceClass> serviceWrapperClass, + @NonNull StaticServiceProducerWithBinder<TServiceClass> serviceProducer) { + ensureInitializing("registerStaticService"); + Preconditions.checkStringNotEmpty(serviceName); + Objects.requireNonNull(serviceWrapperClass); + Objects.requireNonNull(serviceProducer); + + registerService(serviceName, serviceWrapperClass, + new StaticServiceFetcher<TServiceClass>() { + @Override + public TServiceClass createService() throws ServiceNotFoundException { + return serviceProducer.createService( + ServiceManager.getServiceOrThrow(serviceName)); + } + + @Override + public boolean supportsFetchWithoutContext() { + return true; + }}); + } + + /** * Similar to {@link #registerStaticService(String, Class, StaticServiceProducerWithBinder)}, * but used for a "service wrapper" that doesn't take a service binder in its constructor. * @@ -1952,6 +2025,18 @@ public final class SystemServiceRegistry { */ static abstract interface ServiceFetcher<T> { T getService(ContextImpl ctx); + + /** + * Should this service fetcher support being fetched via {@link #getSystemService(String)}, + * without a Context? + * + * This means that the service cannot depend on a Context in future! + * + * @return true if this is supported for this service. + */ + default boolean supportsFetchWithoutContext() { + return false; + } } /** @@ -2059,6 +2144,11 @@ public final class SystemServiceRegistry { } public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException; + + // Services that explicitly use a Context can never be fetched without one. + public final boolean supportsFetchWithoutContext() { + return false; + } } /** @@ -2083,6 +2173,13 @@ public final class SystemServiceRegistry { } public abstract T createService() throws ServiceNotFoundException; + + // Services that do not need a Context can potentially be fetched without one, but the + // default is false, so that the service can require one in future without this being a + // breaking change. + public boolean supportsFetchWithoutContext() { + return false; + } } /** @hide */ diff --git a/core/java/android/webkit/flags.aconfig b/core/java/android/webkit/flags.aconfig new file mode 100644 index 000000000000..6938b29e78e9 --- /dev/null +++ b/core/java/android/webkit/flags.aconfig @@ -0,0 +1,9 @@ +package: "android.webkit" + +flag { + name: "update_service_ipc_wrapper" + namespace: "webview" + description: "New API: proper wrapper for IWebViewUpdateService" + bug: "319292658" + is_fixed_read_only: true +} |