Merge "Adds UiAutomator 'drag' APIs to UiObject and UiDevice"
diff --git a/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java b/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java
index 6f5ac1c..13d7f36 100644
--- a/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java
+++ b/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java
@@ -17,7 +17,10 @@
 package com.android.commands.uiautomator;
 
 import android.app.UiAutomation;
+import android.graphics.Point;
+import android.hardware.display.DisplayManagerGlobal;
 import android.os.Environment;
+import android.view.Display;
 import android.view.accessibility.AccessibilityNodeInfo;
 
 import com.android.commands.uiautomator.Launcher.Command;
@@ -72,7 +75,13 @@
                 System.err.println("ERROR: null root node returned by UiTestAutomationBridge.");
                 return;
             }
-            AccessibilityNodeInfoDumper.dumpWindowToFile(info, dumpFile);
+
+            Display display =
+                    DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
+            int rotation = display.getRotation();
+            Point size = new Point();
+            display.getSize(size);
+            AccessibilityNodeInfoDumper.dumpWindowToFile(info, dumpFile, rotation, size.x, size.y);
         } catch (TimeoutException re) {
             System.err.println("ERROR: could not get idle state.");
             return;
diff --git a/uiautomator/instrumentation/Android.mk b/uiautomator/instrumentation/Android.mk
new file mode 100644
index 0000000..ed20993
--- /dev/null
+++ b/uiautomator/instrumentation/Android.mk
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, testrunner-src) \
+    $(call all-java-files-under, ../library/core-src)
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_MODULE := uiautomator-instrumentation
+# below to be uncommented once core-src is using public API only
+#LOCAL_SDK_VERSION := current
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/core/OnDeviceUiAutomatorBridge.java b/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/core/InstrumentationUiAutomatorBridge.java
similarity index 87%
rename from uiautomator/instrumentation/testrunner-src/com/android/uiautomator/core/OnDeviceUiAutomatorBridge.java
rename to uiautomator/instrumentation/testrunner-src/com/android/uiautomator/core/InstrumentationUiAutomatorBridge.java
index e40bd14..1d4fb93 100644
--- a/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/core/OnDeviceUiAutomatorBridge.java
+++ b/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/core/InstrumentationUiAutomatorBridge.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -27,11 +27,11 @@
 /**
  * @hide
  */
