| Index: device/sensor/sensor_service.cc
 | 
| diff --git a/device/sensor/sensor_service.cc b/device/sensor/sensor_service.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..bc4597bac777b685626766b99df57ddec15e8034
 | 
| --- /dev/null
 | 
| +++ b/device/sensor/sensor_service.cc
 | 
| @@ -0,0 +1,93 @@
 | 
| +// 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/sensor/sensor_service.h"
 | 
| +
 | 
| +#include <utility>
 | 
| +
 | 
| +#include "base/bind.h"
 | 
| +#include "base/message_loop/message_loop.h"
 | 
| +#include "base/single_thread_task_runner.h"
 | 
| +#include "device/sensor/sensor_impl.h"
 | 
| +#include "device/sensor/sensor_manager.h"
 | 
| +
 | 
| +namespace device {
 | 
| +
 | 
| +SensorService::SensorService()
 | 
| +    : main_thread_task_runner_(base::MessageLoop::current()->task_runner()),
 | 
| +      update_callback_(
 | 
| +          base::Bind(&SensorService::NotifyConsumers, base::Unretained(this))),
 | 
| +      reading_updated_(false),
 | 
| +      is_shutdown_(false) {
 | 
| +  callback_list_.set_removal_callback(
 | 
| +      base::Bind(&SensorService::ConsumersChanged, base::Unretained(this)));
 | 
| +}
 | 
| +
 | 
| +SensorService::~SensorService() {}
 | 
| +
 | 
| +SensorService* SensorService::GetInstance() {
 | 
| +  return base::Singleton<SensorService,
 | 
| +                         base::LeakySingletonTraits<SensorService>>::get();
 | 
| +}
 | 
| +
 | 
| +scoped_ptr<SensorService::SensorUpdateSubscription> SensorService::AddCallback(
 | 
| +    const SensorUpdateCallback& callback) {
 | 
| +  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
 | 
| +  DCHECK(!is_shutdown_);
 | 
| +
 | 
| +  if (!sensor_fetcher_)
 | 
| +    sensor_fetcher_ = SensorManager::Create(update_callback_);
 | 
| +
 | 
| +  if (callback_list_.empty()) {
 | 
| +    bool success = sensor_fetcher_->StartListeningSensorChange();
 | 
| +    // On failure pass the default values back.
 | 
| +    if (!success)
 | 
| +      callback.Run(AmbientLightSensorReading());
 | 
| +  }
 | 
| +
 | 
| +  if (reading_updated_) {
 | 
| +    // Send recent reading to the new callback if already available.
 | 
| +    callback.Run(reading_);
 | 
| +  }
 | 
| +
 | 
| +  return callback_list_.Add(callback);
 | 
| +}
 | 
| +
 | 
| +void SensorService::ConsumersChanged() {
 | 
| +  if (is_shutdown_)
 | 
| +    return;
 | 
| +
 | 
| +  if (callback_list_.empty()) {
 | 
| +    sensor_fetcher_->StopListeningSensorChange();
 | 
| +    reading_updated_ = false;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void SensorService::NotifyConsumers(const AmbientLightSensorReading& reading) {
 | 
| +  DCHECK(!is_shutdown_);
 | 
| +
 | 
| +  main_thread_task_runner_->PostTask(
 | 
| +      FROM_HERE, base::Bind(&SensorService::NotifyConsumersOnMainThread,
 | 
| +                            base::Unretained(this), reading));
 | 
| +}
 | 
| +
 | 
| +void SensorService::NotifyConsumersOnMainThread(
 | 
| +    const AmbientLightSensorReading& reading) {
 | 
| +  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
 | 
| +  if (callback_list_.empty())
 | 
| +    return;
 | 
| +
 | 
| +  reading_ = reading;
 | 
| +  reading_updated_ = true;
 | 
| +  callback_list_.Notify(reading_);
 | 
| +}
 | 
| +
 | 
| +void SensorService::Shutdown() {
 | 
| +  if (!callback_list_.empty())
 | 
| +    sensor_fetcher_->StopListeningSensorChange();
 | 
| +  sensor_fetcher_.reset();
 | 
| +  is_shutdown_ = true;
 | 
| +}
 | 
| +
 | 
| +}  // namespace device
 | 
| 
 |