blob: a603775afea9fcc2c439c5e447a9a04bc42b69fb [file] [log] [blame]
// Copyright 2014 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 "content/renderer/device_sensors/device_motion_event_pump.h"
#include <cmath>
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/render_thread_impl.h"
#include "device/sensors/public/cpp/motion_data.h"
#include "services/device/public/interfaces/sensor.mojom.h"
#include "services/service_manager/public/cpp/interface_provider.h"
namespace content {
DeviceMotionEventPump::DeviceMotionEventPump(RenderThread* thread)
: DeviceSensorEventPump<blink::WebDeviceMotionListener>(thread),
accelerometer_(this, device::mojom::SensorType::ACCELEROMETER),
linear_acceleration_sensor_(
this,
device::mojom::SensorType::LINEAR_ACCELERATION),
gyroscope_(this, device::mojom::SensorType::GYROSCOPE) {}
DeviceMotionEventPump::~DeviceMotionEventPump() {}
void DeviceMotionEventPump::SendStartMessage() {
// 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.
// https://crbug.com/774183
if (!RenderThreadImpl::current() ||
RenderThreadImpl::current()->layout_test_mode()) {
return;
}
if (!accelerometer_.sensor && !linear_acceleration_sensor_.sensor &&
!gyroscope_.sensor) {
if (!sensor_provider_) {
RenderFrame* const render_frame = GetRenderFrame();
if (!render_frame)
return;
CHECK(render_frame->GetRemoteInterfaces());
render_frame->GetRemoteInterfaces()->GetInterface(
mojo::MakeRequest(&sensor_provider_));
sensor_provider_.set_connection_error_handler(
base::BindOnce(&DeviceSensorEventPump::HandleSensorProviderError,
base::Unretained(this)));
}
GetSensor(&accelerometer_);
GetSensor(&linear_acceleration_sensor_);
GetSensor(&gyroscope_);
} else {
if (accelerometer_.sensor)
accelerometer_.sensor->Resume();
if (linear_acceleration_sensor_.sensor)
linear_acceleration_sensor_.sensor->Resume();
if (gyroscope_.sensor)
gyroscope_.sensor->Resume();
DidStartIfPossible();
}
}
void DeviceMotionEventPump::SendStopMessage() {
// SendStopMessage() gets called both when the page visibility changes and if
// all device motion event listeners are unregistered. Since removing the
// event listener is more rare than the page visibility changing,
// Sensor::Suspend() is used to optimize this case for not doing extra work.
if (accelerometer_.sensor)
accelerometer_.sensor->Suspend();
if (linear_acceleration_sensor_.sensor)
linear_acceleration_sensor_.sensor->Suspend();
if (gyroscope_.sensor)
gyroscope_.sensor->Suspend();
}
void DeviceMotionEventPump::SendFakeDataForTesting(void* fake_data) {
if (!listener())
return;
device::MotionData data = *static_cast<device::MotionData*>(fake_data);
listener()->DidChangeDeviceMotion(data);
}
void DeviceMotionEventPump::FireEvent() {
device::MotionData data;
// The device orientation spec states that interval should be in milliseconds.
// https://w3c.github.io/deviceorientation/spec-source-orientation.html#devicemotion
data.interval = kDefaultPumpDelayMicroseconds / 1000;
DCHECK(listener());
GetDataFromSharedMemory(&data);
listener()->DidChangeDeviceMotion(data);
}
bool DeviceMotionEventPump::SensorSharedBuffersReady() const {
if (accelerometer_.sensor && !accelerometer_.shared_buffer)
return false;
if (linear_acceleration_sensor_.sensor &&
!linear_acceleration_sensor_.shared_buffer) {
return false;
}
if (gyroscope_.sensor && !gyroscope_.shared_buffer)
return false;
return true;
}
void DeviceMotionEventPump::GetDataFromSharedMemory(device::MotionData* data) {
if (accelerometer_.SensorReadingCouldBeRead()) {
data->acceleration_including_gravity_x = accelerometer_.reading.accel.x;
data->acceleration_including_gravity_y = accelerometer_.reading.accel.y;
data->acceleration_including_gravity_z = accelerometer_.reading.accel.z;
data->has_acceleration_including_gravity_x =
!std::isnan(accelerometer_.reading.accel.x.value());
data->has_acceleration_including_gravity_y =
!std::isnan(accelerometer_.reading.accel.y.value());
data->has_acceleration_including_gravity_z =
!std::isnan(accelerometer_.reading.accel.z.value());
}
if (linear_acceleration_sensor_.SensorReadingCouldBeRead()) {
data->acceleration_x = linear_acceleration_sensor_.reading.accel.x;
data->acceleration_y = linear_acceleration_sensor_.reading.accel.y;
data->acceleration_z = linear_acceleration_sensor_.reading.accel.z;
data->has_acceleration_x =
!std::isnan(linear_acceleration_sensor_.reading.accel.x.value());
data->has_acceleration_y =
!std::isnan(linear_acceleration_sensor_.reading.accel.y.value());
data->has_acceleration_z =
!std::isnan(linear_acceleration_sensor_.reading.accel.z.value());
}
if (gyroscope_.SensorReadingCouldBeRead()) {
data->rotation_rate_alpha = gyroscope_.reading.gyro.x;
data->rotation_rate_beta = gyroscope_.reading.gyro.y;
data->rotation_rate_gamma = gyroscope_.reading.gyro.z;
data->has_rotation_rate_alpha =
!std::isnan(gyroscope_.reading.gyro.x.value());
data->has_rotation_rate_beta =
!std::isnan(gyroscope_.reading.gyro.y.value());
data->has_rotation_rate_gamma =
!std::isnan(gyroscope_.reading.gyro.z.value());
}
}
} // namespace content