blob: 6748d744b7139fb7616cbbe0afa666165376fc5d [file] [log] [blame]
// Copyright (c) 2012 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 "content/browser/device_orientation/data_fetcher_impl_android.h"
#include <string.h>
#include "base/android/jni_android.h"
#include "base/memory/singleton.h"
#include "content/browser/device_orientation/orientation.h"
#include "jni/DeviceMotionAndOrientation_jni.h"
using base::android::AttachCurrentThread;
namespace content {
namespace {
// This should match ProviderImpl::kDesiredSamplingIntervalMs.
// TODO(husky): Make that constant public so we can use it directly.
const int kPeriodInMilliseconds = 100;
} // namespace
DataFetcherImplAndroid::DataFetcherImplAndroid()
: number_active_device_motion_sensors_(0),
device_motion_buffer_(NULL),
is_buffer_ready_(false) {
memset(received_motion_data_, 0, sizeof(received_motion_data_));
device_orientation_.Reset(
Java_DeviceMotionAndOrientation_getInstance(AttachCurrentThread()));
}
DataFetcherImplAndroid::~DataFetcherImplAndroid() {
}
bool DataFetcherImplAndroid::Register(JNIEnv* env) {
return RegisterNativesImpl(env);
}
DataFetcherImplAndroid* DataFetcherImplAndroid::GetInstance() {
return Singleton<DataFetcherImplAndroid,
LeakySingletonTraits<DataFetcherImplAndroid> >::get();
}
const DeviceData* DataFetcherImplAndroid::GetDeviceData(
DeviceData::Type type) {
if (type != DeviceData::kTypeOrientation)
return NULL;
return GetOrientation();
}
const Orientation* DataFetcherImplAndroid::GetOrientation() {
// Do we have a new orientation value? (It's safe to do this outside the lock
// because we only skip the lock if the value is null. We always enter the
// lock if we're going to make use of the new value.)
if (next_orientation_.get()) {
base::AutoLock autolock(next_orientation_lock_);
next_orientation_.swap(current_orientation_);
}
if (!current_orientation_.get())
return new Orientation();
return current_orientation_.get();
}
void DataFetcherImplAndroid::GotOrientation(
JNIEnv*, jobject, double alpha, double beta, double gamma) {
base::AutoLock autolock(next_orientation_lock_);
Orientation* orientation = new Orientation();
orientation->set_alpha(alpha);
orientation->set_beta(beta);
orientation->set_gamma(gamma);
orientation->set_absolute(true);
next_orientation_ = orientation;
}
void DataFetcherImplAndroid::GotAcceleration(
JNIEnv*, jobject, double x, double y, double z) {
device_motion_buffer_->seqlock.WriteBegin();
device_motion_buffer_->data.accelerationX = x;
device_motion_buffer_->data.hasAccelerationX = true;
device_motion_buffer_->data.accelerationY = y;
device_motion_buffer_->data.hasAccelerationY = true;
device_motion_buffer_->data.accelerationZ = z;
device_motion_buffer_->data.hasAccelerationZ = true;
device_motion_buffer_->seqlock.WriteEnd();
if (!is_buffer_ready_) {
received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] = 1;
CheckBufferReadyToRead();
}
}
void DataFetcherImplAndroid::GotAccelerationIncludingGravity(
JNIEnv*, jobject, double x, double y, double z) {
device_motion_buffer_->seqlock.WriteBegin();
device_motion_buffer_->data.accelerationIncludingGravityX = x;
device_motion_buffer_->data.hasAccelerationIncludingGravityX = true;
device_motion_buffer_->data.accelerationIncludingGravityY = y;
device_motion_buffer_->data.hasAccelerationIncludingGravityY = true;
device_motion_buffer_->data.accelerationIncludingGravityZ = z;
device_motion_buffer_->data.hasAccelerationIncludingGravityZ = true;
device_motion_buffer_->seqlock.WriteEnd();
if (!is_buffer_ready_) {
received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] = 1;
CheckBufferReadyToRead();
}
}
void DataFetcherImplAndroid::GotRotationRate(
JNIEnv*, jobject, double alpha, double beta, double gamma) {
device_motion_buffer_->seqlock.WriteBegin();
device_motion_buffer_->data.rotationRateAlpha = alpha;
device_motion_buffer_->data.hasRotationRateAlpha = true;
device_motion_buffer_->data.rotationRateBeta = beta;
device_motion_buffer_->data.hasRotationRateBeta = true;
device_motion_buffer_->data.rotationRateGamma = gamma;
device_motion_buffer_->data.hasRotationRateGamma = true;
device_motion_buffer_->seqlock.WriteEnd();
if (!is_buffer_ready_) {
received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] = 1;
CheckBufferReadyToRead();
}
}
bool DataFetcherImplAndroid::Start(DeviceData::Type event_type) {
DCHECK(!device_orientation_.is_null());
return Java_DeviceMotionAndOrientation_start(
AttachCurrentThread(), device_orientation_.obj(),
reinterpret_cast<jint>(this), static_cast<jint>(event_type),
kPeriodInMilliseconds);
}
void DataFetcherImplAndroid::Stop(DeviceData::Type event_type) {
DCHECK(!device_orientation_.is_null());
Java_DeviceMotionAndOrientation_stop(
AttachCurrentThread(), device_orientation_.obj(),
static_cast<jint>(event_type));
}
int DataFetcherImplAndroid::GetNumberActiveDeviceMotionSensors() {
DCHECK(!device_orientation_.is_null());
return Java_DeviceMotionAndOrientation_getNumberActiveDeviceMotionSensors(
AttachCurrentThread(), device_orientation_.obj());
}
// ----- Shared memory API methods
bool DataFetcherImplAndroid::StartFetchingDeviceMotionData(
DeviceMotionHardwareBuffer* buffer) {
device_motion_buffer_ = buffer;
ClearInternalBuffers();
bool success = Start(DeviceData::kTypeMotion);
// If no motion data can ever be provided, the number of active device motion
// sensors will be zero. In that case flag the shared memory buffer
// as ready to read, as it will not change anyway.
number_active_device_motion_sensors_ = GetNumberActiveDeviceMotionSensors();
CheckBufferReadyToRead();
return success;
}
void DataFetcherImplAndroid::StopFetchingDeviceMotionData() {
Stop(DeviceData::kTypeMotion);
ClearInternalBuffers();
}
void DataFetcherImplAndroid::CheckBufferReadyToRead() {
if (received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] +
received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] +
received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] ==
number_active_device_motion_sensors_) {
device_motion_buffer_->seqlock.WriteBegin();
device_motion_buffer_->data.interval = kPeriodInMilliseconds;
device_motion_buffer_->seqlock.WriteEnd();
SetBufferReadyStatus(true);
}
}
void DataFetcherImplAndroid::SetBufferReadyStatus(bool ready) {
device_motion_buffer_->seqlock.WriteBegin();
device_motion_buffer_->data.allAvailableSensorsAreActive = ready;
device_motion_buffer_->seqlock.WriteEnd();
is_buffer_ready_ = ready;
}
void DataFetcherImplAndroid::ClearInternalBuffers() {
memset(received_motion_data_, 0, sizeof(received_motion_data_));
number_active_device_motion_sensors_ = 0;
SetBufferReadyStatus(false);
}
} // namespace content