0

Revert of [sensors] Ambient light sensor implementation for ChromeOS and Linux. (patchset id:1050001 of https://codereview.chromium.org/2370343002/ )

Reason for revert:
Causing a failure on Linux bot:

https://build.chromium.org/p/chromium/builders/Linux%20x64/builds/28030

Original issue's description:
> [sensors] Ambient light sensor implementation for ChromeOS and Linux.
>
> The patch introduces sensors implementation for
> ChromeOS/Linux platforms using ambient light sensor. Both
> platforms share the same code and require polling threads to
> be used.
>
> SensorDataIio structure is used to initialize a generic
> SensorReader, which is created only when sensor read files
> are found, and to create a concrete sensor, which takes
> an ownership of the SensorReader.
>
> A SensorReader must always be created on a polling thread,
> which is further used by a sensor to poll data. Each new
> sensor will have its own thread in order to avoid blocking of
> each other.
>
> As a temp solution to manage polling threads, which are not
> passed to new sensors, a manager thread is used. It kills a
> polling thread if a sensor cannot be created. In the future,
> the manager thread will evolve to a manager class that will
> manage finding new sensors attached to a system and notify a
> provider about that. The provider will have its own cache in
> order to avoid trying to find sensors each time after it
> fails to find a requested sensor. Once the manager notifies
> the provider about a new sensor, the provider updates its
> cache and starts to process requests for that type of sensor.
>
> Intent to Implement:
> https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/TkfdVqYAYiE/xLGN2b1-AAAJ
>
> BUG=606766
> CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_site_isolation
>
> Committed: https://crrev.com/de2d07084492be68633a47bae161cf9014ac88e2
> Cr-Commit-Position: refs/heads/master@{#429584}

TBR=reillyg@chromium.org,alexander.shalamov@intel.com,alexis.menard@intel.com,alexmos@chromium.org,mikhail.pozdnyakov@intel.com,rockot@chromium.org,timvolodine@chromium.org,maksim.sisov@intel.com
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=606766

Review-Url: https://codereview.chromium.org/2468283003
Cr-Commit-Position: refs/heads/master@{#429604}
This commit is contained in:
mathp
2016-11-03 09:02:54 -07:00
committed by Commit bot
parent 74836cf56a
commit ae21a578c5
17 changed files with 8 additions and 887 deletions

@ -2038,7 +2038,7 @@ const FeatureEntry kFeatureEntries[] = {
IDS_FLAGS_SAVEAS_MENU_LABEL_EXPERIMENT_DESCRIPTION, kOsDesktop,
SINGLE_VALUE_TYPE(switches::kEnableSaveAsMenuLabelExperiment)},
{"enable-generic-sensor", IDS_FLAGS_ENABLE_GENERIC_SENSOR_NAME,
IDS_FLAGS_ENABLE_GENERIC_SENSOR_DESCRIPTION, kOsAll,
IDS_FLAGS_ENABLE_GENERIC_SENSOR_DESCRIPTION, kOsAndroid | kOsMac | kOsWin,
FEATURE_VALUE_TYPE(features::kGenericSensor)},
{"expensive-background-timer-throttling",
IDS_FLAGS_EXPENSIVE_BACKGROUND_TIMER_THROTTLING_NAME,

@ -2212,8 +2212,7 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
#endif
if (base::FeatureList::IsEnabled(features::kGenericSensor)) {
GetInterfaceRegistry()->AddInterface(
base::Bind(&device::SensorProviderImpl::Create,
BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE)),
base::Bind(&device::SensorProviderImpl::Create),
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
}

@ -97,10 +97,6 @@ test("device_unittests") {
deps += [ "//dbus:test_support" ]
}
if (is_linux) {
sources += [ "generic_sensor/linux/sensor_reader_unittest.cc" ]
}
# HID and Serial:
# Android doesn't compile.
# Linux, requires udev.

@ -11,26 +11,18 @@ if (is_android) {
component("generic_sensor") {
output_name = "generic_sensor"
sources = [
"linux/platform_sensor_utils_linux.cc",
"linux/platform_sensor_utils_linux.h",
"linux/sensor_data_linux.cc",
"linux/sensor_data_linux.h",
"platform_sensor.cc",
"platform_sensor.h",
"platform_sensor_ambient_light_mac.cc",
"platform_sensor_ambient_light_mac.h",
"platform_sensor_android.cc",
"platform_sensor_android.h",
"platform_sensor_linux.cc",
"platform_sensor_linux.h",
"platform_sensor_provider.cc",
"platform_sensor_provider.h",
"platform_sensor_provider_android.cc",
"platform_sensor_provider_android.h",
"platform_sensor_provider_base.cc",
"platform_sensor_provider_base.h",
"platform_sensor_provider_linux.cc",
"platform_sensor_provider_linux.h",
"platform_sensor_provider_mac.cc",
"platform_sensor_provider_mac.h",
"platform_sensor_provider_win.cc",
@ -66,11 +58,9 @@ component("generic_sensor") {
deps += [ ":jni_headers" ]
}
if (is_mac || is_linux) {
deps += [ "//device/sensors/public/cpp" ]
}
if (is_mac) {
deps += [ "//device/sensors/public/cpp" ]
libs = [ "IOKit.framework" ]
}

@ -1,94 +0,0 @@
// Copyright 2016 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 "device/generic_sensor/linux/platform_sensor_utils_linux.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
#include "device/generic_sensor/linux/sensor_data_linux.h"
#include "device/generic_sensor/public/cpp/sensor_reading.h"
namespace device {
namespace {
bool InitSensorPaths(const std::vector<std::string>& input_names,
const char* base_path,
std::vector<base::FilePath>* sensor_paths) {
// Search the iio/devices directory for a subdirectory (eg "device0" or
// "iio:device0") that contains the specified input_name file (eg
// "in_illuminance_input" or "in_illuminance0_input").
base::FileEnumerator dir_enumerator(base::FilePath(base_path), false,
base::FileEnumerator::DIRECTORIES);
for (base::FilePath check_path = dir_enumerator.Next(); !check_path.empty();
check_path = dir_enumerator.Next()) {
for (auto const& file_name : input_names) {
base::FilePath full_path = check_path.Append(file_name);
if (base::PathExists(full_path)) {
sensor_paths->push_back(full_path);
return true;
}
}
}
return false;
}
bool GetSensorFilePaths(const SensorDataLinux& data,
std::vector<base::FilePath>* sensor_paths) {
DCHECK(sensor_paths->empty());
// Depending on a sensor, there can be up to three sets of files that need
// to be checked. If one of three files is not found, a sensor is
// treated as a non-existing one.
for (auto const& file_names : data.sensor_file_names) {
// Supply InitSensorPaths() with a set of files.
// Only one file from each set should be found.
if (!InitSensorPaths(file_names, data.base_path_sensor_linux, sensor_paths))
return false;
}
return true;
}
} // namespace
// static
std::unique_ptr<SensorReader> SensorReader::Create(
const SensorDataLinux& data) {
base::ThreadRestrictions::AssertIOAllowed();
std::vector<base::FilePath> sensor_paths;
if (!GetSensorFilePaths(data, &sensor_paths))
return nullptr;
return base::WrapUnique(new SensorReader(std::move(sensor_paths)));
}
SensorReader::SensorReader(std::vector<base::FilePath> sensor_paths)
: sensor_paths_(std::move(sensor_paths)) {
DCHECK(!sensor_paths_.empty());
}
SensorReader::~SensorReader() = default;
bool SensorReader::ReadSensorReading(SensorReading* reading) {
base::ThreadRestrictions::AssertIOAllowed();
SensorReading readings;
DCHECK_LE(sensor_paths_.size(), arraysize(readings.values));
int i = 0;
for (const auto& path : sensor_paths_) {
std::string new_read_value;
if (!base::ReadFileToString(path, &new_read_value))
return false;
double new_value = 0;
base::TrimWhitespaceASCII(new_read_value, base::TRIM_ALL, &new_read_value);
if (!base::StringToDouble(new_read_value, &new_value))
return false;
readings.values[i++] = new_value;
}
*reading = readings;
return true;
}
} // namespace device

@ -1,43 +0,0 @@
// Copyright 2016 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 DEVICE_GENERIC_SENSOR_LINUX_PLATFORM_SENSOR_UTILS_LINUX_H_
#define DEVICE_GENERIC_SENSOR_LINUX_PLATFORM_SENSOR_UTILS_LINUX_H_
#include "base/files/file_path.h"
#include "base/memory/ptr_util.h"
#include "device/generic_sensor/generic_sensor_export.h"
namespace device {
struct SensorDataLinux;
struct SensorReading;
// Generic reader class that reads sensors data from
// sensors files located in the base iio folder.
class DEVICE_GENERIC_SENSOR_EXPORT SensorReader {
public:
~SensorReader();
// Creates a new instance of SensorReader if sensor read files
// has been found and |sensor_paths_| are set.
static std::unique_ptr<SensorReader> Create(const SensorDataLinux& data);
// Reads sensor values into |*reading| from sensor files
// specified in |sensor_paths_|.
bool ReadSensorReading(SensorReading* reading);
private:
explicit SensorReader(std::vector<base::FilePath> sensor_paths);
// Contains paths to sensor files that are set when
// Create() is called.
const std::vector<base::FilePath> sensor_paths_;
DISALLOW_COPY_AND_ASSIGN(SensorReader);
};
} // namespace device
#endif // DEVICE_GENERIC_SENSOR_LINUX_PLATFORM_SENSOR_UTILS_LINUX_H_

@ -1,51 +0,0 @@
// Copyright 2016 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 "device/generic_sensor/linux/sensor_data_linux.h"
#include "device/sensors/public/cpp/device_sensors_consts.h"
namespace device {
namespace {
using mojom::SensorType;
const base::FilePath::CharType* kSensorsBasePath =
FILE_PATH_LITERAL("/sys/bus/iio/devices");
const std::string kAmbientLightFileNames[] = {
"in_illuminance0_input", "in_illuminance_input", "in_illuminance0_raw",
"in_illuminance_raw", "illuminance0_input"};
} // namespace
SensorDataLinux::SensorDataLinux() : base_path_sensor_linux(kSensorsBasePath) {}
SensorDataLinux::~SensorDataLinux() = default;
SensorDataLinux::SensorDataLinux(const SensorDataLinux& other) = default;
bool InitSensorData(SensorType type, SensorDataLinux* data) {
DCHECK(data);
switch (type) {
case SensorType::AMBIENT_LIGHT: {
std::vector<std::string> file_names(
kAmbientLightFileNames,
kAmbientLightFileNames + arraysize(kAmbientLightFileNames));
data->sensor_file_names.push_back(std::move(file_names));
data->reporting_mode = mojom::ReportingMode::ON_CHANGE;
data->default_configuration =
PlatformSensorConfiguration(kDefaultAmbientLightFrequencyHz);
break;
}
default: {
NOTIMPLEMENTED();
return false;
}
}
return true;
}
} // namespace device

@ -1,38 +0,0 @@
// Copyright 2016 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 DEVICE_GENERIC_SENSOR_LINUX_SENSOR_DATA_LINUX_H_
#define DEVICE_GENERIC_SENSOR_LINUX_SENSOR_DATA_LINUX_H_
#include "device/generic_sensor/generic_sensor_export.h"
#include "device/generic_sensor/public/interfaces/sensor.mojom.h"
namespace device {
// This structure represents a context that is used to
// create a type specific SensorReader and a concrete
// sensor that uses the SensorReader to read sensor
// data from files specified in the |sensor_file_names|.
struct DEVICE_GENERIC_SENSOR_EXPORT SensorDataLinux {
SensorDataLinux();
~SensorDataLinux();
SensorDataLinux(const SensorDataLinux& other);
// Provides a base path to all sensors.
const base::FilePath::CharType* base_path_sensor_linux;
// Provides an array of sensor file names to be searched for.
// Different sensors might have up to 3 different file name arrays.
// One file must be found from each array.
std::vector<std::vector<std::string>> sensor_file_names;
// Reporting mode of a sensor.
mojom::ReportingMode reporting_mode;
// Default configuration of a sensor.
PlatformSensorConfiguration default_configuration;
};
// Initializes a sensor type specific data.
bool InitSensorData(mojom::SensorType type, SensorDataLinux* data);
} // namespace device
#endif // DEVICE_GENERIC_SENSOR_LINUX_SENSOR_DATA_LINUX_H_

@ -1,260 +0,0 @@
// Copyright 2016 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 "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/strings/string_number_conversions.h"
#include "device/generic_sensor/linux/platform_sensor_utils_linux.h"
#include "device/generic_sensor/linux/sensor_data_linux.h"
#include "device/generic_sensor/public/cpp/sensor_reading.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace device {
namespace {
const base::FilePath::CharType* kDevice0Dir = FILE_PATH_LITERAL("device0");
const std::string kSensorFileNameTest1 = "sensor_data1";
const std::string kSensorFileNameTest2 = "sensor_data2";
const std::string kSensorFileNameTest3 = "sensor_data3";
const std::string kTestSensorFileNamesTest[3][5] = {
{
kSensorFileNameTest1, "sensor1_input", "sensor1_raw_input", "sensor1",
"sensor1_data_raw",
},
{
"sensor2", kSensorFileNameTest2, "sensor2_raw_input", "sensor2_input",
"sensor2_data_raw",
},
{
"sensor3", "sensor3_input", "sensor3_raw_input", "sensor3_data_raw",
kSensorFileNameTest3,
},
};
void CreateFile(const base::FilePath& file) {
EXPECT_EQ(base::WriteFile(file, nullptr, 0), 0);
}
void DeleteFile(const base::FilePath& file) {
EXPECT_TRUE(base::DeleteFile(file, false));
}
void WriteReadingFieldToFile(const base::FilePath& path, double value) {
const std::string str = base::DoubleToString(value);
int bytes_written = base::WriteFile(path, str.data(), str.size());
EXPECT_EQ(static_cast<size_t>(bytes_written), str.size());
}
} // namespace
class SensorReaderTest : public ::testing::Test {
public:
void SetUp() override {
ASSERT_TRUE(base_temp_dir_.CreateUniqueTempDir());
base_dir_ = base_temp_dir_.GetPath();
sensors_dir_ = base_dir_.Append(kDevice0Dir);
ASSERT_TRUE(base::CreateDirectory(sensors_dir_));
}
// Deletes base dir recursively.
void TearDown() override { ASSERT_TRUE(base_temp_dir_.Delete()); }
// Initialize SensorDataLinux with values for a sensor reader.
void InitSensorDataForTest(size_t rows, SensorDataLinux* data) {
// Corresponds to maximum values in SensorReading.
// We must read only from up to three files. Thus - 3 sets of files
// should be fill in here.
const size_t max_rows = 3;
if (rows > 3)
rows = max_rows;
data->base_path_sensor_linux = base_dir_.value().c_str();
for (size_t i = 0; i < rows; ++i) {
std::vector<std::string> file_names(
kTestSensorFileNamesTest[i],
kTestSensorFileNamesTest[i] + arraysize(kTestSensorFileNamesTest[i]));
data->sensor_file_names.push_back(std::move(file_names));
}
}
// Check SensorReading values are properly read.
void CheckSensorDataFields(const SensorReading& data,
double value1,
double value2,
double value3) {
EXPECT_EQ(value1, data.values[0]);
EXPECT_EQ(value2, data.values[1]);
EXPECT_EQ(value3, data.values[2]);
}
protected:
// Holds a path to a sensor dir that is located in |base_dir_|
base::FilePath sensors_dir_;
// Holds a path to a base dir.
base::FilePath base_dir_;
// Holds base dir where a sensor dir is located.
base::ScopedTempDir base_temp_dir_;
};
// Test a reader is not created if sensor read files
// do not exist.
TEST_F(SensorReaderTest, FileDoesNotExist) {
const char* kGiberishFiles[] = {"temp1", "temp2", "temp3", "temp4"};
const size_t rows = 3;
// Create some gibberish files that we are not interested in.
for (unsigned int i = 0; i < arraysize(kGiberishFiles); ++i) {
base::FilePath some_file = sensors_dir_.Append(kGiberishFiles[i]);
CreateFile(some_file);
}
SensorDataLinux sensor_data;
InitSensorDataForTest(rows, &sensor_data);
std::unique_ptr<SensorReader> reader = SensorReader::Create(sensor_data);
EXPECT_FALSE(reader);
}
// Simulate a sensor, which has only one file to be read from.
TEST_F(SensorReaderTest, ReadValueFromOneFile) {
const size_t rows = 1;
const double value1 = 20;
const double zero_value = 0;
// Create a test sensor file, which must be found to be read from.
base::FilePath temp_sensor_file = sensors_dir_.Append(kSensorFileNameTest1);
CreateFile(temp_sensor_file);
// Initialize sensor data for a reader.
SensorDataLinux sensor_data;
InitSensorDataForTest(rows, &sensor_data);
std::unique_ptr<SensorReader> reader = SensorReader::Create(sensor_data);
EXPECT_TRUE(reader);
// Write a value to the file.
WriteReadingFieldToFile(temp_sensor_file, value1);
// Fill SensorReading's first field with read value. Other fields must
// be 0.
SensorReading reading;
EXPECT_TRUE(reader->ReadSensorReading(&reading));
CheckSensorDataFields(reading, value1, zero_value, zero_value);
}
// Simulate a sensor, which has two files to be read from.
TEST_F(SensorReaderTest, ReadValuesFromTwoFiles) {
const size_t rows = 2;
const double value1 = 20;
const double value2 = 50;
const double zero_value = 0;
// Create a test sensor file, which must be found.
base::FilePath temp_sensor_file1 = sensors_dir_.Append(kSensorFileNameTest1);
CreateFile(temp_sensor_file1);
// Create another test sensor file, which must be found.
base::FilePath temp_sensor_file2 = sensors_dir_.Append(kSensorFileNameTest2);
CreateFile(temp_sensor_file2);
// Initialize sensor data for a reader.
SensorDataLinux sensor_data;
InitSensorDataForTest(rows, &sensor_data);
std::unique_ptr<SensorReader> reader = SensorReader::Create(sensor_data);
EXPECT_TRUE(reader);
// Write a value to the file.
WriteReadingFieldToFile(temp_sensor_file1, value1);
WriteReadingFieldToFile(temp_sensor_file2, value2);
// Fill SensorReading's two first fields with read value. Last field must
// be 0.
SensorReading reading;
EXPECT_TRUE(reader->ReadSensorReading(&reading));
CheckSensorDataFields(reading, value1, value2, zero_value);
}
// Simulate a sensor, which has the files to be read from.
// After read is successful, remove one of the files and try
// to read again. Reading must fail then.
TEST_F(SensorReaderTest, ReadValuesFromThreeFilesAndFail) {
const size_t rows = 4;
const double value1 = 20;
const double value2 = 50;
const double value3 = 80;
const double zero_value = 0;
// Create a test sensor file, which must be found.
base::FilePath temp_sensor_file1 = sensors_dir_.Append(kSensorFileNameTest1);
CreateFile(temp_sensor_file1);
// Create another test sensor file, which must be found.
base::FilePath temp_sensor_file2 = sensors_dir_.Append(kSensorFileNameTest2);
CreateFile(temp_sensor_file2);
// Create third test sensor file, which must be found.
base::FilePath temp_sensor_file3 = sensors_dir_.Append(kSensorFileNameTest3);
CreateFile(temp_sensor_file3);
// Initialize sensor data for a reader.
SensorDataLinux sensor_data;
InitSensorDataForTest(rows, &sensor_data);
std::unique_ptr<SensorReader> reader = SensorReader::Create(sensor_data);
EXPECT_TRUE(reader);
// Write a value to the file.
WriteReadingFieldToFile(temp_sensor_file1, value1);
WriteReadingFieldToFile(temp_sensor_file2, value2);
WriteReadingFieldToFile(temp_sensor_file3, value3);
// Fill SensorReading's values with data from files.
SensorReading reading;
EXPECT_TRUE(reader->ReadSensorReading(&reading));
CheckSensorDataFields(reading, value1, value2, value3);
SensorReading reading2;
DeleteFile(temp_sensor_file2);
EXPECT_FALSE(reader->ReadSensorReading(&reading2));
CheckSensorDataFields(reading2, zero_value, zero_value, zero_value);
}
// Fill in SensorDataLinux with three arrays of files that must be found
// before creating a sensor reader. If even one file is not found,
// a sensor reader must not be created. As soon as all the files are found,
// check the reader is created.
TEST_F(SensorReaderTest, SensorReadFilesDoNotExist) {
const size_t rows = 3;
// Create a test sensor file, which must be found. Other
// files will not be created and the test must fail to create a reader.
base::FilePath temp_sensor_file1 = sensors_dir_.Append(kSensorFileNameTest1);
CreateFile(temp_sensor_file1);
// Initialize sensor data for a reader.
SensorDataLinux sensor_data;
InitSensorDataForTest(rows, &sensor_data);
std::unique_ptr<SensorReader> reader = SensorReader::Create(sensor_data);
EXPECT_FALSE(reader);
// Create one more file. The reader mustn't be created as long as it
// expects three files to be found.
base::FilePath temp_sensor_file2 = sensors_dir_.Append(kSensorFileNameTest2);
CreateFile(temp_sensor_file2);
reader.reset();
reader = SensorReader::Create(sensor_data);
EXPECT_FALSE(reader);
// Create last file.
base::FilePath temp_sensor_file3 = sensors_dir_.Append(kSensorFileNameTest3);
CreateFile(temp_sensor_file3);
reader.reset();
reader = SensorReader::Create(sensor_data);
EXPECT_TRUE(reader);
}
} // namespace device

@ -1,114 +0,0 @@
// Copyright 2016 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 "device/generic_sensor/platform_sensor_linux.h"
#include "base/threading/thread.h"
#include "base/timer/timer.h"
#include "device/generic_sensor/linux/platform_sensor_utils_linux.h"
#include "device/generic_sensor/linux/sensor_data_linux.h"
namespace device {
namespace {
// Checks if at least one value has been changed.
bool HaveValuesChanged(const SensorReading& lhs, const SensorReading& rhs) {
return lhs.values[0] != rhs.values[0] || lhs.values[1] != rhs.values[1] ||
lhs.values[2] != rhs.values[2];
}
} // namespace
PlatformSensorLinux::PlatformSensorLinux(
mojom::SensorType type,
mojo::ScopedSharedBufferMapping mapping,
PlatformSensorProvider* provider,
const SensorDataLinux& data,
std::unique_ptr<SensorReader> sensor_reader,
scoped_refptr<base::SingleThreadTaskRunner> polling_thread_task_runner_)
: PlatformSensor(type, std::move(mapping), provider),
timer_(new base::RepeatingTimer()),
default_configuration_(data.default_configuration),
reporting_mode_(data.reporting_mode),
sensor_reader_(std::move(sensor_reader)),
polling_thread_task_runner_(polling_thread_task_runner_),
weak_factory_(this) {}
PlatformSensorLinux::~PlatformSensorLinux() {
polling_thread_task_runner_->DeleteSoon(FROM_HERE, timer_);
}
mojom::ReportingMode PlatformSensorLinux::GetReportingMode() {
return reporting_mode_;
}
bool PlatformSensorLinux::StartSensor(
const PlatformSensorConfiguration& configuration) {
DCHECK(task_runner_->BelongsToCurrentThread());
return polling_thread_task_runner_->PostTask(
FROM_HERE, base::Bind(&PlatformSensorLinux::BeginPoll,
weak_factory_.GetWeakPtr(), configuration));
}
void PlatformSensorLinux::StopSensor() {
DCHECK(task_runner_->BelongsToCurrentThread());
polling_thread_task_runner_->PostTask(
FROM_HERE, base::Bind(&PlatformSensorLinux::StopPoll, this));
}
bool PlatformSensorLinux::CheckSensorConfiguration(
const PlatformSensorConfiguration& configuration) {
DCHECK(task_runner_->BelongsToCurrentThread());
// TODO(maksims): make this sensor dependent.
// For example, in case of accelerometer, check current polling frequency
// exposed by iio driver.
return configuration.frequency() > 0 &&
configuration.frequency() <=
mojom::SensorConfiguration::kMaxAllowedFrequency;
}
PlatformSensorConfiguration PlatformSensorLinux::GetDefaultConfiguration() {
DCHECK(task_runner_->BelongsToCurrentThread());
return default_configuration_;
}
void PlatformSensorLinux::BeginPoll(
const PlatformSensorConfiguration& configuration) {
DCHECK(polling_thread_task_runner_->BelongsToCurrentThread());
timer_->Start(FROM_HERE, base::TimeDelta::FromMicroseconds(
base::Time::kMicrosecondsPerSecond /
configuration.frequency()),
this, &PlatformSensorLinux::PollForReadingData);
}
void PlatformSensorLinux::StopPoll() {
DCHECK(polling_thread_task_runner_->BelongsToCurrentThread());
timer_->Stop();
}
void PlatformSensorLinux::PollForReadingData() {
DCHECK(polling_thread_task_runner_->BelongsToCurrentThread());
SensorReading reading;
if (!sensor_reader_->ReadSensorReading(&reading)) {
task_runner_->PostTask(
FROM_HERE, base::Bind(&PlatformSensorLinux::NotifySensorError, this));
StopPoll();
return;
}
bool notifyNeeded = false;
if (GetReportingMode() == mojom::ReportingMode::ON_CHANGE) {
if (!HaveValuesChanged(reading, old_values_))
return;
notifyNeeded = true;
}
old_values_ = reading;
reading.timestamp = (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
UpdateSensorReading(reading, notifyNeeded);
}
} // namespace device

@ -1,75 +0,0 @@
// Copyright 2016 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 DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_LINUX_H_
#define DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_LINUX_H_
#include "device/generic_sensor/platform_sensor.h"
namespace base {
class RepeatingTimer;
class SingleThreadTaskRunner;
class Thread;
}
namespace device {
class SensorReader;
struct SensorDataLinux;
class PlatformSensorLinux : public PlatformSensor {
public:
PlatformSensorLinux(
mojom::SensorType type,
mojo::ScopedSharedBufferMapping mapping,
PlatformSensorProvider* provider,
const SensorDataLinux& data,
std::unique_ptr<SensorReader> sensor_reader,
scoped_refptr<base::SingleThreadTaskRunner> polling_thread_task_runner);
// Thread safe.
mojom::ReportingMode GetReportingMode() override;
protected:
~PlatformSensorLinux() override;
bool StartSensor(const PlatformSensorConfiguration& configuration) override;
void StopSensor() override;
bool CheckSensorConfiguration(
const PlatformSensorConfiguration& configuration) override;
PlatformSensorConfiguration GetDefaultConfiguration() override;
private:
void BeginPoll(const PlatformSensorConfiguration& configuration);
void StopPoll();
// Triggers |sensor_reader_| to read new sensor data.
// If new data is read, UpdateSensorReading() is called.
void PollForReadingData();
// Owned timer to be deleted on a polling thread.
base::RepeatingTimer* timer_;
const PlatformSensorConfiguration default_configuration_;
const mojom::ReportingMode reporting_mode_;
// A sensor reader that reads values from sensor files
// and stores them to a SensorReading structure.
std::unique_ptr<SensorReader> sensor_reader_;
// A task runner that is used to poll sensor data.
scoped_refptr<base::SingleThreadTaskRunner> polling_thread_task_runner_;
// Stores previously read values that are used to
// determine whether the recent values are changed
// and IPC can be notified that updates are available.
SensorReading old_values_;
base::WeakPtrFactory<PlatformSensorLinux> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PlatformSensorLinux);
};
} // namespace device
#endif // DEVICE_GENERIC_SENSOR_PLATFORM_SENSOR_LINUX_H_

@ -10,8 +10,6 @@
#include "device/generic_sensor/platform_sensor_provider_android.h"
#elif defined(OS_WIN)
#include "device/generic_sensor/platform_sensor_provider_win.h"
#elif defined(OS_LINUX)
#include "device/generic_sensor/platform_sensor_provider_linux.h"
#endif
namespace {
@ -38,8 +36,8 @@ PlatformSensorProvider* PlatformSensorProvider::GetInstance() {
return PlatformSensorProviderAndroid::GetInstance();
#elif defined(OS_WIN)
return PlatformSensorProviderWin::GetInstance();
#elif defined(OS_LINUX)
return PlatformSensorProviderLinux::GetInstance();
#else
return nullptr;
#endif
}

@ -35,11 +35,6 @@ class DEVICE_GENERIC_SENSOR_EXPORT PlatformSensorProviderBase
// alive; 'false' otherwise.
bool HasSensors() const;
// Implementations might want to override this in order to be able
// to read from sensor files. For example, linux does so.
virtual void SetFileTaskRunner(
scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) {}
protected:
PlatformSensorProviderBase();
virtual ~PlatformSensorProviderBase();

@ -1,102 +0,0 @@
// Copyright 2016 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 "device/generic_sensor/platform_sensor_provider_linux.h"
#include "base/memory/singleton.h"
#include "base/task_runner_util.h"
#include "base/threading/thread.h"
#include "device/generic_sensor/linux/platform_sensor_utils_linux.h"
#include "device/generic_sensor/linux/sensor_data_linux.h"
#include "device/generic_sensor/platform_sensor_linux.h"
namespace device {
// static
PlatformSensorProviderLinux* PlatformSensorProviderLinux::GetInstance() {
return base::Singleton<
PlatformSensorProviderLinux,
base::LeakySingletonTraits<PlatformSensorProviderLinux>>::get();
}
PlatformSensorProviderLinux::PlatformSensorProviderLinux() = default;
PlatformSensorProviderLinux::~PlatformSensorProviderLinux() = default;
void PlatformSensorProviderLinux::CreateSensorInternal(
mojom::SensorType type,
mojo::ScopedSharedBufferMapping mapping,
const CreateSensorCallback& callback) {
SensorDataLinux data;
if (!InitSensorData(type, &data)) {
callback.Run(nullptr);
return;
}
if (!polling_thread_)
polling_thread_.reset(new base::Thread("Sensor polling thread"));
if (!polling_thread_->IsRunning()) {
if (!polling_thread_->StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0))) {
callback.Run(nullptr);
return;
}
polling_thread_task_runner_ = polling_thread_->task_runner();
}
base::PostTaskAndReplyWithResult(
polling_thread_task_runner_.get(), FROM_HERE,
base::Bind(SensorReader::Create, data),
base::Bind(&PlatformSensorProviderLinux::SensorReaderFound,
base::Unretained(this), type, base::Passed(&mapping), callback,
data));
}
void PlatformSensorProviderLinux::SensorReaderFound(
mojom::SensorType type,
mojo::ScopedSharedBufferMapping mapping,
const PlatformSensorProviderBase::CreateSensorCallback& callback,
const SensorDataLinux& data,
std::unique_ptr<SensorReader> sensor_reader) {
DCHECK(CalledOnValidThread());
if (!sensor_reader) {
// If there are no sensors, stop polling thread.
if (!HasSensors())
AllSensorsRemoved();
callback.Run(nullptr);
return;
}
callback.Run(new PlatformSensorLinux(type, std::move(mapping), this, data,
std::move(sensor_reader),
polling_thread_task_runner_));
}
void PlatformSensorProviderLinux::SetFileTaskRunner(
scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) {
DCHECK(CalledOnValidThread());
if (!file_task_runner_)
file_task_runner_ = file_task_runner;
}
void PlatformSensorProviderLinux::AllSensorsRemoved() {
DCHECK(CalledOnValidThread());
DCHECK(file_task_runner_);
// When there are no sensors left, the polling thread must be stopped.
// Stop() can only be called on a different thread that allows io.
// Thus, browser's file thread is used for this purpose.
file_task_runner_->PostTask(
FROM_HERE, base::Bind(&PlatformSensorProviderLinux::StopPollingThread,
base::Unretained(this)));
}
void PlatformSensorProviderLinux::StopPollingThread() {
DCHECK(file_task_runner_);
DCHECK(file_task_runner_->BelongsToCurrentThread());
polling_thread_->Stop();
}
} // namespace device

@ -1,75 +0,0 @@
// Copyright 2016 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 DEVICE_GENERIC_SENSOR_PUBLIC_PLATFORM_SENSOR_PROVIDER_LINUX_H_
#define DEVICE_GENERIC_SENSOR_PUBLIC_PLATFORM_SENSOR_PROVIDER_LINUX_H_
#include "device/generic_sensor/platform_sensor_provider.h"
namespace base {
class Thread;
}
namespace device {
struct SensorDataLinux;
class SensorReader;
class PlatformSensorProviderLinux : public PlatformSensorProvider {
public:
PlatformSensorProviderLinux();
~PlatformSensorProviderLinux() override;
static PlatformSensorProviderLinux* GetInstance();
protected:
void CreateSensorInternal(mojom::SensorType type,
mojo::ScopedSharedBufferMapping mapping,
const CreateSensorCallback& callback) override;
void AllSensorsRemoved() override;
void SetFileTaskRunner(
scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) override;
private:
void SensorReaderFound(
mojom::SensorType type,
mojo::ScopedSharedBufferMapping mapping,
const PlatformSensorProviderBase::CreateSensorCallback& callback,
const SensorDataLinux& data,
std::unique_ptr<SensorReader> sensor_reader);
// Stops a polling thread if there are no sensors left. Must be called on
// a different that polling thread that allows io.
void StopPollingThread();
// TODO(maksims): make a separate class Manager that will
// create provide sensors with a polling task runner, check sensors existence
// and notify provider if a new sensor has appeared and it can be created if a
// request comes again for the same sensor.
// A use case example: a request for a sensor X comes, manager checks if the
// sensor exists on a platform and notifies a provider it is not found.
// The provider stores this information into its cache and doesn't try to
// create this specific sensor if a request comes. But when, for example,
// the sensor X is plugged into a usb port, the manager notices that and
// notifies the provider, which updates its cache and starts handling requests
// for the sensor X.
//
// Right now, this thread is used to find sensors files and poll data.
std::unique_ptr<base::Thread> polling_thread_;
// A task runner that is passed to polling sensors to poll data.
scoped_refptr<base::SingleThreadTaskRunner> polling_thread_task_runner_;
// Browser's file thread task runner passed from renderer. Used to
// stop a polling thread.
scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
DISALLOW_COPY_AND_ASSIGN(PlatformSensorProviderLinux);
};
} // namespace device
#endif // DEVICE_GENERIC_SENSOR_PUBLIC_PLATFORM_SENSOR_PROVIDER_LINUX_H_

@ -32,12 +32,9 @@ void NotifySensorCreated(
} // namespace
// static
void SensorProviderImpl::Create(
scoped_refptr<base::SingleThreadTaskRunner> file_task_runner,
mojom::SensorProviderRequest request) {
void SensorProviderImpl::Create(mojom::SensorProviderRequest request) {
PlatformSensorProvider* provider = PlatformSensorProvider::GetInstance();
if (provider) {
provider->SetFileTaskRunner(file_task_runner);
mojo::MakeStrongBinding(base::WrapUnique(new SensorProviderImpl(provider)),
std::move(request));
}

@ -20,9 +20,7 @@ class PlatformSensor;
class DEVICE_GENERIC_SENSOR_EXPORT SensorProviderImpl final
: public mojom::SensorProvider {
public:
static void Create(
scoped_refptr<base::SingleThreadTaskRunner> file_task_runner,
mojom::SensorProviderRequest request);
static void Create(mojom::SensorProviderRequest request);
~SensorProviderImpl() override;