summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authortimvolodine <timvolodine@chromium.org>2015-11-11 19:23:13 -0800
committerCommit bot <commit-bot@chromium.org>2015-11-12 03:24:38 +0000
commit4b85e559ea40c58dfd3cd57322592a7a2f4dd94b (patch)
tree0979a7523ff31493a32f9eb7a7d8320cbb3ddb2c /content
parent41292597c932bf1bbf08f857b99a44ade44ee80f (diff)
downloadchromium_src-4b85e559ea40c58dfd3cd57322592a7a2f4dd94b.zip
chromium_src-4b85e559ea40c58dfd3cd57322592a7a2f4dd94b.tar.gz
chromium_src-4b85e559ea40c58dfd3cd57322592a7a2f4dd94b.tar.bz2
[Android] Absolute Device Orientation API: java-side implementation.
This patch implements the absolute device orientation api bits for the Android platform. To reuse existing device orientation code the patch does some refactoring. Also unittests are added to provide coverage for the new ConsumerType.ORIENTATION_ABSOLUTE. TEST=http://jsbin.com/tesocobizi/ BUG=520546 Review URL: https://codereview.chromium.org/1411283007 Cr-Commit-Position: refs/heads/master@{#359236}
Diffstat (limited to 'content')
-rw-r--r--content/browser/device_sensors/data_fetcher_shared_memory_android.cc18
-rw-r--r--content/browser/device_sensors/sensor_manager_android.cc160
-rw-r--r--content/browser/device_sensors/sensor_manager_android.h33
-rw-r--r--content/browser/device_sensors/sensor_manager_android_unittest.cc53
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/DeviceSensors.java138
-rw-r--r--content/public/android/javatests/src/org/chromium/content/browser/DeviceSensorsTest.java119
6 files changed, 388 insertions, 133 deletions
diff --git a/content/browser/device_sensors/data_fetcher_shared_memory_android.cc b/content/browser/device_sensors/data_fetcher_shared_memory_android.cc
index d2eebb4..d746b4d 100644
--- a/content/browser/device_sensors/data_fetcher_shared_memory_android.cc
+++ b/content/browser/device_sensors/data_fetcher_shared_memory_android.cc
@@ -23,20 +23,22 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
switch (consumer_type) {
case CONSUMER_TYPE_MOTION:
- return SensorManagerAndroid::GetInstance()->
- StartFetchingDeviceMotionData(
- static_cast<DeviceMotionHardwareBuffer*>(buffer));
+ SensorManagerAndroid::GetInstance()->StartFetchingDeviceMotionData(
+ static_cast<DeviceMotionHardwareBuffer*>(buffer));
+ return true;
case CONSUMER_TYPE_ORIENTATION:
- return SensorManagerAndroid::GetInstance()->
- StartFetchingDeviceOrientationData(
- static_cast<DeviceOrientationHardwareBuffer*>(buffer));
+ SensorManagerAndroid::GetInstance()->StartFetchingDeviceOrientationData(
+ static_cast<DeviceOrientationHardwareBuffer*>(buffer));
+ return true;
case CONSUMER_TYPE_ORIENTATION_ABSOLUTE:
- return SensorManagerAndroid::GetInstance()->
+ SensorManagerAndroid::GetInstance()->
StartFetchingDeviceOrientationAbsoluteData(
static_cast<DeviceOrientationHardwareBuffer*>(buffer));
+ return true;
case CONSUMER_TYPE_LIGHT:
- return SensorManagerAndroid::GetInstance()->StartFetchingDeviceLightData(
+ SensorManagerAndroid::GetInstance()->StartFetchingDeviceLightData(
static_cast<DeviceLightHardwareBuffer*>(buffer));
+ return true;
default:
NOTREACHED();
}
diff --git a/content/browser/device_sensors/sensor_manager_android.cc b/content/browser/device_sensors/sensor_manager_android.cc
index 148ad7b..a108666 100644
--- a/content/browser/device_sensors/sensor_manager_android.cc
+++ b/content/browser/device_sensors/sensor_manager_android.cc
@@ -23,6 +23,28 @@ void UpdateDeviceOrientationHistogram(
type, content::SensorManagerAndroid::ORIENTATION_SENSOR_MAX);
}
+void SetOrientation(content::DeviceOrientationHardwareBuffer* buffer,
+ double alpha, double beta, double gamma) {
+ buffer->seqlock.WriteBegin();
+ buffer->data.alpha = alpha;
+ buffer->data.hasAlpha = true;
+ buffer->data.beta = beta;
+ buffer->data.hasBeta = true;
+ buffer->data.gamma = gamma;
+ buffer->data.hasGamma = true;
+ buffer->seqlock.WriteEnd();
+}
+
+void SetOrientationBufferStatus(
+ content::DeviceOrientationHardwareBuffer* buffer,
+ bool ready, bool absolute) {
+ buffer->seqlock.WriteBegin();
+ buffer->data.absolute = absolute;
+ buffer->data.hasAbsolute = ready;
+ buffer->data.allAvailableSensorsAreActive = ready;
+ buffer->seqlock.WriteEnd();
+}
+
} // namespace
namespace content {
@@ -60,23 +82,35 @@ void SensorManagerAndroid::GotOrientation(
if (!device_orientation_buffer_)
return;
- device_orientation_buffer_->seqlock.WriteBegin();
- device_orientation_buffer_->data.alpha = alpha;
- device_orientation_buffer_->data.hasAlpha = true;
- device_orientation_buffer_->data.beta = beta;
- device_orientation_buffer_->data.hasBeta = true;
- device_orientation_buffer_->data.gamma = gamma;
- device_orientation_buffer_->data.hasGamma = true;
- device_orientation_buffer_->seqlock.WriteEnd();
+ SetOrientation(device_orientation_buffer_, alpha, beta, gamma);
if (!orientation_buffer_initialized_) {
OrientationSensorType type =
static_cast<OrientationSensorType>(GetOrientationSensorTypeUsed());
- SetOrientationBufferStatus(true, type != GAME_ROTATION_VECTOR);
+ SetOrientationBufferStatus(device_orientation_buffer_, true,
+ type != GAME_ROTATION_VECTOR);
+ orientation_buffer_initialized_ = true;
UpdateDeviceOrientationHistogram(type);
}
}
+void SensorManagerAndroid::GotOrientationAbsolute(
+ JNIEnv*, jobject, double alpha, double beta, double gamma) {
+ base::AutoLock autolock(orientation_absolute_buffer_lock_);
+
+ if (!device_orientation_absolute_buffer_)
+ return;
+
+ SetOrientation(device_orientation_absolute_buffer_, alpha, beta, gamma);
+
+ if (!orientation_absolute_buffer_initialized_) {
+ SetOrientationBufferStatus(device_orientation_absolute_buffer_, true, true);
+ orientation_absolute_buffer_initialized_ = true;
+ // TODO(timvolodine): Add UMA.
+ }
+}
+
+
void SensorManagerAndroid::GotAcceleration(
JNIEnv*, jobject, double x, double y, double z) {
base::AutoLock autolock(motion_buffer_lock_);
@@ -154,23 +188,23 @@ void SensorManagerAndroid::GotLight(JNIEnv*, jobject, double value) {
device_light_buffer_->seqlock.WriteEnd();
}
-bool SensorManagerAndroid::Start(ConsumerType event_type) {
+bool SensorManagerAndroid::Start(ConsumerType consumer_type) {
DCHECK(!device_sensors_.is_null());
- int rate_in_microseconds = (event_type == CONSUMER_TYPE_LIGHT)
+ int rate_in_microseconds = (consumer_type == CONSUMER_TYPE_LIGHT)
? kLightSensorIntervalMicroseconds
: kInertialSensorIntervalMicroseconds;
return Java_DeviceSensors_start(AttachCurrentThread(),
device_sensors_.obj(),
reinterpret_cast<intptr_t>(this),
- static_cast<jint>(event_type),
+ static_cast<jint>(consumer_type),
rate_in_microseconds);
}
-void SensorManagerAndroid::Stop(ConsumerType event_type) {
+void SensorManagerAndroid::Stop(ConsumerType consumer_type) {
DCHECK(!device_sensors_.is_null());
Java_DeviceSensors_stop(AttachCurrentThread(),
device_sensors_.obj(),
- static_cast<jint>(event_type));
+ static_cast<jint>(consumer_type));
}
int SensorManagerAndroid::GetNumberActiveDeviceMotionSensors() {
@@ -179,17 +213,19 @@ int SensorManagerAndroid::GetNumberActiveDeviceMotionSensors() {
AttachCurrentThread(), device_sensors_.obj());
}
-int SensorManagerAndroid::GetOrientationSensorTypeUsed() {
+SensorManagerAndroid::OrientationSensorType
+SensorManagerAndroid::GetOrientationSensorTypeUsed() {
DCHECK(!device_sensors_.is_null());
- return Java_DeviceSensors_getOrientationSensorTypeUsed(
- AttachCurrentThread(), device_sensors_.obj());
+ return static_cast<SensorManagerAndroid::OrientationSensorType>(
+ Java_DeviceSensors_getOrientationSensorTypeUsed(
+ AttachCurrentThread(), device_sensors_.obj()));
}
// ----- Shared memory API methods
// --- Device Light
-bool SensorManagerAndroid::StartFetchingDeviceLightData(
+void SensorManagerAndroid::StartFetchingDeviceLightData(
DeviceLightHardwareBuffer* buffer) {
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
StartFetchingLightDataOnUI(buffer);
@@ -200,7 +236,6 @@ bool SensorManagerAndroid::StartFetchingDeviceLightData(
base::Unretained(this),
buffer));
}
- return true;
}
void SensorManagerAndroid::StartFetchingLightDataOnUI(
@@ -257,7 +292,7 @@ void SensorManagerAndroid::SetLightBufferValue(double lux) {
// --- Device Motion
-bool SensorManagerAndroid::StartFetchingDeviceMotionData(
+void SensorManagerAndroid::StartFetchingDeviceMotionData(
DeviceMotionHardwareBuffer* buffer) {
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
StartFetchingMotionDataOnUI(buffer);
@@ -268,7 +303,6 @@ bool SensorManagerAndroid::StartFetchingDeviceMotionData(
base::Unretained(this),
buffer));
}
- return true;
}
void SensorManagerAndroid::StartFetchingMotionDataOnUI(
@@ -359,17 +393,7 @@ void SensorManagerAndroid::ClearInternalMotionBuffers() {
// --- Device Orientation
-void SensorManagerAndroid::SetOrientationBufferStatus(bool ready,
- bool absolute) {
- device_orientation_buffer_->seqlock.WriteBegin();
- device_orientation_buffer_->data.absolute = absolute;
- device_orientation_buffer_->data.hasAbsolute = ready;
- device_orientation_buffer_->data.allAvailableSensorsAreActive = ready;
- device_orientation_buffer_->seqlock.WriteEnd();
- orientation_buffer_initialized_ = ready;
-}
-
-bool SensorManagerAndroid::StartFetchingDeviceOrientationData(
+void SensorManagerAndroid::StartFetchingDeviceOrientationData(
DeviceOrientationHardwareBuffer* buffer) {
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
StartFetchingOrientationDataOnUI(buffer);
@@ -380,7 +404,6 @@ bool SensorManagerAndroid::StartFetchingDeviceOrientationData(
base::Unretained(this),
buffer));
}
- return true;
}
void SensorManagerAndroid::StartFetchingOrientationDataOnUI(
@@ -400,7 +423,9 @@ void SensorManagerAndroid::StartFetchingOrientationDataOnUI(
base::AutoLock autolock(orientation_buffer_lock_);
// If Start() was unsuccessful then set the buffer ready flag to true
// to start firing all-null events.
- SetOrientationBufferStatus(!success /* ready */, false /* absolute */);
+ SetOrientationBufferStatus(buffer, !success /* ready */,
+ false /* absolute */);
+ orientation_buffer_initialized_ = !success;
}
if (!success)
@@ -428,20 +453,77 @@ void SensorManagerAndroid::StopFetchingOrientationDataOnUI() {
{
base::AutoLock autolock(orientation_buffer_lock_);
if (device_orientation_buffer_) {
- SetOrientationBufferStatus(false, false);
+ SetOrientationBufferStatus(device_orientation_buffer_, false, false);
+ orientation_buffer_initialized_ = false;
device_orientation_buffer_ = nullptr;
}
}
}
-bool SensorManagerAndroid::StartFetchingDeviceOrientationAbsoluteData(
+void SensorManagerAndroid::StartFetchingDeviceOrientationAbsoluteData(
DeviceOrientationHardwareBuffer* buffer) {
- NOTIMPLEMENTED();
- return false;
+ if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ StartFetchingOrientationAbsoluteDataOnUI(buffer);
+ } else {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(
+ &SensorManagerAndroid::StartFetchingOrientationAbsoluteDataOnUI,
+ base::Unretained(this),
+ buffer));
+ }
}
void SensorManagerAndroid::StopFetchingDeviceOrientationAbsoluteData() {
- NOTIMPLEMENTED();
+ if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ StopFetchingOrientationAbsoluteDataOnUI();
+ return;
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&SensorManagerAndroid::StopFetchingOrientationAbsoluteDataOnUI,
+ base::Unretained(this)));
+}
+
+void SensorManagerAndroid::StartFetchingOrientationAbsoluteDataOnUI(
+ DeviceOrientationHardwareBuffer* buffer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(buffer);
+ if (is_shutdown_)
+ return;
+
+ {
+ base::AutoLock autolock(orientation_absolute_buffer_lock_);
+ device_orientation_absolute_buffer_ = buffer;
+ }
+ bool success = Start(CONSUMER_TYPE_ORIENTATION_ABSOLUTE);
+
+ {
+ base::AutoLock autolock(orientation_absolute_buffer_lock_);
+ // If Start() was unsuccessful then set the buffer ready flag to true
+ // to start firing all-null events.
+ SetOrientationBufferStatus(buffer, !success /* ready */,
+ false /* absolute */);
+ orientation_absolute_buffer_initialized_ = !success;
+ }
+}
+
+void SensorManagerAndroid::StopFetchingOrientationAbsoluteDataOnUI() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (is_shutdown_)
+ return;
+
+ Stop(CONSUMER_TYPE_ORIENTATION_ABSOLUTE);
+ {
+ base::AutoLock autolock(orientation_absolute_buffer_lock_);
+ if (device_orientation_absolute_buffer_) {
+ SetOrientationBufferStatus(device_orientation_absolute_buffer_, false,
+ false);
+ orientation_absolute_buffer_initialized_ = false;
+ device_orientation_absolute_buffer_ = nullptr;
+ }
+ }
}
void SensorManagerAndroid::Shutdown() {
diff --git a/content/browser/device_sensors/sensor_manager_android.h b/content/browser/device_sensors/sensor_manager_android.h
index e147f79..4459556 100644
--- a/content/browser/device_sensors/sensor_manager_android.h
+++ b/content/browser/device_sensors/sensor_manager_android.h
@@ -38,6 +38,8 @@ class CONTENT_EXPORT SensorManagerAndroid {
void GotLight(JNIEnv*, jobject, double value);
void GotOrientation(JNIEnv*, jobject,
double alpha, double beta, double gamma);
+ void GotOrientationAbsolute(JNIEnv*, jobject,
+ double alpha, double beta, double gamma);
void GotAcceleration(JNIEnv*, jobject,
double x, double y, double z);
void GotAccelerationIncludingGravity(JNIEnv*, jobject,
@@ -46,17 +48,17 @@ class CONTENT_EXPORT SensorManagerAndroid {
double alpha, double beta, double gamma);
// Shared memory related methods.
- bool StartFetchingDeviceLightData(DeviceLightHardwareBuffer* buffer);
+ void StartFetchingDeviceLightData(DeviceLightHardwareBuffer* buffer);
void StopFetchingDeviceLightData();
- bool StartFetchingDeviceMotionData(DeviceMotionHardwareBuffer* buffer);
+ void StartFetchingDeviceMotionData(DeviceMotionHardwareBuffer* buffer);
void StopFetchingDeviceMotionData();
- bool StartFetchingDeviceOrientationData(
+ void StartFetchingDeviceOrientationData(
DeviceOrientationHardwareBuffer* buffer);
void StopFetchingDeviceOrientationData();
- bool StartFetchingDeviceOrientationAbsoluteData(
+ void StartFetchingDeviceOrientationAbsoluteData(
DeviceOrientationHardwareBuffer* buffer);
void StopFetchingDeviceOrientationAbsoluteData();
@@ -77,9 +79,15 @@ class CONTENT_EXPORT SensorManagerAndroid {
SensorManagerAndroid();
virtual ~SensorManagerAndroid();
- virtual bool Start(ConsumerType event_type);
- virtual void Stop(ConsumerType event_type);
- virtual int GetOrientationSensorTypeUsed();
+ // Starts listening to the sensors corresponding to the consumer_type.
+ // Returns true if the registration with sensors was successful.
+ virtual bool Start(ConsumerType consumer_type);
+ // Stops listening to the sensors corresponding to the consumer_type.
+ virtual void Stop(ConsumerType consumer_type);
+ // Returns currently used sensor type for device orientation.
+ virtual OrientationSensorType GetOrientationSensorTypeUsed();
+ // Returns the number of active sensors corresponding to
+ // ConsumerType.DEVICE_MOTION.
virtual int GetNumberActiveDeviceMotionSensors();
void StartFetchingLightDataOnUI(DeviceLightHardwareBuffer* buffer);
@@ -92,6 +100,10 @@ class CONTENT_EXPORT SensorManagerAndroid {
DeviceOrientationHardwareBuffer* buffer);
void StopFetchingOrientationDataOnUI();
+ void StartFetchingOrientationAbsoluteDataOnUI(
+ DeviceOrientationHardwareBuffer* buffer);
+ void StopFetchingOrientationAbsoluteDataOnUI();
+
private:
friend struct base::DefaultSingletonTraits<SensorManagerAndroid>;
@@ -108,22 +120,25 @@ class CONTENT_EXPORT SensorManagerAndroid {
void SetMotionBufferReadyStatus(bool ready);
void ClearInternalMotionBuffers();
- void SetOrientationBufferStatus(bool ready, bool absolute);
-
// The Java provider of sensors info.
base::android::ScopedJavaGlobalRef<jobject> device_sensors_;
int number_active_device_motion_sensors_;
int received_motion_data_[RECEIVED_MOTION_DATA_MAX];
+
+ // Cached pointers to buffers, owned by DataFetcherSharedMemoryBase.
DeviceLightHardwareBuffer* device_light_buffer_;
DeviceMotionHardwareBuffer* device_motion_buffer_;
DeviceOrientationHardwareBuffer* device_orientation_buffer_;
+ DeviceOrientationHardwareBuffer* device_orientation_absolute_buffer_;
bool motion_buffer_initialized_;
bool orientation_buffer_initialized_;
+ bool orientation_absolute_buffer_initialized_;
base::Lock light_buffer_lock_;
base::Lock motion_buffer_lock_;
base::Lock orientation_buffer_lock_;
+ base::Lock orientation_absolute_buffer_lock_;
bool is_shutdown_;
diff --git a/content/browser/device_sensors/sensor_manager_android_unittest.cc b/content/browser/device_sensors/sensor_manager_android_unittest.cc
index 84ee9cb..133b1b5 100644
--- a/content/browser/device_sensors/sensor_manager_android_unittest.cc
+++ b/content/browser/device_sensors/sensor_manager_android_unittest.cc
@@ -20,7 +20,7 @@ class FakeSensorManagerAndroid : public SensorManagerAndroid {
FakeSensorManagerAndroid() {}
~FakeSensorManagerAndroid() override {}
- int GetOrientationSensorTypeUsed() override {
+ OrientationSensorType GetOrientationSensorTypeUsed() override {
return SensorManagerAndroid::ROTATION_VECTOR;
}
@@ -46,11 +46,25 @@ class AndroidSensorManagerTest : public testing::Test {
light_buffer_.reset(new DeviceLightHardwareBuffer);
motion_buffer_.reset(new DeviceMotionHardwareBuffer);
orientation_buffer_.reset(new DeviceOrientationHardwareBuffer);
+ orientation_absolute_buffer_.reset(new DeviceOrientationHardwareBuffer);
+ }
+
+ void VerifyOrientationBufferValues(
+ const DeviceOrientationHardwareBuffer* buffer,
+ double alpha, double beta, double gamma) {
+ ASSERT_TRUE(buffer->data.allAvailableSensorsAreActive);
+ ASSERT_EQ(alpha, buffer->data.alpha);
+ ASSERT_TRUE(buffer->data.hasAlpha);
+ ASSERT_EQ(beta, buffer->data.beta);
+ ASSERT_TRUE(buffer->data.hasBeta);
+ ASSERT_EQ(gamma, buffer->data.gamma);
+ ASSERT_TRUE(buffer->data.hasGamma);
}
scoped_ptr<DeviceLightHardwareBuffer> light_buffer_;
scoped_ptr<DeviceMotionHardwareBuffer> motion_buffer_;
scoped_ptr<DeviceOrientationHardwareBuffer> orientation_buffer_;
+ scoped_ptr<DeviceOrientationHardwareBuffer> orientation_absolute_buffer_;
content::TestBrowserThreadBundle thread_bundle_;
};
@@ -62,7 +76,7 @@ TEST_F(AndroidSensorManagerTest, ThreeDeviceMotionSensorsActive) {
sensorManager.StartFetchingDeviceMotionData(motion_buffer_.get());
ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
- sensorManager.GotAcceleration(0, 0, 1, 2, 3);
+ sensorManager.GotAcceleration(nullptr, nullptr, 1, 2, 3);
ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
ASSERT_EQ(1, motion_buffer_->data.accelerationX);
ASSERT_TRUE(motion_buffer_->data.hasAccelerationX);
@@ -71,7 +85,7 @@ TEST_F(AndroidSensorManagerTest, ThreeDeviceMotionSensorsActive) {
ASSERT_EQ(3, motion_buffer_->data.accelerationZ);
ASSERT_TRUE(motion_buffer_->data.hasAccelerationZ);
- sensorManager.GotAccelerationIncludingGravity(0, 0, 4, 5, 6);
+ sensorManager.GotAccelerationIncludingGravity(nullptr, nullptr, 4, 5, 6);
ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
ASSERT_EQ(4, motion_buffer_->data.accelerationIncludingGravityX);
ASSERT_TRUE(motion_buffer_->data.hasAccelerationIncludingGravityX);
@@ -80,7 +94,7 @@ TEST_F(AndroidSensorManagerTest, ThreeDeviceMotionSensorsActive) {
ASSERT_EQ(6, motion_buffer_->data.accelerationIncludingGravityZ);
ASSERT_TRUE(motion_buffer_->data.hasAccelerationIncludingGravityZ);
- sensorManager.GotRotationRate(0, 0, 7, 8, 9);
+ sensorManager.GotRotationRate(nullptr, nullptr, 7, 8, 9);
ASSERT_TRUE(motion_buffer_->data.allAvailableSensorsAreActive);
ASSERT_EQ(7, motion_buffer_->data.rotationRateAlpha);
ASSERT_TRUE(motion_buffer_->data.hasRotationRateAlpha);
@@ -103,10 +117,10 @@ TEST_F(AndroidSensorManagerTest, TwoDeviceMotionSensorsActive) {
sensorManager.StartFetchingDeviceMotionData(motion_buffer_.get());
ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
- sensorManager.GotAcceleration(0, 0, 1, 2, 3);
+ sensorManager.GotAcceleration(nullptr, nullptr, 1, 2, 3);
ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
- sensorManager.GotAccelerationIncludingGravity(0, 0, 1, 2, 3);
+ sensorManager.GotAccelerationIncludingGravity(nullptr, nullptr, 1, 2, 3);
ASSERT_TRUE(motion_buffer_->data.allAvailableSensorsAreActive);
ASSERT_EQ(kInertialSensorIntervalMicroseconds / 1000.,
motion_buffer_->data.interval);
@@ -136,14 +150,23 @@ TEST_F(AndroidSensorManagerTest, DeviceOrientationSensorsActive) {
sensorManager.StartFetchingDeviceOrientationData(orientation_buffer_.get());
ASSERT_FALSE(orientation_buffer_->data.allAvailableSensorsAreActive);
- sensorManager.GotOrientation(0, 0, 1, 2, 3);
- ASSERT_TRUE(orientation_buffer_->data.allAvailableSensorsAreActive);
- ASSERT_EQ(1, orientation_buffer_->data.alpha);
- ASSERT_TRUE(orientation_buffer_->data.hasAlpha);
- ASSERT_EQ(2, orientation_buffer_->data.beta);
- ASSERT_TRUE(orientation_buffer_->data.hasBeta);
- ASSERT_EQ(3, orientation_buffer_->data.gamma);
- ASSERT_TRUE(orientation_buffer_->data.hasGamma);
+ sensorManager.GotOrientation(nullptr, nullptr, 1, 2, 3);
+ VerifyOrientationBufferValues(orientation_buffer_.get(), 1, 2, 3);
+
+ sensorManager.StopFetchingDeviceOrientationData();
+ ASSERT_FALSE(orientation_buffer_->data.allAvailableSensorsAreActive);
+}
+
+TEST_F(AndroidSensorManagerTest, DeviceOrientationAbsoluteSensorsActive) {
+ FakeSensorManagerAndroid::Register(base::android::AttachCurrentThread());
+ FakeSensorManagerAndroid sensorManager;
+
+ sensorManager.StartFetchingDeviceOrientationAbsoluteData(
+ orientation_absolute_buffer_.get());
+ ASSERT_FALSE(orientation_buffer_->data.allAvailableSensorsAreActive);
+
+ sensorManager.GotOrientationAbsolute(nullptr, nullptr, 4, 5, 6);
+ VerifyOrientationBufferValues(orientation_absolute_buffer_.get(), 4, 5, 6);
sensorManager.StopFetchingDeviceOrientationData();
ASSERT_FALSE(orientation_buffer_->data.allAvailableSensorsAreActive);
@@ -156,7 +179,7 @@ TEST_F(AndroidSensorManagerTest, DeviceLightSensorsActive) {
sensorManager.StartFetchingDeviceLightData(light_buffer_.get());
- sensorManager.GotLight(0, 0, 100);
+ sensorManager.GotLight(nullptr, nullptr, 100);
ASSERT_EQ(100, light_buffer_->data.value);
sensorManager.StopFetchingDeviceLightData();
diff --git a/content/public/android/java/src/org/chromium/content/browser/DeviceSensors.java b/content/public/android/java/src/org/chromium/content/browser/DeviceSensors.java
index 76835ce..fbab3c0 100644
--- a/content/public/android/java/src/org/chromium/content/browser/DeviceSensors.java
+++ b/content/public/android/java/src/org/chromium/content/browser/DeviceSensors.java
@@ -80,6 +80,8 @@ class DeviceSensors implements SensorEventListener {
static final Set<Integer> DEVICE_ORIENTATION_SENSORS_C = CollectionUtil.newHashSet(
Sensor.TYPE_ACCELEROMETER,
Sensor.TYPE_MAGNETIC_FIELD);
+ static final Set<Integer> DEVICE_ORIENTATION_ABSOLUTE_SENSORS = CollectionUtil.newHashSet(
+ Sensor.TYPE_ROTATION_VECTOR);
static final Set<Integer> DEVICE_MOTION_SENSORS = CollectionUtil.newHashSet(
Sensor.TYPE_ACCELEROMETER,
Sensor.TYPE_LINEAR_ACCELERATION,
@@ -95,6 +97,7 @@ class DeviceSensors implements SensorEventListener {
boolean mDeviceMotionIsActive = false;
boolean mDeviceOrientationIsActive = false;
boolean mDeviceOrientationIsActiveWithBackupSensors = false;
+ boolean mDeviceOrientationAbsoluteIsActive = false;
boolean mOrientationNotAvailable = false;
protected DeviceSensors(Context context, boolean relativeByDefault) {
@@ -151,8 +154,8 @@ class DeviceSensors implements SensorEventListener {
* @param nativePtr Value to pass to nativeGotOrientation() for each event.
* @param rateInMicroseconds Requested callback rate in microseconds. The
* actual rate may be higher. Unwanted events should be ignored.
- * @param eventType Type of event to listen to, can be either DEVICE_ORIENTATION or
- * DEVICE_MOTION or DEVICE_LIGHT.
+ * @param eventType Type of event to listen to, can be either DEVICE_ORIENTATION,
+ * DEVICE_ORIENTATION_ABSOLUTE, DEVICE_MOTION or DEVICE_LIGHT.
* @return True on success.
*/
@CalledByNative
@@ -164,9 +167,10 @@ class DeviceSensors implements SensorEventListener {
success = registerOrientationSensorsWithFallback(rateInMicroseconds);
break;
case ConsumerType.ORIENTATION_ABSOLUTE:
- // not implemented
- assert false;
- return false;
+ ensureRotationStructuresAllocated();
+ success = registerSensors(DEVICE_ORIENTATION_ABSOLUTE_SENSORS,
+ rateInMicroseconds, true);
+ break;
case ConsumerType.MOTION:
// note: device motion spec does not require all sensors to be available
success = registerSensors(DEVICE_MOTION_SENSORS, rateInMicroseconds, false);
@@ -224,35 +228,23 @@ class DeviceSensors implements SensorEventListener {
@CalledByNative
public void stop(int eventType) {
Set<Integer> sensorsToRemainActive = new HashSet<Integer>();
+
synchronized (mNativePtrLock) {
- switch (eventType) {
- case ConsumerType.ORIENTATION:
- if (mDeviceMotionIsActive) {
- sensorsToRemainActive.addAll(DEVICE_MOTION_SENSORS);
- }
- if (mDeviceLightIsActive) {
- sensorsToRemainActive.addAll(DEVICE_LIGHT_SENSORS);
- }
- break;
- case ConsumerType.MOTION:
- if (mDeviceOrientationIsActive) {
- sensorsToRemainActive.addAll(mDeviceOrientationSensors);
- }
- if (mDeviceLightIsActive) {
- sensorsToRemainActive.addAll(DEVICE_LIGHT_SENSORS);
- }
- break;
- case ConsumerType.LIGHT:
- if (mDeviceMotionIsActive) {
- sensorsToRemainActive.addAll(DEVICE_MOTION_SENSORS);
- }
- if (mDeviceOrientationIsActive) {
- sensorsToRemainActive.addAll(mDeviceOrientationSensors);
- }
- break;
- default:
- Log.e(TAG, "Unknown event type: %d", eventType);
- return;
+ if (mDeviceOrientationIsActive && eventType != ConsumerType.ORIENTATION) {
+ sensorsToRemainActive.addAll(mDeviceOrientationSensors);
+ }
+
+ if (mDeviceOrientationAbsoluteIsActive
+ && eventType != ConsumerType.ORIENTATION_ABSOLUTE) {
+ sensorsToRemainActive.addAll(DEVICE_ORIENTATION_ABSOLUTE_SENSORS);
+ }
+
+ if (mDeviceMotionIsActive && eventType != ConsumerType.MOTION) {
+ sensorsToRemainActive.addAll(DEVICE_MOTION_SENSORS);
+ }
+
+ if (mDeviceLightIsActive && eventType != ConsumerType.LIGHT) {
+ sensorsToRemainActive.addAll(DEVICE_LIGHT_SENSORS);
}
Set<Integer> sensorsToDeactivate = new HashSet<Integer>(mActiveSensors);
@@ -297,21 +289,24 @@ class DeviceSensors implements SensorEventListener {
}
break;
case Sensor.TYPE_ROTATION_VECTOR:
+ if (mDeviceOrientationAbsoluteIsActive) {
+ convertRotationVectorToAngles(values, mRotationAngles);
+ gotOrientationAbsolute(mRotationAngles[0], mRotationAngles[1],
+ mRotationAngles[2]);
+ }
+ if (mDeviceOrientationIsActive
+ && mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_B) {
+ if (!mDeviceOrientationAbsoluteIsActive) {
+ // only compute if not already computed for absolute orientation above.
+ convertRotationVectorToAngles(values, mRotationAngles);
+ }
+ gotOrientation(mRotationAngles[0], mRotationAngles[1], mRotationAngles[2]);
+ }
+ break;
case Sensor.TYPE_GAME_ROTATION_VECTOR:
if (mDeviceOrientationIsActive) {
- if (values.length > 4) {
- // On some Samsung devices SensorManager.getRotationMatrixFromVector
- // appears to throw an exception if rotation vector has length > 4.
- // For the purposes of this class the first 4 values of the
- // rotation vector are sufficient (see crbug.com/335298 for details).
- if (mTruncatedRotationVector == null) {
- mTruncatedRotationVector = new float[4];
- }
- System.arraycopy(values, 0, mTruncatedRotationVector, 0, 4);
- getOrientationFromRotationVector(mTruncatedRotationVector);
- } else {
- getOrientationFromRotationVector(values);
- }
+ convertRotationVectorToAngles(values, mRotationAngles);
+ gotOrientation(mRotationAngles[0], mRotationAngles[1], mRotationAngles[2]);
}
break;
case Sensor.TYPE_MAGNETIC_FIELD:
@@ -418,13 +413,26 @@ class DeviceSensors implements SensorEventListener {
return values;
}
- private void getOrientationFromRotationVector(float[] rotationVector) {
- SensorManager.getRotationMatrixFromVector(mDeviceRotationMatrix, rotationVector);
- computeDeviceOrientationFromRotationMatrix(mDeviceRotationMatrix, mRotationAngles);
-
- gotOrientation(Math.toDegrees(mRotationAngles[0]),
- Math.toDegrees(mRotationAngles[1]),
- Math.toDegrees(mRotationAngles[2]));
+ /*
+ * Converts a given rotation vector to its Euler angles representation. The angles
+ * are in degrees.
+ */
+ public void convertRotationVectorToAngles(float[] rotationVector, double[] angles) {
+ if (rotationVector.length > 4) {
+ // On some Samsung devices SensorManager.getRotationMatrixFromVector
+ // appears to throw an exception if rotation vector has length > 4.
+ // For the purposes of this class the first 4 values of the
+ // rotation vector are sufficient (see crbug.com/335298 for details).
+ System.arraycopy(rotationVector, 0, mTruncatedRotationVector, 0, 4);
+ SensorManager.getRotationMatrixFromVector(mDeviceRotationMatrix,
+ mTruncatedRotationVector);
+ } else {
+ SensorManager.getRotationMatrixFromVector(mDeviceRotationMatrix, rotationVector);
+ }
+ computeDeviceOrientationFromRotationMatrix(mDeviceRotationMatrix, angles);
+ for (int i = 0; i < 3; i++) {
+ angles[i] = Math.toDegrees(angles[i]);
+ }
}
private void getOrientationFromGeomagneticVectors(float[] acceleration, float[] magnetic) {
@@ -468,6 +476,9 @@ class DeviceSensors implements SensorEventListener {
mDeviceOrientationIsActiveWithBackupSensors = active
&& (mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_C);
return;
+ case ConsumerType.ORIENTATION_ABSOLUTE:
+ mDeviceOrientationAbsoluteIsActive = active;
+ return;
case ConsumerType.MOTION:
mDeviceMotionIsActive = active;
return;
@@ -484,6 +495,9 @@ class DeviceSensors implements SensorEventListener {
if (mRotationAngles == null) {
mRotationAngles = new double[3];
}
+ if (mTruncatedRotationVector == null) {
+ mTruncatedRotationVector = new float[4];
+ }
}
/**
@@ -497,8 +511,9 @@ class DeviceSensors implements SensorEventListener {
boolean failOnMissingSensor) {
Set<Integer> sensorsToActivate = new HashSet<Integer>(sensorTypes);
sensorsToActivate.removeAll(mActiveSensors);
- boolean success = false;
+ if (sensorsToActivate.isEmpty()) return true;
+ boolean success = false;
for (Integer sensorType : sensorsToActivate) {
boolean result = registerForSensorType(sensorType, rateInMicroseconds);
if (!result && failOnMissingSensor) {
@@ -539,6 +554,14 @@ class DeviceSensors implements SensorEventListener {
}
}
+ protected void gotOrientationAbsolute(double alpha, double beta, double gamma) {
+ synchronized (mNativePtrLock) {
+ if (mNativePtr != 0) {
+ nativeGotOrientationAbsolute(mNativePtr, alpha, beta, gamma);
+ }
+ }
+ }
+
protected void gotAcceleration(double x, double y, double z) {
synchronized (mNativePtrLock) {
if (mNativePtr != 0) {
@@ -612,6 +635,13 @@ class DeviceSensors implements SensorEventListener {
double alpha, double beta, double gamma);
/**
+ * Absolute orientation of the device with respect to its reference frame.
+ */
+ private native void nativeGotOrientationAbsolute(
+ long nativeSensorManagerAndroid,
+ double alpha, double beta, double gamma);
+
+ /**
* Linear acceleration without gravity of the device with respect to its body frame.
*/
private native void nativeGotAcceleration(
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/DeviceSensorsTest.java b/content/public/android/javatests/src/org/chromium/content/browser/DeviceSensorsTest.java
index 38ed238..9f491a2 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/DeviceSensorsTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/DeviceSensorsTest.java
@@ -161,6 +161,67 @@ public class DeviceSensorsTest extends AndroidTestCase {
}
@SmallTest
+ public void testRegisterSensorsDeviceOrientationAbsolute() {
+ boolean start = mDeviceSensors.start(0, ConsumerType.ORIENTATION_ABSOLUTE, 100);
+
+ assertTrue(start);
+ assertTrue("should contain all absolute orientation sensors",
+ mDeviceSensors.mActiveSensors.containsAll(
+ DeviceSensors.DEVICE_ORIENTATION_ABSOLUTE_SENSORS));
+ assertFalse(mDeviceSensors.mDeviceMotionIsActive);
+ assertFalse(mDeviceSensors.mDeviceLightIsActive);
+ assertFalse(mDeviceSensors.mDeviceOrientationIsActive);
+ assertFalse(mDeviceSensors.mDeviceOrientationIsActiveWithBackupSensors);
+ assertTrue(mDeviceSensors.mDeviceOrientationAbsoluteIsActive);
+
+ assertEquals(DeviceSensors.DEVICE_ORIENTATION_ABSOLUTE_SENSORS.size(),
+ mMockSensorManager.mNumRegistered);
+ assertEquals(0, mMockSensorManager.mNumUnRegistered);
+ }
+
+ @SmallTest
+ public void testUnregisterSensorsDeviceOrientationAbsolute() {
+ mDeviceSensors.start(0, ConsumerType.ORIENTATION_ABSOLUTE, 100);
+ mDeviceSensors.stop(ConsumerType.ORIENTATION_ABSOLUTE);
+
+ assertTrue("should contain no sensors",
+ mDeviceSensors.mActiveSensors.isEmpty());
+ assertFalse(mDeviceSensors.mDeviceMotionIsActive);
+ assertFalse(mDeviceSensors.mDeviceOrientationIsActive);
+ assertFalse(mDeviceSensors.mDeviceOrientationIsActiveWithBackupSensors);
+ assertFalse(mDeviceSensors.mDeviceLightIsActive);
+ assertEquals(DeviceSensors.DEVICE_ORIENTATION_ABSOLUTE_SENSORS.size(),
+ mMockSensorManager.mNumUnRegistered);
+ }
+
+ @SmallTest
+ public void testRegisterSensorsDeviceOrientationAndOrientationAbsolute() {
+ boolean startOrientation = mDeviceSensors.start(0, ConsumerType.ORIENTATION, 100);
+ boolean startOrientationAbsolute = mDeviceSensors.start(0,
+ ConsumerType.ORIENTATION_ABSOLUTE, 100);
+
+ assertTrue(startOrientation);
+ assertTrue(startOrientationAbsolute);
+ assertTrue("should contain all orientation sensors",
+ mDeviceSensors.mActiveSensors.containsAll(
+ DeviceSensors.DEVICE_ORIENTATION_SENSORS_A));
+ assertTrue("should contain all absolute orientation sensors",
+ mDeviceSensors.mActiveSensors.containsAll(
+ DeviceSensors.DEVICE_ORIENTATION_ABSOLUTE_SENSORS));
+
+ Set<Integer> union = new HashSet<Integer>(DeviceSensors.DEVICE_ORIENTATION_SENSORS_A);
+ union.addAll(DeviceSensors.DEVICE_ORIENTATION_ABSOLUTE_SENSORS);
+
+ assertEquals(union.size(), mDeviceSensors.mActiveSensors.size());
+ assertTrue(mDeviceSensors.mDeviceOrientationIsActive);
+ assertTrue(mDeviceSensors.mDeviceOrientationAbsoluteIsActive);
+ assertFalse(mDeviceSensors.mDeviceMotionIsActive);
+ assertFalse(mDeviceSensors.mDeviceLightIsActive);
+ assertEquals(union.size(), mMockSensorManager.mNumRegistered);
+ assertEquals(0, mMockSensorManager.mNumUnRegistered);
+ }
+
+ @SmallTest
public void testRegisterSensorsDeviceLight() {
boolean start = mDeviceSensors.start(0, ConsumerType.LIGHT, 100);
@@ -254,27 +315,61 @@ public class DeviceSensorsTest extends AndroidTestCase {
/**
* Helper method to trigger an orientation change using the given sensorType.
*/
- private void changeOrientation(int sensorType) {
- boolean startOrientation = mDeviceSensors.start(0, ConsumerType.ORIENTATION, 100);
+ private void changeOrientation(int sensorType, boolean absolute, String expectedChange) {
+ boolean startOrientation = mDeviceSensors.start(0,
+ absolute ? ConsumerType.ORIENTATION_ABSOLUTE : ConsumerType.ORIENTATION, 100);
assertTrue(startOrientation);
- assertTrue(mDeviceSensors.mDeviceOrientationIsActive);
+ assertTrue(absolute ? mDeviceSensors.mDeviceOrientationAbsoluteIsActive
+ : mDeviceSensors.mDeviceOrientationIsActive);
float alpha = (float) Math.PI / 4;
float[] values = {0, 0, (float) Math.sin(alpha / 2), (float) Math.cos(alpha / 2), -1};
mDeviceSensors.sensorChanged(sensorType, values);
- mDeviceSensors.verifyCalls("gotOrientation");
- mDeviceSensors.verifyValuesEpsilon(Math.toDegrees(alpha), 0, 0);
+
+ mDeviceSensors.verifyCalls(expectedChange);
+ if (!expectedChange.isEmpty()) {
+ mDeviceSensors.verifyValuesEpsilon(Math.toDegrees(alpha), 0, 0);
+ }
}
@SmallTest
public void testSensorChangedGotOrientationViaRotationVector() {
- changeOrientation(Sensor.TYPE_ROTATION_VECTOR);
+ changeOrientation(Sensor.TYPE_ROTATION_VECTOR, false /* absolute */, "");
}
@SmallTest
public void testSensorChangedGotOrientationViaGameRotationVector() {
- changeOrientation(Sensor.TYPE_GAME_ROTATION_VECTOR);
+ changeOrientation(Sensor.TYPE_GAME_ROTATION_VECTOR, false /* absolute */, "gotOrientation");
+ }
+
+ @SmallTest
+ public void testSensorChangedGotOrientationAbsoluteViaRotationVector() {
+ changeOrientation(Sensor.TYPE_ROTATION_VECTOR, true /* absolute */,
+ "gotOrientationAbsolute");
+ }
+
+ @SmallTest
+ public void testSensorChangedGotOrientationAbsoluteViaGameRotationVector() {
+ changeOrientation(Sensor.TYPE_GAME_ROTATION_VECTOR, true /* absolute */, "");
+ }
+
+ @SmallTest
+ public void testSensorChangedGotOrientationAndOrientationAbsolute() {
+ changeOrientation(Sensor.TYPE_GAME_ROTATION_VECTOR, false /* absolute */, "gotOrientation");
+ changeOrientation(Sensor.TYPE_ROTATION_VECTOR, true /* absolute */,
+ "gotOrientation" + "gotOrientationAbsolute");
+ }
+
+ @SmallTest
+ public void testSensorChangedGotOrientationViaRotationVectorAndOrientationAbsolute() {
+ MockSensorManager mockSensorManager = new MockSensorManager();
+ mockSensorManager.setGameRotationVectorAvailable(false);
+ mDeviceSensors.setSensorManagerProxy(mockSensorManager);
+
+ changeOrientation(Sensor.TYPE_ROTATION_VECTOR, false /* absolute */, "gotOrientation");
+ changeOrientation(Sensor.TYPE_ROTATION_VECTOR, true /* absolute */,
+ "gotOrientation" + "gotOrientationAbsolute" + "gotOrientation");
}
@SmallTest
@@ -319,7 +414,7 @@ public class DeviceSensorsTest extends AndroidTestCase {
float alpha = (float) Math.PI / 4;
float[] values = {0, 0, (float) Math.sin(alpha / 2), (float) Math.cos(alpha / 2), -1};
- mDeviceSensors.sensorChanged(Sensor.TYPE_ROTATION_VECTOR, values);
+ mDeviceSensors.sensorChanged(Sensor.TYPE_GAME_ROTATION_VECTOR, values);
mDeviceSensors.verifyCalls("gotOrientation");
mDeviceSensors.verifyValuesEpsilon(Math.toDegrees(alpha), 0, 0);
@@ -475,6 +570,14 @@ public class DeviceSensorsTest extends AndroidTestCase {
}
@Override
+ protected void gotOrientationAbsolute(double alpha, double beta, double gamma) {
+ mValue1 = alpha;
+ mValue2 = beta;
+ mValue3 = gamma;
+ mCalls = mCalls.concat("gotOrientationAbsolute");
+ }
+
+ @Override
protected void gotAcceleration(double x, double y, double z) {
mValue1 = x;
mValue2 = y;