aboutsummaryrefslogtreecommitdiff
path: root/src/io/appium/droiddriver/base/DefaultPoller.java
blob: 933ae91ca4ac9748c61dd3d0fdca6bdabf10841e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
 * Copyright (C) 2013 DroidDriver committers
 *
 * 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 io.appium.droiddriver.base;

import android.os.SystemClock;

import java.util.Collection;
import java.util.LinkedList;

import io.appium.droiddriver.DroidDriver;
import io.appium.droiddriver.Poller;
import io.appium.droiddriver.exceptions.NoRunningActivityException;
import io.appium.droiddriver.exceptions.TimeoutException;
import io.appium.droiddriver.finders.Finder;

/**
 * Default implementation of a {@link Poller}.
 */
public class DefaultPoller implements Poller {
  private final Collection<TimeoutListener> timeoutListeners = new LinkedList<TimeoutListener>();
  private final Collection<PollingListener> pollingListeners = new LinkedList<PollingListener>();
  private long timeoutMillis = 10000;
  private long intervalMillis = 500;

  @Override
  public long getIntervalMillis() {
    return intervalMillis;
  }

  @Override
  public void setIntervalMillis(long intervalMillis) {
    this.intervalMillis = intervalMillis;
  }

  @Override
  public long getTimeoutMillis() {
    return timeoutMillis;
  }

  @Override
  public void setTimeoutMillis(long timeoutMillis) {
    this.timeoutMillis = timeoutMillis;
  }

  @Override
  public <T> T pollFor(DroidDriver driver, Finder finder, ConditionChecker<T> checker) {
    return pollFor(driver, finder, checker, timeoutMillis);
  }

  @Override
  public <T> T pollFor(DroidDriver driver, Finder finder, ConditionChecker<T> checker,
      long timeoutMillis) {
    long end = SystemClock.uptimeMillis() + timeoutMillis;
    while (true) {
      try {
        try {
          driver.refreshUiElementTree();
        } catch (NoRunningActivityException nrae) {
          if (checker == GONE) {
            return null;
          }
          throw nrae;
        }
        return checker.check(driver, finder);
      } catch (UnsatisfiedConditionException uce) {
        // fall through to poll
      }

      for (PollingListener pollingListener : pollingListeners) {
        pollingListener.onPolling(driver, finder);
      }

      long remainingMillis = end - SystemClock.uptimeMillis();
      if (remainingMillis < 0) {
        for (TimeoutListener timeoutListener : timeoutListeners) {
          timeoutListener.onTimeout(driver, finder);
        }
        throw new TimeoutException(String.format(
            "Timed out after %d milliseconds waiting for %s %s", timeoutMillis, finder, checker));
      }
      SystemClock.sleep(Math.min(intervalMillis, remainingMillis));
    }
  }

  @Override
  public ListenerRemover addListener(final TimeoutListener timeoutListener) {
    timeoutListeners.add(timeoutListener);
    return new ListenerRemover() {
      @Override
      public void remove() {
        timeoutListeners.remove(timeoutListener);
      }
    };
  }

  @Override
  public ListenerRemover addListener(final PollingListener pollingListener) {
    pollingListeners.add(pollingListener);
    return new ListenerRemover() {
      @Override
      public void remove() {
        pollingListeners.remove(pollingListener);
      }
    };
  }
}