1 /* 2 * Copyright (C) 2013 DroidDriver committers 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 io.appium.droiddriver.base; 18 19 import android.os.SystemClock; 20 21 import java.util.Collection; 22 import java.util.LinkedList; 23 24 import io.appium.droiddriver.DroidDriver; 25 import io.appium.droiddriver.Poller; 26 import io.appium.droiddriver.exceptions.NoRunningActivityException; 27 import io.appium.droiddriver.exceptions.TimeoutException; 28 import io.appium.droiddriver.finders.Finder; 29 30 /** 31 * Default implementation of a {@link Poller}. 32 */ 33 public class DefaultPoller implements Poller { 34 private final Collection<TimeoutListener> timeoutListeners = new LinkedList<TimeoutListener>(); 35 private final Collection<PollingListener> pollingListeners = new LinkedList<PollingListener>(); 36 private long timeoutMillis = 10000; 37 private long intervalMillis = 500; 38 39 @Override getIntervalMillis()40 public long getIntervalMillis() { 41 return intervalMillis; 42 } 43 44 @Override setIntervalMillis(long intervalMillis)45 public void setIntervalMillis(long intervalMillis) { 46 this.intervalMillis = intervalMillis; 47 } 48 49 @Override getTimeoutMillis()50 public long getTimeoutMillis() { 51 return timeoutMillis; 52 } 53 54 @Override setTimeoutMillis(long timeoutMillis)55 public void setTimeoutMillis(long timeoutMillis) { 56 this.timeoutMillis = timeoutMillis; 57 } 58 59 @Override pollFor(DroidDriver driver, Finder finder, ConditionChecker<T> checker)60 public <T> T pollFor(DroidDriver driver, Finder finder, ConditionChecker<T> checker) { 61 return pollFor(driver, finder, checker, timeoutMillis); 62 } 63 64 @Override pollFor(DroidDriver driver, Finder finder, ConditionChecker<T> checker, long timeoutMillis)65 public <T> T pollFor(DroidDriver driver, Finder finder, ConditionChecker<T> checker, 66 long timeoutMillis) { 67 long end = SystemClock.uptimeMillis() + timeoutMillis; 68 while (true) { 69 try { 70 try { 71 driver.refreshUiElementTree(); 72 } catch (NoRunningActivityException nrae) { 73 if (checker == GONE) { 74 return null; 75 } 76 throw nrae; 77 } 78 return checker.check(driver, finder); 79 } catch (UnsatisfiedConditionException uce) { 80 // fall through to poll 81 } 82 83 for (PollingListener pollingListener : pollingListeners) { 84 pollingListener.onPolling(driver, finder); 85 } 86 87 long remainingMillis = end - SystemClock.uptimeMillis(); 88 if (remainingMillis < 0) { 89 for (TimeoutListener timeoutListener : timeoutListeners) { 90 timeoutListener.onTimeout(driver, finder); 91 } 92 throw new TimeoutException(String.format( 93 "Timed out after %d milliseconds waiting for %s %s", timeoutMillis, finder, checker)); 94 } 95 SystemClock.sleep(Math.min(intervalMillis, remainingMillis)); 96 } 97 } 98 99 @Override addListener(final TimeoutListener timeoutListener)100 public ListenerRemover addListener(final TimeoutListener timeoutListener) { 101 timeoutListeners.add(timeoutListener); 102 return new ListenerRemover() { 103 @Override 104 public void remove() { 105 timeoutListeners.remove(timeoutListener); 106 } 107 }; 108 } 109 110 @Override 111 public ListenerRemover addListener(final PollingListener pollingListener) { 112 pollingListeners.add(pollingListener); 113 return new ListenerRemover() { 114 @Override 115 public void remove() { 116 pollingListeners.remove(pollingListener); 117 } 118 }; 119 } 120 } 121