blob: 0abc1c1862825ae937e94020aae8c551d626a445 [file] [log] [blame]
// Copyright 2019 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 SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_READER_WINRT_H_
#define SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_READER_WINRT_H_
#include <windows.devices.sensors.h>
#include <windows.foundation.h>
#include <wrl/client.h>
#include <wrl/event.h>
#include <functional>
#include <memory>
#include "base/callback.h"
#include "base/optional.h"
#include "base/synchronization/lock.h"
#include "services/device/generic_sensor/platform_sensor_reader_win_base.h"
#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
#include "ui/gfx/geometry/angle_conversions.h"
namespace device {
namespace mojom {
enum class SensorType;
}
// Helper class used to create PlatformSensorReaderWinrt instances
class PlatformSensorReaderWinrtFactory {
public:
static std::unique_ptr<PlatformSensorReaderWinBase> Create(
mojom::SensorType type);
};
// Base class that contains common helper functions used between all low
// level sensor types based on the Windows.Devices.Sensors API. Derived
// classes will specialize the template into a specific sensor. See
// PlatformSensorReaderWinrtLightSensor as an example of what WinRT
// interfaces should be passed in. The owner of this class must guarantee
// construction and destruction occur on the same thread and that no
// other thread is accessing it during destruction.
// TODO(crbug.com/995594): Change Windows.Devices.Sensors based
// implementation of W3C sensor API to use hardware thresholding.
template <wchar_t const* runtime_class_id,
class ISensorWinrtStatics,
class ISensorWinrtClass,
class ISensorReadingChangedHandler,
class ISensorReadingChangedEventArgs>
class PlatformSensorReaderWinrtBase : public PlatformSensorReaderWinBase {
public:
using GetSensorFactoryFunctor =
base::RepeatingCallback<HRESULT(ISensorWinrtStatics**)>;
// Sets the client to notify changes about. The consumer should always
// ensure the lifetime of the client surpasses the lifetime of this class.
void SetClient(Client* client) override;
// Allows tests to specify their own implementation of the underlying sensor.
// This function should be called before Initialize().
void InitForTesting(GetSensorFactoryFunctor get_sensor_factory_callback) {
get_sensor_factory_callback_ = get_sensor_factory_callback;
}
// Returns true if the underlying WinRT sensor object is valid, meant
// for testing purposes.
bool IsUnderlyingWinrtObjectValidForTesting() { return sensor_; }
bool Initialize() WARN_UNUSED_RESULT;
bool StartSensor(const PlatformSensorConfiguration& configuration) override
WARN_UNUSED_RESULT;
base::TimeDelta GetMinimalReportingInterval() const override;
void StopSensor() override;
protected:
PlatformSensorReaderWinrtBase();
virtual ~PlatformSensorReaderWinrtBase() { StopSensor(); }
// Derived classes should implement this function to handle sensor specific
// parsing of the sensor reading.
virtual HRESULT OnReadingChangedCallback(
ISensorWinrtClass* sensor,
ISensorReadingChangedEventArgs* reading_changed_args) = 0;
// Helper function which converts the DateTime timestamp format the
// Windows.Devices.Sensors API uses to the second time ticks the
// client expects.
template <class ISensorReading>
HRESULT ConvertSensorReadingTimeStamp(
Microsoft::WRL::ComPtr<ISensorReading> sensor_reading,
base::TimeDelta* timestamp_delta);
// Following class member is protected by lock since SetClient,
// StartSensor, and StopSensor can all be called from different
// threads by PlatformSensorWin.
base::Lock lock_;
// Null if there is no client to notify, non-null otherwise.
Client* client_;
// Always report the first sample received after starting the sensor.
bool has_received_first_sample_ = false;
private:
base::TimeDelta GetMinimumReportIntervalFromSensor();
GetSensorFactoryFunctor get_sensor_factory_callback_;
// base::nullopt if the sensor has not been started, non-empty otherwise.
base::Optional<EventRegistrationToken> reading_callback_token_;
base::TimeDelta minimum_report_interval_;
Microsoft::WRL::ComPtr<ISensorWinrtClass> sensor_;
};
class PlatformSensorReaderWinrtLightSensor final
: public PlatformSensorReaderWinrtBase<
RuntimeClass_Windows_Devices_Sensors_LightSensor,
ABI::Windows::Devices::Sensors::ILightSensorStatics,
ABI::Windows::Devices::Sensors::ILightSensor,
Microsoft::WRL::Implements<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
ABI::Windows::Foundation::ITypedEventHandler<
ABI::Windows::Devices::Sensors::LightSensor*,
ABI::Windows::Devices::Sensors::
LightSensorReadingChangedEventArgs*>,
Microsoft::WRL::FtmBase>,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs> {
public:
// Lux scales exponentially with perceived brightness so use a relative
// threshold instead of an absolute one.
static constexpr float kLuxPercentThreshold = 0.2f; // 20%
static std::unique_ptr<PlatformSensorReaderWinBase> Create();
PlatformSensorReaderWinrtLightSensor();
~PlatformSensorReaderWinrtLightSensor() override = default;
protected:
HRESULT OnReadingChangedCallback(
ABI::Windows::Devices::Sensors::ILightSensor* sensor,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs*
reading_changed_args) override;
private:
float last_reported_lux_ = 0.0f;
PlatformSensorReaderWinrtLightSensor(
const PlatformSensorReaderWinrtLightSensor&) = delete;
PlatformSensorReaderWinrtLightSensor& operator=(
const PlatformSensorReaderWinrtLightSensor&) = delete;
};
class PlatformSensorReaderWinrtAccelerometer final
: public PlatformSensorReaderWinrtBase<
RuntimeClass_Windows_Devices_Sensors_Accelerometer,
ABI::Windows::Devices::Sensors::IAccelerometerStatics,
ABI::Windows::Devices::Sensors::IAccelerometer,
Microsoft::WRL::Implements<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
ABI::Windows::Foundation::ITypedEventHandler<
ABI::Windows::Devices::Sensors::Accelerometer*,
ABI::Windows::Devices::Sensors::
AccelerometerReadingChangedEventArgs*>,
Microsoft::WRL::FtmBase>,
ABI::Windows::Devices::Sensors::
IAccelerometerReadingChangedEventArgs> {
public:
static constexpr double kAxisThreshold = 0.1f;
static std::unique_ptr<PlatformSensorReaderWinBase> Create();
PlatformSensorReaderWinrtAccelerometer();
~PlatformSensorReaderWinrtAccelerometer() override = default;
protected:
HRESULT OnReadingChangedCallback(
ABI::Windows::Devices::Sensors::IAccelerometer* sensor,
ABI::Windows::Devices::Sensors::IAccelerometerReadingChangedEventArgs*
reading_changed_args) override;
private:
double last_reported_x_ = 0.0;
double last_reported_y_ = 0.0;
double last_reported_z_ = 0.0;
PlatformSensorReaderWinrtAccelerometer(
const PlatformSensorReaderWinrtAccelerometer&) = delete;
PlatformSensorReaderWinrtAccelerometer& operator=(
const PlatformSensorReaderWinrtAccelerometer&) = delete;
};
class PlatformSensorReaderWinrtGyrometer final
: public PlatformSensorReaderWinrtBase<
RuntimeClass_Windows_Devices_Sensors_Gyrometer,
ABI::Windows::Devices::Sensors::IGyrometerStatics,
ABI::Windows::Devices::Sensors::IGyrometer,
Microsoft::WRL::Implements<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
ABI::Windows::Foundation::ITypedEventHandler<
ABI::Windows::Devices::Sensors::Gyrometer*,
ABI::Windows::Devices::Sensors::
GyrometerReadingChangedEventArgs*>,
Microsoft::WRL::FtmBase>,
ABI::Windows::Devices::Sensors::IGyrometerReadingChangedEventArgs> {
public:
static constexpr double kDegreeThreshold = 5.0;
static std::unique_ptr<PlatformSensorReaderWinBase> Create();
PlatformSensorReaderWinrtGyrometer();
~PlatformSensorReaderWinrtGyrometer() override = default;
protected:
HRESULT OnReadingChangedCallback(
ABI::Windows::Devices::Sensors::IGyrometer* sensor,
ABI::Windows::Devices::Sensors::IGyrometerReadingChangedEventArgs*
reading_changed_args) override;
private:
double last_reported_x_ = 0.0;
double last_reported_y_ = 0.0;
double last_reported_z_ = 0.0;
PlatformSensorReaderWinrtGyrometer(
const PlatformSensorReaderWinrtGyrometer&) = delete;
PlatformSensorReaderWinrtGyrometer& operator=(
const PlatformSensorReaderWinrtGyrometer&) = delete;
};
class PlatformSensorReaderWinrtMagnetometer final
: public PlatformSensorReaderWinrtBase<
RuntimeClass_Windows_Devices_Sensors_Magnetometer,
ABI::Windows::Devices::Sensors::IMagnetometerStatics,
ABI::Windows::Devices::Sensors::IMagnetometer,
Microsoft::WRL::Implements<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
ABI::Windows::Foundation::ITypedEventHandler<
ABI::Windows::Devices::Sensors::Magnetometer*,
ABI::Windows::Devices::Sensors::
MagnetometerReadingChangedEventArgs*>,
Microsoft::WRL::FtmBase>,
ABI::Windows::Devices::Sensors::
IMagnetometerReadingChangedEventArgs> {
public:
static constexpr double kMicroteslaThreshold = 5.0f;
static std::unique_ptr<PlatformSensorReaderWinBase> Create();
PlatformSensorReaderWinrtMagnetometer();
~PlatformSensorReaderWinrtMagnetometer() override = default;
protected:
HRESULT OnReadingChangedCallback(
ABI::Windows::Devices::Sensors::IMagnetometer* sensor,
ABI::Windows::Devices::Sensors::IMagnetometerReadingChangedEventArgs*
reading_changed_args) override;
private:
double last_reported_x_ = 0.0;
double last_reported_y_ = 0.0;
double last_reported_z_ = 0.0;
PlatformSensorReaderWinrtMagnetometer(
const PlatformSensorReaderWinrtMagnetometer&) = delete;
PlatformSensorReaderWinrtMagnetometer& operator=(
const PlatformSensorReaderWinrtMagnetometer&) = delete;
};
class PlatformSensorReaderWinrtAbsOrientationEulerAngles final
: public PlatformSensorReaderWinrtBase<
RuntimeClass_Windows_Devices_Sensors_Inclinometer,
ABI::Windows::Devices::Sensors::IInclinometerStatics,
ABI::Windows::Devices::Sensors::IInclinometer,
Microsoft::WRL::Implements<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
ABI::Windows::Foundation::ITypedEventHandler<
ABI::Windows::Devices::Sensors::Inclinometer*,
ABI::Windows::Devices::Sensors::
InclinometerReadingChangedEventArgs*>,
Microsoft::WRL::FtmBase>,
ABI::Windows::Devices::Sensors::
IInclinometerReadingChangedEventArgs> {
public:
static constexpr double kDegreeThreshold = 5.0f;
static std::unique_ptr<PlatformSensorReaderWinBase> Create();
PlatformSensorReaderWinrtAbsOrientationEulerAngles();
~PlatformSensorReaderWinrtAbsOrientationEulerAngles() override = default;
protected:
HRESULT OnReadingChangedCallback(
ABI::Windows::Devices::Sensors::IInclinometer* sensor,
ABI::Windows::Devices::Sensors::IInclinometerReadingChangedEventArgs*
reading_changed_args) override;
private:
double last_reported_x_ = 0.0;
double last_reported_y_ = 0.0;
double last_reported_z_ = 0.0;
PlatformSensorReaderWinrtAbsOrientationEulerAngles(
const PlatformSensorReaderWinrtAbsOrientationEulerAngles&) = delete;
PlatformSensorReaderWinrtAbsOrientationEulerAngles& operator=(
const PlatformSensorReaderWinrtAbsOrientationEulerAngles&) = delete;
};
class PlatformSensorReaderWinrtAbsOrientationQuaternion final
: public PlatformSensorReaderWinrtBase<
RuntimeClass_Windows_Devices_Sensors_OrientationSensor,
ABI::Windows::Devices::Sensors::IOrientationSensorStatics,
ABI::Windows::Devices::Sensors::IOrientationSensor,
Microsoft::WRL::Implements<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
ABI::Windows::Foundation::ITypedEventHandler<
ABI::Windows::Devices::Sensors::OrientationSensor*,
ABI::Windows::Devices::Sensors::
OrientationSensorReadingChangedEventArgs*>,
Microsoft::WRL::FtmBase>,
ABI::Windows::Devices::Sensors::
IOrientationSensorReadingChangedEventArgs> {
public:
static constexpr double kRadianThreshold = gfx::DegToRad(5.0);
static std::unique_ptr<PlatformSensorReaderWinBase> Create();
PlatformSensorReaderWinrtAbsOrientationQuaternion();
~PlatformSensorReaderWinrtAbsOrientationQuaternion() override;
protected:
HRESULT OnReadingChangedCallback(
ABI::Windows::Devices::Sensors::IOrientationSensor* sensor,
ABI::Windows::Devices::Sensors::IOrientationSensorReadingChangedEventArgs*
reading_changed_args) override;
private:
SensorReading last_reported_sample{};
PlatformSensorReaderWinrtAbsOrientationQuaternion(
const PlatformSensorReaderWinrtAbsOrientationQuaternion&) = delete;
PlatformSensorReaderWinrtAbsOrientationQuaternion& operator=(
const PlatformSensorReaderWinrtAbsOrientationQuaternion&) = delete;
};
} // namespace device
#endif // SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_READER_WINRT_H_