Home | History | Annotate | Download | only in aupt
      1 /*
      2  * Copyright (C) 2014 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 
     17 package android.support.test.aupt;
     18 
     19 import android.app.Instrumentation;
     20 import android.support.test.uiautomator.By;
     21 import android.support.test.uiautomator.UiDevice;
     22 import android.support.test.uiautomator.UiObject2;
     23 import android.support.test.uiautomator.UiWatcher;
     24 import android.support.test.uiautomator.Until;
     25 import android.util.Log;
     26 
     27 import java.util.ArrayList;
     28 import java.util.Collections;
     29 import java.util.List;
     30 
     31 public class UiWatchers {
     32     private static final String LOG_TAG = UiWatchers.class.getSimpleName();
     33     private final List<String> mErrors = new ArrayList<String>();
     34 
     35     /**
     36      * We can use the UiDevice registerWatcher to register a small script to be executed when the
     37      * framework is waiting for a control to appear. Waiting may be the cause of an unexpected
     38      * dialog on the screen and it is the time when the framework runs the registered watchers.
     39      * This is a sample watcher looking for ANR and crashes. it closes it and moves on. You should
     40      * create your own watchers and handle error logging properly for your type of tests.
     41      */
     42     public void registerAnrAndCrashWatchers(Instrumentation instr) {
     43         final UiDevice device = UiDevice.getInstance(instr);
     44 
     45         // class names may have changed
     46         device.registerWatcher("AnrWatcher", new UiWatcher() {
     47             @Override
     48             public boolean checkForCondition() {
     49                 UiObject2 window = device.findObject(
     50                         By.pkg("android").textContains("isn't responding"));
     51                 if (window != null) {
     52                     String errorText = window.getText();
     53                     onAnrDetected(errorText);
     54                     postHandler(device);
     55                     return true; // triggered
     56                 }
     57                 return false; // no trigger
     58             }
     59         });
     60 
     61         device.registerWatcher("CrashWatcher", new UiWatcher() {
     62             @Override
     63             public boolean checkForCondition() {
     64                 UiObject2 window = device.findObject(
     65                         By.pkg("android").textContains("has stopped"));
     66                 if (window != null) {
     67                     String errorText = window.getText();
     68                     onCrashDetected(errorText);
     69                     postHandler(device);
     70                     return true; // triggered
     71                 }
     72                 return false; // no trigger
     73             }
     74         });
     75 
     76         Log.i(LOG_TAG, "Registed GUI Exception watchers");
     77     }
     78 
     79     public void removeAnrAndCrashWatchers(Instrumentation instr) {
     80         final UiDevice device = UiDevice.getInstance(instr);
     81         device.removeWatcher("AnrWatcher");
     82         device.removeWatcher("CrashWatcher");
     83     }
     84 
     85     public void onAnrDetected(String errorText) {
     86         mErrors.add(errorText);
     87     }
     88 
     89     public void onCrashDetected(String errorText) {
     90         mErrors.add(errorText);
     91     }
     92 
     93     public void reset() {
     94         mErrors.clear();
     95     }
     96 
     97     public List<String> getErrors() {
     98         return Collections.unmodifiableList(mErrors);
     99     }
    100 
    101     /**
    102      * Current implementation ignores the exception and continues.
    103      */
    104     public void postHandler(UiDevice device) {
    105         // TODO: Add custom error logging here
    106 
    107         String formatedOutput = String.format("UI Exception Message: %-20s\n",
    108                 device.getCurrentPackageName());
    109         Log.e(LOG_TAG, formatedOutput);
    110 
    111         UiObject2 buttonMute = device.findObject(By.res("android", "aerr_mute"));
    112         if (buttonMute != null) {
    113             buttonMute.click();
    114         }
    115 
    116         UiObject2 closeAppButton = device.findObject(By.res("android", "aerr_close"));
    117         if (closeAppButton != null) {
    118             closeAppButton.click();
    119         }
    120 
    121         // sometimes it takes a while for the OK button to become enabled
    122         UiObject2 buttonOK = device.findObject(By.text("OK").enabled(true));
    123         if (buttonOK != null) {
    124             buttonOK.click();
    125         }
    126     }
    127 }
    128