-public class OnDeviceUiAutomatorBridge extends UiAutomatorBridge {
+public class InstrumentationUiAutomatorBridge extends UiAutomatorBridge {
 
     private final Context mContext;
 
-    public OnDeviceUiAutomatorBridge(Context context, UiAutomation uiAutomation) {
+    public InstrumentationUiAutomatorBridge(Context context, UiAutomation uiAutomation) {
         super(uiAutomation);
         mContext = context;
     }
diff --git a/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/OnDeviceUiTestCase.java b/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/OnDeviceUiTestCase.java
deleted file mode 100644
index 00897c4..0000000
--- a/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/OnDeviceUiTestCase.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.uiautomator.testrunner;
-
-import android.app.UiAutomation;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.test.AndroidTestCase;
-import android.view.inputmethod.InputMethodInfo;
-
-import com.android.internal.view.IInputMethodManager;
-import com.android.uiautomator.core.OnDeviceUiAutomatorBridge;
-import com.android.uiautomator.core.UiDevice;
-
-import java.util.List;
-
-/**
- * UI automator test case that is executed on the device.
- */
-public class OnDeviceUiTestCase extends AndroidTestCase {
-    private static final String DISABLE_IME = "disable_ime";
-    private static final String DUMMY_IME_PACKAGE = "com.android.testing.dummyime";
-    private boolean mShouldDisableIme;
-
-    private UiAutomation mUiAutomation;
-    private Bundle mParams;
-
-    private final IAutomationSupport mAutomationSupport = new IAutomationSupport() {
-        @Override
-        public void sendStatus(int resultCode, Bundle status) {
-            sendStatus(resultCode, status);
-        }
-    };
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        UiDevice.getInstance().initialize(new OnDeviceUiAutomatorBridge(mContext, mUiAutomation));
-        mShouldDisableIme = "true".equals(getParams().getString(DISABLE_IME));
-        if (mShouldDisableIme) {
-            setDummyIme();
-        }
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        if (mShouldDisableIme) {
-            restoreActiveIme();
-        }
-        super.tearDown();
-    }
-
-    /**
-     * Get current instance of {@link UiDevice}. Works similar to calling the static
-     * {@link UiDevice#getInstance()} from anywhere in the test classes.
-     * @since API Level 16
-     */
-    public UiDevice getUiDevice() {
-        return UiDevice.getInstance();
-    }
-
-    /**
-     * Get command line parameters. On the command line when passing <code>-e key value</code>
-     * pairs, the {@link Bundle} will have the key value pairs conveniently available to the
-     * tests.
-     * @since API Level 16
-     */
-    public Bundle getParams() {
-        return mParams;
-    }
-
-    /**
-     * Initializes this test case.
-     *
-     * @param uiAutomation An {@link UiAutomation} instance.
-     * @param params Instrumentation arguments.
-     */
-    void initialize(UiAutomation uiAutomation,  Bundle params) {
-        mUiAutomation = uiAutomation;
-        mParams = params;
-    }
-
-    /**
-     * Provides support for running tests to report interim status
-     *
-     * @return IAutomationSupport
-     * @since API Level 16
-     */
-    public IAutomationSupport getAutomationSupport() {
-        return mAutomationSupport;
-    }
-
-    /**
-     * Calls {@link SystemClock#sleep(long)} to sleep
-     * @param ms is in milliseconds.
-     * @since API Level 16
-     */
-    public void sleep(long ms) {
-        SystemClock.sleep(ms);
-    }
-
-    private void setDummyIme() throws RemoteException {
-        IInputMethodManager im = IInputMethodManager.Stub.asInterface(ServiceManager
-                .getService(Context.INPUT_METHOD_SERVICE));
-        List<InputMethodInfo> infos = im.getInputMethodList();
-        String id = null;
-        for (InputMethodInfo info : infos) {
-            if (DUMMY_IME_PACKAGE.equals(info.getComponent().getPackageName())) {
-                id = info.getId();
-            }
-        }
-        if (id == null) {
-            throw new RuntimeException(String.format(
-                    "Required testing fixture missing: IME package (%s)", DUMMY_IME_PACKAGE));
-        }
-        im.setInputMethod(null, id);
-    }
-
-    private void restoreActiveIme() throws RemoteException {
-        // TODO: figure out a way to restore active IME
-        // Currently retrieving active IME requires querying secure settings provider, which is hard
-        // to do without a Context; so the caveat here is that to make the post test device usable,
-        // the active IME needs to be manually switched.
-    }
-}
diff --git a/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/OnDeviceUiTestRunner.java b/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/OnDeviceUiTestRunner.java
deleted file mode 100644
index 857d7e9..0000000
--- a/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/OnDeviceUiTestRunner.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.uiautomator.testrunner;
-
-import android.test.AndroidTestRunner;
-import android.test.InstrumentationTestRunner;
-
-import junit.framework.TestCase;
-import junit.framework.TestResult;
-
-import java.util.List;
-
-/**
- * Test runner for {@link OnDeviceUiTestCase}s. Such tests are executed
- * on the device and have access to an applications context.
- */
-public class OnDeviceUiTestRunner extends InstrumentationTestRunner {
-
-    @Override
-    protected AndroidTestRunner getAndroidTestRunner() {
-        return new AndroidTestRunner() {
-            @Override
-            public void runTest(TestResult testResult) {
-                List<TestCase> testCases = getTestCases();
-                final int testCaseCount = testCases.size();
-                for (int i = 0; i < testCaseCount; i++) {
-                    TestCase testCase = testCases.get(i);
-                    if (testCase instanceof OnDeviceUiTestCase) {
-                        OnDeviceUiTestCase uiTestCase = (OnDeviceUiTestCase) testCase;
-                        uiTestCase.initialize(OnDeviceUiTestRunner.this.getUiAutomation(),
-                                getArguments());
-                    }
-                }
-                super.runTest(testResult);
-            }
-        };
-    }
-}
diff --git a/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorInstrumentationTestRunner.java b/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorInstrumentationTestRunner.java
new file mode 100644
index 0000000..ae763f2
--- /dev/null
+++ b/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorInstrumentationTestRunner.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.uiautomator.testrunner;
+
+import android.test.AndroidTestRunner;
+import android.test.InstrumentationTestRunner;
+
+import com.android.uiautomator.core.Tracer;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestListener;
+
+/**
+ * Test runner for {@link UiAutomatorTestCase}s. Such tests are executed
+ * on the device and have access to an applications context.
+ */
+public class UiAutomatorInstrumentationTestRunner extends InstrumentationTestRunner {
+
+    @Override
+    public void onStart() {
+        // process runner arguments before test starts
+        String traceType = getArguments().getString("traceOutputMode");
+        if(traceType != null) {
+            Tracer.Mode mode = Tracer.Mode.valueOf(Tracer.Mode.class, traceType);
+            if (mode == Tracer.Mode.FILE || mode == Tracer.Mode.ALL) {
+                String filename = getArguments().getString("traceLogFilename");
+                if (filename == null) {
+                    throw new RuntimeException("Name of log file not specified. " +
+                            "Please specify it using traceLogFilename parameter");
+                }
+                Tracer.getInstance().setOutputFilename(filename);
+            }
+            Tracer.getInstance().setOutputMode(mode);
+        }
+        super.onStart();
+    }
+
+    @Override
+    protected AndroidTestRunner getAndroidTestRunner() {
+        AndroidTestRunner testRunner = super.getAndroidTestRunner();
+        testRunner.addTestListener(new TestListener() {
+            @Override
+            public void startTest(Test test) {
+                if (test instanceof UiAutomatorTestCase) {
+                    ((UiAutomatorTestCase)test).initialize(getArguments());
+                }
+            }
+
+            @Override
+            public void endTest(Test test) {
+            }
+
+            @Override
+            public void addFailure(Test test, AssertionFailedError e) {
+            }
+
+            @Override
+            public void addError(Test test, Throwable t) {
+            }
+        });
+        return testRunner;
+    }
+}
diff --git a/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java b/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java
new file mode 100644
index 0000000..eaaef14
--- /dev/null
+++ b/uiautomator/instrumentation/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.uiautomator.testrunner;
+
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.test.InstrumentationTestCase;
+
+import com.android.uiautomator.core.InstrumentationUiAutomatorBridge;
+import com.android.uiautomator.core.UiDevice;
+
+/**
+ * UI Automator test case that is executed on the device.
+ */
+public class UiAutomatorTestCase extends InstrumentationTestCase {
+
+    private Bundle mParams;
+
+    /**
+     * Get current instance of {@link UiDevice}. Works similar to calling the static
+     * {@link UiDevice#getInstance()} from anywhere in the test classes.
+     * @since API Level 16
+     */
+    public UiDevice getUiDevice() {
+        return UiDevice.getInstance();
+    }
+
+    /**
+     * Get command line parameters. On the command line when passing <code>-e key value</code>
+     * pairs, the {@link Bundle} will have the key value pairs conveniently available to the
+     * tests.
+     * @since API Level 16
+     */
+    public Bundle getParams() {
+        return mParams;
+    }
+
+    /**
+     * Initializes this test case.
+     *
+     * @param params Instrumentation arguments.
+     */
+    void initialize(Bundle params) {
+        mParams = params;
+        UiDevice.getInstance().initialize(new InstrumentationUiAutomatorBridge(
+                getInstrumentation().getContext(),
+                getInstrumentation().getUiAutomation()));
+    }
+
+    /**
+     * Calls {@link SystemClock#sleep(long)} to sleep
+     * @param ms is in milliseconds.
+     * @since API Level 16
+     */
+    public void sleep(long ms) {
+        SystemClock.sleep(ms);
+    }
+}
diff --git a/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java b/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
index aae9cf2..63c51e8 100644
--- a/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
+++ b/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
@@ -16,21 +16,19 @@
 
 package com.android.uiautomator.core;
 
-import android.hardware.display.DisplayManagerGlobal;
 import android.os.Environment;
 import android.os.SystemClock;
 import android.util.Log;
 import android.util.Xml;
-import android.view.Display;
 import android.view.accessibility.AccessibilityNodeInfo;
 
+import org.xmlpull.v1.XmlSerializer;
+
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.StringWriter;
 
-import org.xmlpull.v1.XmlSerializer;
-
 /**
  *
  * @hide
@@ -46,9 +44,13 @@
     /**
      * Using {@link AccessibilityNodeInfo} this method will walk the layout hierarchy
      * and generates an xml dump into the /data/local/window_dump.xml
-     * @param info
+     * @param root The root accessibility node.
+     * @param rotation The rotaion of current display
+     * @param width The pixel width of current display
+     * @param height The pixel height of current display
      */
-    public static void dumpWindowToFile(AccessibilityNodeInfo info) {
+    public static void dumpWindowToFile(AccessibilityNodeInfo root, int rotation,
+            int width, int height) {
         File baseDir = new File(Environment.getDataDirectory(), "local");
         if (!baseDir.exists()) {
             baseDir.mkdir();
@@ -56,8 +58,9 @@
             baseDir.setWritable(true, false);
             baseDir.setReadable(true, false);
         }
-        dumpWindowToFile(info, new File(
-                new File(Environment.getDataDirectory(), "local"), "window_dump.xml"));
+        dumpWindowToFile(root,
+                new File(new File(Environment.getDataDirectory(), "local"), "window_dump.xml"),
+                rotation, width, height);
     }
 
     /**
@@ -65,8 +68,12 @@
      * and generates an xml dump to the location specified by <code>dumpFile</code>
      * @param root The root accessibility node.
      * @param dumpFile The file to dump to.
+     * @param rotation The rotaion of current display
+     * @param width The pixel width of current display
+     * @param height The pixel height of current display
      */
-    public static void dumpWindowToFile(AccessibilityNodeInfo root, File dumpFile) {
+    public static void dumpWindowToFile(AccessibilityNodeInfo root, File dumpFile, int rotation,
+            int width, int height) {
         if (root == null) {
             return;
         }
@@ -78,10 +85,8 @@
             serializer.setOutput(stringWriter);
             serializer.startDocument("UTF-8", true);
             serializer.startTag("", "hierarchy");
-            serializer.attribute("", "rotation", Integer.toString(
-                    DisplayManagerGlobal.getInstance().getRealDisplay(
-                            Display.DEFAULT_DISPLAY).getRotation()));
-            dumpNodeRec(root, serializer, 0);
+            serializer.attribute("", "rotation", Integer.toString(rotation));
+            dumpNodeRec(root, serializer, 0, width, height);
             serializer.endTag("", "hierarchy");
             serializer.endDocument();
             writer.write(stringWriter.toString());
@@ -93,8 +98,8 @@
         Log.w(LOGTAG, "Fetch time: " + (endTime - startTime) + "ms");
     }
 
-    private static void dumpNodeRec(AccessibilityNodeInfo node, XmlSerializer serializer,
-            int index) throws IOException {
+    private static void dumpNodeRec(AccessibilityNodeInfo node, XmlSerializer serializer,int index,
+            int width, int height) throws IOException {
         serializer.startTag("", "node");
         if (!nafExcludedClass(node) && !nafCheck(node))
             serializer.attribute("", "NAF", Boolean.toString(true));
@@ -114,14 +119,14 @@
         serializer.attribute("", "long-clickable", Boolean.toString(node.isLongClickable()));
         serializer.attribute("", "password", Boolean.toString(node.isPassword()));
         serializer.attribute("", "selected", Boolean.toString(node.isSelected()));
-        serializer.attribute("", "bounds",
-                AccessibilityNodeInfoHelper.getVisibleBoundsInScreen(node).toShortString());
+        serializer.attribute("", "bounds", AccessibilityNodeInfoHelper.getVisibleBoundsInScreen(
+                node, width, height).toShortString());
         int count = node.getChildCount();
         for (int i = 0; i < count; i++) {
             AccessibilityNodeInfo child = node.getChild(i);
             if (child != null) {
                 if (child.isVisibleToUser()) {
-                    dumpNodeRec(child, serializer, i);
+                    dumpNodeRec(child, serializer, i, width, height);
                     child.recycle();
                 } else {
                     Log.i(LOGTAG, String.format("Skipping invisible child: %s", child.toString()));
diff --git a/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoHelper.java b/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoHelper.java
index d66e408..54835e3 100644
--- a/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoHelper.java
+++ b/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoHelper.java
@@ -15,10 +15,7 @@
  */
 package com.android.uiautomator.core;
 
-import android.graphics.Point;
 import android.graphics.Rect;
-import android.hardware.display.DisplayManagerGlobal;
-import android.view.Display;
 import android.view.accessibility.AccessibilityNodeInfo;
 
 /**
@@ -31,9 +28,11 @@
      * Returns the node's bounds clipped to the size of the display
      *
      * @param node
+     * @param width pixel width of the display
+     * @param height pixel height of the display
      * @return null if node is null, else a Rect containing visible bounds
      */
-    static Rect getVisibleBoundsInScreen(AccessibilityNodeInfo node) {
+    static Rect getVisibleBoundsInScreen(AccessibilityNodeInfo node, int width, int height) {
         if (node == null) {
             return null;
         }
@@ -42,14 +41,10 @@
         node.getBoundsInScreen(nodeRect);
 
         Rect displayRect = new Rect();
-        Display display = DisplayManagerGlobal.getInstance()
-                .getRealDisplay(Display.DEFAULT_DISPLAY);
-        Point outSize = new Point();
-        display.getSize(outSize);
         displayRect.top = 0;
         displayRect.left = 0;
-        displayRect.right = outSize.x;
-        displayRect.bottom = outSize.y;
+        displayRect.right = width;
+        displayRect.bottom = height;
 
         nodeRect.intersect(displayRect);
         return nodeRect;
diff --git a/uiautomator/library/core-src/com/android/uiautomator/core/InteractionController.java b/uiautomator/library/core-src/com/android/uiautomator/core/InteractionController.java
index 7d19d1e..a00f2ea 100644
--- a/uiautomator/library/core-src/com/android/uiautomator/core/InteractionController.java
+++ b/uiautomator/library/core-src/com/android/uiautomator/core/InteractionController.java
@@ -193,13 +193,13 @@
             @Override
             public void run() {
                 final long eventTime = SystemClock.uptimeMillis();
-                KeyEvent downEvent = KeyEvent.obtain(eventTime, eventTime, KeyEvent.ACTION_DOWN,
+                KeyEvent downEvent = new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN,
                         keyCode, 0, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0,
-                        InputDevice.SOURCE_KEYBOARD, null);
+                        InputDevice.SOURCE_KEYBOARD);
                 if (injectEventSync(downEvent)) {
-                    KeyEvent upEvent = KeyEvent.obtain(eventTime, eventTime, KeyEvent.ACTION_UP,
+                    KeyEvent upEvent = new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_UP,
                             keyCode, 0, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0,
-                            InputDevice.SOURCE_KEYBOARD, null);
+                            InputDevice.SOURCE_KEYBOARD);
                     injectEventSync(upEvent);
                 }
             }
@@ -546,13 +546,13 @@
         }
 
         final long eventTime = SystemClock.uptimeMillis();
-        KeyEvent downEvent = KeyEvent.obtain(eventTime, eventTime, KeyEvent.ACTION_DOWN,
+        KeyEvent downEvent = new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN,
                 keyCode, 0, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0,
-                InputDevice.SOURCE_KEYBOARD, null);
+                InputDevice.SOURCE_KEYBOARD);
         if (injectEventSync(downEvent)) {
-            KeyEvent upEvent = KeyEvent.obtain(eventTime, eventTime, KeyEvent.ACTION_UP,
+            KeyEvent upEvent = new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_UP,
                     keyCode, 0, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0,
-                    InputDevice.SOURCE_KEYBOARD, null);
+                    InputDevice.SOURCE_KEYBOARD);
             if(injectEventSync(upEvent)) {
                 return true;
             }
@@ -561,17 +561,6 @@
     }
 
     /**
-     * Check if the device is in its natural orientation. This is determined by
-     * checking whether the orientation is at 0 or 180 degrees.
-     * @return true if it is in natural orientation
-     * @throws RemoteException
-     */
-    public boolean isNaturalRotation() throws RemoteException {
-        int ret = mUiAutomatorBridge.getRotation();
-        return ret == UiAutomation.ROTATION_FREEZE_0 || ret == UiAutomation.ROTATION_FREEZE_180;
-    }
-
-    /**
      * Rotates right and also freezes rotation in that position by
      * disabling the sensors. If you want to un-freeze the rotation
      * and re-enable the sensors see {@link #unfreezeRotation()}. Note
diff --git a/uiautomator/library/core-src/com/android/uiautomator/core/UiAutomatorBridge.java b/uiautomator/library/core-src/com/android/uiautomator/core/UiAutomatorBridge.java
index a15cc24..3b519ed 100644
--- a/uiautomator/library/core-src/com/android/uiautomator/core/UiAutomatorBridge.java
+++ b/uiautomator/library/core-src/com/android/uiautomator/core/UiAutomatorBridge.java
@@ -58,14 +58,6 @@
         return mQueryController;
     }
 
-    public void connect() {
-        mUiAutomation.connect();
-    }
-
-    public void disconnect() {
-        mUiAutomation.disconnect();
-    }
-
     public void setOnAccessibilityEventListener(OnAccessibilityEventListener listener) {
         mUiAutomation.setOnAccessibilityEventListener(listener);
     }
diff --git a/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java b/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java
index 1b716f0..4d8016e 100644
--- a/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java
+++ b/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java
@@ -16,12 +16,9 @@
 
 package com.android.uiautomator.core;
 
+import android.app.UiAutomation;
 import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
 import android.graphics.Point;
-import android.hardware.display.DisplayManagerGlobal;
 import android.os.Build;
 import android.os.Environment;
 import android.os.RemoteException;
@@ -39,8 +36,6 @@
 import com.android.internal.util.Predicate;
 
 import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -120,7 +115,7 @@
      */
     public Point getDisplaySizeDp() {
         Tracer.trace();
-        Display display = getDefaultDisplay();
+        Display display = mUiAutomationBridge.getDefaultDisplay();
         Point p = new Point();
         display.getRealSize(p);
         DisplayMetrics metrics = new DisplayMetrics();
@@ -351,7 +346,7 @@
      */
     public int getDisplayWidth() {
         Tracer.trace();
-        Display display = getDefaultDisplay();
+        Display display = mUiAutomationBridge.getDefaultDisplay();
         Point p = new Point();
         display.getSize(p);
         return p.x;
@@ -365,7 +360,7 @@
      */
     public int getDisplayHeight() {
         Tracer.trace();
-        Display display = getDefaultDisplay();
+        Display display = mUiAutomationBridge.getDefaultDisplay();
         Point p = new Point();
         display.getSize(p);
         return p.y;
@@ -599,9 +594,9 @@
      */
     public boolean isNaturalOrientation() {
         Tracer.trace();
-        Display display = getDefaultDisplay();
-        return display.getRotation() == Surface.ROTATION_0 ||
-                display.getRotation() == Surface.ROTATION_180;
+        int ret = mUiAutomationBridge.getRotation();
+        return ret == UiAutomation.ROTATION_FREEZE_0 ||
+                ret == UiAutomation.ROTATION_FREEZE_180;
     }
 
     /**
@@ -611,7 +606,7 @@
     public int getDisplayRotation() {
         Tracer.trace();
         waitForIdle();
-        return getDefaultDisplay().getRotation();
+        return mUiAutomationBridge.getRotation();
     }
 
     /**
@@ -732,9 +727,12 @@
         AccessibilityNodeInfo root =
                 getAutomatorBridge().getQueryController().getAccessibilityRootNode();
         if(root != null) {
-            AccessibilityNodeInfoDumper.dumpWindowToFile(
-                    root, new File(new File(Environment.getDataDirectory(),
-                            "local/tmp"), fileName));
+            Display display = mUiAutomationBridge.getDefaultDisplay();
+            Point size = new Point();
+            display.getSize(size);
+            AccessibilityNodeInfoDumper.dumpWindowToFile(root,
+                    new File(new File(Environment.getDataDirectory(), "local/tmp"), fileName),
+                    display.getRotation(), size.x, size.y);
         }
     }
 
@@ -785,25 +783,6 @@
         return true;
     }
 
-    private static Display getDefaultDisplay() {
-        return DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
-    }
-
-    /**
-     * @return the current display rotation in degrees
-     */
-    private static float getDegreesForRotation(int value) {
-        switch (value) {
-        case Surface.ROTATION_90:
-            return 360f - 90f;
-        case Surface.ROTATION_180:
-            return 360f - 180f;
-        case Surface.ROTATION_270:
-            return 360f - 270f;
-        }
-        return 0f;
-    }
-
     /**
      * Take a screenshot of current window and store it as PNG
      *
@@ -832,66 +811,6 @@
      */
     public boolean takeScreenshot(File storePath, float scale, int quality) {
         Tracer.trace(storePath, scale, quality);
-        // This is from com.android.systemui.screenshot.GlobalScreenshot#takeScreenshot
-        // We need to orient the screenshot correctly (and the Surface api seems to take screenshots
-        // only in the natural orientation of the device :!)
-        DisplayMetrics displayMetrics = new DisplayMetrics();
-        Display display = getDefaultDisplay();
-        display.getRealMetrics(displayMetrics);
-        float[] dims = {displayMetrics.widthPixels, displayMetrics.heightPixels};
-        float degrees = getDegreesForRotation(display.getRotation());
-        boolean requiresRotation = (degrees > 0);
-        Matrix matrix = new Matrix();
-        matrix.reset();
-        if (scale != 1.0f) {
-            matrix.setScale(scale, scale);
-        }
-        if (requiresRotation) {
-            // Get the dimensions of the device in its native orientation
-            matrix.preRotate(-degrees);
-        }
-        matrix.mapPoints(dims);
-        dims[0] = Math.abs(dims[0]);
-        dims[1] = Math.abs(dims[1]);
-
-        // Take the screenshot
-        Bitmap screenShot = Surface.screenshot((int) dims[0], (int) dims[1]);
-        if (screenShot == null) {
-            return false;
-        }
-
-        if (requiresRotation) {
-            // Rotate the screenshot to the current orientation
-            int width = displayMetrics.widthPixels;
-            int height = displayMetrics.heightPixels;
-            if (scale != 1.0f) {
-                width = Math.round(scale * width);
-                height = Math.round(scale * height);
-            }
-            Bitmap ss = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-            Canvas c = new Canvas(ss);
-            c.translate(ss.getWidth() / 2, ss.getHeight() / 2);
-            c.rotate(degrees);
-            c.translate(-dims[0] / 2, -dims[1] / 2);
-            c.drawBitmap(screenShot, 0, 0, null);
-            c.setBitmap(null);
-            screenShot = ss;
-        }
-
-        // Optimizations
-        screenShot.setHasAlpha(false);
-
-        try {
-            FileOutputStream fos = new FileOutputStream(storePath);
-            screenShot.compress(Bitmap.CompressFormat.PNG, quality, fos);
-            fos.flush();
-            fos.close();
-        } catch (IOException ioe) {
-            Log.e(LOG_TAG, "failed to save screen shot to file", ioe);
-            return false;
-        } finally {
-            screenShot.recycle();
-        }
-        return true;
+        return mUiAutomationBridge.takeScreenshot(storePath, quality);
     }
 }
diff --git a/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java b/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java
index ab95545..8e82a98 100644
--- a/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java
+++ b/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java
@@ -326,7 +326,9 @@
         }
 
         // targeted node's bounds
-        Rect nodeRect = AccessibilityNodeInfoHelper.getVisibleBoundsInScreen(node);
+        int w = UiDevice.getInstance().getDisplayWidth();
+        int h = UiDevice.getInstance().getDisplayHeight();
+        Rect nodeRect = AccessibilityNodeInfoHelper.getVisibleBoundsInScreen(node, w, h);
 
         // is the targeted node within a scrollable container?
         AccessibilityNodeInfo scrollableParentNode = getScrollableParent(node);
@@ -337,7 +339,7 @@
 
         // Scrollable parent's visible bounds
         Rect parentRect = AccessibilityNodeInfoHelper
-                .getVisibleBoundsInScreen(scrollableParentNode);
+                .getVisibleBoundsInScreen(scrollableParentNode, w, h);
         // adjust for partial clipping of targeted by parent node if required
         nodeRect.intersect(parentRect);
         return nodeRect;
@@ -1059,4 +1061,4 @@
     public void multiPointerGesture(PointerCoords[] ...touches) {
         getInteractionController().generateMultiPointerGesture(touches);
     }
-}
\ No newline at end of file
+}