Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(484)

Side by Side Diff: chrome/browser/device_orientation/provider_impl.cc

Issue 3136008: Implement device_orientation::Provider. (Closed)
Patch Set: Patch Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <cmath>
6 #include <set>
7 #include <vector>
8
9 #include "base/logging.h"
10 #include "base/task.h"
11 #include "chrome/browser/chrome_thread.h"
12 #include "chrome/browser/device_orientation/orientation.h"
13 #include "chrome/browser/device_orientation/provider_impl.h"
14
15 namespace device_orientation {
16
17 ProviderImpl::ProviderImpl(MessageLoop* message_loop,
18 const DataFetcherFactory factories[])
19 : creator_loop_(message_loop),
20 ALLOW_THIS_IN_INITIALIZER_LIST(do_poll_method_factory_(this)) {
21 for (const DataFetcherFactory* fp = factories; *fp; ++fp)
22 factories_.push_back(*fp);
23 }
24
25 ProviderImpl::~ProviderImpl() {
26 }
27
28 void ProviderImpl::AddObserver(Observer* observer) {
29 DCHECK(MessageLoop::current() == creator_loop_);
30
31 observers_.insert(observer);
32 if (observers_.size() == 1)
33 Start();
34 else
35 observer->OnOrientationUpdate(last_notification_);
36 }
37
38 void ProviderImpl::RemoveObserver(Observer* observer) {
39 DCHECK(MessageLoop::current() == creator_loop_);
40
41 observers_.erase(observer);
42 if (observers_.empty())
43 Stop();
44 }
45
46 void ProviderImpl::Start() {
47 DCHECK(MessageLoop::current() == creator_loop_);
48 DCHECK(!polling_thread_.get());
49
50 polling_thread_.reset(new base::Thread("Device orientation polling thread"));
51 if (!polling_thread_->Start()) {
52 LOG(ERROR) << "Failed to start device orientation polling thread";
53 polling_thread_.reset();
54 return;
55 }
56 ScheduleInitializePollingThread();
57 }
58
59 void ProviderImpl::Stop() {
60 DCHECK(MessageLoop::current() == creator_loop_);
61 polling_thread_.reset();
62 data_fetcher_.reset();
63 }
64
65 void ProviderImpl::DoInitializePollingThread(
66 std::vector<DataFetcherFactory> factories) {
67 DCHECK(MessageLoop::current() == polling_thread_->message_loop());
68
69 typedef std::vector<DataFetcherFactory>::const_iterator Iterator;
70 for (Iterator i = factories_.begin(), e = factories_.end(); i != e; ++i) {
71 DataFetcherFactory factory = *i;
72 scoped_ptr<DataFetcher> fetcher(factory());
73 Orientation orientation;
74
75 if (fetcher.get() && fetcher->GetOrientation(&orientation)) {
76 // Pass ownership of fetcher to provider_.
77 data_fetcher_.swap(fetcher);
78 last_orientation_ = orientation;
79
80 // Notify observers.
81 ScheduleDoNotify(orientation);
82
83 // Start polling.
84 ScheduleDoPoll();
85 return;
86 }
87 }
88
89 // When no orientation data can be provided.
90 ScheduleDoNotify(Orientation::Empty());
91 }
92
93 void ProviderImpl::ScheduleInitializePollingThread() {
94 DCHECK(MessageLoop::current() == creator_loop_);
95
96 Task* task = NewRunnableMethod(this,
97 &ProviderImpl::DoInitializePollingThread,
98 factories_);
99 MessageLoop* polling_loop = polling_thread_->message_loop();
100 polling_loop->PostTask(FROM_HERE, task);
101 }
102
103 void ProviderImpl::DoNotify(Orientation orientation) {
104 DCHECK(MessageLoop::current() == creator_loop_);
105
106 last_notification_ = orientation;
107
108 typedef std::set<Observer*>::const_iterator Iterator;
109 for (Iterator i = observers_.begin(), e = observers_.end(); i != e; ++i)
110 (*i)->OnOrientationUpdate(orientation);
111
112 if (orientation.IsEmpty()) {
113 // Notify observers about failure to provide data exactly once.
114 observers_.clear();
115 Stop();
116 }
117 }
118
119 void ProviderImpl::ScheduleDoNotify(Orientation orientation) {
120 DCHECK(MessageLoop::current() == polling_thread_->message_loop());
121
122 Task* task = NewRunnableMethod(this, &ProviderImpl::DoNotify, orientation);
123 creator_loop_->PostTask(FROM_HERE, task);
124 }
125
126 void ProviderImpl::DoPoll() {
127 DCHECK(MessageLoop::current() == polling_thread_->message_loop());
128
129 Orientation orientation;
130 if (!data_fetcher_->GetOrientation(&orientation)) {
131 LOG(ERROR) << "Failed to poll device orientation data fetcher.";
132
133 ScheduleDoNotify(Orientation::Empty());
134 return;
135 }
136
137 if (SignificantlyDifferent(orientation, last_orientation_)) {
138 last_orientation_ = orientation;
139 ScheduleDoNotify(orientation);
140 }
141
142 ScheduleDoPoll();
143 }
144
145 void ProviderImpl::ScheduleDoPoll() {
146 DCHECK(MessageLoop::current() == polling_thread_->message_loop());
147
148 Task* task = do_poll_method_factory_.NewRunnableMethod(&ProviderImpl::DoPoll);
149 MessageLoop* polling_loop = polling_thread_->message_loop();
150 polling_loop->PostDelayedTask(FROM_HERE, task, SamplingIntervalMs());
151 }
152
153 namespace {
154 bool IsElementSignificantlyDifferent(bool can_provide_element1,
155 bool can_provide_element2,
156 double element1,
157 double element2) {
158 const double kThreshold = 0.1;
159
160 if (can_provide_element1 != can_provide_element2)
161 return true;
162 if (can_provide_element1 &&
163 std::fabs(element1 - element2) >= kThreshold)
164 return true;
165 return false;
166 }
167 } // namespace
168
169 // Returns true if two orientations are considered different enough that
170 // observers should be notified of the new orientation.
171 bool ProviderImpl::SignificantlyDifferent(const Orientation& o1,
172 const Orientation& o2) {
173 return IsElementSignificantlyDifferent(o1.can_provide_alpha_,
174 o2.can_provide_alpha_,
175 o1.alpha_,
176 o2.alpha_) ||
177 IsElementSignificantlyDifferent(o1.can_provide_beta_,
178 o2.can_provide_beta_,
179 o1.beta_,
180 o2.beta_) ||
181 IsElementSignificantlyDifferent(o1.can_provide_gamma_,
182 o2.can_provide_gamma_,
183 o1.gamma_,
184 o2.gamma_);
185 }
186
187 int ProviderImpl::SamplingIntervalMs() const {
188 DCHECK(MessageLoop::current() == polling_thread_->message_loop());
189 DCHECK(data_fetcher_.get());
190
191 int fetcher_interval = data_fetcher_->MinSamplingIntervalMs();
192
193 if (fetcher_interval > kDesiredSamplingIntervalMs)
194 return fetcher_interval;
195 else
196 return kDesiredSamplingIntervalMs;
197 }
198
199 } // namespace device_orientation
OLDNEW
« no previous file with comments | « chrome/browser/device_orientation/provider_impl.h ('k') | chrome/browser/device_orientation/provider_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698