am 43261fa6: updates to released API level 16 method list
* commit '43261fa64275ebae7d30ebdfbc1e8db7680aa010':
updates to released API level 16 method list
diff --git a/uiautomator/library/Android.mk b/uiautomator/library/Android.mk
index a9ad065..d4b745a 100644
--- a/uiautomator/library/Android.mk
+++ b/uiautomator/library/Android.mk
@@ -19,7 +19,7 @@
uiautomator.core_src_files := $(call all-java-files-under, src)
uiautomator.core_java_libraries := android.test.runner core-junit
-INTERNAL_UIAUTOMATOR_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/uiautomator_api.txt
+uiautomator_internal_api_file := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/uiautomator_api.txt
###############################################
include $(CLEAR_VARS)
@@ -40,7 +40,7 @@
LOCAL_DROIDDOC_OPTIONS:= \
-stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android_uiautomator_intermediates/src \
-stubpackages com.android.uiautomator.core:com.android.uiautomator.testrunner \
- -api $(INTERNAL_UIAUTOMATOR_API_FILE) \
+ -api $(uiautomator_internal_api_file) \
-nodocs
LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR := build/tools/droiddoc/templates-sdk
@@ -49,7 +49,8 @@
LOCAL_MODULE := uiautomator-stubs
include $(BUILD_DROIDDOC)
-uiautomator-stubs-stamp := $(full_target)
+uiautomator_stubs_stamp := $(full_target)
+$(uiautomator_internal_api_file) : $(full_target)
###############################################
# Build the stub source files into a jar.
@@ -59,10 +60,63 @@
LOCAL_SOURCE_FILES_ALL_GENERATED := true
include $(BUILD_STATIC_JAVA_LIBRARY)
# Make sure to run droiddoc first to generate the stub source files.
-$(full_classes_compiled_jar) : $(uiautomator-stubs-stamp)
+$(full_classes_compiled_jar) : $(uiautomator_stubs_stamp)
+uiautomator_stubs_jar := $(full_classes_compiled_jar)
+
+###############################################
+# API check
+# Please refer to build/core/tasks/apicheck.mk.
+uiautomator_api_dir := frameworks/testing/uiautomator/api
+last_released_sdk_version := $(lastword $(call numerically_sort, \
+ $(filter-out current, \
+ $(patsubst $(uiautomator_api_dir)/%.txt,%, $(wildcard $(uiautomator_api_dir)/*.txt)) \
+ )))
+
+checkapi_last_error_level_flags := \
+ -hide 2 -hide 3 -hide 4 -hide 5 -hide 6 -hide 24 -hide 25 \
+ -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \
+ -error 16 -error 17 -error 18
+
+# Check that the API we're building hasn't broken the last-released SDK version.
+$(eval $(call check-api, \
+ uiautomator-checkapi-last, \
+ $(uiautomator_api_dir)/$(last_released_sdk_version).txt, \
+ $(uiautomator_internal_api_file), \
+ $(checkapi_last_error_level_flags), \
+ cat $(LOCAL_PATH)/apicheck_msg_last.txt, \
+ $(uiautomator_stubs_jar), \
+ $(uiautomator_stubs_stamp)))
+
+checkapi_current_error_level_flags := \
+ -error 2 -error 3 -error 4 -error 5 -error 6 \
+ -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \
+ -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \
+ -error 25
+
+# Check that the API we're building hasn't changed from the not-yet-released
+# SDK version.
+$(eval $(call check-api, \
+ uiautomator-checkapi-current, \
+ $(uiautomator_api_dir)/current.txt, \
+ $(uiautomator_internal_api_file), \
+ $(checkapi_current_error_level_flags), \
+ cat $(LOCAL_PATH)/apicheck_msg_current.txt, \
+ $(uiautomator_stubs_jar), \
+ $(uiautomator_stubs_stamp)))
+
+.PHONY: update-uiautomator-api
+update-uiautomator-api: PRIVATE_API_DIR := $(uiautomator_api_dir)
+update-uiautomator-api: $(uiautomator_internal_api_file) | $(ACP)
+ @echo Copying uiautomator current.txt
+ $(hide) $(ACP) $< $(PRIVATE_API_DIR)/current.txt
###############################################
# clean up temp vars
uiautomator.core_src_files :=
uiautomator.core_java_libraries :=
-uiautomator-stubs-stamp :=
+uiautomator_stubs_stamp :=
+uiautomator_internal_api_file :=
+uiautomator_stubs_jar :=
+uiautomator_api_dir :=
+checkapi_last_error_level_flags :=
+checkapi_current_error_level_flags :=
diff --git a/uiautomator/library/apicheck_msg_current.txt b/uiautomator/library/apicheck_msg_current.txt
new file mode 100644
index 0000000..989248d
--- /dev/null
+++ b/uiautomator/library/apicheck_msg_current.txt
@@ -0,0 +1,17 @@
+
+******************************
+You have tried to change the API from what has been previously approved.
+
+To make these errors go away, you have two choices:
+ 1) You can add "@hide" javadoc comments to the methods, etc. listed in the
+ errors above.
+
+ 2) You can update current.txt by executing the following command:
+ make update-uiautomator-api
+
+ To submit the revised current.txt to the main Android repository,
+ you will need approval.
+******************************
+
+
+
diff --git a/uiautomator/library/apicheck_msg_last.txt b/uiautomator/library/apicheck_msg_last.txt
new file mode 100644
index 0000000..2993157
--- /dev/null
+++ b/uiautomator/library/apicheck_msg_last.txt
@@ -0,0 +1,7 @@
+
+******************************
+You have tried to change the API from what has been previously released in
+an SDK. Please fix the errors listed above.
+******************************
+
+
diff --git a/uiautomator/library/src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java b/uiautomator/library/src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
index 65fcd28..10878e3 100644
--- a/uiautomator/library/src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
+++ b/uiautomator/library/src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
@@ -63,7 +63,8 @@
/**
* Using {@link AccessibilityNodeInfo} this method will walk the layout hierarchy
* and generates an xml dump to the location specified by <code>dumpFile</code>
- * @param info
+ * @param root The root accessibility node.
+ * @param dumpFile The file to dump to.
*/
public static void dumpWindowToFile(AccessibilityNodeInfo root, File dumpFile) {
if (root == null) {
@@ -137,11 +138,11 @@
* only reduce noise from standard layout classes that may be falsely
* configured to accept clicks and are also enabled.
*
- * @param n
- * @return
+ * @param node
+ * @return true if node is excluded.
*/
- private static boolean nafExcludedClass(AccessibilityNodeInfo n) {
- String className = safeCharSeqToString(n.getClassName());
+ private static boolean nafExcludedClass(AccessibilityNodeInfo node) {
+ String className = safeCharSeqToString(node.getClassName());
for(String excludedClassName : NAF_EXCLUDED_CLASSES) {
if(className.endsWith(excludedClassName))
return true;
@@ -183,7 +184,7 @@
* considered by this dumper as acceptable for accessibility.
*
* @param node
- * @return
+ * @return false if node fails the check.
*/
private static boolean childNafCheck(AccessibilityNodeInfo node) {
int childCount = node.getChildCount();
diff --git a/uiautomator/library/src/com/android/uiautomator/core/InteractionController.java b/uiautomator/library/src/com/android/uiautomator/core/InteractionController.java
index 9a4df13..0fc6466 100644
--- a/uiautomator/library/src/com/android/uiautomator/core/InteractionController.java
+++ b/uiautomator/library/src/com/android/uiautomator/core/InteractionController.java
@@ -162,7 +162,7 @@
* @param timeout
* @param waitForAll boolean to indicate whether to wait for any or all events
* @param eventTypes mask
- * @return
+ * @return true if events are received, else false if timeout.
*/
public boolean clickAndWaitForEvents(final int x, final int y, long timeout,
boolean waitForAll, int eventTypes) {
@@ -180,7 +180,7 @@
}
}
};
- return runAndWaitForEvents(command, timeout, waitForAll, eventTypes);
+ return runAndWaitForEvents(command, timeout, waitForAll, eventTypes) != null;
}
/**
@@ -188,9 +188,9 @@
* @param command is a Runnable to execute before waiting for the event.
* @param timeout
* @param eventType
- * @return
+ * @return The AccessibilityEvent if one is received, otherwise null.
*/
- private boolean runAndWaitForEvent(Runnable command, long timeout, int eventType) {
+ private AccessibilityEvent runAndWaitForEvent(Runnable command, long timeout, int eventType) {
return runAndWaitForEvents(command, timeout, false, eventType);
}
@@ -202,11 +202,10 @@
* @param timeout
* @param waitForAll boolean to indicate whether to wait for any or all events
* @param eventTypesMask
- * @return
+ * @return The AccessibilityEvent if one is received, otherwise null.
*/
- private boolean runAndWaitForEvents(Runnable command, long timeout, final boolean waitForAll,
- final int eventTypesMask) {
-
+ private AccessibilityEvent runAndWaitForEvents(Runnable command, long timeout,
+ final boolean waitForAll, final int eventTypesMask) {
if (eventTypesMask == 0)
throw new IllegalArgumentException("events mask cannot be zero");
@@ -237,17 +236,18 @@
}
}
+ AccessibilityEvent event = null;
try {
- mUiAutomatorBridge.executeCommandAndWaitForAccessibilityEvent(command,
+ event = mUiAutomatorBridge.executeCommandAndWaitForAccessibilityEvent(command,
new EventPredicate(eventTypesMask), timeout);
} catch (TimeoutException e) {
Log.w(LOG_TAG, "runAndwaitForEvent timedout waiting for events: " + eventTypesMask);
- return false;
+ return null;
} catch (Exception e) {
Log.e(LOG_TAG, "exception from executeCommandAndWaitForAccessibilityEvent", e);
- return false;
+ return null;
}
- return true;
+ return event;
}
/**
@@ -255,14 +255,14 @@
*
* Most key presses will cause some UI change to occur. If the device is busy, this will
* block until the device begins to process the key press at which point the call returns
- * and normal wait for idle processing may begin. If no evens are detected for the
+ * and normal wait for idle processing may begin. If no events are detected for the
* timeout period specified, the call will return anyway with false.
*
* @param keyCode
* @param metaState
* @param eventType
* @param timeout
- * @return
+ * @return true if events is received, otherwise false.
*/
public boolean sendKeyAndWaitForEvent(final int keyCode, final int metaState,
final int eventType, long timeout) {
@@ -283,7 +283,7 @@
}
};
- return runAndWaitForEvent(command, timeout, eventType);
+ return runAndWaitForEvent(command, timeout, eventType) != null;
}
/**
@@ -291,7 +291,7 @@
* that require stressing the target.
* @param x
* @param y
- * @return
+ * @return true if the click executed successfully
*/
public boolean click(int x, int y) {
Log.d(LOG_TAG, "click (" + x + ", " + y + ")");
@@ -376,8 +376,8 @@
* @param downY
* @param upX
* @param upY
- * @param duration
- * @return true if the swipe and scrolling have been successfully completed.
+ * @param steps
+ * @return true if we are not at the beginning or end of the scrollable view.
*/
public boolean scrollSwipe(final int downX, final int downY, final int upX, final int upY,
final int steps) {
@@ -391,8 +391,34 @@
}
};
- return runAndWaitForEvent(command, DEFAULT_SCROLL_EVENT_TIMEOUT_MILLIS,
- AccessibilityEvent.TYPE_VIEW_SCROLLED);
+ AccessibilityEvent event = runAndWaitForEvent(command,
+ DEFAULT_SCROLL_EVENT_TIMEOUT_MILLIS, AccessibilityEvent.TYPE_VIEW_SCROLLED);
+ if (event == null) {
+ return false;
+ }
+ // AdapterViews have indices we can use to check for the beginning.
+ if (event.getFromIndex() != -1 && event.getToIndex() != -1 && event.getItemCount() != -1) {
+ boolean foundEnd = event.getFromIndex() == 0 ||
+ (event.getItemCount() - 1) == event.getToIndex();
+ Log.d(LOG_TAG, "scrollSwipe reached scroll end: " + foundEnd);
+ return !foundEnd;
+ } else if (event.getScrollX() != -1 && event.getScrollY() != -1) {
+ // Determine if we are scrolling vertically or horizontally.
+ if (downX == upX) {
+ // Vertical
+ boolean foundEnd = event.getScrollY() == 0 ||
+ event.getScrollY() == event.getMaxScrollY();
+ Log.d(LOG_TAG, "Vertical scrollSwipe reached scroll end: " + foundEnd);
+ return !foundEnd;
+ } else if (downY == upY) {
+ // Horizontal
+ boolean foundEnd = event.getScrollX() == 0 ||
+ event.getScrollX() == event.getMaxScrollX();
+ Log.d(LOG_TAG, "Horizontal scrollSwipe reached scroll end: " + foundEnd);
+ return !foundEnd;
+ }
+ }
+ return event != null;
}
/**
@@ -401,8 +427,8 @@
* @param downY
* @param upX
* @param upY
- * @param duration
- * @return
+ * @param steps
+ * @return true if the swipe executed successfully
*/
public boolean swipe(int downX, int downY, int upX, int upY, int steps) {
boolean ret = false;
diff --git a/uiautomator/library/src/com/android/uiautomator/core/QueryController.java b/uiautomator/library/src/com/android/uiautomator/core/QueryController.java
index d2938ac..f14b017 100644
--- a/uiautomator/library/src/com/android/uiautomator/core/QueryController.java
+++ b/uiautomator/library/src/com/android/uiautomator/core/QueryController.java
@@ -23,10 +23,8 @@
import com.android.uiautomator.core.UiAutomatorBridge.AccessibilityEventListener;
/**
- * The QuertController main purpose is to translate a {@link UiSelector} selectors to
- * {@link AccessibilityNodeInfo}. This is all this controller does. It is typically
- * created in conjunction with a {@link InteractionController} by {@link UiAutomationContext}
- * which owns both. {@link UiAutomationContext} is used by {@link UiBase} classes.
+ * The QueryController main purpose is to translate a {@link UiSelector} selectors to
+ * {@link AccessibilityNodeInfo}. This is all this controller does.
*/
class QueryController {
@@ -88,7 +86,6 @@
* Returns the last text selection reported by accessibility
* event TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY. One way to cause
* this event is using a DPad arrows to focus on UI elements.
- * @return
*/
public String getLastTraversedText() {
mUiAutomatorBridge.waitForIdle();
@@ -115,7 +112,7 @@
mPatternCounter = 0;
mPatternIndexer = 0;
mLogIndent = 0;
- mLogParentIndent = 0;;
+ mLogParentIndent = 0;
}
/**
@@ -134,7 +131,7 @@
/**
* Main search method for translating By selectors to AccessibilityInfoNodes
* @param selector
- * @return
+ * @return AccessibilityNodeInfo
*/
public AccessibilityNodeInfo findAccessibilityNodeInfo(UiSelector selector) {
return findAccessibilityNodeInfo(selector, false);
@@ -212,7 +209,7 @@
* @param selector
* @param fromNode
* @param isCounting
- * @return
+ * @return AccessibilityNodeInfo
*/
private AccessibilityNodeInfo translateCompoundSelector(UiSelector selector,
AccessibilityNodeInfo fromNode, boolean isCounting) {
@@ -282,7 +279,6 @@
* <p/>
* @param selector
* @param fromNode
- * @param index
* @return AccessibilityNodeInfo if found else null
*/
private AccessibilityNodeInfo translateReqularSelector(UiSelector selector,
@@ -369,7 +365,7 @@
* until the end of the tree.
* @param subSelector
* @param fromNode
- * @param originalPattern
+ * @param isCounting
* @return null of node is not found or if counting mode is true.
* See {@link #translateCompoundSelector(UiSelector, AccessibilityNodeInfo, boolean)}
*/
diff --git a/uiautomator/library/src/com/android/uiautomator/core/Tracer.java b/uiautomator/library/src/com/android/uiautomator/core/Tracer.java
new file mode 100644
index 0000000..d574fc0
--- /dev/null
+++ b/uiautomator/library/src/com/android/uiautomator/core/Tracer.java
@@ -0,0 +1,285 @@
+/*
+ * 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.
+ */
+package com.android.uiautomator.core;
+
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Class that creates traces of the calls to the UiAutomator API and outputs the
+ * traces either to logcat or a logfile. Each public method in the UiAutomator
+ * that needs to be traced should include a call to Tracer.trace in the
+ * beginning. Tracing is turned off by defualt and needs to be enabled
+ * explicitly.
+ * @hide
+ */
+public class Tracer {
+ private static final String UNKNOWN_METHOD_STRING = "(unknown method)";
+ private static final String UIAUTOMATOR_PACKAGE = "com.android.uiautomator.core";
+ private static final int CALLER_LOCATION = 6;
+ private static final int METHOD_TO_TRACE_LOCATION = 5;
+ private static final int MIN_STACK_TRACE_LENGTH = 7;
+
+ /**
+ * Enum that determines where the trace output goes. It can go to either
+ * logcat, log file or both.
+ */
+ public enum Mode {
+ NONE,
+ FILE,
+ LOGCAT,
+ ALL
+ }
+
+ private interface TracerSink {
+ public void log(String message);
+
+ public void close();
+ }
+
+ private class FileSink implements TracerSink {
+ private PrintWriter mOut;
+ private SimpleDateFormat mDateFormat;
+
+ public FileSink(File file) throws FileNotFoundException {
+ mOut = new PrintWriter(file);
+ mDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
+ }
+
+ public void log(String message) {
+ mOut.printf("%s %s\n", mDateFormat.format(new Date()), message);
+ }
+
+ public void close() {
+ mOut.close();
+ }
+ }
+
+ private class LogcatSink implements TracerSink {
+
+ private static final String LOGCAT_TAG = "UiAutomatorTrace";
+
+ public void log(String message) {
+ Log.i(LOGCAT_TAG, message);
+ }
+
+ public void close() {
+ // nothing is needed
+ }
+ }
+
+ private Mode mCurrentMode = Mode.NONE;
+ private List<TracerSink> mSinks = new ArrayList<TracerSink>();
+ private File mOutputFile;
+
+ private static Tracer mInstance = null;
+
+ /**
+ * Returns a reference to an instance of the tracer. Useful to set the
+ * parameters before the trace is collected.
+ *
+ * @return
+ */
+ public static Tracer getInstance() {
+ if (mInstance == null) {
+ mInstance = new Tracer();
+ }
+ return mInstance;
+ }
+
+ /**
+ * Sets where the trace output will go. Can be either be logcat or a file or
+ * both. Setting this to NONE will turn off tracing.
+ *
+ * @param mode
+ */
+ public void setOutputMode(Mode mode) {
+ closeSinks();
+ mCurrentMode = mode;
+ try {
+ switch (mode) {
+ case FILE:
+ if (mOutputFile == null) {
+ throw new IllegalArgumentException("Please provide a filename before " +
+ "attempting write trace to a file");
+ }
+ mSinks.add(new FileSink(mOutputFile));
+ break;
+ case LOGCAT:
+ mSinks.add(new LogcatSink());
+ break;
+ case ALL:
+ mSinks.add(new LogcatSink());
+ if (mOutputFile == null) {
+ throw new IllegalArgumentException("Please provide a filename before " +
+ "attempting write trace to a file");
+ }
+ mSinks.add(new FileSink(mOutputFile));
+ break;
+ default:
+ break;
+ }
+ } catch (FileNotFoundException e) {
+ Log.w("Tracer", "Could not open log file: " + e.getMessage());
+ }
+ }
+
+ private void closeSinks() {
+ for (TracerSink sink : mSinks) {
+ sink.close();
+ }
+ mSinks.clear();
+ }
+
+ /**
+ * Sets the name of the log file where tracing output will be written if the
+ * tracer is set to write to a file.
+ *
+ * @param filename name of the log file.
+ */
+ public void setOutputFilename(String filename) {
+ mOutputFile = new File(filename);
+ }
+
+ private void doTrace(Object[] arguments) {
+ if (mCurrentMode == Mode.NONE) {
+ return;
+ }
+
+ String caller = getCaller();
+ if (caller == null) {
+ return;
+ }
+
+ log(String.format("%s (%s)", caller, join(", ", arguments)));
+ }
+
+ private void log(String message) {
+ for (TracerSink sink : mSinks) {
+ sink.log(message);
+ }
+ }
+
+ /**
+ * Queries whether the tracing is enabled.
+ * @return true if tracing is enabled, false otherwise.
+ */
+ public boolean isTracingEnabled() {
+ return mCurrentMode != Mode.NONE;
+ }
+
+ /**
+ * Public methods in the UiAutomator should call this function to generate a
+ * trace. The trace will include the method thats is being called, it's
+ * arguments and where in the user's code the method is called from. If a
+ * public method is called internally from UIAutomator then this will not
+ * output a trace entry. Only calls from outise the UiAutomator package will
+ * produce output.
+ *
+ * Special note about array arguments. You can safely pass arrays of reference types
+ * to this function. Like String[] or Integer[]. The trace function will print their
+ * contents by calling toString() on each of the elements. This will not work for
+ * array of primitive types like int[] or float[]. Before passing them to this function
+ * convert them to arrays of reference types manually. Example: convert int[] to Integer[].
+ *
+ * @param arguments arguments of the method being traced.
+ */
+ public static void trace(Object... arguments) {
+ Tracer.getInstance().doTrace(arguments);
+ }
+
+ private static String join(String separator, Object[] strings) {
+ if (strings.length == 0)
+ return "";
+
+ StringBuilder builder = new StringBuilder(objectToString(strings[0]));
+ for (int i = 1; i < strings.length; i++) {
+ builder.append(separator);
+ builder.append(objectToString(strings[i]));
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Special toString method to handle arrays. If the argument is a normal object then this will
+ * return normal output of obj.toString(). If the argument is an array this will return a
+ * string representation of the elements of the array.
+ *
+ * This method will not work for arrays of primitive types. Arrays of primitive types are
+ * expected to be converted manually by the caller. If the array is not converter then
+ * this function will only output "[...]" instead of the contents of the array.
+ *
+ * @param obj object to convert to a string
+ * @return String representation of the object.
+ */
+ private static String objectToString(Object obj) {
+ if (obj.getClass().isArray()) {
+ if (obj instanceof Object[]) {
+ return Arrays.deepToString((Object[])obj);
+ } else {
+ return "[...]";
+ }
+ } else {
+ return obj.toString();
+ }
+ }
+
+ /**
+ * This method outputs which UiAutomator method was called and where in the
+ * user code it was called from. If it can't deside which method is called
+ * it will output "(unknown method)". If the method was called from inside
+ * the UiAutomator then it returns null.
+ *
+ * @return name of the method called and where it was called from. Null if
+ * method was called from inside UiAutomator.
+ */
+ private static String getCaller() {
+ StackTraceElement stackTrace[] = Thread.currentThread().getStackTrace();
+ if (stackTrace.length < MIN_STACK_TRACE_LENGTH) {
+ return UNKNOWN_METHOD_STRING;
+ }
+
+ StackTraceElement caller = stackTrace[METHOD_TO_TRACE_LOCATION];
+ StackTraceElement previousCaller = stackTrace[CALLER_LOCATION];
+
+ if (previousCaller.getClassName().startsWith(UIAUTOMATOR_PACKAGE)) {
+ return null;
+ }
+
+ int indexOfDot = caller.getClassName().lastIndexOf('.');
+ if (indexOfDot < 0) {
+ indexOfDot = 0;
+ }
+
+ if (indexOfDot + 1 >= caller.getClassName().length()) {
+ return UNKNOWN_METHOD_STRING;
+ }
+
+ String shortClassName = caller.getClassName().substring(indexOfDot + 1);
+ return String.format("%s.%s from %s() at %s:%d", shortClassName, caller.getMethodName(),
+ previousCaller.getMethodName(), previousCaller.getFileName(),
+ previousCaller.getLineNumber());
+ }
+}
diff --git a/uiautomator/library/src/com/android/uiautomator/core/UiCollection.java b/uiautomator/library/src/com/android/uiautomator/core/UiCollection.java
index 20b6d9a..e15beb2 100644
--- a/uiautomator/library/src/com/android/uiautomator/core/UiCollection.java
+++ b/uiautomator/library/src/com/android/uiautomator/core/UiCollection.java
@@ -49,6 +49,7 @@
*/
public UiObject getChildByDescription(UiSelector childPattern, String text)
throws UiObjectNotFoundException {
+ Tracer.trace(childPattern, text);
if (text != null) {
int count = getChildCount(childPattern);
for (int x = 0; x < count; x++) {
@@ -82,6 +83,7 @@
*/
public UiObject getChildByInstance(UiSelector childPattern, int instance)
throws UiObjectNotFoundException {
+ Tracer.trace(childPattern, instance);
UiSelector patternSelector = UiSelector.patternBuilder(getSelector(),
UiSelector.patternBuilder(childPattern).instance(instance));
return new UiObject(patternSelector);
@@ -105,7 +107,7 @@
*/
public UiObject getChildByText(UiSelector childPattern, String text)
throws UiObjectNotFoundException {
-
+ Tracer.trace(childPattern, text);
if (text != null) {
int count = getChildCount(childPattern);
for (int x = 0; x < count; x++) {
@@ -135,6 +137,7 @@
* @since API Level 16
*/
public int getChildCount(UiSelector childPattern) {
+ Tracer.trace(childPattern);
UiSelector patternSelector =
UiSelector.patternBuilder(getSelector(), UiSelector.patternBuilder(childPattern));
return getQueryController().getPatternCount(patternSelector);
diff --git a/uiautomator/library/src/com/android/uiautomator/core/UiDevice.java b/uiautomator/library/src/com/android/uiautomator/core/UiDevice.java
index 09d8af3..b668bea 100644
--- a/uiautomator/library/src/com/android/uiautomator/core/UiDevice.java
+++ b/uiautomator/library/src/com/android/uiautomator/core/UiDevice.java
@@ -27,6 +27,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.os.Trace;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
@@ -112,6 +113,7 @@
* @hide
*/
public Point getDisplaySizeDp() {
+ Tracer.trace();
Display display = getDefaultDisplay();
Point p = new Point();
display.getSize(p);
@@ -134,6 +136,7 @@
* @since API Level 17
*/
public String getProductName() {
+ Tracer.trace();
return Build.PRODUCT;
}
@@ -153,6 +156,7 @@
* @since API Level 16
*/
public String getLastTraversedText() {
+ Tracer.trace();
return mUiAutomationBridge.getQueryController().getLastTraversedText();
}
@@ -162,6 +166,7 @@
* @since API Level 16
*/
public void clearLastTraversedText() {
+ Tracer.trace();
mUiAutomationBridge.getQueryController().clearLastTraversedText();
}
@@ -171,6 +176,7 @@
* @since API Level 16
*/
public boolean pressMenu() {
+ Tracer.trace();
waitForIdle();
return mUiAutomationBridge.getInteractionController().sendKeyAndWaitForEvent(
KeyEvent.KEYCODE_MENU, 0, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
@@ -183,6 +189,7 @@
* @since API Level 16
*/
public boolean pressBack() {
+ Tracer.trace();
waitForIdle();
return mUiAutomationBridge.getInteractionController().sendKeyAndWaitForEvent(
KeyEvent.KEYCODE_BACK, 0, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
@@ -195,6 +202,7 @@
* @since API Level 16
*/
public boolean pressHome() {
+ Tracer.trace();
waitForIdle();
return mUiAutomationBridge.getInteractionController().sendKeyAndWaitForEvent(
KeyEvent.KEYCODE_HOME, 0, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
@@ -207,6 +215,7 @@
* @since API Level 16
*/
public boolean pressSearch() {
+ Tracer.trace();
return pressKeyCode(KeyEvent.KEYCODE_SEARCH);
}
@@ -216,6 +225,7 @@
* @since API Level 16
*/
public boolean pressDPadCenter() {
+ Tracer.trace();
return pressKeyCode(KeyEvent.KEYCODE_DPAD_CENTER);
}
@@ -225,6 +235,7 @@
* @since API Level 16
*/
public boolean pressDPadDown() {
+ Tracer.trace();
return pressKeyCode(KeyEvent.KEYCODE_DPAD_DOWN);
}
@@ -234,6 +245,7 @@
* @since API Level 16
*/
public boolean pressDPadUp() {
+ Tracer.trace();
return pressKeyCode(KeyEvent.KEYCODE_DPAD_UP);
}
@@ -243,6 +255,7 @@
* @since API Level 16
*/
public boolean pressDPadLeft() {
+ Tracer.trace();
return pressKeyCode(KeyEvent.KEYCODE_DPAD_LEFT);
}
@@ -252,6 +265,7 @@
* @since API Level 16
*/
public boolean pressDPadRight() {
+ Tracer.trace();
return pressKeyCode(KeyEvent.KEYCODE_DPAD_RIGHT);
}
@@ -261,6 +275,7 @@
* @since API Level 16
*/
public boolean pressDelete() {
+ Tracer.trace();
return pressKeyCode(KeyEvent.KEYCODE_DEL);
}
@@ -270,6 +285,7 @@
* @since API Level 16
*/
public boolean pressEnter() {
+ Tracer.trace();
return pressKeyCode(KeyEvent.KEYCODE_ENTER);
}
@@ -281,6 +297,7 @@
* @since API Level 16
*/
public boolean pressKeyCode(int keyCode) {
+ Tracer.trace(keyCode);
waitForIdle();
return mUiAutomationBridge.getInteractionController().sendKey(keyCode, 0);
}
@@ -295,6 +312,7 @@
* @since API Level 16
*/
public boolean pressKeyCode(int keyCode, int metaState) {
+ Tracer.trace(keyCode, metaState);
waitForIdle();
return mUiAutomationBridge.getInteractionController().sendKey(keyCode, metaState);
}
@@ -307,6 +325,7 @@
* @since API Level 16
*/
public boolean pressRecentApps() throws RemoteException {
+ Tracer.trace();
waitForIdle();
final IStatusBarService statusBar = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -325,6 +344,7 @@
* @since API Level 16
*/
public int getDisplayWidth() {
+ Tracer.trace();
Display display = getDefaultDisplay();
Point p = new Point();
display.getSize(p);
@@ -338,6 +358,7 @@
* @since API Level 16
*/
public int getDisplayHeight() {
+ Tracer.trace();
Display display = getDefaultDisplay();
Point p = new Point();
display.getSize(p);
@@ -353,6 +374,7 @@
* @since API Level 16
*/
public boolean click(int x, int y) {
+ Tracer.trace(x, y);
if (x >= getDisplayWidth() || y >= getDisplayHeight()) {
return (false);
}
@@ -373,6 +395,7 @@
* @since API Level 16
*/
public boolean swipe(int startX, int startY, int endX, int endY, int steps) {
+ Tracer.trace(startX, startY, endX, endY, steps);
return mUiAutomationBridge.getInteractionController()
.scrollSwipe(startX, startY, endX, endY, steps);
}
@@ -387,6 +410,7 @@
* @since API Level 16
*/
public boolean swipe(Point[] segments, int segmentSteps) {
+ Tracer.trace(segments, segmentSteps);
return mUiAutomationBridge.getInteractionController().swipe(segments, segmentSteps);
}
@@ -396,6 +420,7 @@
* @since API Level 16
*/
public void waitForIdle() {
+ Tracer.trace();
waitForIdle(DEFAULT_TIMEOUT_MILLIS);
}
@@ -404,8 +429,9 @@
* @param timeout in milliseconds
* @since API Level 16
*/
- public void waitForIdle(long time) {
- mUiAutomationBridge.waitForIdle(time);
+ public void waitForIdle(long timeout) {
+ Tracer.trace(timeout);
+ mUiAutomationBridge.waitForIdle(timeout);
}
/**
@@ -416,6 +442,7 @@
*/
@Deprecated
public String getCurrentActivityName() {
+ Tracer.trace();
return mUiAutomationBridge.getQueryController().getCurrentActivityName();
}
@@ -425,6 +452,7 @@
* @since API Level 16
*/
public String getCurrentPackageName() {
+ Tracer.trace();
return mUiAutomationBridge.getQueryController().getCurrentPackageName();
}
@@ -437,6 +465,7 @@
* @since API Level 16
*/
public void registerWatcher(String name, UiWatcher watcher) {
+ Tracer.trace(name, watcher);
if (mInWatcherContext) {
throw new IllegalStateException("Cannot register new watcher from within another");
}
@@ -448,10 +477,10 @@
*
* See {@link #registerWatcher(String, UiWatcher)}
* @param name used to register the UiWatcher
- * @throws UiAutomationException
* @since API Level 16
*/
public void removeWatcher(String name) {
+ Tracer.trace(name);
if (mInWatcherContext) {
throw new IllegalStateException("Cannot remove a watcher from within another");
}
@@ -464,6 +493,7 @@
* @since API Level 16
*/
public void runWatchers() {
+ Tracer.trace();
if (mInWatcherContext) {
return;
}
@@ -493,6 +523,7 @@
* @since API Level 16
*/
public void resetWatcherTriggers() {
+ Tracer.trace();
mWatchersTriggers.clear();
}
@@ -508,6 +539,7 @@
* @since API Level 16
*/
public boolean hasWatcherTriggered(String watcherName) {
+ Tracer.trace(watcherName);
return mWatchersTriggers.contains(watcherName);
}
@@ -519,6 +551,7 @@
* @since API Level 16
*/
public boolean hasAnyWatcherTriggered() {
+ Tracer.trace();
return mWatchersTriggers.size() > 0;
}
@@ -527,6 +560,7 @@
* @param watcherName
*/
private void setWatcherTriggered(String watcherName) {
+ Tracer.trace(watcherName);
if (!hasWatcherTriggered(watcherName)) {
mWatchersTriggers.add(watcherName);
}
@@ -539,6 +573,7 @@
* @since API Level 17
*/
public boolean isNaturalOrientation() {
+ Tracer.trace();
Display display = getDefaultDisplay();
return display.getRotation() == Surface.ROTATION_0 ||
display.getRotation() == Surface.ROTATION_180;
@@ -546,10 +581,10 @@
/**
* Returns the current rotation of the display, as defined in {@link Surface}
- * @return
* @since API Level 17
*/
public int getDisplayRotation() {
+ Tracer.trace();
return getDefaultDisplay().getRotation();
}
@@ -560,6 +595,7 @@
* @since API Level 16
*/
public void freezeRotation() throws RemoteException {
+ Tracer.trace();
getAutomatorBridge().getInteractionController().freezeRotation();
}
@@ -570,6 +606,7 @@
* @throws RemoteException
*/
public void unfreezeRotation() throws RemoteException {
+ Tracer.trace();
getAutomatorBridge().getInteractionController().unfreezeRotation();
}
@@ -583,6 +620,7 @@
* @since API Level 17
*/
public void setOrientationLeft() throws RemoteException {
+ Tracer.trace();
getAutomatorBridge().getInteractionController().setRotationLeft();
}
@@ -596,6 +634,7 @@
* @since API Level 17
*/
public void setOrientationRight() throws RemoteException {
+ Tracer.trace();
getAutomatorBridge().getInteractionController().setRotationRight();
}
@@ -609,6 +648,7 @@
* @since API Level 17
*/
public void setOrientationNatural() throws RemoteException {
+ Tracer.trace();
getAutomatorBridge().getInteractionController().setRotationNatural();
}
@@ -622,6 +662,7 @@
* @since API Level 16
*/
public void wakeUp() throws RemoteException {
+ Tracer.trace();
if(getAutomatorBridge().getInteractionController().wakeDevice()) {
// sync delay to allow the window manager to start accepting input
// after the device is awakened.
@@ -637,6 +678,7 @@
* @since API Level 16
*/
public boolean isScreenOn() throws RemoteException {
+ Tracer.trace();
return getAutomatorBridge().getInteractionController().isScreenOn();
}
@@ -648,6 +690,7 @@
* @since API Level 16
*/
public void sleep() throws RemoteException {
+ Tracer.trace();
getAutomatorBridge().getInteractionController().sleepDevice();
}
@@ -659,6 +702,7 @@
* @since API Level 16
*/
public void dumpWindowHierarchy(String fileName) {
+ Tracer.trace(fileName);
AccessibilityNodeInfo root =
getAutomatorBridge().getQueryController().getAccessibilityRootNode();
if(root != null) {
@@ -683,6 +727,7 @@
* @since API Level 16
*/
public boolean waitForWindowUpdate(final String packageName, long timeout) {
+ Tracer.trace(packageName, timeout);
if (packageName != null) {
if (!packageName.equals(getCurrentPackageName())) {
return false;
@@ -744,6 +789,7 @@
* @since API Level 17
*/
public boolean takeScreenshot(File storePath) {
+ Tracer.trace(storePath);
return takeScreenshot(storePath, 1.0f, 90);
}
@@ -759,6 +805,7 @@
* @since API Level 17
*/
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 :!)
diff --git a/uiautomator/library/src/com/android/uiautomator/core/UiObject.java b/uiautomator/library/src/com/android/uiautomator/core/UiObject.java
index 42819e2..2bf6455 100644
--- a/uiautomator/library/src/com/android/uiautomator/core/UiObject.java
+++ b/uiautomator/library/src/com/android/uiautomator/core/UiObject.java
@@ -77,6 +77,7 @@
* @since API Level 16
*/
public final UiSelector getSelector() {
+ Tracer.trace();
return new UiSelector(mSelector);
}
@@ -109,6 +110,7 @@
* @since API Level 16
*/
public UiObject getChild(UiSelector selector) throws UiObjectNotFoundException {
+ Tracer.trace(selector);
return new UiObject(getSelector().childSelector(selector));
}
@@ -124,6 +126,7 @@
* @since API Level 16
*/
public UiObject getFromParent(UiSelector selector) throws UiObjectNotFoundException {
+ Tracer.trace(selector);
return new UiObject(getSelector().fromParent(selector));
}
@@ -136,6 +139,7 @@
* @since API Level 16
*/
public int getChildCount() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -147,7 +151,6 @@
* Uses the member UiSelector properties to find a matching UI element reported in
* the accessibility hierarchy.
*
- * @param selector {@link UiSelector}
* @param timeout in milliseconds
* @return AccessibilityNodeInfo if found else null
* @since API Level 16
@@ -181,8 +184,8 @@
/**
* Perform the action on the UI element that is represented by this UiObject. Also see
- * {@link #scrollToBeginning(int)}, {@link #scrollToEnd(int)}, {@link #scrollBackward()},
- * {@link #scrollForward()}.
+ * {@link UiScrollable#scrollToBeginning(int)}, {@link UiScrollable#scrollToEnd(int)},
+ * {@link UiScrollable#scrollBackward()}, {@link UiScrollable#scrollForward()}.
*
* @param steps indicates the number of injected move steps into the system. Steps are
* injected about 5ms apart. So a 100 steps may take about 1/2 second to complete.
@@ -191,6 +194,7 @@
* @since API Level 16
*/
public boolean swipeUp(int steps) throws UiObjectNotFoundException {
+ Tracer.trace(steps);
Rect rect = getVisibleBounds();
if(rect.height() <= SWIPE_MARGIN_LIMIT * 2)
return false; // too small to swipe
@@ -201,10 +205,11 @@
/**
* Perform the action on the UI element that is represented by this object, Also see
- * {@link #scrollToBeginning(int)}, {@link #scrollToEnd(int)}, {@link #scrollBackward()},
- * {@link #scrollForward()}. This method will perform the swipe gesture over any
- * surface. The targeted UI element does not need to have the attribute
- * <code>scrollable</code> set to <code>true</code> for this operation to be performed.
+ * {@link UiScrollable#scrollToBeginning(int)}, {@link UiScrollable#scrollToEnd(int)},
+ * {@link UiScrollable#scrollBackward()}, {@link UiScrollable#scrollForward()}. This method will
+ * perform the swipe gesture over any surface. The targeted UI element does not need to have
+ * the attribute <code>scrollable</code> set to <code>true</code> for this operation to be
+ * performed.
*
* @param steps indicates the number of injected move steps into the system. Steps are
* injected about 5ms apart. So a 100 steps may take about 1/2 second to complete.
@@ -213,6 +218,7 @@
* @since API Level 16
*/
public boolean swipeDown(int steps) throws UiObjectNotFoundException {
+ Tracer.trace(steps);
Rect rect = getVisibleBounds();
if(rect.height() <= SWIPE_MARGIN_LIMIT * 2)
return false; // too small to swipe
@@ -223,10 +229,11 @@
/**
* Perform the action on the UI element that is represented by this object. Also see
- * {@link #scrollToBeginning(int)}, {@link #scrollToEnd(int)}, {@link #scrollBackward()},
- * {@link #scrollForward()}. This method will perform the swipe gesture over any
- * surface. The targeted UI element does not need to have the attribute
- * <code>scrollable</code> set to <code>true</code> for this operation to be performed.
+ * {@link UiScrollable#scrollToBeginning(int)}, {@link UiScrollable#scrollToEnd(int)},
+ * {@link UiScrollable#scrollBackward()}, {@link UiScrollable#scrollForward()}. This method will
+ * perform the swipe gesture over any surface. The targeted UI element does not need to have the
+ * attribute <code>scrollable</code> set to <code>true</code> for this operation to be
+ * performed.
*
* @param steps indicates the number of injected move steps into the system. Steps are
* injected about 5ms apart. So a 100 steps may take about 1/2 second to complete.
@@ -235,6 +242,7 @@
* @since API Level 16
*/
public boolean swipeLeft(int steps) throws UiObjectNotFoundException {
+ Tracer.trace(steps);
Rect rect = getVisibleBounds();
if(rect.width() <= SWIPE_MARGIN_LIMIT * 2)
return false; // too small to swipe
@@ -244,10 +252,11 @@
/**
* Perform the action on the UI element that is represented by this object. Also see
- * {@link #scrollToBeginning(int)}, {@link #scrollToEnd(int)}, {@link #scrollBackward()},
- * {@link #scrollForward()}. This method will perform the swipe gesture over any
- * surface. The targeted UI element does not need to have the attribute
- * <code>scrollable</code> set to <code>true</code> for this operation to be performed.
+ * {@link UiScrollable#scrollToBeginning(int)}, {@link UiScrollable#scrollToEnd(int)},
+ * {@link UiScrollable#scrollBackward()}, {@link UiScrollable#scrollForward()}. This method will
+ * perform the swipe gesture over any surface. The targeted UI element does not need to have the
+ * attribute <code>scrollable</code> set to <code>true</code> for this operation to be
+ * performed.
*
* @param steps indicates the number of injected move steps into the system. Steps are
* injected about 5ms apart. So a 100 steps may take about 1/2 second to complete.
@@ -256,6 +265,7 @@
* @since API Level 16
*/
public boolean swipeRight(int steps) throws UiObjectNotFoundException {
+ Tracer.trace(steps);
Rect rect = getVisibleBounds();
if(rect.width() <= SWIPE_MARGIN_LIMIT * 2)
return false; // too small to swipe
@@ -299,7 +309,7 @@
* adjustments should be made to the click coordinates.
*
* @param node
- * @return
+ * @return The accessibility node info.
*/
private AccessibilityNodeInfo getScrollableParent(AccessibilityNodeInfo node) {
AccessibilityNodeInfo parent = node;
@@ -321,6 +331,7 @@
* @since API Level 16
*/
public boolean click() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -341,6 +352,7 @@
* @since API Level 16
*/
public boolean clickAndWaitForNewWindow() throws UiObjectNotFoundException {
+ Tracer.trace();
return clickAndWaitForNewWindow(WAIT_FOR_WINDOW_TMEOUT);
}
@@ -360,6 +372,7 @@
* @since API Level 16
*/
public boolean clickAndWaitForNewWindow(long timeout) throws UiObjectNotFoundException {
+ Tracer.trace(timeout);
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -373,10 +386,11 @@
* Clicks the top and left corner of the UI element
*
* @return true on success
- * @throws Exception
+ * @throws UiObjectNotFoundException
* @since API Level 16
*/
public boolean clickTopLeft() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -393,6 +407,7 @@
* @since API Level 16
*/
public boolean longClickBottomRight() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -405,10 +420,11 @@
* Clicks the bottom and right corner of the UI element
*
* @return true on success
- * @throws Exception
+ * @throws UiObjectNotFoundException
* @since API Level 16
*/
public boolean clickBottomRight() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -425,6 +441,7 @@
* @since API Level 16
*/
public boolean longClick() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -441,6 +458,7 @@
* @since API Level 16
*/
public boolean longClickTopLeft() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -457,6 +475,7 @@
* @since API Level 16
*/
public String getText() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -474,6 +493,7 @@
* @since API Level 16
*/
public String getContentDescription() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -499,6 +519,7 @@
* @since API Level 16
*/
public boolean setText(String text) throws UiObjectNotFoundException {
+ Tracer.trace(text);
clearTextField();
return getInteractionController().sendText(text);
}
@@ -523,6 +544,7 @@
* @since API Level 16
*/
public void clearTextField() throws UiObjectNotFoundException {
+ Tracer.trace();
// long click left + center
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
@@ -547,6 +569,7 @@
* @since API Level 16
*/
public boolean isChecked() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -562,6 +585,7 @@
* @since API Level 16
*/
public boolean isSelected() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -577,6 +601,7 @@
* @since API Level 16
*/
public boolean isCheckable() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -592,6 +617,7 @@
* @since API Level 16
*/
public boolean isEnabled() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -607,6 +633,7 @@
* @since API Level 16
*/
public boolean isClickable() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -622,6 +649,7 @@
* @since API Level 16
*/
public boolean isFocused() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -637,6 +665,7 @@
* @since API Level 16
*/
public boolean isFocusable() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -652,6 +681,7 @@
* @since API Level 16
*/
public boolean isScrollable() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -667,6 +697,7 @@
* @since API Level 16
*/
public boolean isLongClickable() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -682,6 +713,7 @@
* @since API Level 16
*/
public String getPackageName() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -697,10 +729,11 @@
*
* @return Rect
* @throws UiObjectNotFoundException
- * @see {@link #getBound()}
+ * @see {@link #getBounds()}
* @since API Level 17
*/
public Rect getVisibleBounds() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -716,6 +749,7 @@
* @since API Level 16
*/
public Rect getBounds() throws UiObjectNotFoundException {
+ Tracer.trace();
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
@@ -738,6 +772,7 @@
* @since API Level 16
*/
public boolean waitForExists(long timeout) {
+ Tracer.trace(timeout);
if(findAccessibilityNodeInfo(timeout) != null) {
return true;
}
@@ -763,6 +798,7 @@
* @since API Level 16
*/
public boolean waitUntilGone(long timeout) {
+ Tracer.trace(timeout);
long startMills = SystemClock.uptimeMillis();
long currentMills = 0;
while (currentMills <= timeout) {
@@ -787,6 +823,7 @@
* @since API Level 16
*/
public boolean exists() {
+ Tracer.trace();
return waitForExists(0);
}
diff --git a/uiautomator/library/src/com/android/uiautomator/core/UiScrollable.java b/uiautomator/library/src/com/android/uiautomator/core/UiScrollable.java
index 607ae6f..c128ac2 100644
--- a/uiautomator/library/src/com/android/uiautomator/core/UiScrollable.java
+++ b/uiautomator/library/src/com/android/uiautomator/core/UiScrollable.java
@@ -63,6 +63,7 @@
* @since API Level 16
*/
public UiScrollable setAsVerticalList() {
+ Tracer.trace();
mIsVerticalList = true;
return this;
}
@@ -73,6 +74,7 @@
* @since API Level 16
*/
public UiScrollable setAsHorizontalList() {
+ Tracer.trace();
mIsVerticalList = false;
return this;
}
@@ -110,6 +112,7 @@
@Override
public UiObject getChildByDescription(UiSelector childPattern, String text)
throws UiObjectNotFoundException {
+ Tracer.trace(childPattern, text);
return getChildByDescription(childPattern, text, true);
}
@@ -125,6 +128,7 @@
*/
public UiObject getChildByDescription(UiSelector childPattern, String text,
boolean allowScrollSearch) throws UiObjectNotFoundException {
+ Tracer.trace(childPattern, text, allowScrollSearch);
if (text != null) {
if (allowScrollSearch) {
scrollIntoView(new UiSelector().descriptionContains(text));
@@ -148,6 +152,7 @@
@Override
public UiObject getChildByInstance(UiSelector childPattern, int instance)
throws UiObjectNotFoundException {
+ Tracer.trace(childPattern, instance);
UiSelector patternSelector = UiSelector.patternBuilder(getSelector(),
UiSelector.patternBuilder(childPattern).instance(instance));
return new UiObject(patternSelector);
@@ -172,6 +177,7 @@
@Override
public UiObject getChildByText(UiSelector childPattern, String text)
throws UiObjectNotFoundException {
+ Tracer.trace(childPattern, text);
return getChildByText(childPattern, text, true);
}
@@ -187,7 +193,7 @@
*/
public UiObject getChildByText(UiSelector childPattern, String text, boolean allowScrollSearch)
throws UiObjectNotFoundException {
-
+ Tracer.trace(childPattern, text, allowScrollSearch);
if (text != null) {
if (allowScrollSearch) {
scrollIntoView(new UiSelector().text(text));
@@ -206,6 +212,7 @@
* @since API Level 16
*/
public boolean scrollDescriptionIntoView(String text) throws UiObjectNotFoundException {
+ Tracer.trace(text);
return scrollIntoView(new UiSelector().description(text));
}
@@ -218,6 +225,7 @@
* @since API Level 16
*/
public boolean scrollIntoView(UiObject obj) throws UiObjectNotFoundException {
+ Tracer.trace(obj.getSelector());
return scrollIntoView(obj.getSelector());
}
@@ -230,6 +238,7 @@
* @since API Level 16
*/
public boolean scrollIntoView(UiSelector selector) throws UiObjectNotFoundException {
+ Tracer.trace(selector);
// if we happen to be on top of the text we want then return here
if (exists(getSelector().childSelector(selector))) {
return (true);
@@ -261,34 +270,39 @@
* @since API Level 16
*/
public boolean scrollTextIntoView(String text) throws UiObjectNotFoundException {
+ Tracer.trace(text);
return scrollIntoView(new UiSelector().text(text));
}
/**
- * {@link #getChildByDescription(String, boolean)} and {@link #getChildByText(String, boolean)}
- * use an arguments that specifies if scrolling is allowed while searching for the UI element.
- * The number of scrolls allowed to perform a search can be modified by this method.
- * The current value can be read by calling {@link #getMaxSearchSwipes()}
+ * {@link #getChildByDescription(UiSelector, String)} and
+ * {@link #getChildByText(UiSelector, String)} use an arguments that specifies if scrolling is
+ * allowed while searching for the UI element. The number of scrolls allowed to perform a
+ * search can be modified by this method. The current value can be read by calling
+ * {@link #getMaxSearchSwipes()}
*
* @param swipes is the number of search swipes until abort
* @return reference to itself
* @since API Level 16
*/
public UiScrollable setMaxSearchSwipes(int swipes) {
+ Tracer.trace(swipes);
mMaxSearchSwipes = swipes;
return this;
}
/**
- * {@link #getChildByDescription(String, boolean)} and {@link #getChildByText(String, boolean)}
- * use an arguments that specifies if scrolling is allowed while searching for the UI element.
- * The number of scrolls currently allowed to perform a search can be read by this method.
+ * {@link #getChildByDescription(UiSelector, String)} and
+ * {@link #getChildByText(UiSelector, String)} use an arguments that specifies if scrolling is
+ * allowed while searching for the UI element. The number of scrolls currently allowed to
+ * perform a search can be read by this method.
* See {@link #setMaxSearchSwipes(int)}
*
* @return max value of the number of swipes currently allowed during a scroll search
* @since API Level 16
*/
public int getMaxSearchSwipes() {
+ Tracer.trace();
return mMaxSearchSwipes;
}
@@ -299,6 +313,7 @@
* @since API Level 16
*/
public boolean flingForward() throws UiObjectNotFoundException {
+ Tracer.trace();
return scrollForward(FLING_STEPS);
}
@@ -309,6 +324,7 @@
* @since API Level 16
*/
public boolean scrollForward() throws UiObjectNotFoundException {
+ Tracer.trace();
return scrollForward(SCROLL_STEPS);
}
@@ -324,12 +340,13 @@
* @since API Level 16
*/
public boolean scrollForward(int steps) throws UiObjectNotFoundException {
+ Tracer.trace(steps);
Log.d(LOG_TAG, "scrollForward() on selector = " + getSelector());
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if(node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
}
- Rect rect = new Rect();;
+ Rect rect = new Rect();
node.getBoundsInScreen(rect);
int downX = 0;
@@ -365,6 +382,7 @@
* @since API Level 16
*/
public boolean flingBackward() throws UiObjectNotFoundException {
+ Tracer.trace();
return scrollBackward(FLING_STEPS);
}
@@ -375,6 +393,7 @@
* @since API Level 16
*/
public boolean scrollBackward() throws UiObjectNotFoundException {
+ Tracer.trace();
return scrollBackward(SCROLL_STEPS);
}
@@ -390,12 +409,13 @@
* @since API Level 16
*/
public boolean scrollBackward(int steps) throws UiObjectNotFoundException {
+ Tracer.trace(steps);
Log.d(LOG_TAG, "scrollBackward() on selector = " + getSelector());
AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
if (node == null) {
throw new UiObjectNotFoundException(getSelector().toString());
}
- Rect rect = new Rect();;
+ Rect rect = new Rect();
node.getBoundsInScreen(rect);
int downX = 0;
@@ -436,6 +456,7 @@
* @since API Level 16
*/
public boolean scrollToBeginning(int maxSwipes, int steps) throws UiObjectNotFoundException {
+ Tracer.trace(maxSwipes, steps);
Log.d(LOG_TAG, "scrollToBeginning() on selector = " + getSelector());
// protect against potential hanging and return after preset attempts
for(int x = 0; x < maxSwipes; x++) {
@@ -454,6 +475,7 @@
* @since API Level 16
*/
public boolean scrollToBeginning(int maxSwipes) throws UiObjectNotFoundException {
+ Tracer.trace(maxSwipes);
return scrollToBeginning(maxSwipes, SCROLL_STEPS);
}
@@ -465,6 +487,7 @@
* @since API Level 16
*/
public boolean flingToBeginning(int maxSwipes) throws UiObjectNotFoundException {
+ Tracer.trace(maxSwipes);
return scrollToBeginning(maxSwipes, FLING_STEPS);
}
@@ -478,6 +501,7 @@
* @since API Level 16
*/
public boolean scrollToEnd(int maxSwipes, int steps) throws UiObjectNotFoundException {
+ Tracer.trace(maxSwipes, steps);
// protect against potential hanging and return after preset attempts
for(int x = 0; x < maxSwipes; x++) {
if(!scrollForward(steps)) {
@@ -488,13 +512,14 @@
}
/**
- * See {@link UiScrollable#scrollToEnd(int, int)
+ * See {@link UiScrollable#scrollToEnd(int, int)}
*
* @param maxSwipes
* @return true on scrolled else false
* @since API Level 16
*/
public boolean scrollToEnd(int maxSwipes) throws UiObjectNotFoundException {
+ Tracer.trace(maxSwipes);
return scrollToEnd(maxSwipes, SCROLL_STEPS);
}
@@ -506,6 +531,7 @@
* @since API Level 16
*/
public boolean flingToEnd(int maxSwipes) throws UiObjectNotFoundException {
+ Tracer.trace(maxSwipes);
return scrollToEnd(maxSwipes, FLING_STEPS);
}
@@ -524,6 +550,7 @@
* @since API Level 16
*/
public double getSwipeDeadZonePercentage() {
+ Tracer.trace();
return mSwipeDeadZonePercentage;
}
@@ -543,6 +570,7 @@
* @since API Level 16
*/
public UiScrollable setSwipeDeadZonePercentage(double swipeDeadZonePercentage) {
+ Tracer.trace(swipeDeadZonePercentage);
mSwipeDeadZonePercentage = swipeDeadZonePercentage;
return this;
}
diff --git a/uiautomator/library/src/com/android/uiautomator/core/UiSelector.java b/uiautomator/library/src/com/android/uiautomator/core/UiSelector.java
index d240ce9..8963c38 100644
--- a/uiautomator/library/src/com/android/uiautomator/core/UiSelector.java
+++ b/uiautomator/library/src/com/android/uiautomator/core/UiSelector.java
@@ -121,7 +121,7 @@
* The text for the widget must match exactly
* with the string in your input argument.
*
- * @param regular expression
+ * @param regex a regular expression
* @return UiSelector with the specified search criteria
* @since API Level 17
*/
@@ -176,7 +176,7 @@
* Set the search criteria to match the class property
* for a widget (for example, "android.widget.Button").
*
- * @param regular expression
+ * @param regex a regular expression
* @return UiSelector with the specified search criteria
* @since API Level 17
*/
@@ -188,7 +188,7 @@
* Set the search criteria to match the class property
* for a widget (for example, "android.widget.Button").
*
- * @param class type
+ * @param type type
* @return UiSelector with the specified search criteria
* @since API Level 17
*/
@@ -228,7 +228,7 @@
* for the widget must match exactly
* with the string in your input argument.
*
- * @param regular expression
+ * @param regex a regular expression
* @return UiSelector with the specified search criteria
* @since API Level 17
*/
@@ -529,7 +529,7 @@
* Set the search criteria to match the package name
* of the application that contains the widget.
*
- * @param regular expression
+ * @param regex a regular expression
* @return UiSelector with the specified search criteria
* @since API Level 17
*/
diff --git a/uiautomator/library/src/com/android/uiautomator/testrunner/IAutomationSupport.java b/uiautomator/library/src/com/android/uiautomator/testrunner/IAutomationSupport.java
index bea9e9a..f0c60d2 100644
--- a/uiautomator/library/src/com/android/uiautomator/testrunner/IAutomationSupport.java
+++ b/uiautomator/library/src/com/android/uiautomator/testrunner/IAutomationSupport.java
@@ -28,7 +28,8 @@
/**
* Allows the running test cases to send out interim status
*
- * @param bundle status report, consisting of key value pairs
+ * @param resultCode
+ * @param status status report, consisting of key value pairs
* @since API Level 16
*/
public void sendStatus(int resultCode, Bundle status);
diff --git a/uiautomator/library/src/com/android/uiautomator/testrunner/TestCaseCollector.java b/uiautomator/library/src/com/android/uiautomator/testrunner/TestCaseCollector.java
index ae27838..8bc9914 100644
--- a/uiautomator/library/src/com/android/uiautomator/testrunner/TestCaseCollector.java
+++ b/uiautomator/library/src/com/android/uiautomator/testrunner/TestCaseCollector.java
@@ -59,7 +59,7 @@
*
* The class name may be in "<class name>#<method name>" format
*
- * @param classNames classes must be subclass of {@link UiAutomatorTestCase}
+ * @param className classes must be subclass of {@link UiAutomatorTestCase}
* @throws ClassNotFoundException
*/
public void addTestClass(String className) throws ClassNotFoundException {
@@ -96,8 +96,7 @@
/**
* Gets the list of added test cases so far
- *
- * @return
+ * @return a list of {@link TestCase}
*/
public List<TestCase> getTestCases() {
return Collections.unmodifiableList(mTestCases);
diff --git a/uiautomator/library/src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java b/uiautomator/library/src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java
index 926bff7..e7d961b 100644
--- a/uiautomator/library/src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java
+++ b/uiautomator/library/src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java
@@ -85,7 +85,7 @@
/**
* Provides support for running tests to report interim status
*
- * @return
+ * @return IAutomationSupport
* @since API Level 16
*/
public IAutomationSupport getAutomationSupport() {
diff --git a/uiautomator/library/src/com/android/uiautomator/testrunner/UiAutomatorTestRunner.java b/uiautomator/library/src/com/android/uiautomator/testrunner/UiAutomatorTestRunner.java
index 02553e6..a376aa0 100644
--- a/uiautomator/library/src/com/android/uiautomator/testrunner/UiAutomatorTestRunner.java
+++ b/uiautomator/library/src/com/android/uiautomator/testrunner/UiAutomatorTestRunner.java
@@ -26,6 +26,8 @@
import android.test.RepetitiveTest;
import android.util.Log;
+import com.android.uiautomator.core.Tracer;
+import com.android.uiautomator.core.Tracer.Mode;
import com.android.uiautomator.core.UiDevice;
import junit.framework.AssertionFailedError;
@@ -105,6 +107,21 @@
Bundle testRunOutput = new Bundle();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
PrintStream writer = new PrintStream(byteArrayOutputStream);
+
+ String traceType = mParams.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 = mParams.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);
+ }
+
try {
StringResultPrinter resultPrinter = new StringResultPrinter(writer);