diff options
| -rw-r--r-- | core/java/android/view/ViewDebug.java | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 40b6a0876d35..ed128b073156 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -22,6 +22,7 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Rect; import android.os.Debug; +import android.os.Handler; import android.os.RemoteException; import android.util.DisplayMetrics; import android.util.Log; @@ -43,7 +44,12 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; @@ -964,6 +970,48 @@ public class ViewDebug { } while (klass != Object.class); } + private static Object callMethodOnAppropriateTheadBlocking(final Method method, + final Object object) throws IllegalAccessException, InvocationTargetException, + TimeoutException { + if (!(object instanceof View)) { + return method.invoke(object, (Object[]) null); + } + + final View view = (View) object; + Callable<Object> callable = new Callable<Object>() { + @Override + public Object call() throws IllegalAccessException, InvocationTargetException { + return method.invoke(view, (Object[]) null); + } + }; + FutureTask<Object> future = new FutureTask<Object>(callable); + // Try to use the handler provided by the view + Handler handler = view.getHandler(); + // Fall back on using the main thread + if (handler == null) { + handler = new Handler(android.os.Looper.getMainLooper()); + } + handler.post(future); + while (true) { + try { + return future.get(CAPTURE_TIMEOUT, java.util.concurrent.TimeUnit.MILLISECONDS); + } catch (ExecutionException e) { + Throwable t = e.getCause(); + if (t instanceof IllegalAccessException) { + throw (IllegalAccessException)t; + } + if (t instanceof InvocationTargetException) { + throw (InvocationTargetException)t; + } + throw new RuntimeException("Unexpected exception", t); + } catch (InterruptedException e) { + // Call get again + } catch (CancellationException e) { + throw new RuntimeException("Unexpected cancellation exception", e); + } + } + } + private static void exportMethods(Context context, Object view, BufferedWriter out, Class<?> klass, String prefix) throws IOException { @@ -974,8 +1022,7 @@ public class ViewDebug { final Method method = methods[i]; //noinspection EmptyCatchBlock try { - // TODO: This should happen on the UI thread - Object methodValue = method.invoke(view, (Object[]) null); + Object methodValue = callMethodOnAppropriateTheadBlocking(method, view); final Class<?> returnType = method.getReturnType(); final ExportedProperty property = sAnnotations.get(method); String categoryPrefix = @@ -1033,6 +1080,7 @@ public class ViewDebug { writeEntry(out, categoryPrefix + prefix, method.getName(), "()", methodValue); } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { + } catch (TimeoutException e) { } } } |