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

Side by Side Diff: third_party/WebKit/Source/modules/sensor/SensorProxy.cpp

Issue 2551223003: [Sensors] Align sensor reading updates and 'onchange' notification with rAF. (Closed)
Patch Set: Re-implemented, rAF covers all sensors now Created 4 years 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "modules/sensor/SensorProxy.h" 5 #include "modules/sensor/SensorProxy.h"
6 6
7 #include "core/dom/Document.h"
7 #include "core/frame/LocalFrame.h" 8 #include "core/frame/LocalFrame.h"
8 #include "modules/sensor/SensorProviderProxy.h" 9 #include "modules/sensor/SensorProviderProxy.h"
9 #include "modules/sensor/SensorReading.h" 10 #include "modules/sensor/SensorReading.h"
11 #include "modules/sensor/SensorReadingUpdater.h"
10 #include "platform/mojo/MojoHelper.h" 12 #include "platform/mojo/MojoHelper.h"
11 #include "public/platform/Platform.h" 13 #include "public/platform/Platform.h"
12 14
13 using namespace device::mojom::blink; 15 using namespace device::mojom::blink;
14 16
15 namespace blink { 17 namespace blink {
16 18
17 SensorProxy::SensorProxy(SensorType sensorType, 19 SensorProxy::SensorProxy(SensorType sensorType,
18 SensorProviderProxy* provider, 20 SensorProviderProxy* provider,
19 Page* page, 21 Document* document,
20 std::unique_ptr<SensorReadingFactory> readingFactory) 22 std::unique_ptr<SensorReadingFactory> readingFactory)
21 : PageVisibilityObserver(page), 23 : PageVisibilityObserver(document->page()),
22 m_type(sensorType), 24 m_type(sensorType),
23 m_mode(ReportingMode::CONTINUOUS), 25 m_mode(ReportingMode::CONTINUOUS),
24 m_provider(provider), 26 m_provider(provider),
25 m_clientBinding(this), 27 m_clientBinding(this),
26 m_state(SensorProxy::Uninitialized), 28 m_state(SensorProxy::Uninitialized),
27 m_suspended(false), 29 m_suspended(false),
30 m_document(document),
28 m_readingFactory(std::move(readingFactory)), 31 m_readingFactory(std::move(readingFactory)),
29 m_maximumFrequency(0.0), 32 m_maximumFrequency(0.0) {}
30 m_timer(this, &SensorProxy::onTimerFired) {}
31 33
32 SensorProxy::~SensorProxy() {} 34 SensorProxy::~SensorProxy() {}
33 35
34 void SensorProxy::dispose() { 36 void SensorProxy::dispose() {
35 m_clientBinding.Close(); 37 m_clientBinding.Close();
36 } 38 }
37 39
38 DEFINE_TRACE(SensorProxy) { 40 DEFINE_TRACE(SensorProxy) {
41 visitor->trace(m_document);
42 visitor->trace(m_readingUpdater);
39 visitor->trace(m_reading); 43 visitor->trace(m_reading);
40 visitor->trace(m_observers); 44 visitor->trace(m_observers);
41 visitor->trace(m_provider); 45 visitor->trace(m_provider);
42 PageVisibilityObserver::trace(visitor); 46 PageVisibilityObserver::trace(visitor);
43 } 47 }
44 48
45 void SensorProxy::addObserver(Observer* observer) { 49 void SensorProxy::addObserver(Observer* observer) {
46 if (!m_observers.contains(observer)) 50 if (!m_observers.contains(observer))
47 m_observers.add(observer); 51 m_observers.add(observer);
48 } 52 }
(...skipping 11 matching lines...) Expand all
60 return; 64 return;
61 } 65 }
62 66
63 m_state = Initializing; 67 m_state = Initializing;
64 auto callback = convertToBaseCallback( 68 auto callback = convertToBaseCallback(
65 WTF::bind(&SensorProxy::onSensorCreated, wrapWeakPersistent(this))); 69 WTF::bind(&SensorProxy::onSensorCreated, wrapWeakPersistent(this)));
66 m_provider->getSensorProvider()->GetSensor(m_type, mojo::GetProxy(&m_sensor), 70 m_provider->getSensorProvider()->GetSensor(m_type, mojo::GetProxy(&m_sensor),
67 callback); 71 callback);
68 } 72 }
69 73
74 bool SensorProxy::isActive() const {
75 return isInitialized() && !m_suspended && !m_frequenciesUsed.isEmpty();
76 }
77
70 void SensorProxy::addConfiguration( 78 void SensorProxy::addConfiguration(
71 SensorConfigurationPtr configuration, 79 SensorConfigurationPtr configuration,
72 std::unique_ptr<Function<void(bool)>> callback) { 80 std::unique_ptr<Function<void(bool)>> callback) {
73 DCHECK(isInitialized()); 81 DCHECK(isInitialized());
74 auto wrapper = WTF::bind(&SensorProxy::onAddConfigurationCompleted, 82 auto wrapper = WTF::bind(&SensorProxy::onAddConfigurationCompleted,
75 wrapWeakPersistent(this), configuration->frequency, 83 wrapWeakPersistent(this), configuration->frequency,
76 passed(std::move(callback))); 84 passed(std::move(callback)));
77 m_sensor->AddConfiguration(std::move(configuration), 85 m_sensor->AddConfiguration(std::move(configuration),
78 convertToBaseCallback(std::move(wrapper))); 86 convertToBaseCallback(std::move(wrapper)));
79 } 87 }
80 88
81 void SensorProxy::removeConfiguration(SensorConfigurationPtr configuration) { 89 void SensorProxy::removeConfiguration(SensorConfigurationPtr configuration) {
82 DCHECK(isInitialized()); 90 DCHECK(isInitialized());
83 auto callback = WTF::bind(&SensorProxy::onRemoveConfigurationCompleted, 91 auto callback = WTF::bind(&SensorProxy::onRemoveConfigurationCompleted,
84 wrapWeakPersistent(this), configuration->frequency); 92 wrapWeakPersistent(this), configuration->frequency);
85 m_sensor->RemoveConfiguration(std::move(configuration), 93 m_sensor->RemoveConfiguration(std::move(configuration),
86 convertToBaseCallback(std::move(callback))); 94 convertToBaseCallback(std::move(callback)));
87 } 95 }
88 96
89 void SensorProxy::suspend() { 97 void SensorProxy::suspend() {
90 DCHECK(isInitialized()); 98 DCHECK(isInitialized());
91 if (m_suspended) 99 if (m_suspended)
92 return; 100 return;
93 101
94 m_sensor->Suspend(); 102 m_sensor->Suspend();
95 m_suspended = true; 103 m_suspended = true;
96 104
97 if (usesPollingTimer()) 105 m_readingUpdater->stop();
98 updatePollingStatus();
99
100 for (Observer* observer : m_observers)
101 observer->onSuspended();
102 } 106 }
103 107
104 void SensorProxy::resume() { 108 void SensorProxy::resume() {
105 DCHECK(isInitialized()); 109 DCHECK(isInitialized());
106 if (!m_suspended) 110 if (!m_suspended)
107 return; 111 return;
108 112
109 m_sensor->Resume(); 113 m_sensor->Resume();
110 m_suspended = false; 114 m_suspended = false;
111 115
112 if (usesPollingTimer()) 116 if (isActive())
113 updatePollingStatus(); 117 m_readingUpdater->start();
114 } 118 }
115 119
116 const SensorConfiguration* SensorProxy::defaultConfig() const { 120 const SensorConfiguration* SensorProxy::defaultConfig() const {
117 DCHECK(isInitialized()); 121 DCHECK(isInitialized());
118 return m_defaultConfig.get(); 122 return m_defaultConfig.get();
119 } 123 }
120 124
121 bool SensorProxy::usesPollingTimer() const {
122 return isInitialized() && (m_mode == ReportingMode::CONTINUOUS);
123 }
124
125 void SensorProxy::updateSensorReading() { 125 void SensorProxy::updateSensorReading() {
126 DCHECK(isInitialized()); 126 DCHECK(isInitialized());
127 DCHECK(m_readingFactory); 127 DCHECK(m_readingFactory);
128 int readAttempts = 0; 128 int readAttempts = 0;
129 const int kMaxReadAttemptsCount = 10; 129 const int kMaxReadAttemptsCount = 10;
130 device::SensorReading readingData; 130 device::SensorReading readingData;
131 while (!tryReadFromBuffer(readingData)) { 131 while (!tryReadFromBuffer(readingData)) {
132 if (++readAttempts == kMaxReadAttemptsCount) { 132 if (++readAttempts == kMaxReadAttemptsCount) {
133 handleSensorError(); 133 handleSensorError();
134 return; 134 return;
135 } 135 }
136 } 136 }
137 137
138 m_reading = m_readingFactory->createSensorReading(readingData); 138 m_reading = m_readingFactory->createSensorReading(readingData);
139 }
139 140
140 for (Observer* observer : m_observers) 141 void SensorProxy::notifySensorChanged(double timestamp) {
141 observer->onSensorReadingChanged(); 142 // This notification leads to sync 'onchange' event sending, so
143 // we must cache m_observers as it can be modified within event handlers.
144 auto copy = m_observers;
145 for (Observer* observer : copy)
146 observer->onSensorReadingChanged(timestamp);
142 } 147 }
143 148
144 void SensorProxy::RaiseError() { 149 void SensorProxy::RaiseError() {
145 handleSensorError(); 150 handleSensorError();
146 } 151 }
147 152
148 void SensorProxy::SensorReadingChanged() { 153 void SensorProxy::SensorReadingChanged() {
149 DCHECK_EQ(ReportingMode::ON_CHANGE, m_mode); 154 DCHECK_EQ(ReportingMode::ON_CHANGE, m_mode);
150 updateSensorReading(); 155 if (isActive())
156 m_readingUpdater->start();
151 } 157 }
152 158
153 void SensorProxy::pageVisibilityChanged() { 159 void SensorProxy::pageVisibilityChanged() {
154 if (!isInitialized()) 160 if (!isInitialized())
155 return; 161 return;
156 162
157 if (page()->visibilityState() != PageVisibilityStateVisible) { 163 if (page()->visibilityState() != PageVisibilityStateVisible) {
158 suspend(); 164 suspend();
159 } else { 165 } else {
160 resume(); 166 resume();
161 } 167 }
162 } 168 }
163 169
164 void SensorProxy::handleSensorError(ExceptionCode code, 170 void SensorProxy::handleSensorError(ExceptionCode code,
165 String sanitizedMessage, 171 String sanitizedMessage,
166 String unsanitizedMessage) { 172 String unsanitizedMessage) {
167 if (!Platform::current()) { 173 if (!Platform::current()) {
168 // TODO(rockot): Remove this hack once renderer shutdown sequence is fixed. 174 // TODO(rockot): Remove this hack once renderer shutdown sequence is fixed.
169 return; 175 return;
170 } 176 }
171 177
172 if (usesPollingTimer()) { // Stop polling. 178 m_state = Uninitialized;
173 m_frequenciesUsed.clear(); 179 m_frequenciesUsed.clear();
174 updatePollingStatus(); 180 if (m_readingUpdater)
175 } 181 m_readingUpdater->stop();
176 182
177 m_state = Uninitialized;
178 // The m_sensor.reset() will release all callbacks and its bound parameters, 183 // The m_sensor.reset() will release all callbacks and its bound parameters,
179 // therefore, handleSensorError accepts messages by value. 184 // therefore, handleSensorError accepts messages by value.
180 m_sensor.reset(); 185 m_sensor.reset();
181 m_sharedBuffer.reset(); 186 m_sharedBuffer.reset();
182 m_sharedBufferHandle.reset(); 187 m_sharedBufferHandle.reset();
183 m_defaultConfig.reset(); 188 m_defaultConfig.reset();
184 m_clientBinding.Close(); 189 m_clientBinding.Close();
185 m_reading = nullptr; 190 m_reading = nullptr;
186 191
187 for (Observer* observer : m_observers) 192 for (Observer* observer : m_observers)
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 226
222 m_maximumFrequency = params->maximum_frequency; 227 m_maximumFrequency = params->maximum_frequency;
223 DCHECK(m_maximumFrequency <= SensorConfiguration::kMaxAllowedFrequency); 228 DCHECK(m_maximumFrequency <= SensorConfiguration::kMaxAllowedFrequency);
224 229
225 auto errorCallback = 230 auto errorCallback =
226 WTF::bind(&SensorProxy::handleSensorError, wrapWeakPersistent(this), 231 WTF::bind(&SensorProxy::handleSensorError, wrapWeakPersistent(this),
227 UnknownError, String("Internal error"), String()); 232 UnknownError, String("Internal error"), String());
228 m_sensor.set_connection_error_handler( 233 m_sensor.set_connection_error_handler(
229 convertToBaseCallback(std::move(errorCallback))); 234 convertToBaseCallback(std::move(errorCallback)));
230 235
236 m_readingUpdater = SensorReadingUpdater::create(this, m_mode);
237
231 m_state = Initialized; 238 m_state = Initialized;
239
232 for (Observer* observer : m_observers) 240 for (Observer* observer : m_observers)
233 observer->onSensorInitialized(); 241 observer->onSensorInitialized();
234 } 242 }
235 243
236 void SensorProxy::onAddConfigurationCompleted( 244 void SensorProxy::onAddConfigurationCompleted(
237 double frequency, 245 double frequency,
238 std::unique_ptr<Function<void(bool)>> callback, 246 std::unique_ptr<Function<void(bool)>> callback,
239 bool result) { 247 bool result) {
240 if (usesPollingTimer() && result) { 248 if (result) {
241 m_frequenciesUsed.append(frequency); 249 m_frequenciesUsed.append(frequency);
242 updatePollingStatus(); 250 std::sort(m_frequenciesUsed.begin(), m_frequenciesUsed.end());
251 if (isActive())
252 m_readingUpdater->start();
243 } 253 }
244 254
245 (*callback)(result); 255 (*callback)(result);
246 } 256 }
247 257
248 void SensorProxy::onRemoveConfigurationCompleted(double frequency, 258 void SensorProxy::onRemoveConfigurationCompleted(double frequency,
249 bool result) { 259 bool result) {
250 if (!result) 260 if (!result)
251 DVLOG(1) << "Failure at sensor configuration removal"; 261 DVLOG(1) << "Failure at sensor configuration removal";
252 262
253 if (!usesPollingTimer())
254 return;
255
256 size_t index = m_frequenciesUsed.find(frequency); 263 size_t index = m_frequenciesUsed.find(frequency);
257 if (index == kNotFound) { 264 if (index == kNotFound) {
258 // Could happen e.g. if 'handleSensorError' was called before. 265 // Could happen e.g. if 'handleSensorError' was called before.
259 return; 266 return;
260 } 267 }
261 268
262 m_frequenciesUsed.remove(index); 269 m_frequenciesUsed.remove(index);
263 updatePollingStatus(); 270
271 if (m_frequenciesUsed.isEmpty())
272 m_readingUpdater->stop();
264 } 273 }
265 274
266 bool SensorProxy::tryReadFromBuffer(device::SensorReading& result) { 275 bool SensorProxy::tryReadFromBuffer(device::SensorReading& result) {
267 DCHECK(isInitialized()); 276 DCHECK(isInitialized());
268 const ReadingBuffer* buffer = 277 const ReadingBuffer* buffer =
269 static_cast<const ReadingBuffer*>(m_sharedBuffer.get()); 278 static_cast<const ReadingBuffer*>(m_sharedBuffer.get());
270 const device::OneWriterSeqLock& seqlock = buffer->seqlock.value(); 279 const device::OneWriterSeqLock& seqlock = buffer->seqlock.value();
271 auto version = seqlock.ReadBegin(); 280 auto version = seqlock.ReadBegin();
272 auto readingData = buffer->reading; 281 auto readingData = buffer->reading;
273 if (seqlock.ReadRetry(version)) 282 if (seqlock.ReadRetry(version))
274 return false; 283 return false;
275 result = readingData; 284 result = readingData;
276 return true; 285 return true;
277 } 286 }
278 287
279 void SensorProxy::updatePollingStatus() {
280 DCHECK(usesPollingTimer());
281
282 if (m_suspended || m_frequenciesUsed.isEmpty()) {
283 m_timer.stop();
284 return;
285 }
286 // TODO(Mikhail): Consider using sorted queue instead of searching
287 // max element each time.
288 auto it =
289 std::max_element(m_frequenciesUsed.begin(), m_frequenciesUsed.end());
290 DCHECK_GT(*it, 0.0);
291
292 double repeatInterval = 1 / *it;
293 if (!m_timer.isActive() || m_timer.repeatInterval() != repeatInterval) {
294 updateSensorReading();
295 m_timer.startRepeating(repeatInterval, BLINK_FROM_HERE);
296 }
297 }
298
299 void SensorProxy::onTimerFired(TimerBase*) {
300 updateSensorReading();
301 }
302
303 } // namespace blink 288 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698