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

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

Powered by Google App Engine
This is Rietveld 408576698