package org.bookdash.android.presentation;
import android.Manifest;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.test.runner.AndroidJUnitRunner;
import android.util.Log;
import java.lang.reflect.Method;
/**
* Tests can fail for other reasons than code, it´ because of the animations and espresso sync and
* emulator state (screen off or locked)
* <p/>
* Before all the tests prepare the device to run tests and avoid these problems.
* <p/>
* - Disable animations
* - Disable keyguard lock
* - Set it to be awake all the time (dont let the processor sleep)
*
* @see <a href="u2020 open source app by Jake Wharton">https://github.com/JakeWharton/u2020</a>
* @see <a href="Daj gist">https://gist.github.com/daj/7b48f1b8a92abf960e7b</a>
*/
public final class CustomTestRunner extends AndroidJUnitRunner {
private static final String TAG = "CustomTestRunner";
@Override
public void onStart() {
runOnMainSync(new Runnable() {
@Override
public void run() {
Context app = CustomTestRunner.this.getTargetContext().getApplicationContext();
CustomTestRunner.this.disableAnimations(app);
String name = CustomTestRunner.class.getSimpleName();
unlockScreen(app, name);
keepSceenAwake(app, name);
}
});
super.onStart();
}
@Override
public void finish(int resultCode, Bundle results) {
super.finish(resultCode, results);
enableAnimations(getContext());
}
private void keepSceenAwake(Context app, String name) {
PowerManager power = (PowerManager) app.getSystemService(Context.POWER_SERVICE);
power.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, name)
.acquire();
}
private void unlockScreen(Context app, String name) {
KeyguardManager keyguard = (KeyguardManager) app.getSystemService(Context.KEYGUARD_SERVICE);
keyguard.newKeyguardLock(name).disableKeyguard();
}
void disableAnimations(Context context) {
int permStatus = context.checkCallingOrSelfPermission(Manifest.permission.SET_ANIMATION_SCALE);
if (permStatus == PackageManager.PERMISSION_GRANTED) {
setSystemAnimationsScale(0.0f);
}
}
void enableAnimations(Context context) {
int permStatus = context.checkCallingOrSelfPermission(Manifest.permission.SET_ANIMATION_SCALE);
if (permStatus == PackageManager.PERMISSION_GRANTED) {
setSystemAnimationsScale(1.0f);
}
}
private void setSystemAnimationsScale(float animationScale) {
try {
Class<?> windowManagerStubClazz = Class.forName("android.view.IWindowManager$Stub");
Method asInterface = windowManagerStubClazz.getDeclaredMethod("asInterface", IBinder.class);
Class<?> serviceManagerClazz = Class.forName("android.os.ServiceManager");
Method getService = serviceManagerClazz.getDeclaredMethod("getService", String.class);
Class<?> windowManagerClazz = Class.forName("android.view.IWindowManager");
Method setAnimationScales = windowManagerClazz.getDeclaredMethod("setAnimationScales", float[].class);
Method getAnimationScales = windowManagerClazz.getDeclaredMethod("getAnimationScales");
IBinder windowManagerBinder = (IBinder) getService.invoke(null, "window");
Object windowManagerObj = asInterface.invoke(null, windowManagerBinder);
float[] currentScales = (float[]) getAnimationScales.invoke(windowManagerObj);
for (int i = 0; i < currentScales.length; i++) {
currentScales[i] = animationScale;
}
setAnimationScales.invoke(windowManagerObj, new Object[]{currentScales});
Log.d(TAG, "Changed permissions of animations");
} catch (Exception e) {
Log.e(TAG, "Could not change animation scale to " + animationScale + " :'(");
}
}
}