public class

BaseLayerModule

extends java.lang.Object

 java.lang.Object

↳androidx.test.espresso.base.BaseLayerModule

Gradle dependencies

compile group: 'androidx.test.espresso', name: 'espresso-core', version: '3.5.0-alpha06'

  • groupId: androidx.test.espresso
  • artifactId: espresso-core
  • version: 3.5.0-alpha06

Artifact androidx.test.espresso:espresso-core:3.5.0-alpha06 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.test.espresso:espresso-core com.android.support.test.espresso:espresso-core

Androidx class mapping:

androidx.test.espresso.base.BaseLayerModule android.support.test.espresso.base.BaseLayerModule

Overview

Dagger module for creating the implementation classes within the base package.

Summary

Constructors
publicBaseLayerModule()

Methods
public ActiveRootListerprovideActiveRootLister(androidx.test.espresso.base.RootsOracle rootsOracle)

public androidx.test.espresso.base.IdleNotifier<java.lang.Runnable>provideCompatAsyncTaskMonitor(androidx.test.espresso.base.ThreadPoolExecutorExtractor extractor)

public ControlledLooperprovideControlledLooper()

public androidx.test.espresso.base.IdleNotifier<androidx.test.espresso.base.IdlingResourceRegistry.IdleNotificationCallback>provideDynamicNotifer(IdlingResourceRegistry dynamicRegistry)

public androidx.test.espresso.base.EventInjectorprovideEventInjector()

public ActivityLifecycleMonitorprovideLifecycleMonitor()

public LooperprovideMainLooper()

public java.util.concurrent.ExecutorprovideMainThreadExecutor(Looper mainLooper)

public ListeningExecutorServiceprovideRemoteExecutor()

public androidx.test.espresso.base.IdleNotifier<java.lang.Runnable>provideSdkAsyncTaskMonitor(androidx.test.espresso.base.ThreadPoolExecutorExtractor extractor)

public ContextprovideTargetContext()

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

Constructors

public BaseLayerModule()

Methods

public ActivityLifecycleMonitor provideLifecycleMonitor()

public Context provideTargetContext()

public Looper provideMainLooper()

public androidx.test.espresso.base.IdleNotifier<java.lang.Runnable> provideCompatAsyncTaskMonitor(androidx.test.espresso.base.ThreadPoolExecutorExtractor extractor)

public java.util.concurrent.Executor provideMainThreadExecutor(Looper mainLooper)

public androidx.test.espresso.base.IdleNotifier<androidx.test.espresso.base.IdlingResourceRegistry.IdleNotificationCallback> provideDynamicNotifer(IdlingResourceRegistry dynamicRegistry)

public androidx.test.espresso.base.IdleNotifier<java.lang.Runnable> provideSdkAsyncTaskMonitor(androidx.test.espresso.base.ThreadPoolExecutorExtractor extractor)

public ActiveRootLister provideActiveRootLister(androidx.test.espresso.base.RootsOracle rootsOracle)

public androidx.test.espresso.base.EventInjector provideEventInjector()

public ListeningExecutorService provideRemoteExecutor()

public ControlledLooper provideControlledLooper()

Source

/*
 * Copyright (C) 2014 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.espresso.base;

import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
import androidx.test.espresso.FailureHandler;
import androidx.test.espresso.IdlingRegistry;
import androidx.test.espresso.base.IdlingResourceRegistry.IdleNotificationCallback;
import androidx.test.espresso.internal.inject.TargetContext;
import androidx.test.internal.platform.ServiceLoaderWrapper;
import androidx.test.internal.platform.os.ControlledLooper;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.platform.io.PlatformTestStorage;
import androidx.test.platform.tracing.Tracing;
import androidx.test.runner.lifecycle.ActivityLifecycleMonitor;
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
import com.google.common.base.Optional;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import dagger.Module;
import dagger.Provides;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Inject;
import javax.inject.Singleton;

/**
 * Dagger module for creating the implementation classes within the base package.
 *
 * @hide
 */
@RestrictTo(Scope.LIBRARY)
@Module(includes = {PlatformTestStorageModule.class})
public class BaseLayerModule {

  @Provides
  public ActivityLifecycleMonitor provideLifecycleMonitor() {
    return ActivityLifecycleMonitorRegistry.getInstance();
  }

  @Provides
  @TargetContext
  public Context provideTargetContext() {
    return InstrumentationRegistry.getInstrumentation().getTargetContext();
  }

  @Provides
  @Singleton
  public Looper provideMainLooper() {
    return Looper.getMainLooper();
  }

