package com.tomtom.espresso.test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import cucumber.api.android.CucumberInstrumentationCore;
/**
* A simple extension of the {@link android.support.test.runner.AndroidJUnitRunner} utilizing the {@link cucumber.api.android.CucumberInstrumentationCore}.
*/
public class EspressoInstrumentation extends android.support.test.runner.AndroidJUnitRunner {
private static final String TAG = "EspressoInstrumentation";
private static final String ANIMATION_PERMISSION = "android.permission.SET_ANIMATION_SCALE";
/**
* The {@link cucumber.api.android.CucumberInstrumentationCore} which will run the actual logic using this {@link android.support.test.runner.AndroidJUnitRunner}
* implementation.
*/
private CucumberInstrumentationCore cucumberInstrumentationCore = new CucumberInstrumentationCore(this);
@Override
public void onCreate(final Bundle bundle) {
cucumberInstrumentationCore.create(bundle);
super.onCreate(bundle);
disableAnimation();
}
@Override
public void onStart() {
cucumberInstrumentationCore.start();
}
private void disableAnimation() {
final int permStatus = getContext().checkCallingOrSelfPermission(ANIMATION_PERMISSION);
if (permStatus == PackageManager.PERMISSION_GRANTED) {
if (reflectivelyDisableAnimation()) {
Log.i(TAG, "All animations disabled.");
} else {
Log.i(TAG, "Could not disable animations.");
}
} else {
Log.i(TAG, "Cannot disable animations due to lack of permission.");
}
}
private boolean reflectivelyDisableAnimation() {
try {
final Class<?> windowManagerStubClazz = Class.forName("android.view.IWindowManager$Stub");
final Method asInterface = windowManagerStubClazz.getDeclaredMethod("asInterface", IBinder.class);
final Class<?> serviceManagerClazz = Class.forName("android.os.ServiceManager");
final Method getService = serviceManagerClazz.getDeclaredMethod("getService", String.class);
final Class<?> windowManagerClazz = Class.forName("android.view.IWindowManager");
final Method setAnimationScales = windowManagerClazz.getDeclaredMethod("setAnimationScales",
float[].class);
final Method getAnimationScales = windowManagerClazz.getDeclaredMethod("getAnimationScales");
final IBinder windowManagerBinder = (IBinder) getService.invoke(null, "window");
final Object windowManagerObj = asInterface.invoke(null, windowManagerBinder);
float[] currentScales = (float[]) getAnimationScales.invoke(windowManagerObj);
for (int i = 0; i < currentScales.length; i++) {
currentScales[i] = 0.0f;
}
setAnimationScales.invoke(windowManagerObj, currentScales);
return true;
} catch (final ClassNotFoundException cnfe) {
Log.w(TAG, "Cannot disable animations reflectively.", cnfe);
} catch (final NoSuchMethodException mnfe) {
Log.w(TAG, "Cannot disable animations reflectively.", mnfe);
} catch (final SecurityException se) {
Log.w(TAG, "Cannot disable animations reflectively.", se);
} catch (final InvocationTargetException ite) {
Log.w(TAG, "Cannot disable animations reflectively.", ite);
} catch (final IllegalAccessException iae) {
Log.w(TAG, "Cannot disable animations reflectively.", iae);
} catch (final RuntimeException re) {
Log.w(TAG, "Cannot disable animations reflectively.", re);
}
return false;
}
}