From 1dbff05bf375557ea73e07632d732bd90a71af9e Mon Sep 17 00:00:00 2001
From: Kevin Jin
+ * Propagates {@code throwable} as-is if it is an instance of {@link RuntimeException} or {@link
+ * Error}, or else as a last resort, wraps it in a {@code DroidDriverException} and then
+ * propagates. This method always throws an exception. The {@code DroidDriverException} return
+ * type is only for client code to make Java type system happy in case a return value is required
+ * by the enclosing method. Example usage:
+ * This is a safer variation of {@link Instrumentation#runOnMainSync}
- * because the latter may hang. But it is heavy because a new thread is created for each call. You
- * may turn off this behavior by setting {@code "-e dd.runOnMainSyncTimeout 0"} on the am command
- * line.
+ * T doSomething() {
+ * try {
+ * return someMethodThatCouldThrowAnything();
+ * } catch (IKnowWhatToDoWithThisException e) {
+ * return handle(e);
+ * } catch (Throwable t) {
+ * throw DroidDriverException.propagate(t);
+ * }
+ * }
+ *
+ *
+ * @param throwable the Throwable to propagate
+ * @return nothing will ever be returned; this return type is only for your convenience, as
+ * illustrated in the example above
+ */
+ public static DroidDriverException propagate(Throwable throwable) {
+ if (throwable instanceof RuntimeException) {
+ throw (RuntimeException) throwable;
+ }
+ if (throwable instanceof Error) {
+ throw (Error) throwable;
+ }
+ throw new DroidDriverException(throwable);
+ }
}
diff --git a/src/io/appium/droiddriver/helpers/DroidDrivers.java b/src/io/appium/droiddriver/helpers/DroidDrivers.java
index 5cddb4f..7725bf5 100644
--- a/src/io/appium/droiddriver/helpers/DroidDrivers.java
+++ b/src/io/appium/droiddriver/helpers/DroidDrivers.java
@@ -20,8 +20,6 @@ import android.annotation.TargetApi;
import android.app.Instrumentation;
import android.os.Build;
-import java.lang.reflect.InvocationTargetException;
-
import io.appium.droiddriver.DroidDriver;
import io.appium.droiddriver.exceptions.DroidDriverException;
import io.appium.droiddriver.instrumentation.InstrumentationDriver;
@@ -77,18 +75,8 @@ public class DroidDrivers {
try {
return (DroidDriver) Class.forName(driverClass).getConstructor(Instrumentation.class)
.newInstance(instrumentation);
- } catch (ClassNotFoundException e) {
- throw new DroidDriverException(e);
- } catch (NoSuchMethodException e) {
- throw new DroidDriverException(e);
- } catch (InstantiationException e) {
- throw new DroidDriverException(e);
- } catch (IllegalAccessException e) {
- throw new DroidDriverException(e);
- } catch (IllegalArgumentException e) {
- throw new DroidDriverException(e);
- } catch (InvocationTargetException e) {
- throw new DroidDriverException(e);
+ } catch (Throwable t) {
+ throw DroidDriverException.propagate(t);
}
}
diff --git a/src/io/appium/droiddriver/util/InstrumentationUtils.java b/src/io/appium/droiddriver/util/InstrumentationUtils.java
index a019008..95eb48c 100644
--- a/src/io/appium/droiddriver/util/InstrumentationUtils.java
+++ b/src/io/appium/droiddriver/util/InstrumentationUtils.java
@@ -22,6 +22,8 @@ import android.os.Looper;
import android.util.Log;
import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
@@ -41,6 +43,7 @@ public class InstrumentationUtils {
public void run() {
}
};
+ private static final Executor RUN_ON_MAIN_SYNC_EXECUTOR = Executors.newSingleThreadExecutor();
/**
* Initializes this class. If you use a runner that is not DroidDriver-aware, you need to call
@@ -112,8 +115,8 @@ public class InstrumentationUtils {
Logs.log(Log.INFO,
"Timed out after " + timeoutMillis + " milliseconds waiting for idle on main looper");
return false;
- } catch (Throwable e) {
- throw new DroidDriverException(e);
+ } catch (Throwable t) {
+ throw DroidDriverException.propagate(t);
}
return true;
}
@@ -132,12 +135,10 @@ public class InstrumentationUtils {
* Runs {@code callable} on the main thread on best-effort basis up to a time limit, which
* defaults to {@code 10000L} and can be set as an am instrument option under the key {@code
* dd.runOnMainSyncTimeout}.