| // Copyright 2018 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 "services/device/public/cpp/test/fake_sensor_and_provider.h" |
| |
| #include <memory> |
| #include <utility> |
| |
| #include "base/logging.h" |
| #include "base/time/time.h" |
| #include "mojo/public/cpp/bindings/interface_request.h" |
| #include "mojo/public/cpp/bindings/strong_binding.h" |
| #include "services/device/public/cpp/generic_sensor/sensor_traits.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| |
| const uint64_t kReadingBufferSize = sizeof(device::SensorReadingSharedBuffer); |
| const uint64_t kSharedBufferSizeInBytes = |
| kReadingBufferSize * |
| (static_cast<uint64_t>(device::mojom::SensorType::kMaxValue) + 1); |
| |
| } // namespace |
| |
| namespace device { |
| |
| FakeSensor::FakeSensor(mojom::SensorType sensor_type, |
| SensorReadingSharedBuffer* buffer) |
| : sensor_type_(sensor_type), buffer_(buffer) {} |
| |
| FakeSensor::~FakeSensor() = default; |
| |
| void FakeSensor::AddConfiguration( |
| const PlatformSensorConfiguration& configuration, |
| AddConfigurationCallback callback) { |
| std::move(callback).Run(true); |
| SensorReadingChanged(); |
| } |
| |
| void FakeSensor::GetDefaultConfiguration( |
| GetDefaultConfigurationCallback callback) { |
| std::move(callback).Run(GetDefaultConfiguration()); |
| } |
| |
| void FakeSensor::RemoveConfiguration( |
| const PlatformSensorConfiguration& configuration) {} |
| |
| void FakeSensor::Suspend() {} |
| |
| void FakeSensor::Resume() {} |
| |
| void FakeSensor::ConfigureReadingChangeNotifications(bool enabled) { |
| reading_notification_enabled_ = enabled; |
| } |
| |
| PlatformSensorConfiguration FakeSensor::GetDefaultConfiguration() { |
| return PlatformSensorConfiguration(GetSensorDefaultFrequency(sensor_type_)); |
| } |
| |
| mojom::ReportingMode FakeSensor::GetReportingMode() { |
| return mojom::ReportingMode::ON_CHANGE; |
| } |
| |
| double FakeSensor::GetMaximumSupportedFrequency() { |
| return GetSensorMaxAllowedFrequency(sensor_type_); |
| } |
| |
| double FakeSensor::GetMinimumSupportedFrequency() { |
| return 1.0; |
| } |
| |
| mojom::SensorClientRequest FakeSensor::GetClient() { |
| return mojo::MakeRequest(&client_); |
| } |
| |
| uint64_t FakeSensor::GetBufferOffset() { |
| return SensorReadingSharedBuffer::GetOffset(sensor_type_); |
| } |
| |
| void FakeSensor::SetReading(SensorReading reading) { |
| reading_ = reading; |
| SensorReadingChanged(); |
| } |
| |
| void FakeSensor::SensorReadingChanged() { |
| auto& seqlock = buffer_->seqlock.value(); |
| seqlock.WriteBegin(); |
| buffer_->reading = reading_; |
| seqlock.WriteEnd(); |
| |
| if (client_ && reading_notification_enabled_) |
| client_->SensorReadingChanged(); |
| } |
| |
| FakeSensorProvider::FakeSensorProvider() : binding_(this) {} |
| |
| FakeSensorProvider::~FakeSensorProvider() = default; |
| |
| void FakeSensorProvider::GetSensor(mojom::SensorType type, |
| GetSensorCallback callback) { |
| if (!CreateSharedBufferIfNeeded()) { |
| std::move(callback).Run(mojom::SensorCreationResult::ERROR_NOT_AVAILABLE, |
| nullptr); |
| return; |
| } |
| |
| SensorReadingSharedBuffer* buffer = GetSensorReadingSharedBufferForType(type); |
| |
| std::unique_ptr<FakeSensor> sensor; |
| |
| switch (type) { |
| case mojom::SensorType::AMBIENT_LIGHT: |
| if (ambient_light_sensor_is_available_) { |
| sensor = std::make_unique<FakeSensor>(mojom::SensorType::AMBIENT_LIGHT, |
| buffer); |
| ambient_light_sensor_ = sensor.get(); |
| ambient_light_sensor_->SetReading(ambient_light_sensor_reading_); |
| } |
| break; |
| case mojom::SensorType::ACCELEROMETER: |
| if (accelerometer_is_available_) { |
| sensor = std::make_unique<FakeSensor>(mojom::SensorType::ACCELEROMETER, |
| buffer); |
| accelerometer_ = sensor.get(); |
| accelerometer_->SetReading(accelerometer_reading_); |
| } |
| break; |
| case mojom::SensorType::LINEAR_ACCELERATION: |
| if (linear_acceleration_sensor_is_available_) { |
| sensor = std::make_unique<FakeSensor>( |
| mojom::SensorType::LINEAR_ACCELERATION, buffer); |
| linear_acceleration_sensor_ = sensor.get(); |
| linear_acceleration_sensor_->SetReading( |
| linear_acceleration_sensor_reading_); |
| } |
| break; |
| case mojom::SensorType::GYROSCOPE: |
| if (gyroscope_is_available_) { |
| sensor = |
| std::make_unique<FakeSensor>(mojom::SensorType::GYROSCOPE, buffer); |
| gyroscope_ = sensor.get(); |
| gyroscope_->SetReading(gyroscope_reading_); |
| } |
| break; |
| case mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES: |
| if (relative_orientation_sensor_is_available_) { |
| sensor = std::make_unique<FakeSensor>( |
| mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES, buffer); |
| relative_orientation_sensor_ = sensor.get(); |
| relative_orientation_sensor_->SetReading( |
| relative_orientation_sensor_reading_); |
| } |
| break; |
| case mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES: |
| if (absolute_orientation_sensor_is_available_) { |
| sensor = std::make_unique<FakeSensor>( |
| mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES, buffer); |
| absolute_orientation_sensor_ = sensor.get(); |
| absolute_orientation_sensor_->SetReading( |
| absolute_orientation_sensor_reading_); |
| } |
| break; |
| default: |
| NOTIMPLEMENTED(); |
| } |
| |
| if (sensor) { |
| auto init_params = mojom::SensorInitParams::New(); |
| init_params->client_request = sensor->GetClient(); |
| init_params->memory = shared_buffer_handle_->Clone( |
| mojo::SharedBufferHandle::AccessMode::READ_ONLY); |
| init_params->buffer_offset = sensor->GetBufferOffset(); |
| init_params->default_configuration = sensor->GetDefaultConfiguration(); |
| init_params->maximum_frequency = sensor->GetMaximumSupportedFrequency(); |
| init_params->minimum_frequency = sensor->GetMinimumSupportedFrequency(); |
| |
| mojo::MakeStrongBinding(std::move(sensor), |
| mojo::MakeRequest(&init_params->sensor)); |
| std::move(callback).Run(mojom::SensorCreationResult::SUCCESS, |
| std::move(init_params)); |
| } else { |
| std::move(callback).Run(mojom::SensorCreationResult::ERROR_NOT_AVAILABLE, |
| nullptr); |
| } |
| } |
| |
| void FakeSensorProvider::Bind(mojom::SensorProviderRequest request) { |
| DCHECK(!binding_.is_bound()); |
| binding_.Bind(std::move(request)); |
| } |
| |
| void FakeSensorProvider::SetAmbientLightSensorData(double value) { |
| ambient_light_sensor_reading_.als.timestamp = |
| (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); |
| ambient_light_sensor_reading_.als.value = value; |
| } |
| |
| void FakeSensorProvider::SetAccelerometerData(double x, double y, double z) { |
| accelerometer_reading_.raw.timestamp = |
| (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); |
| accelerometer_reading_.accel.x = x; |
| accelerometer_reading_.accel.y = y; |
| accelerometer_reading_.accel.z = z; |
| } |
| |
| void FakeSensorProvider::SetLinearAccelerationSensorData(double x, |
| double y, |
| double z) { |
| linear_acceleration_sensor_reading_.raw.timestamp = |
| (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); |
| linear_acceleration_sensor_reading_.accel.x = x; |
| linear_acceleration_sensor_reading_.accel.y = y; |
| linear_acceleration_sensor_reading_.accel.z = z; |
| } |
| |
| void FakeSensorProvider::SetGyroscopeData(double x, double y, double z) { |
| gyroscope_reading_.raw.timestamp = |
| (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); |
| gyroscope_reading_.gyro.x = x; |
| gyroscope_reading_.gyro.y = y; |
| gyroscope_reading_.gyro.z = z; |
| } |
| |
| void FakeSensorProvider::SetRelativeOrientationSensorData(double alpha, |
| double beta, |
| double gamma) { |
| relative_orientation_sensor_reading_.raw.timestamp = |
| (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); |
| relative_orientation_sensor_reading_.orientation_euler.x = beta; |
| relative_orientation_sensor_reading_.orientation_euler.y = gamma; |
| relative_orientation_sensor_reading_.orientation_euler.z = alpha; |
| } |
| |
| void FakeSensorProvider::SetAbsoluteOrientationSensorData(double alpha, |
| double beta, |
| double gamma) { |
| absolute_orientation_sensor_reading_.raw.timestamp = |
| (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); |
| absolute_orientation_sensor_reading_.orientation_euler.x = beta; |
| absolute_orientation_sensor_reading_.orientation_euler.y = gamma; |
| absolute_orientation_sensor_reading_.orientation_euler.z = alpha; |
| } |
| |
| void FakeSensorProvider::UpdateAmbientLightSensorData(double value) { |
| SetAmbientLightSensorData(value); |
| EXPECT_TRUE(ambient_light_sensor_); |
| ambient_light_sensor_->SetReading(ambient_light_sensor_reading_); |
| } |
| |
| void FakeSensorProvider::UpdateAccelerometerData(double x, double y, double z) { |
| SetAccelerometerData(x, y, z); |
| EXPECT_TRUE(accelerometer_); |
| accelerometer_->SetReading(accelerometer_reading_); |
| } |
| |
| void FakeSensorProvider::UpdateLinearAccelerationSensorData(double x, |
| double y, |
| double z) { |
| SetLinearAccelerationSensorData(x, y, z); |
| EXPECT_TRUE(linear_acceleration_sensor_); |
| linear_acceleration_sensor_->SetReading(linear_acceleration_sensor_reading_); |
| } |
| |
| void FakeSensorProvider::UpdateGyroscopeData(double x, double y, double z) { |
| SetGyroscopeData(x, y, z); |
| EXPECT_TRUE(gyroscope_); |
| gyroscope_->SetReading(gyroscope_reading_); |
| } |
| |
| void FakeSensorProvider::UpdateRelativeOrientationSensorData(double alpha, |
| double beta, |
| double gamma) { |
| SetRelativeOrientationSensorData(alpha, beta, gamma); |
| EXPECT_TRUE(relative_orientation_sensor_); |
| relative_orientation_sensor_->SetReading( |
| relative_orientation_sensor_reading_); |
| } |
| |
| void FakeSensorProvider::UpdateAbsoluteOrientationSensorData(double alpha, |
| double beta, |
| double gamma) { |
| SetAbsoluteOrientationSensorData(alpha, beta, gamma); |
| EXPECT_TRUE(absolute_orientation_sensor_); |
| absolute_orientation_sensor_->SetReading( |
| absolute_orientation_sensor_reading_); |
| } |
| |
| bool FakeSensorProvider::CreateSharedBufferIfNeeded() { |
| if (shared_buffer_mapping_.get()) |
| return true; |
| |
| if (!shared_buffer_handle_.is_valid()) { |
| shared_buffer_handle_ = |
| mojo::SharedBufferHandle::Create(kSharedBufferSizeInBytes); |
| if (!shared_buffer_handle_.is_valid()) |
| return false; |
| } |
| |
| // Create read/write mapping now, to ensure it is kept writable |
| // after the region is sealed read-only on Android. |
| shared_buffer_mapping_ = shared_buffer_handle_->Map(kSharedBufferSizeInBytes); |
| return shared_buffer_mapping_.get() != nullptr; |
| } |
| |
| SensorReadingSharedBuffer* |
| FakeSensorProvider::GetSensorReadingSharedBufferForType( |
| mojom::SensorType type) { |
| auto* ptr = static_cast<char*>(shared_buffer_mapping_.get()); |
| if (!ptr) |
| return nullptr; |
| |
| ptr += SensorReadingSharedBuffer::GetOffset(type); |
| memset(ptr, 0, kReadingBufferSize); |
| return reinterpret_cast<SensorReadingSharedBuffer*>(ptr); |
| } |
| |
| } // namespace device |