public final class

ServiceLoaderWrapper

extends java.lang.Object

 java.lang.Object

↳androidx.test.internal.platform.ServiceLoaderWrapper

Gradle dependencies

compile group: 'androidx.test', name: 'orchestrator', version: '1.5.0'

  • groupId: androidx.test
  • artifactId: orchestrator
  • version: 1.5.0

Artifact androidx.test:orchestrator:1.5.0 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.test:orchestrator com.android.support.test:orchestrator

Overview

Wrapper class for java.util.ServiceLoader that disables StrictMode.

Loading a service via ServiceLoader can result in disk I/O. Disk I/O on Android can be restricted via StrictMode. This class disables disk access checking and then reenables StrictMode when loading a service.

Summary

Methods
public static java.util.List<java.lang.Object>loadService(java.lang.Class<java.lang.Object> serviceClass)

Loads the implementing classes for given service.

public static java.lang.ObjectloadSingleService(java.lang.Class<java.lang.Object> serviceClass, ServiceLoaderWrapper.Factory<java.lang.Object> defaultImplFactory)

A wrapper method around ServiceLoaderWrapper.loadService(Class) that strictly enforces there is only one implementation of the service.

public static java.lang.ObjectloadSingleServiceOrNull(java.lang.Class<java.lang.Object> serviceClass)

A wrapper method around ServiceLoaderWrapper.loadService(Class) that returns one implementation of the service or null if no implementation is found.

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Methods

public static java.util.List<java.lang.Object> loadService(java.lang.Class<java.lang.Object> serviceClass)

Loads the implementing classes for given service.

Returns:

List of implementing classes. Returns an empty list if no implementing classes were defined.

public static java.lang.Object loadSingleService(java.lang.Class<java.lang.Object> serviceClass, ServiceLoaderWrapper.Factory<java.lang.Object> defaultImplFactory)

A wrapper method around ServiceLoaderWrapper.loadService(Class) that strictly enforces there is only one implementation of the service.

Parameters:

serviceClass: the service type class to load implementation for
defaultImplFactory: the factory implementation for creating instances

Returns:

the implementing service, or a new instance via defaultImplFactory.create() if no implementations are defined.

public static java.lang.Object loadSingleServiceOrNull(java.lang.Class<java.lang.Object> serviceClass)

A wrapper method around ServiceLoaderWrapper.loadService(Class) that returns one implementation of the service or null if no implementation is found.

Parameters:

serviceClass: the service type class to load implementation for

Returns:

the implementing service or null if none is found.

Source

/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package androidx.test.internal.platform;

import android.os.StrictMode;
import androidx.annotation.RestrictTo;
import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;

/**
 * Wrapper class for {@link ServiceLoader} that disables StrictMode.
 *
 * <p>Loading a service via ServiceLoader can result in disk I/O. Disk I/O on Android can be
 * restricted via StrictMode. This class disables disk access checking and then reenables StrictMode
 * when loading a service.
 *
 * @hide
 */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) // used by core, espresso, rule
public final class ServiceLoaderWrapper {

  private ServiceLoaderWrapper() {}

  /**
   * Loads the implementing classes for given service.
   *
   * @return List of implementing classes. Returns an empty list if no implementing classes were
   *     defined.
   */
  public static <T> List<T> loadService(Class<T> serviceClass) {
    StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();

    // load using ServiceLoader
    List<T> services = new ArrayList<>();
    for (T element : ServiceLoader.load(serviceClass)) {
      services.add(element);
    }
    StrictMode.setThreadPolicy(oldPolicy);
    return services;
  }

  /** A factory for creating default implementations of service classes. */
  public interface Factory<T> {
    T create();
  }

  /**
   * A wrapper method around {@link #loadService(Class)} that strictly enforces there is only one
   * implementation of the service.
   *
   * @param serviceClass the service type class to load implementation for
   * @param defaultImplFactory the factory implementation for creating instances
   * @return the implementing service, or a new instance via defaultImplFactory.create() if no
   *     implementations are defined.
   * @throws IllegalStateException if more than one service implementations are found
   */
  public static <T> T loadSingleService(Class<T> serviceClass, Factory<T> defaultImplFactory) {
    T impl = loadSingleServiceOrNull(serviceClass);
    if (impl == null) {
      return defaultImplFactory.create();
    } else {
      return impl;
    }
  }

  /**
   * A wrapper method around {@link #loadService(Class)} that returns one implementation of the
   * service or {@code null} if no implementation is found.
   *
   * @param serviceClass the service type class to load implementation for
   * @return the implementing service or null if none is found.
   * @throws IllegalStateException if more than one service implementations are found
   */
  public static <T> T loadSingleServiceOrNull(Class<T> serviceClass) {
    List<T> impls = ServiceLoaderWrapper.loadService(serviceClass);
    if (impls.isEmpty()) {
      return null;
    } else if (impls.size() == 1) {
      return impls.get(0);
    } else {
      String combinedImpls = null;
      for (T impl : impls) {
        combinedImpls = (combinedImpls != null) ? combinedImpls + ", " : ": ";
        combinedImpls += impl.getClass().getName();
      }

      throw new IllegalStateException(
          "Found more than one implementation for " + serviceClass.getName() + combinedImpls);
    }
  }
}