Merge "Changed clickAndWaitForNewWindow() to respect the timeout parameter"
diff --git a/src/com/android/uiautomator/core/UiObject.java b/src/com/android/uiautomator/core/UiObject.java
index 4bb99cd..bd0b733 100644
--- a/src/com/android/uiautomator/core/UiObject.java
+++ b/src/com/android/uiautomator/core/UiObject.java
@@ -433,7 +433,7 @@
         }
         Rect rect = getVisibleBounds(node);
         return getInteractionController().clickAndWaitForNewWindow(rect.centerX(), rect.centerY(),
-                mConfig.getActionAcknowledgmentTimeout());
+                timeout);
     }
 
     /**
diff --git a/tests/CtsUiAutomatorTest/src/com/android/uiautomator/tests/cts/TimeoutTest.java b/tests/CtsUiAutomatorTest/src/com/android/uiautomator/tests/cts/TimeoutTest.java
new file mode 100644
index 0000000..b35c9d9
--- /dev/null
+++ b/tests/CtsUiAutomatorTest/src/com/android/uiautomator/tests/cts/TimeoutTest.java
@@ -0,0 +1,144 @@
+/*
+ * 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.tests.cts;
+
+import com.android.uiautomator.core.UiDevice;
+import com.android.uiautomator.core.UiObject;
+import com.android.uiautomator.core.UiObjectNotFoundException;
+import com.android.uiautomator.core.UiScrollable;
+import com.android.uiautomator.core.UiSelector;
+import com.android.uiautomator.testrunner.UiAutomatorTestCase;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.RemoteException;
+
+public class TimeoutTest extends UiAutomatorTestCase {
+
+    private static final String TEST_APP_PKG = "com.android.uiautomator.tests.cts.testapp";
+
+    private static final Intent START_MAIN_ACTIVITY = new Intent(Intent.ACTION_MAIN)
+            .setComponent(new ComponentName(TEST_APP_PKG, TEST_APP_PKG + ".MainActivity"))
+            .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+
+    private final UiObject mActionButton = new UiObject(new UiSelector().text("Go"));
+    private final UiObject mDelayField = new UiObject(new UiSelector().description("delay"));
+
+    private static final int DEFAULT_WAIT_FOR_WINDOW_TIMEOUT = 5500;
+    private static final int SHORT_WAIT_FOR_WINDOW_TIMEOUT = 1000;
+    private static final int LONG_WAIT_FOR_WINDOW_TIMEOUT = 30000;
+    private static final int THRESHOLD = 500;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // Launch the test app
+        getInstrumentation().getContext().startActivity(START_MAIN_ACTIVITY);
+
+        // Navigate to the Timeout Test
+        UiScrollable listView = new UiScrollable(new UiSelector()
+                .className(android.widget.ListView.class.getName()));
+        UiObject testItem = listView.getChildByText(new UiSelector()
+                .className(android.widget.TextView.class.getName()), "Timeout Test");
+        testItem.click();
+    }
+
+    public void testClickAndWaitForNewWindowShortTimeoutNotReached()
+            throws UiObjectNotFoundException {
+
+        // Trigger the app to start a new activity just before the short timeout expires
+        mDelayField.setText(Integer.toString(SHORT_WAIT_FOR_WINDOW_TIMEOUT - THRESHOLD));
+        assertTrue("clickAndWaitForNewWindow() timed out too early",
+                mActionButton.clickAndWaitForNewWindow(SHORT_WAIT_FOR_WINDOW_TIMEOUT));
+
+        // Wait until the new activity launches
+        mActionButton.waitUntilGone(2 * THRESHOLD);
+        getUiDevice().pressBack();
+    }
+
+    public void testClickAndWaitForNewWindowShortTimeoutReached()
+            throws UiObjectNotFoundException {
+
+        // Trigger the app to start a new activity just after the short timeout expires
+        mDelayField.setText(Integer.toString(SHORT_WAIT_FOR_WINDOW_TIMEOUT + THRESHOLD));
+        assertFalse("clickAndWaitForNewWindow() did not timeout",
+                mActionButton.clickAndWaitForNewWindow(SHORT_WAIT_FOR_WINDOW_TIMEOUT));
+
+        // Wait until the new activity launches
+        mActionButton.waitUntilGone(2 * THRESHOLD);
+        getUiDevice().pressBack();
+    }
+
+    public void testClickAndWaitForNewWindowDefaultTimeoutNotReached()
+            throws UiObjectNotFoundException {
+
+        // Trigger the app to start a new activity just before the default timeout expires
+        mDelayField.setText(Integer.toString(DEFAULT_WAIT_FOR_WINDOW_TIMEOUT - THRESHOLD));
+        assertTrue("clickAndWaitForNewWindow() timed out too early",
+                mActionButton.clickAndWaitForNewWindow());
+
+        // Wait until the new activity launches
+        mActionButton.waitUntilGone(2 * THRESHOLD);
+        getUiDevice().pressBack();
+    }
+
+    public void testClickAndWaitForNewWindowDefaultTimeoutReached()
+            throws UiObjectNotFoundException {
+
+        // Trigger the app to start a new activity just after the default timeout expires
+        mDelayField.setText(Integer.toString(DEFAULT_WAIT_FOR_WINDOW_TIMEOUT + THRESHOLD));
+        assertFalse("clickAndWaitForNewWindow() did not timeout",
+                mActionButton.clickAndWaitForNewWindow());
+
+        // Wait until the new activity launches
+        mActionButton.waitUntilGone(2 * THRESHOLD);
+        getUiDevice().pressBack();
+    }
+
+    public void testClickAndWaitForNewWindowLongTimeoutNotReached()
+            throws UiObjectNotFoundException {
+
+        // Trigger the app to start a new activity just before the short timeout expires
+        mDelayField.setText(Integer.toString(LONG_WAIT_FOR_WINDOW_TIMEOUT - THRESHOLD));
+        assertTrue("clickAndWaitForNewWindow() timed out too early",
+                mActionButton.clickAndWaitForNewWindow(LONG_WAIT_FOR_WINDOW_TIMEOUT));
+
+        // Wait until the new activity launches
+        mActionButton.waitUntilGone(2 * THRESHOLD);
+        getUiDevice().pressBack();
+    }
+
+    public void testClickAndWaitForNewWindowLongTimeoutReached()
+            throws UiObjectNotFoundException {
+
+        // Trigger the app to start a new activity just after the short timeout expires
+        mDelayField.setText(Integer.toString(LONG_WAIT_FOR_WINDOW_TIMEOUT + THRESHOLD));
+        assertFalse("clickAndWaitForNewWindow() did not timeout",
+                mActionButton.clickAndWaitForNewWindow(LONG_WAIT_FOR_WINDOW_TIMEOUT));
+
+        // Wait until the new activity launches
+        mActionButton.waitUntilGone(2 * THRESHOLD);
+        getUiDevice().pressBack();
+    }
+
+    @Override
+    protected void tearDown() {
+        // Return to the homescreen after each test
+        getUiDevice().pressHome();
+    }
+}
diff --git a/tests/CtsUiAutomatorTest/testapp/AndroidManifest.xml b/tests/CtsUiAutomatorTest/testapp/AndroidManifest.xml
index bc80e26..559e11c 100644
--- a/tests/CtsUiAutomatorTest/testapp/AndroidManifest.xml
+++ b/tests/CtsUiAutomatorTest/testapp/AndroidManifest.xml
@@ -43,6 +43,7 @@
                 android:name="android.support.PARENT_ACTIVITY"
                 android:value="FragmentActivity" />
         </activity>
+        <activity android:name=".LaunchedActivity" />
      </application>
 
 </manifest>
diff --git a/tests/CtsUiAutomatorTest/testapp/res/layout/launched_activity.xml b/tests/CtsUiAutomatorTest/testapp/res/layout/launched_activity.xml
new file mode 100644
index 0000000..f5b3478
--- /dev/null
+++ b/tests/CtsUiAutomatorTest/testapp/res/layout/launched_activity.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal" >
+</LinearLayout>
diff --git a/tests/CtsUiAutomatorTest/testapp/res/layout/test_timeout_fragment.xml b/tests/CtsUiAutomatorTest/testapp/res/layout/test_timeout_fragment.xml
new file mode 100644
index 0000000..cf0439c
--- /dev/null
+++ b/tests/CtsUiAutomatorTest/testapp/res/layout/test_timeout_fragment.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <LinearLayout android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+            <TextView android:text="Delay"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textSize="18sp"/>
+            <EditText android:id="@+id/delay"
+                    android:contentDescription="delay"
+                    android:inputType="number"
+                    android:layout_width="100sp"
+                    android:layout_height="wrap_content"
+                    android:hint="0" />
+            <Button android:id="@+id/go_btn"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="Go" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/LaunchedActivity.java b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/LaunchedActivity.java
new file mode 100644
index 0000000..ca48974
--- /dev/null
+++ b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/LaunchedActivity.java
@@ -0,0 +1,31 @@
+/*
+ * 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.tests.cts.testapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class LaunchedActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.launched_activity);
+    }
+
+}
diff --git a/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestItems.java b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestItems.java
index 59b65f3..17ef46d 100644
--- a/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestItems.java
+++ b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestItems.java
@@ -90,6 +90,7 @@
         addTestItem(new TestItem("38", "Test 38", TestGenericDetailFragment.class));
         addTestItem(new TestItem("39", "Test 39", TestGenericDetailFragment.class));
         addTestItem(new TestItem("40", "Test 40", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("41", "Timeout Test", TestTimeoutFragment.class));
     }
 
     private static void addTestItem(TestItem item) {
diff --git a/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestTimeoutFragment.java b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestTimeoutFragment.java
new file mode 100644
index 0000000..3b3fd8b
--- /dev/null
+++ b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestTimeoutFragment.java
@@ -0,0 +1,74 @@
+/*
+ * 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.tests.cts.testapp;
+
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.EditText;
+
+public class TestTimeoutFragment extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+        View v = inflater.inflate(R.layout.test_timeout_fragment, container, false);
+
+        Button goButton = (Button)v.findViewById(R.id.go_btn);
+        goButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                doAction(v);
+            }
+        });
+
+        return v;
+    }
+
+    public void doAction(View v) {
+        String delayText = ((EditText)getView().findViewById(R.id.delay)).getText().toString();
+        final int delayValue = delayText.isEmpty() ? 0 : Integer.parseInt(delayText);
+
+        new StartActivityDelayed(delayValue).execute();
+    }
+
+    private class StartActivityDelayed extends AsyncTask<Void, Void, Void> {
+        private final long mDelay;
+
+        public StartActivityDelayed(int delay) {
+            mDelay = delay;
+        }
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            try {
+                Thread.sleep(mDelay);
+            } catch (InterruptedException e) { }
+
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(Void result) {
+            getActivity().startActivity(new Intent(getActivity(), LaunchedActivity.class));
+        }
+    }
+}