  @Provides
  @Singleton
  @CompatAsyncTask
  public IdleNotifier<Runnable> provideCompatAsyncTaskMonitor(
      ThreadPoolExecutorExtractor extractor) {
    Optional<ThreadPoolExecutor> compatThreadPool = extractor.getCompatAsyncTaskThreadPool();
    if (compatThreadPool.isPresent()) {
      return new AsyncTaskPoolMonitor(compatThreadPool.get()).asIdleNotifier();
    } else {
      return new NoopRunnableIdleNotifier();
    }
  }

  @Provides
  @Singleton
  @MainThread
  public Executor provideMainThreadExecutor(Looper mainLooper) {
    final Handler handler = new Handler(mainLooper);
    return new Executor() {
      @Override
      public void execute(Runnable runnable) {
        handler.post(runnable);
      }
    };
  }

  @Provides
  public IdleNotifier<IdleNotificationCallback> provideDynamicNotifer(
      IdlingResourceRegistry dynamicRegistry) {
    // Since a dynamic notifier will be created for each Espresso interaction this is a good time
    // to sync the IdlingRegistry with IdlingResourceRegistry.
    dynamicRegistry.sync(
        IdlingRegistry.getInstance().getResources(), IdlingRegistry.getInstance().getLoopers());
    return dynamicRegistry.asIdleNotifier();
  }

  @Provides
  @Singleton
  @SdkAsyncTask
  public IdleNotifier<Runnable> provideSdkAsyncTaskMonitor(ThreadPoolExecutorExtractor extractor) {
    return new AsyncTaskPoolMonitor(extractor.getAsyncTaskThreadPool()).asIdleNotifier();
  }

  @Provides
  public ActiveRootLister provideActiveRootLister(RootsOracle rootsOracle) {
    return rootsOracle;
  }

  @Provides
  @Singleton
  public EventInjector provideEventInjector() {
    // On API 16 and above, android uses input manager to inject events. On API < 16,
    // they use Window Manager. So we need to create our InjectionStrategy depending on the api
    // level. Instrumentation does not check if the event presses went through by checking the
    // boolean return value of injectInputEvent, which is why we created this class to better
    // handle lost/dropped press events. Instrumentation cannot be used as a fallback strategy,
    // since this will be executed on the main thread.
    int sdkVersion = Build.VERSION.SDK_INT;
    EventInjectionStrategy injectionStrategy = null;
    if (sdkVersion >= 16) { // Use InputManager for API level 16 and up.
      InputManagerEventInjectionStrategy strategy = new InputManagerEventInjectionStrategy();
      strategy.initialize();
      injectionStrategy = strategy;
    } else if (sdkVersion >= 7) {
      // else Use WindowManager for API level 15 through 7.
      WindowManagerEventInjectionStrategy strategy = new WindowManagerEventInjectionStrategy();
      strategy.initialize();
      injectionStrategy = strategy;
    } else {
      throw new RuntimeException(
          "API Level 6 and below is not supported. You are running: " + sdkVersion);
    }
    return new EventInjector(injectionStrategy);
  }

  /** Holder for AtomicReference<FailureHandler> which allows updating it at runtime. */
  @Singleton
  public static class FailureHandlerHolder {
    private final AtomicReference<FailureHandler> holder;

    @Inject
    public FailureHandlerHolder(@Default FailureHandler defaultHandler) {
      holder = new AtomicReference<FailureHandler>(defaultHandler);
    }

    public void update(FailureHandler handler) {
      holder.set(handler);
    }

    public FailureHandler get() {
      return holder.get();
    }
  }

  @Provides
  FailureHandler provideFailureHandler(FailureHandlerHolder holder) {
    return holder.get();
  }

  @Provides
  @Singleton
  public ListeningExecutorService provideRemoteExecutor() {
    return MoreExecutors.listeningDecorator(
        new ThreadPoolExecutor(
            0 /*corePoolSize*/,
            5 /*maximumPoolSize*/,
            10,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(),
            new ThreadFactoryBuilder().setNameFormat("Espresso Remote #%d").build()));
  }

  @Provides
  @Default
  FailureHandler provideFailureHander(DefaultFailureHandler impl) {
    return impl;
  }

  @Provides
  DefaultFailureHandler provideDefaultFailureHander(
      @TargetContext Context context, PlatformTestStorage testStorage) {
    return new DefaultFailureHandler(context, testStorage);
  }

  @Provides
  @Singleton
  public ControlledLooper provideControlledLooper() {
    // load a service loaded provided ControlledLooper if available, otherwise return a no-op
    return ServiceLoaderWrapper.loadSingleService(
        ControlledLooper.class, () -> ControlledLooper.NO_OP_CONTROLLED_LOOPER);
  }

  @Provides
  @Singleton
  Tracing providesTracing() {
    return Tracing.getInstance();
  }
}