Commit fbf954d4 authored by wjmaclean's avatar wjmaclean Committed by Commit bot

Revert of [Sensors] Align sensor reading updates and 'onchange' notification...

Revert of [Sensors] Align sensor reading updates and 'onchange' notification with rAF. (patchset #6 id:140001 of https://codereview.chromium.org/2551223003/ )

Reason for revert:
Seems like a likely cause for failures on:

https://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=sensor%2Faccelerometer.html&testType=webkit_tests

Original issue's description:
> [Sensors] Align sensor reading updates and 'onchange' notification with rAF.
>
> For all sensors new reading values are read and 'onchange' notfication is send from rAF callbacks, thus avoiding possible Critical Rendering Path interruption.
>
> Before this change a timers were used and this could unnecessarily drain CPU and battery.
>
> BUG=668052
> BUG=606766
>
> Committed: https://crrev.com/6b071fe7dc3bd64a2914eadd5c67b483d064a6cb
> Cr-Commit-Position: refs/heads/master@{#439467}

TBR=reillyg@chromium.org,alexander.shalamov@intel.com,haraken@chromium.org,foolip@chromium.org,mikhail.pozdnyakov@intel.com
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=668052

Review-Url: https://codereview.chromium.org/2590513002
Cr-Commit-Position: refs/heads/master@{#439487}
parent dc9f8282
...@@ -304,10 +304,7 @@ function runGenericSensorTests(sensorType, updateReading, verifyReading) { ...@@ -304,10 +304,7 @@ function runGenericSensorTests(sensorType, updateReading, verifyReading) {
// By the moment slow sensor (9 Hz) is notified for the // By the moment slow sensor (9 Hz) is notified for the
// next time, the fast sensor (30 Hz) has been notified // next time, the fast sensor (30 Hz) has been notified
// for int(30/9) = 3 times. // for int(30/9) = 3 times.
// In actual implementation updates are bound to rAF, assert_equals(fastSensorNotifiedCounter, 3);
// (not to a timer) sometimes fast sensor gets invoked 4 times.
assert_true(fastSensorNotifiedCounter == 3 ||
fastSensorNotifiedCounter == 4);
fastSensor.stop(); fastSensor.stop();
slowSensor.stop(); slowSensor.stop();
resolve(mockSensor); resolve(mockSensor);
......
...@@ -32,8 +32,8 @@ blink_modules_sources("sensor") { ...@@ -32,8 +32,8 @@ blink_modules_sources("sensor") {
"SensorProxy.h", "SensorProxy.h",
"SensorReading.cpp", "SensorReading.cpp",
"SensorReading.h", "SensorReading.h",
"SensorReadingUpdater.cpp", "SensorUpdateNotificationStrategy.cpp",
"SensorReadingUpdater.h", "SensorUpdateNotificationStrategy.h",
] ]
deps = [ deps = [
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "modules/sensor/SensorErrorEvent.h" #include "modules/sensor/SensorErrorEvent.h"
#include "modules/sensor/SensorProviderProxy.h" #include "modules/sensor/SensorProviderProxy.h"
#include "modules/sensor/SensorReading.h" #include "modules/sensor/SensorReading.h"
#include "modules/sensor/SensorUpdateNotificationStrategy.h"
using namespace device::mojom::blink; using namespace device::mojom::blink;
...@@ -25,8 +26,7 @@ Sensor::Sensor(ExecutionContext* executionContext, ...@@ -25,8 +26,7 @@ Sensor::Sensor(ExecutionContext* executionContext,
: ContextLifecycleObserver(executionContext), : ContextLifecycleObserver(executionContext),
m_sensorOptions(sensorOptions), m_sensorOptions(sensorOptions),
m_type(type), m_type(type),
m_state(Sensor::SensorState::Idle), m_state(Sensor::SensorState::Idle) {
m_lastUpdateTimestamp(0.0) {
// Check secure context. // Check secure context.
String errorMessage; String errorMessage;
if (!executionContext->isSecureContext(errorMessage)) { if (!executionContext->isSecureContext(errorMessage)) {
...@@ -164,7 +164,7 @@ void Sensor::initSensorProxyIfNeeded() { ...@@ -164,7 +164,7 @@ void Sensor::initSensorProxyIfNeeded() {
m_sensorProxy = provider->getSensorProxy(m_type); m_sensorProxy = provider->getSensorProxy(m_type);
if (!m_sensorProxy) { if (!m_sensorProxy) {
m_sensorProxy = provider->createSensorProxy(m_type, document, m_sensorProxy = provider->createSensorProxy(m_type, document->page(),
createSensorReadingFactory()); createSensorReadingFactory());
} }
} }
...@@ -182,15 +182,10 @@ void Sensor::onSensorInitialized() { ...@@ -182,15 +182,10 @@ void Sensor::onSensorInitialized() {
startListening(); startListening();
} }
void Sensor::onSensorReadingChanged(double timestamp) { void Sensor::onSensorReadingChanged() {
if (m_state != Sensor::SensorState::Activated) if (m_state == Sensor::SensorState::Activated) {
return; DCHECK(m_sensorUpdateNotifier);
m_sensorUpdateNotifier->onSensorReadingChanged();
DCHECK_GT(m_configuration->frequency, 0.0);
double period = 1 / m_configuration->frequency;
if (timestamp - m_lastUpdateTimestamp >= period) {
m_lastUpdateTimestamp = timestamp;
notifySensorReadingChanged();
} }
} }
...@@ -198,6 +193,8 @@ void Sensor::onSensorError(ExceptionCode code, ...@@ -198,6 +193,8 @@ void Sensor::onSensorError(ExceptionCode code,
const String& sanitizedMessage, const String& sanitizedMessage,
const String& unsanitizedMessage) { const String& unsanitizedMessage) {
reportError(code, sanitizedMessage, unsanitizedMessage); reportError(code, sanitizedMessage, unsanitizedMessage);
if (m_sensorUpdateNotifier)
m_sensorUpdateNotifier->cancelPendingNotifications();
} }
void Sensor::onStartRequestCompleted(bool result) { void Sensor::onStartRequestCompleted(bool result) {
...@@ -211,6 +208,13 @@ void Sensor::onStartRequestCompleted(bool result) { ...@@ -211,6 +208,13 @@ void Sensor::onStartRequestCompleted(bool result) {
return; return;
} }
DCHECK(m_configuration);
DCHECK(m_sensorProxy);
auto updateCallback =
WTF::bind(&Sensor::onSensorUpdateNotification, wrapWeakPersistent(this));
DCHECK_GT(m_configuration->frequency, 0);
m_sensorUpdateNotifier = SensorUpdateNotificationStrategy::create(
m_configuration->frequency, std::move(updateCallback));
updateState(Sensor::SensorState::Activated); updateState(Sensor::SensorState::Activated);
} }
...@@ -241,6 +245,9 @@ void Sensor::stopListening() { ...@@ -241,6 +245,9 @@ void Sensor::stopListening() {
DCHECK(m_sensorProxy); DCHECK(m_sensorProxy);
updateState(Sensor::SensorState::Idle); updateState(Sensor::SensorState::Idle);
if (m_sensorUpdateNotifier)
m_sensorUpdateNotifier->cancelPendingNotifications();
if (m_sensorProxy->isInitialized()) { if (m_sensorProxy->isInitialized()) {
DCHECK(m_configuration); DCHECK(m_configuration);
m_sensorProxy->removeConfiguration(m_configuration->Clone()); m_sensorProxy->removeConfiguration(m_configuration->Clone());
...@@ -248,6 +255,25 @@ void Sensor::stopListening() { ...@@ -248,6 +255,25 @@ void Sensor::stopListening() {
m_sensorProxy->removeObserver(this); m_sensorProxy->removeObserver(this);
} }
void Sensor::onSensorUpdateNotification() {
if (m_state != Sensor::SensorState::Activated)
return;
DCHECK(m_sensorProxy);
DCHECK(m_sensorProxy->isInitialized());
DCHECK(m_sensorProxy->sensorReading());
if (getExecutionContext() &&
m_sensorProxy->sensorReading()->isReadingUpdated(m_storedData)) {
getExecutionContext()->postTask(
TaskType::Sensor, BLINK_FROM_HERE,
createSameThreadTask(&Sensor::notifySensorReadingChanged,
wrapWeakPersistent(this)));
}
m_storedData = m_sensorProxy->sensorReading()->data();
}
void Sensor::updateState(Sensor::SensorState newState) { void Sensor::updateState(Sensor::SensorState newState) {
if (newState == m_state) if (newState == m_state)
return; return;
...@@ -277,14 +303,13 @@ void Sensor::reportError(ExceptionCode code, ...@@ -277,14 +303,13 @@ void Sensor::reportError(ExceptionCode code,
} }
} }
void Sensor::notifySensorReadingChanged() { void Sensor::onSuspended() {
DCHECK(m_sensorProxy); if (m_sensorUpdateNotifier)
DCHECK(m_sensorProxy->sensorReading()); m_sensorUpdateNotifier->cancelPendingNotifications();
}
if (m_sensorProxy->sensorReading()->isReadingUpdated(m_storedData)) { void Sensor::notifySensorReadingChanged() {
m_storedData = m_sensorProxy->sensorReading()->data();
dispatchEvent(Event::create(EventTypeNames::change)); dispatchEvent(Event::create(EventTypeNames::change));
}
} }
void Sensor::notifyOnActivate() { void Sensor::notifyOnActivate() {
......
...@@ -20,6 +20,7 @@ namespace blink { ...@@ -20,6 +20,7 @@ namespace blink {
class ExceptionState; class ExceptionState;
class ExecutionContext; class ExecutionContext;
class SensorReading; class SensorReading;
class SensorUpdateNotificationStrategy;
class Sensor : public EventTargetWithInlineData, class Sensor : public EventTargetWithInlineData,
public ActiveScriptWrappable<Sensor>, public ActiveScriptWrappable<Sensor>,
...@@ -82,10 +83,11 @@ class Sensor : public EventTargetWithInlineData, ...@@ -82,10 +83,11 @@ class Sensor : public EventTargetWithInlineData,
// SensorController::Observer overrides. // SensorController::Observer overrides.
void onSensorInitialized() override; void onSensorInitialized() override;
void onSensorReadingChanged(double timestamp) override; void onSensorReadingChanged() override;
void onSensorError(ExceptionCode, void onSensorError(ExceptionCode,
const String& sanitizedMessage, const String& sanitizedMessage,
const String& unsanitizedMessage) override; const String& unsanitizedMessage) override;
void onSuspended() override;
void onStartRequestCompleted(bool); void onStartRequestCompleted(bool);
void onStopRequestCompleted(bool); void onStopRequestCompleted(bool);
...@@ -93,6 +95,8 @@ class Sensor : public EventTargetWithInlineData, ...@@ -93,6 +95,8 @@ class Sensor : public EventTargetWithInlineData,
void startListening(); void startListening();
void stopListening(); void stopListening();
void onSensorUpdateNotification();
void updateState(SensorState newState); void updateState(SensorState newState);
void reportError(ExceptionCode = UnknownError, void reportError(ExceptionCode = UnknownError,
const String& sanitizedMessage = String(), const String& sanitizedMessage = String(),
...@@ -107,9 +111,9 @@ class Sensor : public EventTargetWithInlineData, ...@@ -107,9 +111,9 @@ class Sensor : public EventTargetWithInlineData,
device::mojom::blink::SensorType m_type; device::mojom::blink::SensorType m_type;
SensorState m_state; SensorState m_state;
Member<SensorProxy> m_sensorProxy; Member<SensorProxy> m_sensorProxy;
std::unique_ptr<SensorUpdateNotificationStrategy> m_sensorUpdateNotifier;
device::SensorReading m_storedData; device::SensorReading m_storedData;
SensorConfigurationPtr m_configuration; SensorConfigurationPtr m_configuration;
double m_lastUpdateTimestamp;
}; };
} // namespace blink } // namespace blink
......
...@@ -55,12 +55,12 @@ DEFINE_TRACE(SensorProviderProxy) { ...@@ -55,12 +55,12 @@ DEFINE_TRACE(SensorProviderProxy) {
SensorProxy* SensorProviderProxy::createSensorProxy( SensorProxy* SensorProviderProxy::createSensorProxy(
device::mojom::blink::SensorType type, device::mojom::blink::SensorType type,
Document* document, Page* page,
std::unique_ptr<SensorReadingFactory> readingFactory) { std::unique_ptr<SensorReadingFactory> readingFactory) {
DCHECK(!getSensorProxy(type)); DCHECK(!getSensorProxy(type));
SensorProxy* sensor = SensorProxy* sensor =
new SensorProxy(type, this, document, std::move(readingFactory)); new SensorProxy(type, this, page, std::move(readingFactory));
m_sensorProxies.add(sensor); m_sensorProxies.add(sensor);
return sensor; return sensor;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
namespace blink { namespace blink {
class Document; class Page;
class SensorProxy; class SensorProxy;
class SensorReadingFactory; class SensorReadingFactory;
...@@ -31,7 +31,7 @@ class SensorProviderProxy final ...@@ -31,7 +31,7 @@ class SensorProviderProxy final
~SensorProviderProxy(); ~SensorProviderProxy();
SensorProxy* createSensorProxy(device::mojom::blink::SensorType, SensorProxy* createSensorProxy(device::mojom::blink::SensorType,
Document*, Page*,
std::unique_ptr<SensorReadingFactory>); std::unique_ptr<SensorReadingFactory>);
SensorProxy* getSensorProxy(device::mojom::blink::SensorType); SensorProxy* getSensorProxy(device::mojom::blink::SensorType);
......
...@@ -4,11 +4,9 @@ ...@@ -4,11 +4,9 @@
#include "modules/sensor/SensorProxy.h" #include "modules/sensor/SensorProxy.h"
#include "core/dom/Document.h"
#include "core/frame/LocalFrame.h" #include "core/frame/LocalFrame.h"
#include "modules/sensor/SensorProviderProxy.h" #include "modules/sensor/SensorProviderProxy.h"
#include "modules/sensor/SensorReading.h" #include "modules/sensor/SensorReading.h"
#include "modules/sensor/SensorReadingUpdater.h"
#include "platform/mojo/MojoHelper.h" #include "platform/mojo/MojoHelper.h"
#include "public/platform/Platform.h" #include "public/platform/Platform.h"
...@@ -18,18 +16,18 @@ namespace blink { ...@@ -18,18 +16,18 @@ namespace blink {
SensorProxy::SensorProxy(SensorType sensorType, SensorProxy::SensorProxy(SensorType sensorType,
SensorProviderProxy* provider, SensorProviderProxy* provider,
Document* document, Page* page,
std::unique_ptr<SensorReadingFactory> readingFactory) std::unique_ptr<SensorReadingFactory> readingFactory)
: PageVisibilityObserver(document->page()), : PageVisibilityObserver(page),
m_type(sensorType), m_type(sensorType),
m_mode(ReportingMode::CONTINUOUS), m_mode(ReportingMode::CONTINUOUS),
m_provider(provider), m_provider(provider),
m_clientBinding(this), m_clientBinding(this),
m_state(SensorProxy::Uninitialized), m_state(SensorProxy::Uninitialized),
m_suspended(false), m_suspended(false),
m_document(document),
m_readingFactory(std::move(readingFactory)), m_readingFactory(std::move(readingFactory)),
m_maximumFrequency(0.0) {} m_maximumFrequency(0.0),
m_timer(this, &SensorProxy::onTimerFired) {}
SensorProxy::~SensorProxy() {} SensorProxy::~SensorProxy() {}
...@@ -38,8 +36,6 @@ void SensorProxy::dispose() { ...@@ -38,8 +36,6 @@ void SensorProxy::dispose() {
} }
DEFINE_TRACE(SensorProxy) { DEFINE_TRACE(SensorProxy) {
visitor->trace(m_document);
visitor->trace(m_readingUpdater);
visitor->trace(m_reading); visitor->trace(m_reading);
visitor->trace(m_observers); visitor->trace(m_observers);
visitor->trace(m_provider); visitor->trace(m_provider);
...@@ -71,10 +67,6 @@ void SensorProxy::initialize() { ...@@ -71,10 +67,6 @@ void SensorProxy::initialize() {
callback); callback);
} }
bool SensorProxy::isActive() const {
return isInitialized() && !m_suspended && !m_frequenciesUsed.isEmpty();
}
void SensorProxy::addConfiguration( void SensorProxy::addConfiguration(
SensorConfigurationPtr configuration, SensorConfigurationPtr configuration,
std::unique_ptr<Function<void(bool)>> callback) { std::unique_ptr<Function<void(bool)>> callback) {
...@@ -101,6 +93,12 @@ void SensorProxy::suspend() { ...@@ -101,6 +93,12 @@ void SensorProxy::suspend() {
m_sensor->Suspend(); m_sensor->Suspend();
m_suspended = true; m_suspended = true;
if (usesPollingTimer())
updatePollingStatus();
for (Observer* observer : m_observers)
observer->onSuspended();
} }
void SensorProxy::resume() { void SensorProxy::resume() {
...@@ -111,8 +109,8 @@ void SensorProxy::resume() { ...@@ -111,8 +109,8 @@ void SensorProxy::resume() {
m_sensor->Resume(); m_sensor->Resume();
m_suspended = false; m_suspended = false;
if (isActive()) if (usesPollingTimer())
m_readingUpdater->start(); updatePollingStatus();
} }
const SensorConfiguration* SensorProxy::defaultConfig() const { const SensorConfiguration* SensorProxy::defaultConfig() const {
...@@ -120,6 +118,10 @@ const SensorConfiguration* SensorProxy::defaultConfig() const { ...@@ -120,6 +118,10 @@ const SensorConfiguration* SensorProxy::defaultConfig() const {
return m_defaultConfig.get(); return m_defaultConfig.get();
} }
bool SensorProxy::usesPollingTimer() const {
return isInitialized() && (m_mode == ReportingMode::CONTINUOUS);
}
void SensorProxy::updateSensorReading() { void SensorProxy::updateSensorReading() {
DCHECK(isInitialized()); DCHECK(isInitialized());
DCHECK(m_readingFactory); DCHECK(m_readingFactory);
...@@ -134,14 +136,9 @@ void SensorProxy::updateSensorReading() { ...@@ -134,14 +136,9 @@ void SensorProxy::updateSensorReading() {
} }
m_reading = m_readingFactory->createSensorReading(readingData); m_reading = m_readingFactory->createSensorReading(readingData);
}
void SensorProxy::notifySensorChanged(double timestamp) { for (Observer* observer : m_observers)
// This notification leads to sync 'onchange' event sending, so observer->onSensorReadingChanged();
// we must cache m_observers as it can be modified within event handlers.
auto copy = m_observers;
for (Observer* observer : copy)
observer->onSensorReadingChanged(timestamp);
} }
void SensorProxy::RaiseError() { void SensorProxy::RaiseError() {
...@@ -150,8 +147,7 @@ void SensorProxy::RaiseError() { ...@@ -150,8 +147,7 @@ void SensorProxy::RaiseError() {
void SensorProxy::SensorReadingChanged() { void SensorProxy::SensorReadingChanged() {
DCHECK_EQ(ReportingMode::ON_CHANGE, m_mode); DCHECK_EQ(ReportingMode::ON_CHANGE, m_mode);
if (isActive()) updateSensorReading();
m_readingUpdater->start();
} }
void SensorProxy::pageVisibilityChanged() { void SensorProxy::pageVisibilityChanged() {
...@@ -173,9 +169,12 @@ void SensorProxy::handleSensorError(ExceptionCode code, ...@@ -173,9 +169,12 @@ void SensorProxy::handleSensorError(ExceptionCode code,
return; return;
} }
m_state = Uninitialized; if (usesPollingTimer()) { // Stop polling.
m_frequenciesUsed.clear(); m_frequenciesUsed.clear();
updatePollingStatus();
}
m_state = Uninitialized;
// The m_sensor.reset() will release all callbacks and its bound parameters, // The m_sensor.reset() will release all callbacks and its bound parameters,
// therefore, handleSensorError accepts messages by value. // therefore, handleSensorError accepts messages by value.
m_sensor.reset(); m_sensor.reset();
...@@ -229,10 +228,7 @@ void SensorProxy::onSensorCreated(SensorInitParamsPtr params, ...@@ -229,10 +228,7 @@ void SensorProxy::onSensorCreated(SensorInitParamsPtr params,
m_sensor.set_connection_error_handler( m_sensor.set_connection_error_handler(
convertToBaseCallback(std::move(errorCallback))); convertToBaseCallback(std::move(errorCallback)));
m_readingUpdater = SensorReadingUpdater::create(this, m_mode);
m_state = Initialized; m_state = Initialized;
for (Observer* observer : m_observers) for (Observer* observer : m_observers)
observer->onSensorInitialized(); observer->onSensorInitialized();
} }
...@@ -241,11 +237,9 @@ void SensorProxy::onAddConfigurationCompleted( ...@@ -241,11 +237,9 @@ void SensorProxy::onAddConfigurationCompleted(
double frequency, double frequency,
std::unique_ptr<Function<void(bool)>> callback, std::unique_ptr<Function<void(bool)>> callback,
bool result) { bool result) {
if (result) { if (usesPollingTimer() && result) {
m_frequenciesUsed.append(frequency); m_frequenciesUsed.append(frequency);
std::sort(m_frequenciesUsed.begin(), m_frequenciesUsed.end()); updatePollingStatus();
if (isActive())
m_readingUpdater->start();
} }
(*callback)(result); (*callback)(result);
...@@ -256,6 +250,9 @@ void SensorProxy::onRemoveConfigurationCompleted(double frequency, ...@@ -256,6 +250,9 @@ void SensorProxy::onRemoveConfigurationCompleted(double frequency,
if (!result) if (!result)
DVLOG(1) << "Failure at sensor configuration removal"; DVLOG(1) << "Failure at sensor configuration removal";
if (!usesPollingTimer())
return;
size_t index = m_frequenciesUsed.find(frequency); size_t index = m_frequenciesUsed.find(frequency);
if (index == kNotFound) { if (index == kNotFound) {
// Could happen e.g. if 'handleSensorError' was called before. // Could happen e.g. if 'handleSensorError' was called before.
...@@ -263,6 +260,7 @@ void SensorProxy::onRemoveConfigurationCompleted(double frequency, ...@@ -263,6 +260,7 @@ void SensorProxy::onRemoveConfigurationCompleted(double frequency,
} }
m_frequenciesUsed.remove(index); m_frequenciesUsed.remove(index);
updatePollingStatus();
} }
bool SensorProxy::tryReadFromBuffer(device::SensorReading& result) { bool SensorProxy::tryReadFromBuffer(device::SensorReading& result) {
...@@ -278,4 +276,28 @@ bool SensorProxy::tryReadFromBuffer(device::SensorReading& result) { ...@@ -278,4 +276,28 @@ bool SensorProxy::tryReadFromBuffer(device::SensorReading& result) {
return true; return true;
} }
void SensorProxy::updatePollingStatus() {
DCHECK(usesPollingTimer());
if (m_suspended || m_frequenciesUsed.isEmpty()) {
m_timer.stop();
return;
}
// TODO(Mikhail): Consider using sorted queue instead of searching
// max element each time.
auto it =
std::max_element(m_frequenciesUsed.begin(), m_frequenciesUsed.end());
DCHECK_GT(*it, 0.0);
double repeatInterval = 1 / *it;
if (!m_timer.isActive() || m_timer.repeatInterval() != repeatInterval) {
updateSensorReading();
m_timer.startRepeating(repeatInterval, BLINK_FROM_HERE);
}
}
void SensorProxy::onTimerFired(TimerBase*) {
updateSensorReading();
}
} // namespace blink } // namespace blink
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "device/generic_sensor/public/interfaces/sensor_provider.mojom-blink.h" #include "device/generic_sensor/public/interfaces/sensor_provider.mojom-blink.h"
#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding.h"
#include "platform/Supplementable.h" #include "platform/Supplementable.h"
#include "platform/Timer.h"
#include "platform/heap/Handle.h" #include "platform/heap/Handle.h"
#include "wtf/Vector.h" #include "wtf/Vector.h"
...@@ -20,7 +21,6 @@ namespace blink { ...@@ -20,7 +21,6 @@ namespace blink {
class SensorProviderProxy; class SensorProviderProxy;
class SensorReading; class SensorReading;
class SensorReadingFactory; class SensorReadingFactory;
class SensorReadingUpdater;
// This class wraps 'Sensor' mojo interface and used by multiple // This class wraps 'Sensor' mojo interface and used by multiple
// JS sensor instances of the same type (within a single frame). // JS sensor instances of the same type (within a single frame).
...@@ -38,16 +38,13 @@ class SensorProxy final : public GarbageCollectedFinalized<SensorProxy>, ...@@ -38,16 +38,13 @@ class SensorProxy final : public GarbageCollectedFinalized<SensorProxy>,
// methods can be called. // methods can be called.
virtual void onSensorInitialized() {} virtual void onSensorInitialized() {}
// Platfrom sensort reading has changed. // Platfrom sensort reading has changed.
// |timestamp| Reference timestamp in seconds of the moment when virtual void onSensorReadingChanged() {}
// sensor reading was updated from the buffer.
// Note: |timestamp| values are only used to calculate elapsed time
// between shared buffer readings. These values *do not* correspond
// to sensor reading timestamps which are obtained on platform side.
virtual void onSensorReadingChanged(double timestamp) {}
// An error has occurred. // An error has occurred.
virtual void onSensorError(ExceptionCode, virtual void onSensorError(ExceptionCode,
const String& sanitizedMessage, const String& sanitizedMessage,
const String& unsanitizedMessage) {} const String& unsanitizedMessage) {}
// Sensor reading change notification is suspended.
virtual void onSuspended() {}
}; };
~SensorProxy(); ~SensorProxy();
...@@ -62,10 +59,6 @@ class SensorProxy final : public GarbageCollectedFinalized<SensorProxy>, ...@@ -62,10 +59,6 @@ class SensorProxy final : public GarbageCollectedFinalized<SensorProxy>,
bool isInitializing() const { return m_state == Initializing; } bool isInitializing() const { return m_state == Initializing; }
bool isInitialized() const { return m_state == Initialized; } bool isInitialized() const { return m_state == Initialized; }
// Is watching new reading data (initialized, not suspended and has
// configurations added).
bool isActive() const;
void addConfiguration(device::mojom::blink::SensorConfigurationPtr, void addConfiguration(device::mojom::blink::SensorConfigurationPtr,
std::unique_ptr<Function<void(bool)>>); std::unique_ptr<Function<void(bool)>>);
...@@ -86,25 +79,20 @@ class SensorProxy final : public GarbageCollectedFinalized<SensorProxy>, ...@@ -86,25 +79,20 @@ class SensorProxy final : public GarbageCollectedFinalized<SensorProxy>,
double maximumFrequency() const { return m_maximumFrequency; } double maximumFrequency() const { return m_maximumFrequency; }
Document* document() const { return m_document; }
const WTF::Vector<double>& frequenciesUsed() const {
return m_frequenciesUsed;
}
DECLARE_VIRTUAL_TRACE(); DECLARE_VIRTUAL_TRACE();
private: private:
friend class SensorProviderProxy; friend class SensorProviderProxy;
friend class SensorReadingUpdaterContinuous;
friend class SensorReadingUpdaterOnChange;
SensorProxy(device::mojom::blink::SensorType, SensorProxy(device::mojom::blink::SensorType,
SensorProviderProxy*, SensorProviderProxy*,
Document*, Page*,
std::unique_ptr<SensorReadingFactory>); std::unique_ptr<SensorReadingFactory>);
// Returns true if this instance is using polling timer to
// periodically fetch reading data from shared buffer.
bool usesPollingTimer() const;
// Updates sensor reading from shared buffer. // Updates sensor reading from shared buffer.
void updateSensorReading(); void updateSensorReading();
void notifySensorChanged(double timestamp);
// device::mojom::blink::SensorClient overrides. // device::mojom::blink::SensorClient overrides.
void RaiseError() override; void RaiseError() override;
...@@ -128,7 +116,8 @@ class SensorProxy final : public GarbageCollectedFinalized<SensorProxy>, ...@@ -128,7 +116,8 @@ class SensorProxy final : public GarbageCollectedFinalized<SensorProxy>,
void onRemoveConfigurationCompleted(double frequency, bool result); void onRemoveConfigurationCompleted(double frequency, bool result);
bool tryReadFromBuffer(device::SensorReading& result); bool tryReadFromBuffer(device::SensorReading& result);
void onAnimationFrame(double timestamp); void updatePollingStatus();
void onTimerFired(TimerBase*);
device::mojom::blink::SensorType m_type; device::mojom::blink::SensorType m_type;
device::mojom::blink::ReportingMode m_mode; device::mojom::blink::ReportingMode m_mode;
...@@ -145,14 +134,13 @@ class SensorProxy final : public GarbageCollectedFinalized<SensorProxy>, ...@@ -145,14 +134,13 @@ class SensorProxy final : public GarbageCollectedFinalized<SensorProxy>,
mojo::ScopedSharedBufferHandle m_sharedBufferHandle; mojo::ScopedSharedBufferHandle m_sharedBufferHandle;
mojo::ScopedSharedBufferMapping m_sharedBuffer; mojo::ScopedSharedBufferMapping m_sharedBuffer;
bool m_suspended; bool m_suspended;
Member<Document> m_document;
Member<SensorReading> m_reading; Member<SensorReading> m_reading;
std::unique_ptr<SensorReadingFactory> m_readingFactory; std::unique_ptr<SensorReadingFactory> m_readingFactory;
double m_maximumFrequency; double m_maximumFrequency;
Member<SensorReadingUpdater> m_readingUpdater; // Used for continious reporting mode.
Timer<SensorProxy> m_timer;
WTF::Vector<double> m_frequenciesUsed; WTF::Vector<double> m_frequenciesUsed;
double m_lastRafTimestamp;
using ReadingBuffer = device::SensorReadingSharedBuffer; using ReadingBuffer = device::SensorReadingSharedBuffer;
static_assert( static_assert(
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "modules/sensor/SensorReadingUpdater.h"
#include "core/dom/Document.h"
#include "device/generic_sensor/public/interfaces/sensor.mojom-blink.h"
#include "modules/sensor/SensorProxy.h"
#include "wtf/CurrentTime.h"
using device::mojom::blink::ReportingMode;
namespace blink {
SensorReadingUpdater::SensorReadingUpdater(SensorProxy* sensorProxy)
: m_sensorProxy(sensorProxy), m_hasPendingAnimationFrameTask(false) {}
void SensorReadingUpdater::enqueueAnimationFrameTask() {
if (m_hasPendingAnimationFrameTask)
return;
auto callback = WTF::bind(&SensorReadingUpdater::onAnimationFrame,
wrapWeakPersistent(this));
m_sensorProxy->document()->enqueueAnimationFrameTask(std::move(callback));
m_hasPendingAnimationFrameTask = true;
}
void SensorReadingUpdater::start() {
enqueueAnimationFrameTask();
}
void SensorReadingUpdater::onAnimationFrame() {
m_hasPendingAnimationFrameTask = false;
onAnimationFrameInternal();
}
DEFINE_TRACE(SensorReadingUpdater) {
visitor->trace(m_sensorProxy);
}
class SensorReadingUpdaterContinuous : public SensorReadingUpdater {
public:
explicit SensorReadingUpdaterContinuous(SensorProxy* sensorProxy)
: SensorReadingUpdater(sensorProxy) {}
DEFINE_INLINE_VIRTUAL_TRACE() { SensorReadingUpdater::trace(visitor); }
protected:
void onAnimationFrameInternal() override {
if (!m_sensorProxy->isActive())
return;
m_sensorProxy->updateSensorReading();
m_sensorProxy->notifySensorChanged(WTF::monotonicallyIncreasingTime());
enqueueAnimationFrameTask();
}
};
// New data is fetched from shared buffer only once after 'start()'
// call. Further, notification is send until every client is updated
// (i.e. until longest notification period elapses) rAF stops after that.
class SensorReadingUpdaterOnChange : public SensorReadingUpdater {
public:
explicit SensorReadingUpdaterOnChange(SensorProxy* sensorProxy)
: SensorReadingUpdater(sensorProxy),
m_newDataArrivedTime(0.0),
m_newDataArrived(false) {}
DEFINE_INLINE_VIRTUAL_TRACE() { SensorReadingUpdater::trace(visitor); }
void start() override {
m_newDataArrived = true;
SensorReadingUpdater::start();
}
protected:
void onAnimationFrameInternal() override {
if (!m_sensorProxy->isActive())
return;
double timestamp = WTF::monotonicallyIncreasingTime();
if (m_newDataArrived) {
m_newDataArrived = false;
m_sensorProxy->updateSensorReading();
m_newDataArrivedTime = timestamp;
}
m_sensorProxy->notifySensorChanged(timestamp);
DCHECK_GT(m_sensorProxy->frequenciesUsed().front(), 0.0);
double longestNotificationPeriod =
1 / m_sensorProxy->frequenciesUsed().front();
if (timestamp - m_newDataArrivedTime <= longestNotificationPeriod)
enqueueAnimationFrameTask();
}
private:
double m_newDataArrivedTime;
bool m_newDataArrived;
};
// static
SensorReadingUpdater* SensorReadingUpdater::create(SensorProxy* proxy,
ReportingMode mode) {
if (mode == ReportingMode::CONTINUOUS)
return new SensorReadingUpdaterContinuous(proxy);
return new SensorReadingUpdaterOnChange(proxy);
}
} // namespace blink
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SensorReadingUpdater_h
#define SensorReadingUpdater_h
#include "device/generic_sensor/public/interfaces/sensor_provider.mojom-blink.h"
#include "platform/heap/Handle.h"
namespace blink {
class SensorProxy;
// This class encapsulates sensor reading update notification logic.
class SensorReadingUpdater : public GarbageCollected<SensorProxy> {
public:
static SensorReadingUpdater* create(SensorProxy*,
device::mojom::blink::ReportingMode);
virtual void start();
DECLARE_VIRTUAL_TRACE();
protected:
explicit SensorReadingUpdater(SensorProxy*);
void enqueueAnimationFrameTask();
virtual void onAnimationFrameInternal() = 0;
Member<SensorProxy> m_sensorProxy;
bool m_hasPendingAnimationFrameTask;
private:
void onAnimationFrame();
};
} // namespace blink
#endif // SensorReadingUpdater_h
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "modules/sensor/SensorUpdateNotificationStrategy.h"
#include "device/generic_sensor/public/interfaces/sensor.mojom-blink.h"
#include "platform/Timer.h"
#include "wtf/CurrentTime.h"
namespace blink {
// Polls the buffer on signal from platform but not more frequently
// than the given 'pollingPeriod'.
class SensorUpdateNotificationStrategyImpl
: public SensorUpdateNotificationStrategy {
public:
SensorUpdateNotificationStrategyImpl(double frequency,
std::unique_ptr<Function<void()>> func)
: m_pollingPeriod(1 / frequency),
m_func(std::move(func)),
m_timer(this, &SensorUpdateNotificationStrategyImpl::onTimer),
m_lastPollingTimestamp(0.0) {
DCHECK_GT(frequency, 0.0);
DCHECK(m_func);
}
private:
// SensorUpdateNotificationStrategy overrides.
void onSensorReadingChanged() override;
void cancelPendingNotifications() override;
void onTimer(TimerBase*);
void notifyUpdate();
double m_pollingPeriod;
std::unique_ptr<Function<void()>> m_func;
Timer<SensorUpdateNotificationStrategyImpl> m_timer;
double m_lastPollingTimestamp;
};
void SensorUpdateNotificationStrategyImpl::onSensorReadingChanged() {
if (m_timer.isActive())
return; // Skipping changes if update notification was already sheduled.
double elapsedTime =
WTF::monotonicallyIncreasingTime() - m_lastPollingTimestamp;
double waitingTime = m_pollingPeriod - elapsedTime;
const double minInterval =
1 / device::mojom::blink::SensorConfiguration::kMaxAllowedFrequency;
// Negative or zero 'waitingTime' means that polling period has elapsed.
// We also avoid scheduling if the elapsed time is slightly behind the
// polling period.
if (waitingTime < minInterval) {
notifyUpdate();
} else {
m_timer.startOneShot(waitingTime, BLINK_FROM_HERE);
}
}
void SensorUpdateNotificationStrategyImpl::cancelPendingNotifications() {
m_timer.stop();
}
void SensorUpdateNotificationStrategyImpl::notifyUpdate() {
m_lastPollingTimestamp = WTF::monotonicallyIncreasingTime();
(*m_func)();
}
void SensorUpdateNotificationStrategyImpl::onTimer(TimerBase*) {
notifyUpdate();
}
// static
std::unique_ptr<SensorUpdateNotificationStrategy>
SensorUpdateNotificationStrategy::create(
double pollingPeriod,
std::unique_ptr<Function<void()>> func) {
return std::unique_ptr<SensorUpdateNotificationStrategy>(
new SensorUpdateNotificationStrategyImpl(pollingPeriod, std::move(func)));
}
} // namespace blink
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SensorUpdateNotificationStrategy_h
#define SensorUpdateNotificationStrategy_h
#include "wtf/Functional.h"
namespace blink {
// This class encapsulates sensor reading update notification logic:
// the callback is invoked after client calls 'onSensorReadingChanged()'
// however considering the given sample frequency:
// guaranteed not to be called more often than expected.
class SensorUpdateNotificationStrategy {
public:
static std::unique_ptr<SensorUpdateNotificationStrategy> create(
double frequency,
std::unique_ptr<Function<void()>>);
virtual void onSensorReadingChanged() = 0;
virtual void cancelPendingNotifications() = 0;
virtual ~SensorUpdateNotificationStrategy() {}
};
} // namespace blink
#endif // SensorUpdateNotificationStrategy_h
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment