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
+}