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

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: Comments from haraken@ 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"
8 #include "core/dom/FrameRequestCallback.h"
7 #include "core/frame/LocalFrame.h" 9 #include "core/frame/LocalFrame.h"
8 #include "modules/sensor/SensorProviderProxy.h" 10 #include "modules/sensor/SensorProviderProxy.h"
9 #include "modules/sensor/SensorReading.h" 11 #include "modules/sensor/SensorReading.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"
14 #include "wtf/CurrentTime.h"
12 15
13 using namespace device::mojom::blink; 16 using namespace device::mojom::blink;
14 17
15 namespace blink { 18 namespace blink {
16 19
20 class SensorFrameRequestCallback : public FrameRequestCallback {
21 public:
22 explicit SensorFrameRequestCallback(SensorProxy* sensorProxy)
23 : m_sensorProxy(sensorProxy) {}
24
25 void handleEvent(double highResTimeMs) override {
26 m_sensorProxy->onAnimationFrame(highResTimeMs * 0.001);
27 }
28
29 DEFINE_INLINE_VIRTUAL_TRACE() {
30 visitor->trace(m_sensorProxy);
31 FrameRequestCallback::trace(visitor);
32 }
33
34 private:
35 Member<SensorProxy> m_sensorProxy;
36 };
37
17 SensorProxy::SensorProxy(SensorType sensorType, 38 SensorProxy::SensorProxy(SensorType sensorType,
18 SensorProviderProxy* provider, 39 SensorProviderProxy* provider,
19 Page* page, 40 Document* document,
20 std::unique_ptr<SensorReadingFactory> readingFactory) 41 std::unique_ptr<SensorReadingFactory> readingFactory)
21 : PageVisibilityObserver(page), 42 : PageVisibilityObserver(document->page()),
22 m_type(sensorType), 43 m_type(sensorType),
23 m_mode(ReportingMode::CONTINUOUS), 44 m_mode(ReportingMode::CONTINUOUS),
24 m_provider(provider), 45 m_provider(provider),
25 m_clientBinding(this), 46 m_clientBinding(this),
26 m_state(SensorProxy::Uninitialized), 47 m_state(SensorProxy::Uninitialized),
27 m_suspended(false), 48 m_suspended(false),
49 m_document(document),
28 m_readingFactory(std::move(readingFactory)), 50 m_readingFactory(std::move(readingFactory)),
29 m_maximumFrequency(0.0), 51 m_maximumFrequency(0.0),
30 m_timer(this, &SensorProxy::onTimerFired) {} 52 m_rafCallbackId(0),
53 m_lastRafTimestamp(0.0) {}
31 54
32 SensorProxy::~SensorProxy() {} 55 SensorProxy::~SensorProxy() {}
33 56
34 void SensorProxy::dispose() { 57 void SensorProxy::dispose() {
35 m_clientBinding.Close(); 58 m_clientBinding.Close();
36 } 59 }
37 60
38 DEFINE_TRACE(SensorProxy) { 61 DEFINE_TRACE(SensorProxy) {
62 visitor->trace(m_document);
63 visitor->trace(m_rafCallback);
39 visitor->trace(m_reading); 64 visitor->trace(m_reading);
40 visitor->trace(m_observers); 65 visitor->trace(m_observers);
41 visitor->trace(m_provider); 66 visitor->trace(m_provider);
42 PageVisibilityObserver::trace(visitor); 67 PageVisibilityObserver::trace(visitor);
43 } 68 }
44 69
45 void SensorProxy::addObserver(Observer* observer) { 70 void SensorProxy::addObserver(Observer* observer) {
46 if (!m_observers.contains(observer)) 71 if (!m_observers.contains(observer))
47 m_observers.add(observer); 72 m_observers.add(observer);
48 } 73 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 } 112 }
88 113
89 void SensorProxy::suspend() { 114 void SensorProxy::suspend() {
90 DCHECK(isInitialized()); 115 DCHECK(isInitialized());
91 if (m_suspended) 116 if (m_suspended)
92 return; 117 return;
93 118
94 m_sensor->Suspend(); 119 m_sensor->Suspend();
95 m_suspended = true; 120 m_suspended = true;
96 121
97 if (usesPollingTimer()) 122 if (isPollingBuffer())
98 updatePollingStatus(); 123 processRAFQueue();
99 124
100 for (Observer* observer : m_observers) 125 for (Observer* observer : m_observers)
101 observer->onSuspended(); 126 observer->onSuspended();
102 } 127 }
103 128
104 void SensorProxy::resume() { 129 void SensorProxy::resume() {
105 DCHECK(isInitialized()); 130 DCHECK(isInitialized());
106 if (!m_suspended) 131 if (!m_suspended)
107 return; 132 return;
108 133
109 m_sensor->Resume(); 134 m_sensor->Resume();
110 m_suspended = false; 135 m_suspended = false;
111 136
112 if (usesPollingTimer()) 137 if (isPollingBuffer())
113 updatePollingStatus(); 138 processRAFQueue();
114 } 139 }
115 140
116 const SensorConfiguration* SensorProxy::defaultConfig() const { 141 const SensorConfiguration* SensorProxy::defaultConfig() const {
117 DCHECK(isInitialized()); 142 DCHECK(isInitialized());
118 return m_defaultConfig.get(); 143 return m_defaultConfig.get();
119 } 144 }
120 145
121 bool SensorProxy::usesPollingTimer() const { 146 bool SensorProxy::isPollingBuffer() const {
122 return isInitialized() && (m_mode == ReportingMode::CONTINUOUS); 147 return isInitialized() && (m_mode == ReportingMode::CONTINUOUS);
123 } 148 }
124 149
125 void SensorProxy::updateSensorReading() { 150 void SensorProxy::updateSensorReading(double timestamp) {
126 DCHECK(isInitialized()); 151 DCHECK(isInitialized());
127 DCHECK(m_readingFactory); 152 DCHECK(m_readingFactory);
128 int readAttempts = 0; 153 int readAttempts = 0;
129 const int kMaxReadAttemptsCount = 10; 154 const int kMaxReadAttemptsCount = 10;
130 device::SensorReading readingData; 155 device::SensorReading readingData;
131 while (!tryReadFromBuffer(readingData)) { 156 while (!tryReadFromBuffer(readingData)) {
132 if (++readAttempts == kMaxReadAttemptsCount) { 157 if (++readAttempts == kMaxReadAttemptsCount) {
133 handleSensorError(); 158 handleSensorError();
134 return; 159 return;
135 } 160 }
136 } 161 }
137 162
138 m_reading = m_readingFactory->createSensorReading(readingData); 163 m_reading = m_readingFactory->createSensorReading(readingData);
139 164
140 for (Observer* observer : m_observers) 165 for (Observer* observer : m_observers)
141 observer->onSensorReadingChanged(); 166 observer->onSensorReadingChanged(timestamp);
142 } 167 }
143 168
144 void SensorProxy::RaiseError() { 169 void SensorProxy::RaiseError() {
145 handleSensorError(); 170 handleSensorError();
146 } 171 }
147 172
148 void SensorProxy::SensorReadingChanged() { 173 void SensorProxy::SensorReadingChanged() {
149 DCHECK_EQ(ReportingMode::ON_CHANGE, m_mode); 174 DCHECK_EQ(ReportingMode::ON_CHANGE, m_mode);
150 updateSensorReading(); 175 updateSensorReading(WTF::monotonicallyIncreasingTime());
151 } 176 }
152 177
153 void SensorProxy::pageVisibilityChanged() { 178 void SensorProxy::pageVisibilityChanged() {
154 if (!isInitialized()) 179 if (!isInitialized())
155 return; 180 return;
156 181
157 if (page()->visibilityState() != PageVisibilityStateVisible) { 182 if (page()->visibilityState() != PageVisibilityStateVisible) {
158 suspend(); 183 suspend();
159 } else { 184 } else {
160 resume(); 185 resume();
161 } 186 }
162 } 187 }
163 188
164 void SensorProxy::handleSensorError(ExceptionCode code, 189 void SensorProxy::handleSensorError(ExceptionCode code,
165 String sanitizedMessage, 190 String sanitizedMessage,
166 String unsanitizedMessage) { 191 String unsanitizedMessage) {
167 if (!Platform::current()) { 192 if (!Platform::current()) {
168 // TODO(rockot): Remove this hack once renderer shutdown sequence is fixed. 193 // TODO(rockot): Remove this hack once renderer shutdown sequence is fixed.
169 return; 194 return;
170 } 195 }
171 196
172 if (usesPollingTimer()) { // Stop polling. 197 if (isPollingBuffer()) { // Stop polling.
173 m_frequenciesUsed.clear(); 198 m_frequenciesUsed.clear();
174 updatePollingStatus(); 199 processRAFQueue();
175 } 200 }
176 201
177 m_state = Uninitialized; 202 m_state = Uninitialized;
178 // The m_sensor.reset() will release all callbacks and its bound parameters, 203 // The m_sensor.reset() will release all callbacks and its bound parameters,
179 // therefore, handleSensorError accepts messages by value. 204 // therefore, handleSensorError accepts messages by value.
180 m_sensor.reset(); 205 m_sensor.reset();
181 m_sharedBuffer.reset(); 206 m_sharedBuffer.reset();
182 m_sharedBufferHandle.reset(); 207 m_sharedBufferHandle.reset();
183 m_defaultConfig.reset(); 208 m_defaultConfig.reset();
184 m_clientBinding.Close(); 209 m_clientBinding.Close();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 m_maximumFrequency = params->maximum_frequency; 247 m_maximumFrequency = params->maximum_frequency;
223 DCHECK(m_maximumFrequency <= SensorConfiguration::kMaxAllowedFrequency); 248 DCHECK(m_maximumFrequency <= SensorConfiguration::kMaxAllowedFrequency);
224 249
225 auto errorCallback = 250 auto errorCallback =
226 WTF::bind(&SensorProxy::handleSensorError, wrapWeakPersistent(this), 251 WTF::bind(&SensorProxy::handleSensorError, wrapWeakPersistent(this),
227 UnknownError, String("Internal error"), String()); 252 UnknownError, String("Internal error"), String());
228 m_sensor.set_connection_error_handler( 253 m_sensor.set_connection_error_handler(
229 convertToBaseCallback(std::move(errorCallback))); 254 convertToBaseCallback(std::move(errorCallback)));
230 255
231 m_state = Initialized; 256 m_state = Initialized;
257
258 if (isPollingBuffer())
259 m_rafCallback = new SensorFrameRequestCallback(this);
260
232 for (Observer* observer : m_observers) 261 for (Observer* observer : m_observers)
233 observer->onSensorInitialized(); 262 observer->onSensorInitialized();
234 } 263 }
235 264
236 void SensorProxy::onAddConfigurationCompleted( 265 void SensorProxy::onAddConfigurationCompleted(
237 double frequency, 266 double frequency,
238 std::unique_ptr<Function<void(bool)>> callback, 267 std::unique_ptr<Function<void(bool)>> callback,
239 bool result) { 268 bool result) {
240 if (usesPollingTimer() && result) { 269 if (isPollingBuffer() && result) {
241 m_frequenciesUsed.append(frequency); 270 m_frequenciesUsed.append(frequency);
242 updatePollingStatus(); 271 std::sort(m_frequenciesUsed.begin(), m_frequenciesUsed.end());
272 processRAFQueue();
243 } 273 }
244 274
245 (*callback)(result); 275 (*callback)(result);
246 } 276 }
247 277
248 void SensorProxy::onRemoveConfigurationCompleted(double frequency, 278 void SensorProxy::onRemoveConfigurationCompleted(double frequency,
249 bool result) { 279 bool result) {
250 if (!result) 280 if (!result)
251 DVLOG(1) << "Failure at sensor configuration removal"; 281 DVLOG(1) << "Failure at sensor configuration removal";
252 282
253 if (!usesPollingTimer()) 283 if (!isPollingBuffer())
254 return; 284 return;
255 285
256 size_t index = m_frequenciesUsed.find(frequency); 286 size_t index = m_frequenciesUsed.find(frequency);
257 if (index == kNotFound) { 287 if (index == kNotFound) {
258 // Could happen e.g. if 'handleSensorError' was called before. 288 // Could happen e.g. if 'handleSensorError' was called before.
259 return; 289 return;
260 } 290 }
261 291
262 m_frequenciesUsed.remove(index); 292 m_frequenciesUsed.remove(index);
263 updatePollingStatus(); 293 processRAFQueue();
264 } 294 }
265 295
266 bool SensorProxy::tryReadFromBuffer(device::SensorReading& result) { 296 bool SensorProxy::tryReadFromBuffer(device::SensorReading& result) {
267 DCHECK(isInitialized()); 297 DCHECK(isInitialized());
268 const ReadingBuffer* buffer = 298 const ReadingBuffer* buffer =
269 static_cast<const ReadingBuffer*>(m_sharedBuffer.get()); 299 static_cast<const ReadingBuffer*>(m_sharedBuffer.get());
270 const device::OneWriterSeqLock& seqlock = buffer->seqlock.value(); 300 const device::OneWriterSeqLock& seqlock = buffer->seqlock.value();
271 auto version = seqlock.ReadBegin(); 301 auto version = seqlock.ReadBegin();
272 auto readingData = buffer->reading; 302 auto readingData = buffer->reading;
273 if (seqlock.ReadRetry(version)) 303 if (seqlock.ReadRetry(version))
274 return false; 304 return false;
275 result = readingData; 305 result = readingData;
276 return true; 306 return true;
277 } 307 }
278 308
279 void SensorProxy::updatePollingStatus() { 309 bool SensorProxy::processRAFQueue() {
280 DCHECK(usesPollingTimer()); 310 DCHECK(isPollingBuffer());
311 if (m_rafCallbackId) { // Cancel pending request.
312 m_document->cancelAnimationFrame(m_rafCallbackId);
313 m_rafCallbackId = 0;
314 }
281 315
282 if (m_suspended || m_frequenciesUsed.isEmpty()) { 316 if (!m_suspended && !m_frequenciesUsed.isEmpty()) {
283 m_timer.stop(); 317 DCHECK(m_rafCallback);
318 m_rafCallbackId = m_document->requestAnimationFrame(m_rafCallback);
319 return true;
320 }
321
322 return false;
323 }
324
325 void SensorProxy::onAnimationFrame(double timestamp) {
326 DCHECK(isPollingBuffer());
327 m_rafCallbackId = 0;
328 if (!processRAFQueue())
284 return; 329 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 330
292 double repeatInterval = 1 / *it; 331 double minBufferPollingPeriod = 1 / m_frequenciesUsed.back();
293 if (!m_timer.isActive() || m_timer.repeatInterval() != repeatInterval) { 332 if (timestamp - m_lastRafTimestamp >= minBufferPollingPeriod) {
294 updateSensorReading(); 333 m_lastRafTimestamp = timestamp;
295 m_timer.startRepeating(repeatInterval, BLINK_FROM_HERE); 334 updateSensorReading(timestamp);
296 } 335 }
297 } 336 }
298 337
299 void SensorProxy::onTimerFired(TimerBase*) {
300 updateSensorReading();
301 }
302
303 } // namespace blink 338 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698