10529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// found in the LICENSE file. 4424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 5424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "data_fetcher_shared_memory.h" 6424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 7424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/logging.h" 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/histogram.h" 9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h" 10424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 11424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace { 12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const double kMeanGravity = 9.80665; 1458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 15424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void FetchMotion(SuddenMotionSensor* sensor, 16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) content::DeviceMotionHardwareBuffer* buffer) { 17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK(buffer); 18424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) float axis_value[3]; 20424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!sensor->ReadSensorValues(axis_value)) 21424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 22424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 23424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) buffer->seqlock.WriteBegin(); 2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) buffer->data.accelerationIncludingGravityX = axis_value[0] * kMeanGravity; 25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) buffer->data.hasAccelerationIncludingGravityX = true; 2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) buffer->data.accelerationIncludingGravityY = axis_value[1] * kMeanGravity; 27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) buffer->data.hasAccelerationIncludingGravityY = true; 2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) buffer->data.accelerationIncludingGravityZ = axis_value[2] * kMeanGravity; 29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) buffer->data.hasAccelerationIncludingGravityZ = true; 30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) buffer->data.allAvailableSensorsAreActive = true; 31424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) buffer->seqlock.WriteEnd(); 32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void FetchOrientation(SuddenMotionSensor* sensor, 35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) content::DeviceOrientationHardwareBuffer* buffer) { 36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK(buffer); 37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Retrieve per-axis calibrated values. 39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) float axis_value[3]; 40424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!sensor->ReadSensorValues(axis_value)) 41424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 42424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Transform the accelerometer values to W3C draft angles. 44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // 45424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Accelerometer values are just dot products of the sensor axes 46424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // by the gravity vector 'g' with the result for the z axis inverted. 47424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // 48424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // To understand this transformation calculate the 3rd row of the z-x-y 49424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Euler angles rotation matrix (because of the 'g' vector, only 3rd row 50424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // affects to the result). Note that z-x-y matrix means R = Ry * Rx * Rz. 51424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Then, assume alpha = 0 and you get this: 52424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // 53424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // x_acc = sin(gamma) 54424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // y_acc = - cos(gamma) * sin(beta) 55424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // z_acc = cos(beta) * cos(gamma) 56424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // 57424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // After that the rest is just a bit of trigonometry. 58424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // 59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Also note that alpha can't be provided but it's assumed to be always zero. 60424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // This is necessary in order to provide enough information to solve 61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // the equations. 62424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // 63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const double kRad2deg = 180.0 / M_PI; 64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) double beta = kRad2deg * atan2(-axis_value[1], axis_value[2]); 65424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) double gamma = kRad2deg * asin(axis_value[0]); 66424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 67424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Make sure that the interval boundaries comply with the specification. At 68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // this point, beta is [-180, 180] and gamma is [-90, 90], but the spec has 69424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // the upper bound open on both. 70424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (beta == 180.0) 71424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) beta = -180; // -180 == 180 (upside-down) 72424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (gamma == 90.0) 73424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) gamma = nextafter(90, 0); 74424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 75424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // At this point, DCHECKing is paranoia. Never hurts. 76424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK_GE(beta, -180.0); 77424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK_LT(beta, 180.0); 78424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK_GE(gamma, -90.0); 79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK_LT(gamma, 90.0); 80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 81424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) buffer->seqlock.WriteBegin(); 82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) buffer->data.beta = beta; 83424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) buffer->data.hasBeta = true; 84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) buffer->data.gamma = gamma; 85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) buffer->data.hasGamma = true; 86424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) buffer->data.allAvailableSensorsAreActive = true; 87424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) buffer->seqlock.WriteEnd(); 88424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 89424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 90424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} // namespace 91424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 92424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace content { 93424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 94424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)DataFetcherSharedMemory::DataFetcherSharedMemory() { 95424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 96424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)DataFetcherSharedMemory::~DataFetcherSharedMemory() { 98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 99424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void DataFetcherSharedMemory::Fetch(unsigned consumer_bitmask) { 101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK(base::MessageLoop::current() == GetPollingMessageLoop()); 102424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK(sudden_motion_sensor_); 10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(consumer_bitmask & CONSUMER_TYPE_ORIENTATION || 10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) consumer_bitmask & CONSUMER_TYPE_MOTION); 105424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 106424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (consumer_bitmask & CONSUMER_TYPE_ORIENTATION) 107424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) FetchOrientation(sudden_motion_sensor_.get(), orientation_buffer_); 10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (consumer_bitmask & CONSUMER_TYPE_MOTION) 109424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) FetchMotion(sudden_motion_sensor_.get(), motion_buffer_); 110424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 111424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 1128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)DataFetcherSharedMemory::FetcherType DataFetcherSharedMemory::GetType() const { 1138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return FETCHER_TYPE_POLLING_CALLBACK; 114424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 115424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) { 117424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK(base::MessageLoop::current() == GetPollingMessageLoop()); 11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(buffer); 11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!sudden_motion_sensor_) 121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sudden_motion_sensor_.reset(SuddenMotionSensor::Create()); 122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bool sudden_motion_sensor_available = sudden_motion_sensor_.get() != NULL; 123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 124424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) switch (consumer_type) { 125424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case CONSUMER_TYPE_MOTION: 12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer); 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("InertialSensor.MotionMacAvailable", 128effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sudden_motion_sensor_available); 129effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!sudden_motion_sensor_available) { 130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // No motion sensor available, fire an all-null event. 131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch motion_buffer_->seqlock.WriteBegin(); 132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch motion_buffer_->data.allAvailableSensorsAreActive = true; 133effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch motion_buffer_->seqlock.WriteEnd(); 134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return sudden_motion_sensor_available; 136424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case CONSUMER_TYPE_ORIENTATION: 13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) orientation_buffer_ = 13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) static_cast<DeviceOrientationHardwareBuffer*>(buffer); 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("InertialSensor.OrientationMacAvailable", 140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sudden_motion_sensor_available); 141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (sudden_motion_sensor_available) { 142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // On Mac we cannot provide absolute orientation. 143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch orientation_buffer_->seqlock.WriteBegin(); 144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch orientation_buffer_->data.absolute = false; 145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch orientation_buffer_->data.hasAbsolute = true; 146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch orientation_buffer_->seqlock.WriteEnd(); 147effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else { 148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // No motion sensor available, fire an all-null event. 149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch orientation_buffer_->seqlock.WriteBegin(); 150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch orientation_buffer_->data.allAvailableSensorsAreActive = true; 151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch orientation_buffer_->seqlock.WriteEnd(); 152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return sudden_motion_sensor_available; 154424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) default: 155424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) NOTREACHED(); 156424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 157424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 158424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 159424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 160424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) { 161424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK(base::MessageLoop::current() == GetPollingMessageLoop()); 16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 163424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) switch (consumer_type) { 164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case CONSUMER_TYPE_MOTION: 16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (motion_buffer_) { 16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) motion_buffer_->seqlock.WriteBegin(); 16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) motion_buffer_->data.allAvailableSensorsAreActive = false; 16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) motion_buffer_->seqlock.WriteEnd(); 16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) motion_buffer_ = NULL; 17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 171424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 172424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case CONSUMER_TYPE_ORIENTATION: 17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (orientation_buffer_) { 17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) orientation_buffer_->seqlock.WriteBegin(); 17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) orientation_buffer_->data.allAvailableSensorsAreActive = false; 17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) orientation_buffer_->seqlock.WriteEnd(); 17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) orientation_buffer_ = NULL; 17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 179424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 180424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) default: 181424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) NOTREACHED(); 182424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 183424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 184424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 185424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 186424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} // namespace content 187