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