Home | History | Annotate | Download | only in uiautomatortest
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.cts.uiautomatortest;
     17 
     18 import android.graphics.Point;
     19 import android.graphics.Rect;
     20 import android.os.RemoteException;
     21 import android.os.SystemClock;
     22 import android.util.Log;
     23 
     24 import com.android.uiautomator.core.UiCollection;
     25 import com.android.uiautomator.core.UiDevice;
     26 import com.android.uiautomator.core.UiObject;
     27 import com.android.uiautomator.core.UiObjectNotFoundException;
     28 import com.android.uiautomator.core.UiScrollable;
     29 import com.android.uiautomator.core.UiSelector;
     30 import com.android.uiautomator.core.UiWatcher;
     31 import com.android.uiautomator.testrunner.UiAutomatorTestCase;
     32 
     33 import java.io.BufferedReader;
     34 import java.io.File;
     35 import java.io.IOException;
     36 
     37 /**
     38  * Sanity test uiautomator functionality on target device.
     39  */
     40 public class CtsUiAutomatorTest extends UiAutomatorTestCase {
     41     private static final String LOG_TAG = CtsUiAutomatorTest.class.getSimpleName();
     42     private static final String[] LIST_SCROLL_TESTS = new String[] {
     43             "Test 17", "Test 11", "Test 20"
     44     };
     45     private static final String LAUNCH_APP = "am start -a android.intent.action.MAIN"
     46             + " -n com.android.cts.uiautomator/.MainActivity -W";
     47     private static final String PKG_NAME = "com.android.cts.uiautomator";
     48 
     49     // Maximum wait for key object to become visible
     50     private static final int WAIT_EXIST_TIMEOUT = 5 * 1000;
     51 
     52     private static final String SCREEN_SHOT_FILE_PATH_NAME = "/data/local/tmp/ctsScreenShot";
     53 
     54     @Override
     55     protected void setUp() throws Exception {
     56         super.setUp();
     57         // Make sure the test app is always running
     58         UiDevice.getInstance().waitForIdle();
     59         if (!new UiObject(new UiSelector().packageName(PKG_NAME)).exists())
     60             runShellCommand(LAUNCH_APP);
     61     }
     62 
     63     /**
     64      * Helper to execute a command on the shell
     65      *
     66      * @throws IOException
     67      * @throws InterruptedException
     68      */
     69     private void runShellCommand(String command) throws IOException, InterruptedException {
     70         Process p = null;
     71         BufferedReader resultReader = null;
     72         try {
     73             p = Runtime.getRuntime().exec(command);
     74             int status = p.waitFor();
     75             if (status != 0) {
     76                 throw new RuntimeException(String.format("Run shell command: %s, status: %s",
     77                         command, status));
     78             }
     79         } finally {
     80             if (resultReader != null) {
     81                 resultReader.close();
     82             }
     83             if (p != null) {
     84                 p.destroy();
     85             }
     86         }
     87     }
     88 
     89     /*
     90      * Items in the listScrollTests array should be spread out such that a
     91      * scroll is required to reach each item at each of the far ends.
     92      */
     93     public void testListScrollAndSelect() throws UiObjectNotFoundException {
     94         UiScrollable listView = new UiScrollable(
     95                 new UiSelector().className(android.widget.ListView.class.getName()));
     96 
     97         // on single fragment display
     98         if (!listView.exists())
     99             UiDevice.getInstance().pressBack();
    100 
    101         for (String test : LIST_SCROLL_TESTS) {
    102             openTest(test);
    103             verifyTestDetailsExists(test);
    104         }
    105     }
    106 
    107     /**
    108      * Test erasing of multi word text in edit field and input of new text. Test
    109      * verifying input text using a complex UiSelector
    110      *
    111      * @throws UiObjectNotFoundException
    112      */
    113     public void testTextEraseAndInput() throws UiObjectNotFoundException {
    114         String testText = "Android Ui Automator Input Text";
    115         openTest("Test 1");
    116 
    117         UiObject editText = new UiObject(new UiSelector().className(android.widget.EditText.class
    118                 .getName()));
    119         editText.setText(testText);
    120 
    121         UiObject submitButton = new UiObject(new UiSelector()
    122                 .className(android.widget.Button.class.getName()).clickable(true)
    123                 .textStartsWith("Submit"));
    124         submitButton.click();
    125 
    126         UiObject result = new UiObject(new UiSelector().className(
    127                 android.widget.LinearLayout.class.getName()).childSelector(
    128                 (new UiSelector().className(android.widget.ScrollView.class.getName())
    129                         .childSelector(new UiSelector().className(android.widget.TextView.class
    130                                 .getName())))));
    131 
    132         if (!testText.equals(result.getText())) {
    133             throw new UiObjectNotFoundException("Test text: " + testText);
    134         }
    135 
    136         getObjectByText("OK").click();
    137     }
    138 
    139     /**
    140      * Select each of the buttons by using only the content description property
    141      *
    142      * @throws UiObjectNotFoundException
    143      */
    144     public void testSelectByContentDescription() throws UiObjectNotFoundException {
    145         openTest("Test 2");
    146         getObjectByDescription("Button 1").click();
    147         verifyDialogActionResults("Button 1");
    148         getObjectByDescription("Button 2").click();
    149         verifyDialogActionResults("Button 2");
    150         getObjectByDescription("Button 3").click();
    151         verifyDialogActionResults("Button 3");
    152     }
    153 
    154     /**
    155      * Select each of the buttons by using only the text property
    156      *
    157      * @throws UiObjectNotFoundException
    158      */
    159     public void testSelectByText() throws UiObjectNotFoundException {
    160         openTest("Test 2");
    161         getObjectByText("Button 1").click();
    162         verifyDialogActionResults("Button 1");
    163         getObjectByText("Button 2").click();
    164         verifyDialogActionResults("Button 2");
    165         getObjectByText("Button 3").click();
    166         verifyDialogActionResults("Button 3");
    167     }
    168 
    169     /**
    170      * Select each of the buttons by using only the index property
    171      *
    172      * @throws UiObjectNotFoundException
    173      */
    174     public void testSelectByIndex() throws UiObjectNotFoundException {
    175         openTest("Test 2");
    176         getObjectByIndex(android.widget.Button.class.getName(), 0).click();
    177         verifyDialogActionResults("Button 1");
    178         getObjectByIndex(android.widget.Button.class.getName(), 1).click();
    179         verifyDialogActionResults("Button 2");
    180         getObjectByIndex(android.widget.Button.class.getName(), 2).click();
    181         verifyDialogActionResults("Button 3");
    182     }
    183 
    184     /**
    185      * Select each of the buttons by using only the instance number
    186      *
    187      * @throws UiObjectNotFoundException
    188      */
    189     public void testSelectByInstance() throws UiObjectNotFoundException {
    190         openTest("Test 2");
    191         getObjectByInstance(android.widget.Button.class.getName(), 0).click();
    192         verifyDialogActionResults("Button 1");
    193         getObjectByInstance(android.widget.Button.class.getName(), 1).click();
    194         verifyDialogActionResults("Button 2");
    195         getObjectByInstance(android.widget.Button.class.getName(), 2).click();
    196         verifyDialogActionResults("Button 3");
    197     }
    198 
    199     /**
    200      * Test when a node's state is changed due to an action, it is updated in the accessibility
    201      * hierarchy.
    202      *
    203      * @throws UiObjectNotFoundException
    204      */
    205     public void testSelectAfterContentChanged() throws UiObjectNotFoundException {
    206         openTest("Test 2");
    207         UiObject dynaButton = getObjectByText("Before");
    208         dynaButton.click();
    209         assertTrue("Button state change is not refreshed in accessibility hierarchy",
    210                 getObjectByText("After").exists());
    211     }
    212 
    213     /**
    214      * Test opening the options menu using the soft buttons
    215      *
    216      * @throws UiObjectNotFoundException
    217      * @throws InterruptedException
    218      * @throws IOException
    219      */
    220     public void testDeviceSoftKeys() throws UiObjectNotFoundException, IOException,
    221             InterruptedException {
    222         openTest("Test 2");
    223         UiDevice device = UiDevice.getInstance();
    224         device.pressMenu();
    225         getObjectByText("Finish").click();
    226         verifyDialogActionResults("Finish");
    227 
    228         // Back button
    229         openTest("Test 1");
    230         UiObject editText = new UiObject(new UiSelector().className(android.widget.EditText.class
    231                 .getName()));
    232         editText.setText("Android Geppetto Test Application");
    233 
    234         UiObject submitButton = new UiObject(new UiSelector()
    235                 .className(android.widget.Button.class.getName()).clickable(true)
    236                 .textStartsWith("Submit"));
    237         submitButton.click();
    238 
    239         // Text from the popup dialog
    240         UiObject result = new UiObject(new UiSelector().textContains("geppetto"));
    241 
    242         // Back button test to dismiss the dialog
    243         assertTrue("Wait for exist must return true", result.waitForExists(2000));
    244         device.pressBack();
    245         result.waitUntilGone(1000);
    246         assertFalse("Wait for exist must return false after press back", result.exists());
    247 
    248         // Home button test
    249         openTest("Test 5");
    250         String pkgName = device.getCurrentPackageName();
    251         assertTrue("CTS test app must be running", pkgName.equals(PKG_NAME));
    252         device.pressHome();
    253         boolean gone = new UiObject(new UiSelector().packageName(PKG_NAME)).waitUntilGone(5000);
    254         assertTrue("CTS test app still visble after pressing home", gone);
    255     }
    256 
    257     /**
    258      * This view is in constant update generating window content changed events.
    259      * The test will read the time displayed and exhaust each wait for idle
    260      * timeout until it read and sets the text back into the edit field and
    261      * presses submit. A dialog box should pop up with the time it took since
    262      * reading the value until pressing submit.
    263      *
    264      * @throws UiObjectNotFoundException
    265      */
    266     public void testWaitForIdleTimeout() throws UiObjectNotFoundException {
    267         openTest("Test 3");
    268         UiObject clk = new UiObject(new UiSelector().descriptionStartsWith("Performance "));
    269 
    270         // First default wait for idle timeout assumed to be 10 seconds
    271         String txtTime = clk.getText();
    272         UiObject edit = new UiObject(new UiSelector().className(android.widget.EditText.class
    273                 .getName()));
    274 
    275         // Second default wait for idle timeout assumed to be 10 seconds.
    276         // Total ~20.
    277         edit.setText(txtTime);
    278 
    279         // Third default wait for idle timeout assumed to be 10 seconds.
    280         // Total ~30.
    281         getObjectByText("Submit").click();
    282 
    283         // The value read should have value between 30 and 60 seconds indicating
    284         // that the internal default timeouts for wait-for-idle is in acceptable
    285         // range.
    286         UiObject readTime = new UiObject(new UiSelector().className(
    287                 android.widget.TextView.class.getName()).instance(1));
    288         String timeDiff = readTime.getText();
    289         Log.i(LOG_TAG, "Sync time: " + timeDiff);
    290 
    291         getObjectByText("OK").click();
    292 
    293         int totalDelay = Integer.parseInt(timeDiff);
    294 
    295         // Cumulative waits in this test should add up to at minimum 30 seconds
    296         assertFalse("Timeout for wait-for-idle is too short. Expecting minimum 30 seconds",
    297                 totalDelay < 30 * 1000);
    298 
    299         // allow for tolerance in time measurements due to differences between
    300         // device speeds
    301         assertFalse("Timeout for wait-for-idle is too long. Expecting maximum 60 seconds",
    302                 totalDelay > 60 * 1000);
    303     }
    304 
    305     /**
    306      * This view is in constant update generating window content changed events.
    307      * This test uses the soft key presses and clicks while the background
    308      * screen is constantly updating causing a constant busy state.
    309      *
    310      * @throws UiObjectNotFoundException
    311      */
    312     public void testVerifyMenuClicks() throws UiObjectNotFoundException {
    313         openTest("Test 3");
    314         UiDevice.getInstance().pressMenu();
    315         new UiObject(new UiSelector().text("Submit")).click();
    316         verifyDialogActionResults("Submit");
    317         UiDevice.getInstance().pressMenu();
    318         new UiObject(new UiSelector().text("Exit")).click();
    319         verifyDialogActionResults("Exit");
    320     }
    321 
    322     /**
    323      * Verifies swipeRight, swipeLeft and raw swipe APIs perform as expected.
    324      *
    325      * @throws UiObjectNotFoundException
    326      */
    327     public void testSwipes() throws UiObjectNotFoundException {
    328         openTest("Test 4");
    329         UiObject textView = new UiObject(new UiSelector().textContains("["));
    330 
    331         textView.swipeLeft(10);
    332         assertTrue("UiObject swipe left 1->2", "[ 2 ]".equals(textView.getText()));
    333 
    334         textView.swipeLeft(10);
    335         assertTrue("UiObject swipe left 2->3", "[ 3 ]".equals(textView.getText()));
    336 
    337         textView.swipeLeft(10);
    338         assertTrue("UiObject swipe left 3->4", "[ 4 ]".equals(textView.getText()));
    339 
    340         textView.swipeRight(10);
    341         assertTrue("UiObject swipe right 3<-4", "[ 3 ]".equals(textView.getText()));
    342 
    343         textView.swipeRight(10);
    344         assertTrue("UiObject swipe right 2<-3", "[ 2 ]".equals(textView.getText()));
    345 
    346         textView.swipeRight(10);
    347         assertTrue("UiObject swipe right 1<-2", "[ 1 ]".equals(textView.getText()));
    348 
    349         Rect tb = textView.getBounds();
    350         UiDevice.getInstance().swipe(tb.right - 20, tb.centerY(), tb.left + 20, tb.centerY(), 50);
    351 
    352         SystemClock.sleep(100);
    353         assertTrue("UiDevice raw swipe 1->2", "[ 2 ]".equals(textView.getText()));
    354     }
    355 
    356     /**
    357      * Creates a complex selector
    358      *
    359      * @throws UiObjectNotFoundException
    360      */
    361     public void testComplexSelectors() throws UiObjectNotFoundException {
    362         openTest("Test 5");
    363         UiSelector frameLayout = new UiSelector().className(android.widget.FrameLayout.class
    364                 .getName());
    365         UiSelector gridLayout = new UiSelector().className(android.widget.GridLayout.class
    366                 .getName());
    367         UiSelector toggleButton = new UiSelector().className(android.widget.ToggleButton.class
    368                 .getName());
    369         UiObject button = new UiObject(frameLayout.childSelector(gridLayout).childSelector(
    370                 toggleButton));
    371 
    372         assertTrue("Toggle button value should be OFF", "OFF".equals(button.getText()));
    373         button.click();
    374         assertTrue("Toggle button value should be ON", "ON".equals(button.getText()));
    375         button.click();
    376         assertTrue("Toggle button value should be OFF", "OFF".equals(button.getText()));
    377     }
    378 
    379     /**
    380      * Test when an object does not exist, an exception is thrown
    381      * @throws UiObjectNotFoundException
    382      */
    383     public void testExceptionObjectNotFound() throws UiObjectNotFoundException {
    384         UiSelector selector = new UiSelector().text("Nothing should be found");
    385         UiSelector child = new UiSelector().className("Nothing");
    386         UiObject obj = new UiObject(selector.childSelector(child));
    387 
    388         assertFalse("Object is reported as existing", obj.exists());
    389 
    390         try {
    391             obj.click();
    392         } catch (UiObjectNotFoundException e) {
    393             return;
    394         }
    395         assertTrue("Exception not thrown for Object not found", false);
    396     }
    397 
    398     /**
    399      * Verifies the UiWatcher registration and trigger function
    400      *
    401      * @throws UiObjectNotFoundException
    402      */
    403     public void testUiWatcher() throws UiObjectNotFoundException {
    404         openTest("Test 5");
    405         UiDevice device = UiDevice.getInstance();
    406         device.registerWatcher("Artificial crash", new UiWatcher() {
    407 
    408             @Override
    409             public boolean checkForCondition() {
    410                 if (new UiObject(new UiSelector().packageName("android")).exists()) {
    411                     try {
    412                         // Expecting a localized OK button
    413                         new UiObject(new UiSelector().className(
    414                                 android.widget.Button.class.getName()).enabled(true)).click();
    415                     } catch (UiObjectNotFoundException e) {
    416                     }
    417                     return true;
    418                 }
    419                 return false;
    420             }
    421         });
    422 
    423         // Causes a runtime exception to be thrown
    424         getObjectByText("Button").click();
    425 
    426         // Fake doing something while the exception is being displayed
    427         SystemClock.sleep(2000);
    428         device.runWatchers();
    429         assertTrue("UiWatcher not triggered", device.hasAnyWatcherTriggered());
    430     }
    431 
    432     /**
    433      * Verifies the 'checked' property of both UiSelector and UiObject
    434      *
    435      * @throws UiObjectNotFoundException
    436      */
    437     public void testSelectorChecked() throws UiObjectNotFoundException {
    438         openTest("Test 5");
    439         UiObject checkboxChecked = new UiObject(new UiSelector().className(
    440                 android.widget.CheckBox.class.getName()).checked(true));
    441         UiObject checkboxNotChecked = new UiObject(new UiSelector().className(
    442                 android.widget.CheckBox.class.getName()).checked(false));
    443 
    444         checkboxNotChecked.click();
    445         assertTrue("Checkbox should be checked", checkboxChecked.isChecked());
    446         checkboxChecked.click();
    447         assertFalse("Checkbox should be unchecked", checkboxNotChecked.isChecked());
    448     }
    449 
    450     /**
    451      * Verifies the 'Clickable' property of both the UiSelector and UiObject
    452      *
    453      * @throws UiObjectNotFoundException
    454      */
    455     public void testSelectorClickable() throws UiObjectNotFoundException {
    456         openTest("Test 5");
    457         UiSelector clickableCheckbox = new UiSelector().clickable(true).className(
    458                 android.widget.CheckBox.class.getName());
    459         UiSelector notClickableProgress = new UiSelector().clickable(false).className(
    460                 android.widget.ProgressBar.class.getName());
    461 
    462         assertTrue("Selector clickable", new UiObject(clickableCheckbox).isClickable());
    463         assertFalse("Selector not clickable", new UiObject(notClickableProgress).isClickable());
    464     }
    465 
    466     /**
    467      * Verifies the 'focusable' property of both UiSelector and UiObject
    468      *
    469      * @throws UiObjectNotFoundException
    470      */
    471     public void testSelectorFocusable() throws UiObjectNotFoundException {
    472         openTest("Test 5");
    473         UiSelector mainLayout = new UiSelector().description("Widgets Collection");
    474         UiSelector focusableCheckbox = mainLayout.childSelector(new UiSelector().className(
    475                 android.widget.CheckBox.class.getName()).focusable(true));
    476         UiSelector notFocusableSpinner = mainLayout.childSelector(new UiSelector().className(
    477                 android.widget.Spinner.class.getName()).focusable(false));
    478 
    479         assertTrue("Selector focusable", new UiObject(focusableCheckbox).isFocusable());
    480         assertFalse("Selector not focusable", new UiObject(notFocusableSpinner).isFocusable());
    481     }
    482 
    483     /**
    484      * Verifies the 'DescriptionContains' property of UiSelector
    485      *
    486      * @throws UiObjectNotFoundException
    487      */
    488     public void testSelectorDescriptionContains() throws UiObjectNotFoundException {
    489         openTest("Test 5");
    490         UiSelector progressDescriptionContains = new UiSelector().descriptionContains("%");
    491         assertTrue("Selector descriptionContains", "Progress is 50 %".equals(new UiObject(
    492                 progressDescriptionContains).getContentDescription()));
    493     }
    494 
    495     /**
    496      * Verifies the 'DescriptionStarts' property of UiSelector
    497      *
    498      * @throws UiObjectNotFoundException
    499      */
    500     public void testSelectorDescriptionStarts() throws UiObjectNotFoundException {
    501         openTest("Test 5");
    502         UiSelector progressDescriptionStart = new UiSelector().descriptionStartsWith("progress");
    503         assertTrue("Selector descriptionStart", "Progress is 50 %".equals(new UiObject(
    504                 progressDescriptionStart).getContentDescription()));
    505     }
    506 
    507     /**
    508      * Verifies the 'Enabled' property of both UiSelector and UiObject
    509      *
    510      * @throws UiObjectNotFoundException
    511      */
    512     public void testSelectorEnabled() throws UiObjectNotFoundException {
    513         openTest("Test 5");
    514         UiSelector mainLayout = new UiSelector().description("Widgets Collection");
    515         UiSelector buttonDisabled = mainLayout.childSelector(new UiSelector().className(
    516                 android.widget.Button.class.getName()).enabled(false));
    517         UiSelector buttonEnabled = mainLayout.childSelector(new UiSelector().className(
    518                 android.widget.Button.class.getName()).enabled(true));
    519 
    520         assertFalse("Selector enabled false", new UiObject(buttonDisabled).isEnabled());
    521         assertTrue("Selector enabled true", new UiObject(buttonEnabled).isEnabled());
    522     }
    523 
    524     /**
    525      * Verifies the UiCollection object child counting by object pattern
    526      *
    527      * @throws UiObjectNotFoundException
    528      */
    529     public void testCollectionCount() throws UiObjectNotFoundException {
    530         openTest("Test 5");
    531         UiCollection collection = new UiCollection(
    532                 new UiSelector().description("Widgets Collection"));
    533         assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
    534 
    535         assertTrue("Collection count",
    536                 collection.getChildCount(new UiSelector().clickable(true)) == 6);
    537     }
    538 
    539     /**
    540      * Verifies the UiCollection can find an object by text and returning by
    541      * pattern
    542      *
    543      * @throws UiObjectNotFoundException
    544      */
    545     public void testCollectionGetChildByText() throws UiObjectNotFoundException {
    546         openTest("Test 5");
    547         UiCollection collection = new UiCollection(
    548                 new UiSelector().description("Widgets Collection"));
    549         assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
    550 
    551         UiObject item = collection.getChildByText(
    552                 new UiSelector().className(android.widget.Button.class.getName()), "Button");
    553 
    554         assertTrue("Collection get child by text", "Button".equals(item.getText()));
    555     }
    556 
    557     /**
    558      * Verifies the UiCollection can find an object by instance and returning by
    559      * pattern
    560      *
    561      * @throws UiObjectNotFoundException
    562      */
    563     public void testCollectionGetChildByInstance() throws UiObjectNotFoundException {
    564         openTest("Test 5");
    565         UiCollection collection = new UiCollection(
    566                 new UiSelector().description("Widgets Collection"));
    567         assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
    568 
    569         // find the second button
    570         UiObject item = collection.getChildByInstance(
    571                 new UiSelector().className(android.widget.Button.class.getName()), 1);
    572 
    573         assertTrue("Collection get child by instance", "Button".equals(item.getText()));
    574     }
    575 
    576     /**
    577      * Verifies the UiCollection can find an object by description and returning
    578      * by pattern
    579      *
    580      * @throws UiObjectNotFoundException
    581      */
    582     public void testCollectionGetChildByDescription() throws UiObjectNotFoundException {
    583         openTest("Test 5");
    584         UiCollection collection = new UiCollection(
    585                 new UiSelector().description("Widgets Collection"));
    586         assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
    587 
    588         UiObject item = collection.getChildByDescription(
    589                 new UiSelector().className(android.widget.Button.class.getName()),
    590                 "Description for Button");
    591 
    592         assertTrue("Collection get child by description", "Button".equals(item.getText()));
    593     }
    594 
    595     /**
    596      * Test Orientation APIs by causing rotations and verifying current state
    597      *
    598      * @throws RemoteException
    599      * @throws UiObjectNotFoundException
    600      * @since API Level 17
    601      */
    602     public void testRotation() throws RemoteException, UiObjectNotFoundException {
    603         openTest("Test 5");
    604         UiDevice device = UiDevice.getInstance();
    605 
    606         device.setOrientationLeft();
    607         device.waitForIdle(); // isNaturalOrientation is not waiting for idle
    608         SystemClock.sleep(1000);
    609         assertFalse("Device orientation should not be natural", device.isNaturalOrientation());
    610 
    611         device.setOrientationNatural();
    612         device.waitForIdle(); // isNaturalOrientation is not waiting for idle
    613         SystemClock.sleep(1000);
    614         assertTrue("Device orientation should be natural", device.isNaturalOrientation());
    615 
    616         device.setOrientationRight();
    617         device.waitForIdle(); // isNaturalOrientation is not waiting for idle
    618         SystemClock.sleep(1000);
    619         assertFalse("Device orientation should not be natural", device.isNaturalOrientation());
    620 
    621         device.setOrientationNatural();
    622     }
    623 
    624     /**
    625      * Reads the current device's product name. Since it is not possible to predetermine the
    626      * would be value, the check verifies that the value is not null and not empty.
    627      *
    628      * @since API Level 17
    629      */
    630     public void testGetProductName() {
    631         String name = UiDevice.getInstance().getProductName();
    632         assertFalse("Product name check returned empty string", name.isEmpty());
    633     }
    634 
    635     /**
    636      * Select each of the buttons by using only regex text
    637      *
    638      * @throws UiObjectNotFoundException
    639      * @since API Level 17
    640      */
    641     public void testSelectByTextMatch() throws UiObjectNotFoundException {
    642         openTest("Test 2");
    643         getObjectByTextMatch(".*n\\s1$").click();
    644         verifyDialogActionResults("Button 1");
    645         getObjectByTextMatch(".*n\\s2$").click();
    646         verifyDialogActionResults("Button 2");
    647         getObjectByTextMatch(".*n\\s3$").click();
    648         verifyDialogActionResults("Button 3");
    649     }
    650 
    651     /**
    652      * Select each of the buttons by using only regex content-description
    653      *
    654      * @throws UiObjectNotFoundException
    655      * @since API Level 17
    656      */
    657     public void testSelectByDescriptionMatch() throws UiObjectNotFoundException {
    658         openTest("Test 2");
    659         getObjectByDescriptionMatch(".*n\\s1$").click();
    660         verifyDialogActionResults("Button 1");
    661         getObjectByDescriptionMatch(".*n\\s2$").click();
    662         verifyDialogActionResults("Button 2");
    663         getObjectByDescriptionMatch(".*n\\s3$").click();
    664         verifyDialogActionResults("Button 3");
    665     }
    666 
    667     /**
    668      * Select each of the buttons by using only regex class name
    669      *
    670      * @throws UiObjectNotFoundException
    671      * @since API Level 17
    672      */
    673     public void testSelectByClassMatch() throws UiObjectNotFoundException {
    674         openTest("Test 5");
    675         UiObject tgl = getObjectByClassMatch(".*ToggleButton$", 0);
    676         String tglValue = tgl.getText();
    677         tgl.click();
    678 
    679         assertFalse("Matching class by Regex failed", tglValue.equals(tgl.getText()));
    680     }
    681 
    682     /**
    683      * Select each of the buttons by using only class type
    684      *
    685      * @throws UiObjectNotFoundException
    686      * @since API Level 17
    687      */
    688     public void testSelectByClassType() throws UiObjectNotFoundException {
    689         openTest("Test 5");
    690         UiObject tgl = getObjectByClass(android.widget.ToggleButton.class, 0);
    691         String tglValue = tgl.getText();
    692         tgl.click();
    693 
    694         assertFalse("Matching class by class type failed", tglValue.equals(tgl.getText()));
    695     }
    696 
    697     /**
    698      * Test the coordinates of 3 buttons side by side verifying vertical and
    699      * horizontal coordinates.
    700      *
    701      * @throws UiObjectNotFoundException
    702      * @since API Level 17
    703      */
    704     public void testGetVisibleBounds() throws UiObjectNotFoundException {
    705         openTest("Test 2");
    706         Rect rect1 = getObjectByText("Button 1").getVisibleBounds();
    707         Rect rect2 = getObjectByText("Button 2").getVisibleBounds();
    708         Rect rect3 = getObjectByText("Button 3").getVisibleBounds();
    709 
    710         assertTrue("X coordinate check failed",
    711                 rect1.left < rect2.left && rect2.right < rect3.right);
    712         assertTrue("Y coordinate check failed",
    713                 rect1.top == rect2.top && rect2.bottom == rect3.bottom);
    714     }
    715 
    716    /**
    717      * Tests the LongClick functionality in the API
    718      *
    719      * @throws UiObjectNotFoundException
    720      * @since API Level 17
    721      */
    722     public void testSelectorLongClickable() throws UiObjectNotFoundException {
    723         openTest("Test 2");
    724         getObjectByText("Button 1").longClick();
    725         verifyDialogActionResults("Longclick Button 1");
    726     }
    727 
    728     /**
    729      * Test the UiSelector's long-clickable property
    730      *
    731      * @throws UiObjectNotFoundException
    732      * @since API Level 17
    733      */
    734     public void testSelectorLongClickableProperty() throws UiObjectNotFoundException {
    735         openTest("Test 2");
    736         UiObject button3 = new UiObject(new UiSelector().className(
    737                 android.widget.Button.class).longClickable(true).instance(2));
    738         button3.longClick();
    739         verifyDialogActionResults("Longclick Button 3");
    740     }
    741 
    742     /**
    743      * Takes a screen shot of the current display and checks if the file is
    744      * created and is not zero size.
    745      *
    746      * @since API Level 17
    747      */
    748     public void testTakeScreenShots() {
    749         File storePath = new File(SCREEN_SHOT_FILE_PATH_NAME);
    750         getUiDevice().takeScreenshot(storePath);
    751 
    752         assertTrue("Screenshot file not detected in store", storePath.exists());
    753         assertTrue("Zero size for screenshot file", storePath.length() > 0);
    754     }
    755 
    756     /**
    757      * Verifies the 'Resource-Id' property of UiSelector
    758      *
    759      * @throws UiObjectNotFoundException
    760      * @since API Level 18
    761      */
    762     public void testSelectorResourceId() throws UiObjectNotFoundException {
    763         openTest("Test 5");
    764         UiSelector toggleSelector =
    765                 new UiSelector().resourceId("com.android.cts.uiautomator:id/test_5_toggleButton");
    766         UiObject toggleButton = new UiObject(toggleSelector);
    767         assertTrue("Object with selector resource-id not found", toggleButton.exists());
    768         assertTrue("Incorrect object for selector resource-id returned",
    769                 "OFF".equals(toggleButton.getText()) || "ON".equals(toggleButton.getText()));
    770     }
    771 
    772     /**
    773      * Verify the UiSelector property resourceIdMatches
    774      *
    775      * @throws UiObjectNotFoundException
    776      * @since API Level 18
    777      */
    778     public void testSelectorResourceIdMatches() throws UiObjectNotFoundException {
    779         openTest("Test 2");
    780         new UiObject(new UiSelector().resourceIdMatches("(?i).*button.*").instance(2)).click();
    781         verifyDialogActionResults("Button 3");
    782         new UiObject(new UiSelector().resourceIdMatches("(?i).*button1.*")).click();
    783         verifyDialogActionResults("Button 1");
    784     }
    785 
    786     /**
    787      * Performs a pinch out from the center of a view to its edges and listens to
    788      * the motion events to make sure the starting and ending points of both pointers
    789      * are correct.
    790      *
    791      * @throws UiObjectNotFoundException
    792      * @since API Level 18
    793      */
    794     public void testPinchOut() throws UiObjectNotFoundException {
    795         openTest("Test 12");
    796 
    797         UiObject screen = new UiObject(
    798                 new UiSelector().description("Details View"));
    799 
    800         // get the current view dimensions
    801         Rect screenRect = screen.getBounds();
    802 
    803         // perform the pinch for 100% of the view dimensions starting form
    804         // the center out to the edges.
    805         screen.pinchOut(100, 30);
    806 
    807         // dialog with the detected pointers motion coordinates is displayed.
    808         UiObject results = new UiObject(new UiSelector().className(
    809                 android.widget.ScrollView.class).childSelector(new UiSelector().className(
    810                         android.widget.TextView.class)));
    811         String allPointers = results.getText();
    812         new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
    813 
    814         // parse pointer 1
    815         Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
    816         Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
    817         // parse pointer 2
    818         Point p2s = parsePointerCoordinates(allPointers, 1, 0); // start
    819         Point p2e = parsePointerCoordinates(allPointers, 1, 1); // end
    820 
    821         assertTrue("All Y axis coordinates for pointer 1 must be the same", p1s.y == p1e.y);
    822         assertTrue("All Y axis coordinates for pointer 2 must be the same", p2s.y == p2e.y);
    823         assertTrue("All Y axis coordinates for both pointers must be the same", p1s.y == p2s.y);
    824         assertTrue("Pinch must be in center of target view", p2s.y == screenRect.centerY());
    825 
    826         assertTrue("Touch-down X coordinate for pointer 1 is invalid",
    827                 withinMarginOfError(0.1f, screenRect.centerX(), p1s.x));
    828 
    829         assertTrue("Touch-down X coordinate for pointer 2 is invalid",
    830                 withinMarginOfError(0.1f, screenRect.centerX(), p2s.x));
    831 
    832         assertTrue("Touch-up X coordinate for pointer 1 is invalid",
    833                 withinMarginOfError(0.1f, screenRect.centerX() - screenRect.left,
    834                         screenRect.centerX() - p1e.x));
    835 
    836         assertTrue("Touch-up X coordinate for pointer 2 is invalid",
    837                 withinMarginOfError(0.1f, screenRect.right, p2e.x));
    838     }
    839 
    840     /**
    841      * Performs a pinch in from the edges of a view to its center and listens to
    842      * the motion events to make sure the starting and ending points of both pointers
    843      * are correct.
    844      *
    845      * @throws UiObjectNotFoundException
    846      * @since API Level 18
    847      */
    848     public void testPinchIn() throws UiObjectNotFoundException {
    849         openTest("Test 12");
    850 
    851         UiObject screen = new UiObject(
    852                 new UiSelector().description("Details View"));
    853 
    854         // get the current view dimensions
    855         Rect screenRect = screen.getBounds();
    856 
    857         // perform the pinch for 100% of the view dimensions starting form
    858         // the edges in towards the center.
    859         screen.pinchIn(100, 30);
    860 
    861         // dialog with the detected pointers motion coordinates is displayed.
    862         UiObject results = new UiObject(new UiSelector().className(
    863                 android.widget.ScrollView.class).childSelector(new UiSelector().className(
    864                         android.widget.TextView.class)));
    865         String allPointers = results.getText();
    866         new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
    867 
    868         // parse pointer 1
    869         Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
    870         Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
    871         // parse pointer 2
    872         Point p2s = parsePointerCoordinates(allPointers, 1, 0); // start
    873         Point p2e = parsePointerCoordinates(allPointers, 1, 1); // end
    874 
    875         assertTrue("All Y axis coordinates for pointer 1 must be the same", p1s.y == p1e.y);
    876         assertTrue("All Y axis coordinates for pointer 2 must be the same", p2s.y == p2e.y);
    877         assertTrue("All Y axis coordinates for both pointers must be the same", p1s.y == p2s.y);
    878         assertTrue("Pinch must be in center of target view", p2s.y == screenRect.centerY());
    879 
    880         assertTrue("Touch-down X coordinate for pointer 1 is invalid",
    881                 withinMarginOfError(0.1f, screenRect.centerX() - screenRect.left,
    882                         screenRect.centerX() -  p1s.x));
    883 
    884         assertTrue("Touch-down X coordinate for pointer 2 is invalid",
    885                 withinMarginOfError(0.1f, screenRect.right, p2s.x));
    886 
    887         assertTrue("Touch-up X coordinate for pointer 1 is invalid",
    888                 withinMarginOfError(0.1f, screenRect.centerX(), p1e.x));
    889 
    890         assertTrue("Touch-up X coordinate for pointer 2 is invalid",
    891                 withinMarginOfError(0.1f, screenRect.centerX(), p2e.x));
    892     }
    893 
    894     /**
    895      * Performs a drag and drop operation from one UiObject to another UiObject
    896      *
    897      * @throws UiObjectNotFoundException
    898      * @since API Level 18
    899      */
    900     public void testDragToObject() throws UiObjectNotFoundException {
    901         openTest("Test 5");
    902 
    903         UiObject imageButton = new UiObject(new UiSelector().description("Image button"));
    904         UiObject starsBar = new UiObject(new UiSelector().className(android.widget.RatingBar.class));
    905 
    906         Rect starsBarRect = starsBar.getBounds();
    907         Rect imageButtonRect = imageButton.getBounds();
    908         imageButton.dragTo(starsBar, 30);
    909 
    910         // dialog with the detected pointers motion coordinates is displayed.
    911         UiObject results = new UiObject(new UiSelector().className(
    912                 android.widget.ScrollView.class).childSelector(new UiSelector().className(
    913                         android.widget.TextView.class)));
    914         String allPointers = results.getText();
    915         new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
    916 
    917         // parse pointer 1
    918         Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
    919         Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
    920 
    921         assertTrue("Invalid touch starting.X reported",
    922                 withinMarginOfError(0.05f, imageButtonRect.centerX(), p1s.x));
    923         assertTrue("Invalid touch starting.Y reported",
    924                 withinMarginOfError(0.05f, imageButtonRect.centerY(), p1s.y));
    925         assertTrue("Invalid touch ending.X reported",
    926                 withinMarginOfError(0.05f, starsBarRect.centerX(), p1e.x));
    927         assertTrue("Invalid touch ending.Y reported",
    928                 withinMarginOfError(0.05f, starsBarRect.centerY(), p1e.y));
    929     }
    930 
    931     /**
    932      * Performs a drag and drop operation from one UiObject to a specified coordinates
    933      *
    934      * @throws UiObjectNotFoundException
    935      * @since API Level 18
    936      */
    937    public void testDragToCoordinates() throws UiObjectNotFoundException {
    938        openTest("Test 5");
    939 
    940        UiObject imageButton = new UiObject(new UiSelector().description("Image button"));
    941        UiObject starsBar = new UiObject(new UiSelector().className(android.widget.RatingBar.class));
    942 
    943        Rect starsBarRect = starsBar.getBounds();
    944        Rect imageButtonRect = imageButton.getBounds();
    945        imageButton.dragTo(starsBarRect.centerX(), starsBarRect.centerY(), 30);
    946 
    947        // dialog with the detected pointers motion coordinates is displayed.
    948        UiObject results = new UiObject(new UiSelector().className(
    949                android.widget.ScrollView.class).childSelector(new UiSelector().className(
    950                        android.widget.TextView.class)));
    951        String allPointers = results.getText();
    952        new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
    953 
    954        // parse pointer 1
    955        Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
    956        Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
    957 
    958        assertTrue("Invalid touch starting.X reported",
    959                withinMarginOfError(0.05f, imageButtonRect.centerX(), p1s.x));
    960        assertTrue("Invalid touch starting.Y reported",
    961                withinMarginOfError(0.05f, imageButtonRect.centerY(), p1s.y));
    962        assertTrue("Invalid touch ending.X reported",
    963                withinMarginOfError(0.05f, starsBarRect.centerX(), p1e.x));
    964        assertTrue("Invalid touch ending.Y reported",
    965                withinMarginOfError(0.05f, starsBarRect.centerY(), p1e.y));
    966    }
    967 
    968    /**
    969     * Detect if actual value is within the allowable margin of error of the expected value.
    970     *
    971     * Used essentially with actual values that may vary from the expected values such in the
    972     * cases of touch and pinch and touch and swipe where the starting or ending points may
    973     * not exactly match the expected value.
    974     *
    975     * @param marginPrecent is values between 0 and 1
    976     * @param expected
    977     * @param actual
    978     * @return true if actual is within the allowed range from expected
    979     */
    980    private boolean withinMarginOfError(float marginPrecent, int expected, int actual) {
    981        int m = (int) (marginPrecent * expected);
    982        return actual >= expected - m && actual <= expected + m;
    983    }
    984 
    985    /**
    986      * Parses a string containing starting to ending coordinates of one or more pointers.
    987      *
    988      * @param allPointers is a raw string with coordinates from all detected pointers
    989      * @param pointerNumber is the desired pointer to be parsed
    990      * @param edge is the 0 for the start or 1 for the end of the swipe
    991      * @return Point containing the start or end coordinates of the specified pointer number
    992      */
    993     private Point parsePointerCoordinates(String allPointers, int pointerNumber, int edge) {
    994         String pointers[] = allPointers.split("\n");
    995         String coordinates = pointers[pointerNumber].split(":")[edge];
    996         String xy[] = coordinates.split(",");
    997         return new Point(Integer.parseInt(xy[0]), Integer.parseInt(xy[1]));
    998     }
    999 
   1000     /**
   1001      * Private helper to open test views. Also covers UiScrollable tests
   1002      *
   1003      * @param name
   1004      * @throws UiObjectNotFoundException
   1005      */
   1006     private void openTest(String name) throws UiObjectNotFoundException {
   1007         try {
   1008             UiDevice.getInstance().setOrientationNatural();
   1009         } catch (RemoteException e) {
   1010             // will catch it in its own test. For now try to put the device
   1011             // in its natural orientation prior to each test
   1012         }
   1013         UiScrollable listView = new UiScrollable(
   1014                 new UiSelector().className(android.widget.ListView.class.getName()));
   1015 
   1016         // on single fragment display
   1017         if (!listView.exists())
   1018             UiDevice.getInstance().pressBack();
   1019 
   1020         UiObject testItem = listView.getChildByText(
   1021                 new UiSelector().className(android.widget.TextView.class.getName()), name);
   1022 
   1023         testItem.click();
   1024     }
   1025 
   1026     private void verifyTestDetailsExists(String name) throws UiObjectNotFoundException {
   1027         // verify that we're at the right test
   1028         new UiObject(new UiSelector().description("Details").text(name)).getText();
   1029     }
   1030 
   1031     private UiObject getObjectByText(String txt) {
   1032         return new UiObject(new UiSelector().text(txt));
   1033     }
   1034 
   1035     private UiObject getObjectByTextMatch(String regex) {
   1036         return new UiObject(new UiSelector().textMatches(regex));
   1037     }
   1038 
   1039     private UiObject getObjectByDescriptionMatch(String regex) {
   1040         return new UiObject(new UiSelector().descriptionMatches(regex));
   1041     }
   1042 
   1043     private UiObject getObjectByDescription(String txt) {
   1044         return new UiObject(new UiSelector().description(txt));
   1045     }
   1046 
   1047     private UiObject getObjectByClassMatch(String regex, int instance) {
   1048         return new UiObject(new UiSelector().classNameMatches(regex).instance(instance));
   1049     }
   1050 
   1051     private <T> UiObject getObjectByClass(Class<T> type, int instance) {
   1052         return new UiObject(new UiSelector().className(type).instance(instance));
   1053     }
   1054 
   1055     private UiObject getObjectByIndex(String className, int index) {
   1056         return new UiObject(new UiSelector().className(className).index(index));
   1057     }
   1058 
   1059     private UiObject getObjectByInstance(String className, int instance) {
   1060         return new UiObject(new UiSelector().className(className).instance(instance));
   1061     }
   1062 
   1063     private void verifyDialogActionResults(String txt) throws UiObjectNotFoundException {
   1064         if (!getObjectByText("Action results").exists() || !getObjectByText(txt).exists()) {
   1065             throw new UiObjectNotFoundException(txt);
   1066         }
   1067         getObjectByText("OK").click();
   1068     }
   1069 }
   1070