1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "third_party/blink/renderer/modules/sensor/sensor_proxy_impl.h"
6
7 #include "services/device/public/cpp/generic_sensor/sensor_traits.h"
8 #include "third_party/blink/public/platform/platform.h"
9 #include "third_party/blink/public/platform/task_type.h"
10 #include "third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h"
11 #include "third_party/blink/renderer/modules/sensor/sensor_reading_remapper.h"
12 #include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
13
14 using device::mojom::blink::SensorCreationResult;
15
16 namespace blink {
17
SensorProxyImpl(device::mojom::blink::SensorType sensor_type,SensorProviderProxy * provider,Page * page)18 SensorProxyImpl::SensorProxyImpl(device::mojom::blink::SensorType sensor_type,
19 SensorProviderProxy* provider,
20 Page* page)
21 : SensorProxy(sensor_type, provider, page),
22 polling_timer_(
23 provider->GetSupplementable()->GetTaskRunner(TaskType::kSensor),
24 this,
25 &SensorProxyImpl::OnPollingTimer) {}
26
~SensorProxyImpl()27 SensorProxyImpl::~SensorProxyImpl() {}
28
Dispose()29 void SensorProxyImpl::Dispose() {
30 client_receiver_.reset();
31 }
32
Trace(Visitor * visitor)33 void SensorProxyImpl::Trace(Visitor* visitor) {
34 SensorProxy::Trace(visitor);
35 }
36
Initialize()37 void SensorProxyImpl::Initialize() {
38 if (state_ != kUninitialized)
39 return;
40
41 if (!sensor_provider()) {
42 HandleSensorError();
43 return;
44 }
45
46 state_ = kInitializing;
47 auto callback =
48 WTF::Bind(&SensorProxyImpl::OnSensorCreated, WrapWeakPersistent(this));
49 sensor_provider()->GetSensor(type_, std::move(callback));
50 }
51
AddConfiguration(device::mojom::blink::SensorConfigurationPtr configuration,base::OnceCallback<void (bool)> callback)52 void SensorProxyImpl::AddConfiguration(
53 device::mojom::blink::SensorConfigurationPtr configuration,
54 base::OnceCallback<void(bool)> callback) {
55 DCHECK(IsInitialized());
56 AddActiveFrequency(configuration->frequency);
57 sensor_remote_->AddConfiguration(std::move(configuration),
58 std::move(callback));
59 }
60
RemoveConfiguration(device::mojom::blink::SensorConfigurationPtr configuration)61 void SensorProxyImpl::RemoveConfiguration(
62 device::mojom::blink::SensorConfigurationPtr configuration) {
63 DCHECK(IsInitialized());
64 RemoveActiveFrequency(configuration->frequency);
65 sensor_remote_->RemoveConfiguration(std::move(configuration));
66 }
67
GetDefaultFrequency() const68 double SensorProxyImpl::GetDefaultFrequency() const {
69 DCHECK(IsInitialized());
70 return default_frequency_;
71 }
72
GetFrequencyLimits() const73 std::pair<double, double> SensorProxyImpl::GetFrequencyLimits() const {
74 DCHECK(IsInitialized());
75 return frequency_limits_;
76 }
77
Suspend()78 void SensorProxyImpl::Suspend() {
79 if (suspended_)
80 return;
81
82 sensor_remote_->Suspend();
83 suspended_ = true;
84 UpdatePollingStatus();
85 }
86
Resume()87 void SensorProxyImpl::Resume() {
88 if (!suspended_)
89 return;
90
91 sensor_remote_->Resume();
92 suspended_ = false;
93 UpdatePollingStatus();
94 }
95
UpdateSensorReading()96 void SensorProxyImpl::UpdateSensorReading() {
97 DCHECK(ShouldProcessReadings());
98 DCHECK(shared_buffer_reader_);
99
100 // Try to read the latest value from shared memory. Failure should not be
101 // fatal because we only retry a finite number of times.
102 device::SensorReading reading_data;
103 if (!shared_buffer_reader_->GetReading(&reading_data))
104 return;
105
106 double latest_timestamp = reading_data.timestamp();
107 if (reading_.timestamp() != latest_timestamp &&
108 latest_timestamp != 0.0) // The shared buffer is zeroed when
109 // sensor is stopped, we skip this
110 // reading.
111 {
112 DCHECK_GT(latest_timestamp, reading_.timestamp())
113 << "Timestamps must increase monotonically";
114 reading_ = reading_data;
115 for (Observer* observer : observers_)
116 observer->OnSensorReadingChanged();
117 }
118 }
119
RaiseError()120 void SensorProxyImpl::RaiseError() {
121 HandleSensorError();
122 }
123
SensorReadingChanged()124 void SensorProxyImpl::SensorReadingChanged() {
125 DCHECK_EQ(device::mojom::blink::ReportingMode::ON_CHANGE, mode_);
126 if (ShouldProcessReadings())
127 UpdateSensorReading();
128 }
129
ReportError(DOMExceptionCode code,const String & message)130 void SensorProxyImpl::ReportError(DOMExceptionCode code,
131 const String& message) {
132 state_ = kUninitialized;
133 active_frequencies_.clear();
134 reading_ = device::SensorReading();
135 UpdatePollingStatus();
136
137 // The m_sensor.reset() will release all callbacks and its bound parameters,
138 // therefore, handleSensorError accepts messages by value.
139 sensor_remote_.reset();
140 shared_buffer_reader_.reset();
141 default_frequency_ = 0.0;
142 frequency_limits_ = {0.0, 0.0};
143 client_receiver_.reset();
144
145 SensorProxy::ReportError(code, message);
146 }
147
HandleSensorError(SensorCreationResult error)148 void SensorProxyImpl::HandleSensorError(SensorCreationResult error) {
149 if (error == SensorCreationResult::ERROR_NOT_ALLOWED) {
150 String description = "Permissions to access sensor are not granted";
151 ReportError(DOMExceptionCode::kNotAllowedError, std::move(description));
152 } else {
153 ReportError(DOMExceptionCode::kNotReadableError, kDefaultErrorDescription);
154 }
155 }
156
OnSensorCreated(SensorCreationResult result,device::mojom::blink::SensorInitParamsPtr params)157 void SensorProxyImpl::OnSensorCreated(
158 SensorCreationResult result,
159 device::mojom::blink::SensorInitParamsPtr params) {
160 DCHECK_EQ(kInitializing, state_);
161 if (!params) {
162 DCHECK_NE(SensorCreationResult::SUCCESS, result);
163 HandleSensorError(result);
164 return;
165 }
166
167 DCHECK_EQ(SensorCreationResult::SUCCESS, result);
168
169 mode_ = params->mode;
170 if (!params->default_configuration) {
171 HandleSensorError();
172 return;
173 }
174
175 default_frequency_ = params->default_configuration->frequency;
176 DCHECK_GT(default_frequency_, 0.0);
177
178 sensor_remote_.Bind(std::move(params->sensor));
179 client_receiver_.Bind(std::move(params->client_receiver));
180
181 shared_buffer_reader_ = device::SensorReadingSharedBufferReader::Create(
182 std::move(params->memory), params->buffer_offset);
183 if (!shared_buffer_reader_) {
184 HandleSensorError();
185 return;
186 }
187
188 shared_buffer_reader_->GetReading(&reading_);
189
190 frequency_limits_.first = params->minimum_frequency;
191 frequency_limits_.second = params->maximum_frequency;
192
193 DCHECK_GT(frequency_limits_.first, 0.0);
194 DCHECK_GE(frequency_limits_.second, frequency_limits_.first);
195 DCHECK_GE(device::GetSensorMaxAllowedFrequency(type_),
196 frequency_limits_.second);
197
198 auto error_callback =
199 WTF::Bind(&SensorProxyImpl::HandleSensorError, WrapWeakPersistent(this),
200 SensorCreationResult::ERROR_NOT_AVAILABLE);
201 sensor_remote_.set_disconnect_handler(std::move(error_callback));
202
203 state_ = kInitialized;
204
205 UpdateSuspendedStatus();
206
207 for (Observer* observer : observers_)
208 observer->OnSensorInitialized();
209 }
210
OnPollingTimer(TimerBase *)211 void SensorProxyImpl::OnPollingTimer(TimerBase*) {
212 UpdateSensorReading();
213 }
214
ShouldProcessReadings() const215 bool SensorProxyImpl::ShouldProcessReadings() const {
216 return IsInitialized() && !suspended_ && !active_frequencies_.IsEmpty();
217 }
218
UpdatePollingStatus()219 void SensorProxyImpl::UpdatePollingStatus() {
220 if (mode_ != device::mojom::blink::ReportingMode::CONTINUOUS)
221 return;
222
223 if (ShouldProcessReadings()) {
224 // TODO(crbug/721297) : We need to find out an algorithm for resulting
225 // polling frequency.
226 polling_timer_.StartRepeating(
227 base::TimeDelta::FromSecondsD(1 / active_frequencies_.back()),
228 FROM_HERE);
229 } else {
230 polling_timer_.Stop();
231 }
232 }
233
RemoveActiveFrequency(double frequency)234 void SensorProxyImpl::RemoveActiveFrequency(double frequency) {
235 // Can use binary search as active_frequencies_ is sorted.
236 Vector<double>::iterator it = std::lower_bound(
237 active_frequencies_.begin(), active_frequencies_.end(), frequency);
238 if (it == active_frequencies_.end() || *it != frequency) {
239 NOTREACHED() << "Attempted to remove active frequency which is not present "
240 "in the list";
241 return;
242 }
243
244 active_frequencies_.erase(it);
245 UpdatePollingStatus();
246
247 if (active_frequencies_.IsEmpty())
248 reading_ = device::SensorReading();
249 }
250
AddActiveFrequency(double frequency)251 void SensorProxyImpl::AddActiveFrequency(double frequency) {
252 Vector<double>::iterator it = std::lower_bound(
253 active_frequencies_.begin(), active_frequencies_.end(), frequency);
254 if (it == active_frequencies_.end()) {
255 active_frequencies_.push_back(frequency);
256 } else {
257 active_frequencies_.insert(
258 static_cast<wtf_size_t>(std::distance(active_frequencies_.begin(), it)),
259 frequency);
260 }
261 UpdatePollingStatus();
262 }
263
264 } // namespace blink
265