From fd7acd6304fd139b23678bcdd54e974e109e6028 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 14 Aug 2018 12:52:06 +0200 Subject: [PATCH] disable all animations in emulator for Espresso tests * https://gist.github.com/xrigau/11284124 * https://gist.github.com/xrigau/ea8d306e0a751fafb1e6 * https://artemzin.com/blog/easiest-way-to-give-set_animation_scale-permission-for-your-ui-tests-on-android/ * https://github.com/finn-no/android_emulator_hacks * https://gist.github.com/caipivara/9371a79a7222a156ddad --- app/build.gradle | 1 + app/lint.xml | 1 + app/src/androidTest/AndroidManifest.xml | 2 + .../fdroid/MainActivityEspressoTest.java | 27 +++++++- .../org/fdroid/fdroid/SystemAnimations.java | 62 +++++++++++++++++++ app/src/debug/AndroidManifest.xml | 7 +++ 6 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 app/src/androidTest/java/org/fdroid/fdroid/SystemAnimations.java create mode 100644 app/src/debug/AndroidManifest.xml diff --git a/app/build.gradle b/app/build.gradle index 13f90b4b8..1e9133f80 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -177,6 +177,7 @@ dependencies { androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:rules:1.0.2' + androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3' } checkstyle { diff --git a/app/lint.xml b/app/lint.xml index 5ce172832..f38e22391 100644 --- a/app/lint.xml +++ b/app/lint.xml @@ -50,6 +50,7 @@ + diff --git a/app/src/androidTest/AndroidManifest.xml b/app/src/androidTest/AndroidManifest.xml index bf0cb30d6..6527ef9ae 100644 --- a/app/src/androidTest/AndroidManifest.xml +++ b/app/src/androidTest/AndroidManifest.xml @@ -1,9 +1,11 @@ + diff --git a/app/src/androidTest/java/org/fdroid/fdroid/MainActivityEspressoTest.java b/app/src/androidTest/java/org/fdroid/fdroid/MainActivityEspressoTest.java index 53e12895f..44034d45d 100644 --- a/app/src/androidTest/java/org/fdroid/fdroid/MainActivityEspressoTest.java +++ b/app/src/androidTest/java/org/fdroid/fdroid/MainActivityEspressoTest.java @@ -1,19 +1,25 @@ package org.fdroid.fdroid; +import android.app.Instrumentation; +import android.support.test.InstrumentationRegistry; import android.support.test.espresso.IdlingPolicies; import android.support.test.espresso.ViewInteraction; import android.support.test.filters.LargeTest; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; +import android.support.test.uiautomator.UiDevice; import android.util.Log; import android.view.View; import org.fdroid.fdroid.views.BannerUpdatingRepos; import org.fdroid.fdroid.views.main.MainActivity; import org.hamcrest.Matchers; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import java.io.IOException; import java.util.concurrent.TimeUnit; import static android.support.test.espresso.Espresso.onView; @@ -37,8 +43,25 @@ import static org.junit.Assert.assertTrue; public class MainActivityEspressoTest { public static final String TAG = "MainActivityEspressoTest"; - static { + @BeforeClass + public static void classSetUp() { IdlingPolicies.setIdlingResourceTimeout(10, TimeUnit.MINUTES); + IdlingPolicies.setMasterPolicyTimeout(10, TimeUnit.MINUTES); + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + try { + UiDevice.getInstance(instrumentation) + .executeShellCommand("pm grant " + + instrumentation.getTargetContext().getPackageName() + + " android.permission.SET_ANIMATION_SCALE"); + } catch (IOException e) { + e.printStackTrace(); + } + SystemAnimations.disableAll(InstrumentationRegistry.getTargetContext()); + } + + @AfterClass + public static void classTearDown() { + SystemAnimations.enableAll(InstrumentationRegistry.getTargetContext()); } @Rule @@ -130,7 +153,7 @@ public class MainActivityEspressoTest { } @Test - public void showLatest() throws InterruptedException { + public void showLatest() { if (!BuildConfig.FLAVOR.startsWith("full")) { return; } diff --git a/app/src/androidTest/java/org/fdroid/fdroid/SystemAnimations.java b/app/src/androidTest/java/org/fdroid/fdroid/SystemAnimations.java new file mode 100644 index 000000000..f46d5495a --- /dev/null +++ b/app/src/androidTest/java/org/fdroid/fdroid/SystemAnimations.java @@ -0,0 +1,62 @@ +package org.fdroid.fdroid; + +import android.Manifest; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.IBinder; +import android.util.Log; + +import java.lang.reflect.Method; + +/** + * @see Disable animations for Espresso tests + */ +class SystemAnimations { + public static final String TAG = "SystemAnimations"; + + private static final float DISABLED = 0.0f; + private static final float DEFAULT = 1.0f; + + static void disableAll(Context context) { + int permStatus = context.checkCallingOrSelfPermission(Manifest.permission.SET_ANIMATION_SCALE); + if (permStatus == PackageManager.PERMISSION_GRANTED) { + Log.i(TAG, "Manifest.permission.SET_ANIMATION_SCALE PERMISSION_GRANTED"); + setSystemAnimationsScale(DISABLED); + } else { + Log.i(TAG, "Disabling Manifest.permission.SET_ANIMATION_SCALE failed: " + permStatus); + } + } + + static void enableAll(Context context) { + int permStatus = context.checkCallingOrSelfPermission(Manifest.permission.SET_ANIMATION_SCALE); + if (permStatus == PackageManager.PERMISSION_GRANTED) { + Log.i(TAG, "Manifest.permission.SET_ANIMATION_SCALE PERMISSION_GRANTED"); + setSystemAnimationsScale(DEFAULT); + } else { + Log.i(TAG, "Enabling Manifest.permission.SET_ANIMATION_SCALE failed: " + permStatus); + } + } + + private static 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}); + } catch (Exception e) { + Log.e(TAG, "Could not change animation scale to " + animationScale + " :'("); + } + } +} diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..9a241f133 --- /dev/null +++ b/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + +