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

Unified Diff: content/renderer/device_sensors/device_sensor_event_pump.h

Issue 2885203004: Refactor content/renderer/device_sensors to use device/generic_sensor instead of device/sensors (Closed)
Patch Set: updated content/renderer/BUILD.gn Created 3 years, 7 months 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 side-by-side diff with in-line comments
Download patch
Index: content/renderer/device_sensors/device_sensor_event_pump.h
diff --git a/content/renderer/device_sensors/device_sensor_event_pump.h b/content/renderer/device_sensors/device_sensor_event_pump.h
index 17a8ff96b4aee4e1902208197f187af685feb4b4..435a0a080395e262147e03b6cb6c53cde7c0bb63 100644
--- a/content/renderer/device_sensors/device_sensor_event_pump.h
+++ b/content/renderer/device_sensors/device_sensor_event_pump.h
@@ -5,142 +5,283 @@
#ifndef CONTENT_RENDERER_DEVICE_SENSORS_DEVICE_SENSOR_EVENT_PUMP_H_
#define CONTENT_RENDERER_DEVICE_SENSORS_DEVICE_SENSOR_EVENT_PUMP_H_
+#include <memory>
+#include <utility>
+#include <vector>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
-#include "base/memory/shared_memory.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "content/public/common/service_names.mojom.h"
#include "content/public/renderer/platform_event_observer.h"
#include "content/renderer/render_thread_impl.h"
+#include "device/generic_sensor/public/cpp/sensor_reading.h"
+#include "device/generic_sensor/public/interfaces/sensor.mojom.h"
+#include "device/generic_sensor/public/interfaces/sensor_provider.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "services/device/public/interfaces/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
namespace content {
-template <typename Base, typename MojoInterface>
-class CONTENT_EXPORT DeviceSensorMojoClientMixin : public Base {
- public:
- template <typename... Args>
- explicit DeviceSensorMojoClientMixin(Args&&... args)
- : Base(std::forward<Args>(args)...) {
- auto request = mojo::MakeRequest(&mojo_interface_);
-
- // When running layout tests, those observers should not listen to the
- // actual hardware changes. In order to make that happen, don't connect
- // the other end of the mojo pipe to anything.
- //
- // TODO(sammc): Remove this when JS layout test support for shared buffers
- // is ready and the layout tests are converted to use that for mocking.
- if (RenderThreadImpl::current() &&
- !RenderThreadImpl::current()->layout_test_mode()) {
- RenderThread::Get()->GetConnector()->BindInterface(
- device::mojom::kServiceName, std::move(request));
- }
- }
-
- void SendStartMessage() override {
- mojo_interface_->StartPolling(
- base::Bind(&DeviceSensorMojoClientMixin<Base, MojoInterface>::DidStart,
- base::Unretained(this)));
- }
- void SendStopMessage() override { mojo_interface_->StopPolling(); }
-
- protected:
- void DidStart(mojo::ScopedSharedBufferHandle buffer_handle) {
- Base::DidStart(std::move(buffer_handle));
- }
-
- private:
- mojo::InterfacePtr<MojoInterface> mojo_interface_;
-};
-
template <typename ListenerType>
class CONTENT_EXPORT DeviceSensorEventPump
: NON_EXPORTED_BASE(public PlatformEventObserver<ListenerType>) {
public:
- // Default rate for firing events.
- static const int kDefaultPumpFrequencyHz = 60;
- static const int kDefaultPumpDelayMicroseconds =
- base::Time::kMicrosecondsPerSecond / kDefaultPumpFrequencyHz;
-
- // PlatformEventObserver
+ // PlatformEventObserver:
void Start(blink::WebPlatformEventListener* listener) override {
DVLOG(2) << "requested start";
- if (state_ != STOPPED)
+ if (state_ != PumpState::STOPPED)
return;
DCHECK(!timer_.IsRunning());
PlatformEventObserver<ListenerType>::Start(listener);
- state_ = PENDING_START;
+ state_ = PumpState::PENDING_START;
}
+ // PlatformEventObserver:
void Stop() override {
- DVLOG(2) << "stop";
+ DVLOG(2) << "requested stop";
- if (state_ == STOPPED)
+ if (state_ == PumpState::STOPPED)
return;
- DCHECK((state_ == PENDING_START && !timer_.IsRunning()) ||
- (state_ == RUNNING && timer_.IsRunning()));
+ DCHECK((state_ == PumpState::PENDING_START && !timer_.IsRunning()) ||
+ (state_ == PumpState::RUNNING && timer_.IsRunning()));
if (timer_.IsRunning())
timer_.Stop();
+
PlatformEventObserver<ListenerType>::Stop();
- state_ = STOPPED;
+ state_ = PumpState::STOPPED;
+ }
+
+ // PlatformEventObserver:
+ void SendStopMessage() override {
+ sensors_.clear();
+ num_sensors_tried_ = 0;
+ num_available_sensors_ = 0;
}
protected:
explicit DeviceSensorEventPump(RenderThread* thread)
: PlatformEventObserver<ListenerType>(thread),
pump_delay_microseconds_(kDefaultPumpDelayMicroseconds),
- state_(STOPPED) {}
+ num_sensors_tried_(0),
+ num_available_sensors_(0),
+ state_(PumpState::STOPPED) {
+ auto request = mojo::MakeRequest(&sensor_provider_);
+
+ // When running layout tests, those observers should not listen to the
+ // actual hardware changes. In order to make that happen, don't connect
+ // the other end of the mojo pipe to anything.
+ if (RenderThreadImpl::current() &&
+ !RenderThreadImpl::current()->layout_test_mode()) {
+ RenderThread::Get()->GetConnector()->BindInterface(
+ device::mojom::kServiceName, std::move(request));
+ sensor_provider_.set_connection_error_handler(
+ base::Bind(&DeviceSensorEventPump::HandleSensorProviderError,
+ base::Unretained(this)));
+ }
+ }
~DeviceSensorEventPump() override {
PlatformEventObserver<ListenerType>::StopIfObserving();
}
+ // Default rate for firing events.
+ static constexpr int kDefaultPumpFrequencyHz = 60;
+ static constexpr int kDefaultPumpDelayMicroseconds =
+ base::Time::kMicrosecondsPerSecond / kDefaultPumpFrequencyHz;
+
+ static constexpr int kMaxReadAttemptsCount = 10;
+
+ struct CONTENT_EXPORT SensorEntry : public device::mojom::SensorClient {
+ explicit SensorEntry(DeviceSensorEventPump* pump)
+ : event_pump(pump), active(false), client_binding(this) {}
+
+ ~SensorEntry() { client_binding.Close(); }
+
+ // device::mojom::SensorClient:
+ void RaiseError() override { HandleSensorError(); }
+
+ // device::mojom::SensorClient:
+ void SensorReadingChanged() override {
+ // Since DeviceSensorEventPump::FireEvent is called in a certain
+ // frequency, the |shared_buffer| is read frequently, so this
+ // method doesn't need to be implemented.
+ }
+
+ // Mojo callback for SensorProvider::GetSensor().
+ void OnSensorCreated(device::mojom::SensorInitParamsPtr params,
+ device::mojom::SensorClientRequest client_request) {
+ ++event_pump->num_sensors_tried_;
+
+ if (!params) {
+ HandleSensorError();
+ if (event_pump->CanStart())
+ event_pump->DidStart();
+ return;
+ }
+
+ constexpr size_t kReadBufferSize =
+ sizeof(device::SensorReadingSharedBuffer);
+
+ DCHECK_EQ(0u, params->buffer_offset % kReadBufferSize);
+
+ mode = params->mode;
+ default_config = params->default_configuration;
+
+ DCHECK(sensor.is_bound());
+ client_binding.Bind(std::move(client_request));
+
+ shared_buffer_handle = std::move(params->memory);
+ DCHECK(!shared_buffer);
+ shared_buffer = shared_buffer_handle->MapAtOffset(kReadBufferSize,
+ params->buffer_offset);
+
+ if (!shared_buffer) {
+ HandleSensorError();
+ if (event_pump->CanStart())
+ event_pump->DidStart();
+ return;
+ }
+
+ ++event_pump->num_available_sensors_;
+
+ frequency_limits.first = params->minimum_frequency;
+ frequency_limits.second = params->maximum_frequency;
+
+ DCHECK_GT(frequency_limits.first, 0.0);
+ DCHECK_GE(frequency_limits.second, frequency_limits.first);
+ constexpr double kMaxAllowedFrequency =
+ device::mojom::SensorConfiguration::kMaxAllowedFrequency;
+ DCHECK_GE(kMaxAllowedFrequency, frequency_limits.second);
+
+ sensor.set_connection_error_handler(
+ base::Bind(&SensorEntry::HandleSensorError, base::Unretained(this)));
+ sensor->AddConfiguration(
+ default_config, base::Bind(&SensorEntry::OnSensorAddConfiguration,
+ base::Unretained(this)));
+ }
+
+ // Mojo callback for Sensor::AddConfiguration().
+ void OnSensorAddConfiguration(bool success) {
+ active = success;
+ if (event_pump->CanStart())
+ event_pump->DidStart();
+ }
+
+ void HandleSensorError() {
+ sensor.reset();
+ active = false;
+ shared_buffer_handle.reset();
+ shared_buffer.reset();
+ client_binding.Close();
+ }
+
+ // Updates sensor reading from shared buffer.
+ bool UpdateSensorReading() {
+ int read_attempts = 0;
+ device::SensorReading reading_data;
+ while (!TryReadFromBuffer(&reading_data)) {
+ if (++read_attempts == kMaxReadAttemptsCount) {
+ HandleSensorError();
+ return false;
+ }
+ }
+
+ reading = reading_data;
+ return true;
+ }
+
+ bool TryReadFromBuffer(device::SensorReading* result) {
+ const device::SensorReadingSharedBuffer* buffer =
+ static_cast<const device::SensorReadingSharedBuffer*>(
+ shared_buffer.get());
+ const device::OneWriterSeqLock& seqlock = buffer->seqlock.value();
+ auto version = seqlock.ReadBegin();
+ auto reading_data = buffer->reading;
+ if (seqlock.ReadRetry(version))
+ return false;
+ *result = reading_data;
+ return true;
+ }
+
+ bool SensorReadingUpdated() { return active && UpdateSensorReading(); }
+
+ DeviceSensorEventPump* event_pump;
+ device::mojom::SensorPtr sensor;
+ device::mojom::SensorType type;
+ bool active;
+ device::mojom::ReportingMode mode;
+ device::PlatformSensorConfiguration default_config;
+ mojo::ScopedSharedBufferHandle shared_buffer_handle;
+ mojo::ScopedSharedBufferMapping shared_buffer;
+ device::SensorReading reading;
+ std::pair<double, double> frequency_limits;
+ mojo::Binding<device::mojom::SensorClient> client_binding;
+ };
+
+ friend struct SensorEntry;
+
// The pump is a tri-state automaton with allowed transitions as follows:
// STOPPED -> PENDING_START
// PENDING_START -> RUNNING
// PENDING_START -> STOPPED
// RUNNING -> STOPPED
- enum PumpState {
- STOPPED,
- RUNNING,
- PENDING_START
- };
+ enum class PumpState { STOPPED, RUNNING, PENDING_START };
- void DidStart(mojo::ScopedSharedBufferHandle buffer_handle) {
+ void GetSensor(device::mojom::SensorType type, SensorEntry* sensor_entry) {
+ sensor_entry->type = type;
+ auto request = mojo::MakeRequest(&sensor_entry->sensor);
+ sensor_provider_->GetSensor(type, std::move(request),
+ base::Bind(&SensorEntry::OnSensorCreated,
+ base::Unretained(sensor_entry)));
+ }
+
+ void DidStart() {
DVLOG(2) << "did start sensor event pump";
- if (state_ != PENDING_START)
+ if (state_ != PumpState::PENDING_START)
return;
DCHECK(!timer_.IsRunning());
- base::SharedMemoryHandle handle;
- MojoResult result = mojo::UnwrapSharedMemoryHandle(
- std::move(buffer_handle), &handle, nullptr, nullptr);
- DCHECK_EQ(MOJO_RESULT_OK, result);
-
- if (InitializeReader(handle)) {
- timer_.Start(FROM_HERE,
- base::TimeDelta::FromMicroseconds(pump_delay_microseconds_),
- this,
- &DeviceSensorEventPump::FireEvent);
- state_ = RUNNING;
- }
+ timer_.Start(FROM_HERE,
+ base::TimeDelta::FromMicroseconds(pump_delay_microseconds_),
+ this, &DeviceSensorEventPump::FireEvent);
+ state_ = PumpState::RUNNING;
}
+ void HandleSensorProviderError() {
+ sensor_provider_.reset();
+ for (auto& sensor : sensors_)
+ sensor->HandleSensorError();
+ }
+
+ // Notify the renderer of a certain device event.
virtual void FireEvent() = 0;
- virtual bool InitializeReader(base::SharedMemoryHandle handle) = 0;
+ mojo::InterfacePtr<device::mojom::SensorProvider> sensor_provider_;
+ std::vector<std::unique_ptr<SensorEntry>> sensors_;
int pump_delay_microseconds_;
+ // The number of sensors that are tried obtaining by calling
+ // SensorProvider::GetSensor().
+ int num_sensors_tried_;
+ // The number of sensors that are available from a successful
+ // SensorProvider::GetSensor() call.
+ int num_available_sensors_;
+
+ private:
+ // Returns if the |sensors_| are ready to start a certain device event.
+ virtual bool CanStart() const = 0;
+
PumpState state_;
base::RepeatingTimer timer_;

Powered by Google App Engine
This is Rietveld 408576698