Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 14b06dc4 authored by Torne (Richard Coles)'s avatar Torne (Richard Coles)
Browse files

Add SystemServiceRegistry.getService(String).

Allow services to opt in to being fetched entirely without a Context.
This is not enabled by default because it would be a compatibility break
for the service to need a Context in future, but if a service can commit
to never needing a Context, this allows additional flexibility for
callers.

Bug: 319292658
Test: Tested indirectly in followup CL using the API
Change-Id: I4e8a15420a207c93bfa07e41e45edbd06e548204
parent a9d2c1f1
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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 {
+102 −5
Original line number Diff line number Diff line
@@ -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) {
@@ -1709,6 +1718,26 @@ public final class SystemServiceRegistry {
        return ret;
    }

    /**
     * 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
@@ -1862,6 +1891,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 */
+9 −0
Original line number Diff line number Diff line
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
}