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

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 Reilly 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 WTF::passed(std::move(callback))); 84 WTF::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
97 if (usesPollingTimer())
98 updatePollingStatus();
99
100 for (Observer* observer : m_observers)
101 observer->onSuspended();
102 } 104 }
103 105
104 void SensorProxy::resume() { 106 void SensorProxy::resume() {
105 DCHECK(isInitialized()); 107 DCHECK(isInitialized());
106 if (!m_suspended) 108 if (!m_suspended)
107 return; 109 return;
108 110
109 m_sensor->Resume(); 111 m_sensor->Resume();
110 m_suspended = false; 112 m_suspended = false;
111 113
112 if (usesPollingTimer()) 114 if (isActive())
113 updatePollingStatus(); 115 m_readingUpdater->start();
114 } 116 }
115 117
116 const SensorConfiguration* SensorProxy::defaultConfig() const { 118 const SensorConfiguration* SensorProxy::defaultConfig() const {
117 DCHECK(isInitialized()); 119 DCHECK(isInitialized());
118 return m_defaultConfig.get(); 120 return m_defaultConfig.get();
119 } 121 }
120 122
121 bool SensorProxy::usesPollingTimer() const {
122 return isInitialized() && (m_mode == ReportingMode::CONTINUOUS);
123 }
124
125 void SensorProxy::updateSensorReading() { 123 void SensorProxy::updateSensorReading() {
126 DCHECK(isInitialized()); 124 DCHECK(isInitialized());
127 DCHECK(m_readingFactory); 125 DCHECK(m_readingFactory);
128 int readAttempts = 0; 126 int readAttempts = 0;
129 const int kMaxReadAttemptsCount = 10; 127 const int kMaxReadAttemptsCount = 10;
130 device::SensorReading readingData; 128 device::SensorReading readingData;
131 while (!tryReadFromBuffer(readingData)) { 129 while (!tryReadFromBuffer(readingData)) {
132 if (++readAttempts == kMaxReadAttemptsCount) { 130 if (++readAttempts == kMaxReadAttemptsCount) {
133 handleSensorError(); 131 handleSensorError();
134 return; 132 return;
135 } 133 }
136 } 134 }
137 135
138 m_reading = m_readingFactory->createSensorReading(readingData); 136 m_reading = m_readingFactory->createSensorReading(readingData);
137 }
139 138
140 for (Observer* observer : m_observers) 139 void SensorProxy::notifySensorChanged(double timestamp) {
141 observer->onSensorReadingChanged(); 140 // This notification leads to sync 'onchange' event sending, so
141 // we must cache m_observers as it can be modified within event handlers.
142 auto copy = m_observers;
143 for (Observer* observer : copy)
144 observer->onSensorReadingChanged(timestamp);
142 } 145 }
143 146
144 void SensorProxy::RaiseError() { 147 void SensorProxy::RaiseError() {
145 handleSensorError(); 148 handleSensorError();
146 } 149 }
147 150
148 void SensorProxy::SensorReadingChanged() { 151 void SensorProxy::SensorReadingChanged() {
149 DCHECK_EQ(ReportingMode::ON_CHANGE, m_mode); 152 DCHECK_EQ(ReportingMode::ON_CHANGE, m_mode);
150 updateSensorReading(); 153 if (isActive())
154 m_readingUpdater->start();
151 } 155 }
152 156
153 void SensorProxy::pageVisibilityChanged() { 157 void SensorProxy::pageVisibilityChanged() {
154 if (!isInitialized()) 158 if (!isInitialized())
155 return; 159 return;
156 160
157 if (page()->visibilityState() != PageVisibilityStateVisible) { 161 if (page()->visibilityState() != PageVisibilityStateVisible) {
158 suspend(); 162 suspend();
159 } else { 163 } else {
160 resume(); 164 resume();
161 } 165 }
162 } 166 }
163 167
164 void SensorProxy::handleSensorError(ExceptionCode code, 168 void SensorProxy::handleSensorError(ExceptionCode code,
165 String sanitizedMessage, 169 String sanitizedMessage,
166 String unsanitizedMessage) { 170 String unsanitizedMessage) {
167 if (!Platform::current()) { 171 if (!Platform::current()) {
168 // TODO(rockot): Remove this hack once renderer shutdown sequence is fixed. 172 // TODO(rockot): Remove this hack once renderer shutdown sequence is fixed.
169 return; 173 return;
170 } 174 }
171 175
172 if (usesPollingTimer()) { // Stop polling. 176 m_state = Uninitialized;
173 m_frequenciesUsed.clear(); 177 m_frequenciesUsed.clear();
174 updatePollingStatus();
175 }
176 178
177 m_state = Uninitialized;
178 // The m_sensor.reset() will release all callbacks and its bound parameters, 179 // The m_sensor.reset() will release all callbacks and its bound parameters,
179 // therefore, handleSensorError accepts messages by value. 180 // therefore, handleSensorError accepts messages by value.
180 m_sensor.reset(); 181 m_sensor.reset();
181 m_sharedBuffer.reset(); 182 m_sharedBuffer.reset();
182 m_sharedBufferHandle.reset(); 183 m_sharedBufferHandle.reset();
183 m_defaultConfig.reset(); 184 m_defaultConfig.reset();
184 m_clientBinding.Close(); 185 m_clientBinding.Close();
185 m_reading = nullptr; 186 m_reading = nullptr;
186 187
187 for (Observer* observer : m_observers) 188 for (Observer* observer : m_observers)
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 222
222 m_maximumFrequency = params->maximum_frequency; 223 m_maximumFrequency = params->maximum_frequency;
223 DCHECK(m_maximumFrequency <= SensorConfiguration::kMaxAllowedFrequency); 224 DCHECK(m_maximumFrequency <= SensorConfiguration::kMaxAllowedFrequency);
224 225
225 auto errorCallback = 226 auto errorCallback =
226 WTF::bind(&SensorProxy::handleSensorError, wrapWeakPersistent(this), 227 WTF::bind(&SensorProxy::handleSensorError, wrapWeakPersistent(this),
227 UnknownError, String("Internal error"), String()); 228 UnknownError, String("Internal error"), String());
228 m_sensor.set_connection_error_handler( 229 m_sensor.set_connection_error_handler(
229 convertToBaseCallback(std::move(errorCallback))); 230 convertToBaseCallback(std::move(errorCallback)));
230 231
232 m_readingUpdater = SensorReadingUpdater::create(this, m_mode);
233
231 m_state = Initialized; 234 m_state = Initialized;
235
232 for (Observer* observer : m_observers) 236 for (Observer* observer : m_observers)
233 observer->onSensorInitialized(); 237 observer->onSensorInitialized();
234 } 238 }
235 239
236 void SensorProxy::onAddConfigurationCompleted( 240 void SensorProxy::onAddConfigurationCompleted(
237 double frequency, 241 double frequency,
238 std::unique_ptr<Function<void(bool)>> callback, 242 std::unique_ptr<Function<void(bool)>> callback,
239 bool result) { 243 bool result) {
240 if (usesPollingTimer() && result) { 244 if (result) {
241 m_frequenciesUsed.append(frequency); 245 m_frequenciesUsed.append(frequency);
242 updatePollingStatus(); 246 std::sort(m_frequenciesUsed.begin(), m_frequenciesUsed.end());
247 if (isActive())
248 m_readingUpdater->start();
243 } 249 }
244 250
245 (*callback)(result); 251 (*callback)(result);
246 } 252 }
247 253
248 void SensorProxy::onRemoveConfigurationCompleted(double frequency, 254 void SensorProxy::onRemoveConfigurationCompleted(double frequency,
249 bool result) { 255 bool result) {
250 if (!result) 256 if (!result)
251 DVLOG(1) << "Failure at sensor configuration removal"; 257 DVLOG(1) << "Failure at sensor configuration removal";
252 258
253 if (!usesPollingTimer())
254 return;
255
256 size_t index = m_frequenciesUsed.find(frequency); 259 size_t index = m_frequenciesUsed.find(frequency);
257 if (index == kNotFound) { 260 if (index == kNotFound) {
258 // Could happen e.g. if 'handleSensorError' was called before. 261 // Could happen e.g. if 'handleSensorError' was called before.
259 return; 262 return;
260 } 263 }
261 264
262 m_frequenciesUsed.remove(index); 265 m_frequenciesUsed.remove(index);
263 updatePollingStatus();
264 } 266 }
265 267
266 bool SensorProxy::tryReadFromBuffer(device::SensorReading& result) { 268 bool SensorProxy::tryReadFromBuffer(device::SensorReading& result) {
267 DCHECK(isInitialized()); 269 DCHECK(isInitialized());
268 const ReadingBuffer* buffer = 270 const ReadingBuffer* buffer =
269 static_cast<const ReadingBuffer*>(m_sharedBuffer.get()); 271 static_cast<const ReadingBuffer*>(m_sharedBuffer.get());
270 const device::OneWriterSeqLock& seqlock = buffer->seqlock.value(); 272 const device::OneWriterSeqLock& seqlock = buffer->seqlock.value();
271 auto version = seqlock.ReadBegin(); 273 auto version = seqlock.ReadBegin();
272 auto readingData = buffer->reading; 274 auto readingData = buffer->reading;
273 if (seqlock.ReadRetry(version)) 275 if (seqlock.ReadRetry(version))
274 return false; 276 return false;
275 result = readingData; 277 result = readingData;
276 return true; 278 return true;
277 } 279 }
278 280
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 281 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698