Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1108)

Unified Diff: services/device/sensors/device_sensor_service_unittest.cc

Issue 2812223006: Replace device_sensor browsertest by service unittest. (Closed)
Patch Set: eliminate "unreachable code" warning. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « services/device/sensors/OWNERS ('k') | services/device/unittest_manifest.json » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: services/device/sensors/device_sensor_service_unittest.cc
diff --git a/services/device/sensors/device_sensor_service_unittest.cc b/services/device/sensors/device_sensor_service_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..59647393fda92d937c80cffef65c424e685b81ca
--- /dev/null
+++ b/services/device/sensors/device_sensor_service_unittest.cc
@@ -0,0 +1,530 @@
+// Copyright 2014 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/sensors/device_sensor_service.h"
+#include <limits>
+#include "base/memory/singleton.h"
+#include "base/run_loop.h"
+#include "base/threading/platform_thread.h"
+#include "build/build_config.h"
+#include "device/sensors/data_fetcher_shared_memory.h"
+#include "device/sensors/public/cpp/device_light_data.h"
+#include "device/sensors/public/cpp/device_light_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_motion_hardware_buffer.h"
+#include "device/sensors/public/cpp/device_orientation_hardware_buffer.h"
+#include "device/sensors/public/cpp/motion_data.h"
+#include "device/sensors/public/cpp/orientation_data.h"
+#include "device/sensors/public/cpp/shared_memory_seqlock_reader.h"
+#include "device/sensors/public/interfaces/light.mojom.h"
+#include "device/sensors/public/interfaces/motion.mojom.h"
+#include "device/sensors/public/interfaces/orientation.mojom.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "services/device/device_service_test_base.h"
+#include "services/device/public/interfaces/constants.mojom.h"
+
+namespace device {
+
+namespace {
+
+class FakeDataFetcher : public device::DataFetcherSharedMemory {
+ public:
+ FakeDataFetcher()
+ : main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ sensor_data_available_(true) {}
+ ~FakeDataFetcher() override {}
+
+ void SetPollingStoppedCallback(base::Closure polling_stopped_callback) {
+ polling_stopped_callback_ = polling_stopped_callback;
+ }
+
+ bool Start(device::ConsumerType consumer_type, void* buffer) override {
+ EXPECT_TRUE(buffer);
+
+ switch (consumer_type) {
+ case device::CONSUMER_TYPE_MOTION: {
+ device::DeviceMotionHardwareBuffer* motion_buffer =
+ static_cast<device::DeviceMotionHardwareBuffer*>(buffer);
+ if (sensor_data_available_) {
+ is_motion_polling_started_ = true;
+ UpdateMotion(motion_buffer);
+ }
+ SetMotionBufferReady(motion_buffer);
+ return true;
+ }
+ case device::CONSUMER_TYPE_ORIENTATION: {
+ device::DeviceOrientationHardwareBuffer* orientation_buffer =
+ static_cast<device::DeviceOrientationHardwareBuffer*>(buffer);
+ if (sensor_data_available_) {
+ is_orientation_polling_started_ = true;
+ UpdateOrientation(orientation_buffer);
+ }
+ SetOrientationBufferReady(orientation_buffer);
+ return true;
+ }
+ case device::CONSUMER_TYPE_ORIENTATION_ABSOLUTE: {
+ device::DeviceOrientationHardwareBuffer* orientation_buffer =
+ static_cast<device::DeviceOrientationHardwareBuffer*>(buffer);
+ if (sensor_data_available_) {
+ is_orientation_absolute_polling_started_ = true;
+ UpdateOrientationAbsolute(orientation_buffer);
+ }
+ SetOrientationBufferReady(orientation_buffer);
+ return true;
+ }
+ case device::CONSUMER_TYPE_LIGHT: {
+ device::DeviceLightHardwareBuffer* light_buffer =
+ static_cast<device::DeviceLightHardwareBuffer*>(buffer);
+ is_light_polling_started_ = true;
+ UpdateLight(light_buffer,
+ sensor_data_available_
+ ? 100
+ : std::numeric_limits<double>::infinity());
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ bool Stop(device::ConsumerType consumer_type) override {
+ switch (consumer_type) {
+ case device::CONSUMER_TYPE_MOTION: {
+ is_motion_polling_started_ = false;
+ main_thread_task_runner_->PostTask(FROM_HERE,
+ polling_stopped_callback_);
+ return true;
+ }
+ case device::CONSUMER_TYPE_ORIENTATION: {
+ is_orientation_polling_started_ = false;
+ main_thread_task_runner_->PostTask(FROM_HERE,
+ polling_stopped_callback_);
+ return true;
+ }
+ case device::CONSUMER_TYPE_ORIENTATION_ABSOLUTE: {
+ is_orientation_absolute_polling_started_ = false;
+ main_thread_task_runner_->PostTask(FROM_HERE,
+ polling_stopped_callback_);
+ return true;
+ }
+ case device::CONSUMER_TYPE_LIGHT: {
+ is_light_polling_started_ = false;
+ main_thread_task_runner_->PostTask(FROM_HERE,
+ polling_stopped_callback_);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ void Fetch(unsigned consumer_bitmask) override {
+ FAIL() << "fetch should not be called";
+ }
+
+ FetcherType GetType() const override { return FETCHER_TYPE_DEFAULT; }
+
+ void SetSensorDataAvailable(bool available) {
+ sensor_data_available_ = available;
+ }
+
+ bool IsLightPollingStarted() { return is_light_polling_started_; }
+
+ bool IsMotionPollingStarted() { return is_motion_polling_started_; }
+
+ bool IsOrientationAbsolutePollingStarted() {
+ return is_orientation_absolute_polling_started_;
+ }
+
+ bool IsOrientationPollingStarted() { return is_orientation_polling_started_; }
+
+ void SetMotionBufferReady(device::DeviceMotionHardwareBuffer* buffer) {
+ buffer->seqlock.WriteBegin();
+ buffer->data.all_available_sensors_are_active = true;
+ buffer->seqlock.WriteEnd();
+ }
+
+ void SetOrientationBufferReady(
+ device::DeviceOrientationHardwareBuffer* buffer) {
+ buffer->seqlock.WriteBegin();
+ buffer->data.all_available_sensors_are_active = true;
+ buffer->seqlock.WriteEnd();
+ }
+
+ void UpdateMotion(device::DeviceMotionHardwareBuffer* buffer) {
+ buffer->seqlock.WriteBegin();
+ buffer->data.acceleration_x = 1;
+ buffer->data.has_acceleration_x = true;
+ buffer->data.acceleration_y = 2;
+ buffer->data.has_acceleration_y = true;
+ buffer->data.acceleration_z = 3;
+ buffer->data.has_acceleration_z = true;
+
+ buffer->data.acceleration_including_gravity_x = 4;
+ buffer->data.has_acceleration_including_gravity_x = true;
+ buffer->data.acceleration_including_gravity_y = 5;
+ buffer->data.has_acceleration_including_gravity_y = true;
+ buffer->data.acceleration_including_gravity_z = 6;
+ buffer->data.has_acceleration_including_gravity_z = true;
+
+ buffer->data.rotation_rate_alpha = 7;
+ buffer->data.has_rotation_rate_alpha = true;
+ buffer->data.rotation_rate_beta = 8;
+ buffer->data.has_rotation_rate_beta = true;
+ buffer->data.rotation_rate_gamma = 9;
+ buffer->data.has_rotation_rate_gamma = true;
+
+ buffer->data.interval = 100;
+ buffer->data.all_available_sensors_are_active = true;
+ buffer->seqlock.WriteEnd();
+ }
+
+ void UpdateOrientation(device::DeviceOrientationHardwareBuffer* buffer) {
+ buffer->seqlock.WriteBegin();
+ buffer->data.alpha = 1;
+ buffer->data.has_alpha = true;
+ buffer->data.beta = 2;
+ buffer->data.has_beta = true;
+ buffer->data.gamma = 3;
+ buffer->data.has_gamma = true;
+ buffer->data.all_available_sensors_are_active = true;
+ buffer->seqlock.WriteEnd();
+ }
+
+ void UpdateOrientationAbsolute(
+ device::DeviceOrientationHardwareBuffer* buffer) {
+ buffer->seqlock.WriteBegin();
+ buffer->data.alpha = 4;
+ buffer->data.has_alpha = true;
+ buffer->data.beta = 5;
+ buffer->data.has_beta = true;
+ buffer->data.gamma = 6;
+ buffer->data.has_gamma = true;
+ buffer->data.absolute = true;
+ buffer->data.all_available_sensors_are_active = true;
+ buffer->seqlock.WriteEnd();
+ }
+
+ void UpdateLight(device::DeviceLightHardwareBuffer* buffer, double lux) {
+ buffer->seqlock.WriteBegin();
+ buffer->data.value = lux;
+ buffer->seqlock.WriteEnd();
+ }
+
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
+
+ // |polling_stopped_callback_| should be run on the main thread.
+ base::Closure polling_stopped_callback_;
+
+ bool sensor_data_available_;
+ bool is_light_polling_started_;
+ bool is_motion_polling_started_;
+ bool is_orientation_absolute_polling_started_;
+ bool is_orientation_polling_started_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FakeDataFetcher);
+};
+
+class DeviceSensorServiceTest : public DeviceServiceTestBase {
+ public:
+ DeviceSensorServiceTest() : fetcher_(nullptr) {}
+
+ void SetUpFetcher() {
+ device::DeviceSensorService::GetInstance()->SetDataFetcherForTesting(
+ fetcher_);
+ }
+
+ void GetLightData(device::DeviceLightData* data,
+ mojo::ScopedSharedBufferHandle buffer_handle) {
+ base::SharedMemoryHandle handle;
+ MojoResult result = mojo::UnwrapSharedMemoryHandle(
+ std::move(buffer_handle), &handle, nullptr, nullptr);
+ DCHECK_EQ(MOJO_RESULT_OK, result);
+
+ if (!light_reader_) {
+ light_reader_ = base::MakeUnique<
+ SharedMemorySeqLockReader<device::DeviceLightData>>();
+ }
+ EXPECT_TRUE(light_reader_->Initialize(handle));
+ EXPECT_TRUE(light_reader_->GetLatestData(data));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ runloop_->QuitClosure());
+ }
+
+ void GetMotionData(device::MotionData* data,
+ mojo::ScopedSharedBufferHandle buffer_handle) {
+ base::SharedMemoryHandle handle;
+ MojoResult result = mojo::UnwrapSharedMemoryHandle(
+ std::move(buffer_handle), &handle, nullptr, nullptr);
+ DCHECK_EQ(MOJO_RESULT_OK, result);
+
+ if (!motion_reader_) {
+ motion_reader_ =
+ base::MakeUnique<SharedMemorySeqLockReader<device::MotionData>>();
+ }
+ EXPECT_TRUE(motion_reader_->Initialize(handle));
+ EXPECT_TRUE(motion_reader_->GetLatestData(data));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ runloop_->QuitClosure());
+ }
+
+ void GetOrientationData(device::OrientationData* data,
+ mojo::ScopedSharedBufferHandle buffer_handle) {
+ base::SharedMemoryHandle handle;
+ MojoResult result = mojo::UnwrapSharedMemoryHandle(
+ std::move(buffer_handle), &handle, nullptr, nullptr);
+ DCHECK_EQ(MOJO_RESULT_OK, result);
+
+ if (!orientation_reader_) {
+ orientation_reader_ = base::MakeUnique<
+ SharedMemorySeqLockReader<device::OrientationData>>();
+ }
+ EXPECT_TRUE(orientation_reader_->Initialize(handle));
+ EXPECT_TRUE(orientation_reader_->GetLatestData(data));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ runloop_->QuitClosure());
+ }
+
+ FakeDataFetcher* fetcher_;
+
+ // NOTE: These can only be initialized once the main thread has been created
+ // and so must be pointers instead of plain objects.
+ std::unique_ptr<base::RunLoop> runloop_;
+ std::unique_ptr<base::RunLoop> polling_stopped_runloop_;
+
+ protected:
+ void SetUp() override {
+ DeviceServiceTestBase::SetUp();
+
+ // Initialize the RunLoops for tests.
+ runloop_.reset(new base::RunLoop());
+ polling_stopped_runloop_.reset(new base::RunLoop());
+
+ fetcher_ = new FakeDataFetcher();
+ fetcher_->SetPollingStoppedCallback(
+ polling_stopped_runloop_->QuitClosure());
+
+ // On non-Android platform, SetUpFetcher() should be called in IO thread,
+ // because the IO thread is actually main thread in service unittest, so
+ // it is ok call it directly. See comments in
+ // DeviceServiceTestBase::CreateService() why the IO thread is simulated by
+ // main thread.
+ SetUpFetcher();
+ }
+
+ mojom::LightSensorPtr light_sensor_;
+ mojom::MotionSensorPtr motion_sensor_;
+ mojom::OrientationAbsoluteSensorPtr orientation_absolute_sensor_;
+ mojom::OrientationSensorPtr orientation_sensor_;
+
+ private:
+ std::unique_ptr<SharedMemorySeqLockReader<device::DeviceLightData>>
+ light_reader_;
+ std::unique_ptr<SharedMemorySeqLockReader<device::MotionData>> motion_reader_;
+ std::unique_ptr<SharedMemorySeqLockReader<device::OrientationData>>
+ orientation_reader_;
+};
+
+TEST_F(DeviceSensorServiceTest, OrientationTest) {
+ device::OrientationData data;
+ memset(&data, 0, sizeof(device::OrientationData));
+ connector()->BindInterface(mojom::kServiceName, &orientation_sensor_);
+ orientation_sensor_->StartPolling(
+ base::Bind(&DeviceSensorServiceTest::GetOrientationData,
+ base::Unretained(this), &data));
+ runloop_->Run();
+ EXPECT_TRUE(fetcher_->IsOrientationPollingStarted());
+ EXPECT_EQ(1, data.alpha);
+ EXPECT_TRUE(data.has_alpha);
+ EXPECT_EQ(2, data.beta);
+ EXPECT_TRUE(data.has_beta);
+ EXPECT_EQ(3, data.gamma);
+ EXPECT_TRUE(data.has_gamma);
+ EXPECT_TRUE(data.all_available_sensors_are_active);
+
+ orientation_sensor_->StopPolling();
+ polling_stopped_runloop_->Run();
+ EXPECT_FALSE(fetcher_->IsOrientationPollingStarted());
+}
+
+TEST_F(DeviceSensorServiceTest, OrientationAbsoluteTest) {
+ device::OrientationData data;
+ memset(&data, 0, sizeof(device::OrientationData));
+ connector()->BindInterface(mojom::kServiceName,
+ &orientation_absolute_sensor_);
+ orientation_absolute_sensor_->StartPolling(
+ base::Bind(&DeviceSensorServiceTest::GetOrientationData,
+ base::Unretained(this), &data));
+ runloop_->Run();
+
+ EXPECT_TRUE(fetcher_->IsOrientationAbsolutePollingStarted());
+ EXPECT_EQ(4, data.alpha);
+ EXPECT_TRUE(data.has_alpha);
+ EXPECT_EQ(5, data.beta);
+ EXPECT_TRUE(data.has_beta);
+ EXPECT_EQ(6, data.gamma);
+ EXPECT_TRUE(data.has_gamma);
+ EXPECT_TRUE(data.all_available_sensors_are_active);
+
+ orientation_absolute_sensor_->StopPolling();
+ polling_stopped_runloop_->Run();
+ EXPECT_FALSE(fetcher_->IsOrientationAbsolutePollingStarted());
+}
+
+TEST_F(DeviceSensorServiceTest, LightTest) {
+ device::DeviceLightData data;
+ memset(&data, 0, sizeof(device::DeviceLightData));
+ connector()->BindInterface(mojom::kServiceName, &light_sensor_);
+ light_sensor_->StartPolling(base::Bind(&DeviceSensorServiceTest::GetLightData,
+ base::Unretained(this), &data));
+ runloop_->Run();
+
+ EXPECT_TRUE(fetcher_->IsLightPollingStarted());
+ EXPECT_EQ(100, data.value);
+
+ light_sensor_->StopPolling();
+ polling_stopped_runloop_->Run();
+ EXPECT_FALSE(fetcher_->IsLightPollingStarted());
+}
+
+TEST_F(DeviceSensorServiceTest, MotionTest) {
+ device::MotionData data;
+ memset(&data, 0, sizeof(device::MotionData));
+ connector()->BindInterface(mojom::kServiceName, &motion_sensor_);
+ motion_sensor_->StartPolling(base::Bind(
+ &DeviceSensorServiceTest::GetMotionData, base::Unretained(this), &data));
+ runloop_->Run();
+
+ EXPECT_TRUE(fetcher_->IsMotionPollingStarted());
+ EXPECT_EQ(1, data.acceleration_x);
+ EXPECT_TRUE(data.has_acceleration_x);
+ EXPECT_EQ(2, data.acceleration_y);
+ EXPECT_TRUE(data.has_acceleration_y);
+ EXPECT_EQ(3, data.acceleration_z);
+ EXPECT_TRUE(data.has_acceleration_z);
+ EXPECT_EQ(4, data.acceleration_including_gravity_x);
+ EXPECT_TRUE(data.has_acceleration_including_gravity_x);
+ EXPECT_EQ(5, data.acceleration_including_gravity_y);
+ EXPECT_TRUE(data.has_acceleration_including_gravity_y);
+ EXPECT_EQ(6, data.acceleration_including_gravity_z);
+ EXPECT_TRUE(data.has_acceleration_including_gravity_z);
+ EXPECT_EQ(7, data.rotation_rate_alpha);
+ EXPECT_TRUE(data.has_rotation_rate_alpha);
+ EXPECT_EQ(8, data.rotation_rate_beta);
+ EXPECT_TRUE(data.has_rotation_rate_beta);
+ EXPECT_EQ(9, data.rotation_rate_gamma);
+ EXPECT_TRUE(data.has_rotation_rate_gamma);
+ EXPECT_EQ(100, data.interval);
+ EXPECT_TRUE(data.all_available_sensors_are_active);
+
+ motion_sensor_->StopPolling();
+ polling_stopped_runloop_->Run();
+ EXPECT_FALSE(fetcher_->IsMotionPollingStarted());
+}
+
+TEST_F(DeviceSensorServiceTest, LightOneOffInfintyTest) {
+ fetcher_->SetSensorDataAvailable(false);
+ device::DeviceLightData data;
+ memset(&data, 0, sizeof(device::DeviceLightData));
+ connector()->BindInterface(mojom::kServiceName, &light_sensor_);
+ light_sensor_->StartPolling(base::Bind(&DeviceSensorServiceTest::GetLightData,
+ base::Unretained(this), &data));
+ runloop_->Run();
+
+ EXPECT_TRUE(fetcher_->IsLightPollingStarted());
+ EXPECT_EQ(std::numeric_limits<double>::infinity(), data.value);
+
+ light_sensor_->StopPolling();
+ polling_stopped_runloop_->Run();
+ EXPECT_FALSE(fetcher_->IsLightPollingStarted());
+}
+
+TEST_F(DeviceSensorServiceTest, OrientationNullTest) {
+ fetcher_->SetSensorDataAvailable(false);
+ device::OrientationData data;
+ memset(&data, 0, sizeof(device::OrientationData));
+ connector()->BindInterface(mojom::kServiceName, &orientation_sensor_);
+ orientation_sensor_->StartPolling(
+ base::Bind(&DeviceSensorServiceTest::GetOrientationData,
+ base::Unretained(this), &data));
+ runloop_->Run();
+
+ EXPECT_FALSE(fetcher_->IsOrientationPollingStarted());
+ EXPECT_EQ(0, data.alpha);
+ EXPECT_FALSE(data.has_alpha);
+ EXPECT_EQ(0, data.beta);
+ EXPECT_FALSE(data.has_beta);
+ EXPECT_EQ(0, data.gamma);
+ EXPECT_FALSE(data.has_gamma);
+ EXPECT_TRUE(data.all_available_sensors_are_active);
+
+ orientation_sensor_->StopPolling();
+ polling_stopped_runloop_->Run();
+ EXPECT_FALSE(fetcher_->IsOrientationPollingStarted());
+}
+
+TEST_F(DeviceSensorServiceTest, OrientationAbsoluteNullTest) {
+ fetcher_->SetSensorDataAvailable(false);
+ device::OrientationData data;
+ memset(&data, 0, sizeof(device::OrientationData));
+ connector()->BindInterface(mojom::kServiceName,
+ &orientation_absolute_sensor_);
+ orientation_absolute_sensor_->StartPolling(
+ base::Bind(&DeviceSensorServiceTest::GetOrientationData,
+ base::Unretained(this), &data));
+ runloop_->Run();
+
+ EXPECT_FALSE(fetcher_->IsOrientationAbsolutePollingStarted());
+ EXPECT_EQ(0, data.alpha);
+ EXPECT_FALSE(data.has_alpha);
+ EXPECT_EQ(0, data.beta);
+ EXPECT_FALSE(data.has_beta);
+ EXPECT_EQ(0, data.gamma);
+ EXPECT_FALSE(data.has_gamma);
+ EXPECT_TRUE(data.all_available_sensors_are_active);
+
+ orientation_absolute_sensor_->StopPolling();
+ polling_stopped_runloop_->Run();
+ EXPECT_FALSE(fetcher_->IsOrientationAbsolutePollingStarted());
+}
+
+TEST_F(DeviceSensorServiceTest, MotionNullTest) {
+ fetcher_->SetSensorDataAvailable(false);
+ device::MotionData data;
+ memset(&data, 0, sizeof(device::MotionData));
+ connector()->BindInterface(mojom::kServiceName, &motion_sensor_);
+ motion_sensor_->StartPolling(base::Bind(
+ &DeviceSensorServiceTest::GetMotionData, base::Unretained(this), &data));
+ runloop_->Run();
+
+ EXPECT_FALSE(fetcher_->IsMotionPollingStarted());
+ EXPECT_EQ(0, data.acceleration_x);
+ EXPECT_FALSE(data.has_acceleration_x);
+ EXPECT_EQ(0, data.acceleration_y);
+ EXPECT_FALSE(data.has_acceleration_y);
+ EXPECT_EQ(0, data.acceleration_z);
+ EXPECT_FALSE(data.has_acceleration_z);
+ EXPECT_EQ(0, data.acceleration_including_gravity_x);
+ EXPECT_FALSE(data.has_acceleration_including_gravity_x);
+ EXPECT_EQ(0, data.acceleration_including_gravity_y);
+ EXPECT_FALSE(data.has_acceleration_including_gravity_y);
+ EXPECT_EQ(0, data.acceleration_including_gravity_z);
+ EXPECT_FALSE(data.has_acceleration_including_gravity_z);
+ EXPECT_EQ(0, data.rotation_rate_alpha);
+ EXPECT_FALSE(data.has_rotation_rate_alpha);
+ EXPECT_EQ(0, data.rotation_rate_beta);
+ EXPECT_FALSE(data.has_rotation_rate_beta);
+ EXPECT_EQ(0, data.rotation_rate_gamma);
+ EXPECT_FALSE(data.has_rotation_rate_gamma);
+ EXPECT_EQ(0, data.interval);
+ EXPECT_TRUE(data.all_available_sensors_are_active);
+
+ motion_sensor_->StopPolling();
+ polling_stopped_runloop_->Run();
+ EXPECT_FALSE(fetcher_->IsMotionPollingStarted());
+}
+
+} // namespace
+
+} // namespace device
« no previous file with comments | « services/device/sensors/OWNERS ('k') | services/device/unittest_manifest.json » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698