Commit d016df33 authored by Wenjie Shi's avatar Wenjie Shi Committed by Commit Bot

Implement PlatformSensorReaderWinrt and

PlatformSensorReaderWinrtLightSensor

As the third step for implementing usage of the
Windows.Devices.Sensors WinRT API in Chromium, this CL:
  - Implements PlatformSensorReaderWinrtBase, the base class
    used to implement all of the Windows.Devices.Sensors based
    PlatformSensorReaders.
  - Implements PlatformSensorReaderWinrtLightSensor, the derived
    class of PlatformSensorReaderWinrtBase which adds support
    for light sensors using Windows.Devices.Sensors.LightSensor.
There is heavy use of templates since the Windows.Devices.Sensors
API is strongly typed.

Verified functionally by:
  - Built chrome.exe.
  - Ran chrome.exe on laptop with light sensor.
  - Navigated to website that polls the W3C light sensor:
    - Verified light sensor could be polled with WinRT feature
      flag on and off.
  - Ran chrome.exe on laptop without light sensor.
  - Navigated to website that polls the W3C light sensor:
    - Verified the light sensor failed to instantiate with the
      WinRT feature flag on and off.
Also ran new PlatformSensorReaderTestWinrt unit tests.

Bug: 958266
Change-Id: Iaa69d92f9e7923099653b4f554efc2852162b53f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1703327
Commit-Queue: Wenjie Shi <wensh@microsoft.com>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#683005}
parent b4581ba3
......@@ -87,6 +87,14 @@
#include "base/win/windows_types.h"
#endif
namespace ABI {
namespace Windows {
namespace Foundation {
struct DateTime;
} // namespace Foundation
} // namespace Windows
} // namespace ABI
namespace base {
class PlatformThreadHandle;
......@@ -126,7 +134,10 @@ class BASE_EXPORT TimeDelta {
static constexpr TimeDelta FromNanosecondsD(double ns);
#if defined(OS_WIN)
static TimeDelta FromQPCValue(LONGLONG qpc_value);
// TODO(crbug.com/989694): Avoid base::TimeDelta factory functions
// based on absolute time
static TimeDelta FromFileTime(FILETIME ft);
static TimeDelta FromWinrtDateTime(ABI::Windows::Foundation::DateTime dt);
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
static TimeDelta FromTimeSpec(const timespec& ts);
#endif
......@@ -188,6 +199,9 @@ class BASE_EXPORT TimeDelta {
#if defined(OS_FUCHSIA)
zx_duration_t ToZxDuration() const;
#endif
#if defined(OS_WIN)
ABI::Windows::Foundation::DateTime ToWinrtDateTime() const;
#endif
// Returns the time delta in some unit. The InXYZF versions return a floating
// point value. The InXYZ versions return a truncated value (aka rounded
......
......@@ -31,9 +31,9 @@
// will only increase the system-wide timer if we're not running on battery
// power.
#include "base/feature_list.h"
#include "base/time/time.h"
#include <windows.foundation.h>
#include <windows.h>
#include <mmsystem.h>
#include <stdint.h>
......@@ -41,6 +41,7 @@
#include "base/atomicops.h"
#include "base/bit_cast.h"
#include "base/cpu.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/synchronization/lock.h"
#include "base/threading/platform_thread.h"
......@@ -761,4 +762,16 @@ TimeDelta TimeDelta::FromFileTime(FILETIME ft) {
return TimeDelta::FromMicroseconds(FileTimeToMicroseconds(ft));
}
// static
TimeDelta TimeDelta::FromWinrtDateTime(ABI::Windows::Foundation::DateTime dt) {
// UniversalTime is 100 ns intervals since January 1, 1601 (UTC)
return TimeDelta::FromMicroseconds(dt.UniversalTime / 10);
}
ABI::Windows::Foundation::DateTime TimeDelta::ToWinrtDateTime() const {
ABI::Windows::Foundation::DateTime date_time;
date_time.UniversalTime = InMicroseconds() * 10;
return date_time;
}
} // namespace base
......@@ -7,6 +7,7 @@
#include <mmsystem.h>
#include <process.h>
#include <stdint.h>
#include <windows.foundation.h>
#include <cmath>
#include <limits>
......@@ -366,6 +367,32 @@ TEST(TimeDelta, FromFileTime) {
TimeDelta::FromFileTime(ft));
}
TEST(TimeDelta, FromWinrtDateTime) {
ABI::Windows::Foundation::DateTime dt;
dt.UniversalTime = 0;
// 0 UniversalTime = no delta since epoch.
EXPECT_EQ(TimeDelta(), TimeDelta::FromWinrtDateTime(dt));
dt.UniversalTime = 101;
// 101 * 100 ns ~= 10.1 microseconds.
EXPECT_EQ(TimeDelta::FromMicrosecondsD(10.1),
TimeDelta::FromWinrtDateTime(dt));
}
TEST(TimeDelta, ToWinrtDateTime) {
auto time_delta = TimeDelta::FromSeconds(0);
// No delta since epoch = 0 DateTime.
EXPECT_EQ(0, time_delta.ToWinrtDateTime().UniversalTime);
time_delta = TimeDelta::FromMicrosecondsD(10);
// 10 microseconds = 100 * 100 ns.
EXPECT_EQ(100, time_delta.ToWinrtDateTime().UniversalTime);
}
TEST(HighResolutionTimer, GetUsage) {
EXPECT_EQ(0.0, Time::GetHighResolutionTimerUsage());
......
......@@ -271,7 +271,10 @@ source_set("tests") {
}
if (is_win) {
sources += [ "generic_sensor/platform_sensor_provider_winrt_unittest.cc" ]
sources += [
"generic_sensor/platform_sensor_provider_winrt_unittest.cc",
"generic_sensor/platform_sensor_reader_winrt_unittests.cc",
]
# Needed for "generic_sensor/platform_sensor_and_provider_unittest_win.cc"
libs = [
......
......@@ -5,8 +5,16 @@
#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"
namespace device {
......@@ -22,6 +30,117 @@ class PlatformSensorReaderWinrtFactory {
mojom::SensorType type);
};
enum SensorWinrtCreateFailure {
kOk = 0,
kErrorISensorWinrtStaticsActivationFailed = 1,
kErrorGetDefaultSensorFailed = 2,
kErrorDefaultSensorNull = 3,
kErrorGetMinReportIntervalFailed = 4
};
// 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.
template <wchar_t const* runtime_class_id,
class ISensorWinrtStatics,
class ISensorWinrtClass,
class ISensorReadingChangedHandler,
class ISensorReadingChangedEventArgs>
class PlatformSensorReaderWinrtBase : public PlatformSensorReaderWinBase {
public:
using GetSensorFactoryFunctor =
base::Callback<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 InitForTests(GetSensorFactoryFunctor get_sensor_factory_callback) {
get_sensor_factory_callback_ = get_sensor_factory_callback;
}
SensorWinrtCreateFailure 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();
// 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_;
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:
static std::unique_ptr<PlatformSensorReaderWinBase> Create();
PlatformSensorReaderWinrtLightSensor() = default;
~PlatformSensorReaderWinrtLightSensor() override = default;
protected:
HRESULT OnReadingChangedCallback(
ABI::Windows::Devices::Sensors::ILightSensor* sensor,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs*
reading_changed_args) override;
private:
PlatformSensorReaderWinrtLightSensor(
const PlatformSensorReaderWinrtLightSensor&) = delete;
PlatformSensorReaderWinrtLightSensor& operator=(
const PlatformSensorReaderWinrtLightSensor&) = delete;
};
} // namespace device
#endif // SERVICES_DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_READER_WINRT_H_
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment