[Android] Moved sensor implementation to the right place

This commit is contained in:
Jonathan De Wachter 2014-01-06 05:38:25 +01:00
parent 7daaaa649e
commit 349fe380e4
6 changed files with 239 additions and 196 deletions

View File

@ -52,12 +52,15 @@ namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
ActivityStates* retrieveStates(ANativeActivity* activity)
{
// Hide the ugly cast we find in each callback function
return (ActivityStates*)activity->instance;
}
////////////////////////////////////////////////////////////
static void initializeMain(ActivityStates* states)
{
// Protect from concurent access
@ -72,6 +75,8 @@ static void initializeMain(ActivityStates* states)
AConfiguration_fromAssetManager(states->config, states->activity->assetManager);
}
////////////////////////////////////////////////////////////
static void terminateMain(ActivityStates* states)
{
// Protect from concurent access
@ -82,6 +87,8 @@ static void terminateMain(ActivityStates* states)
ANativeActivity_finish(states->activity);
}
////////////////////////////////////////////////////////////
void* main(ActivityStates* states)
{
// Initialize the thread before giving the hand
@ -111,10 +118,14 @@ void* main(ActivityStates* states)
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
static void onStart(ANativeActivity* activity)
{
}
////////////////////////////////////////////////////////////
static void onResume(ANativeActivity* activity)
{
// Retrieve our activity states from the activity instance
@ -128,6 +139,8 @@ static void onResume(ANativeActivity* activity)
states->pendingEvents.push_back(event);
}
////////////////////////////////////////////////////////////
static void onPause(ANativeActivity* activity)
{
// Retrieve our activity states from the activity instance
@ -141,10 +154,14 @@ static void onPause(ANativeActivity* activity)
states->pendingEvents.push_back(event);
}
////////////////////////////////////////////////////////////
static void onStop(ANativeActivity* activity)
{
}
////////////////////////////////////////////////////////////
static void onDestroy(ANativeActivity* activity)
{
// Retrieve our activity states from the activity instance
@ -186,6 +203,8 @@ static void onDestroy(ANativeActivity* activity)
// The application should now terminate
}
////////////////////////////////////////////////////////////
static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window)
{
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
@ -209,6 +228,8 @@ static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* wind
}
}
////////////////////////////////////////////////////////////
static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window)
{
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
@ -232,14 +253,20 @@ static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* wi
}
}
////////////////////////////////////////////////////////////
static void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window)
{
}
////////////////////////////////////////////////////////////
static void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* window)
{
}
////////////////////////////////////////////////////////////
static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue)
{
// Retrieve our activity states from the activity instance
@ -254,6 +281,8 @@ static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue)
}
}
////////////////////////////////////////////////////////////
static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue)
{
// Retrieve our activity states from the activity instance
@ -268,16 +297,14 @@ static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue)
}
}
////////////////////////////////////////////////////////////
static void onWindowFocusChanged(ANativeActivity* activity, int focused)
{
// Retrieve our activity states from the activity instance
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
// Disable or enable sensors according the window focused state
if (states->enableSensors && states->disableSensors)
focused ? states->enableSensors() : states->disableSensors();
}
////////////////////////////////////////////////////////////
static void onContentRectChanged(ANativeActivity* activity, const ARect* rect)
{
// Retrieve our activity states from the activity instance
@ -293,10 +320,14 @@ static void onContentRectChanged(ANativeActivity* activity, const ARect* rect)
states->pendingEvents.push_back(event);
}
////////////////////////////////////////////////////////////
static void onConfigurationChanged(ANativeActivity* activity)
{
}
////////////////////////////////////////////////////////////
static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen)
{
*outLen = 0;
@ -304,16 +335,22 @@ static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen)
return NULL;
}
////////////////////////////////////////////////////////////
static void onLowMemory(ANativeActivity* activity)
{
}
////////////////////////////////////////////////////////////
int dummyProcessEvent(int fd, int events, void* data)
{
// Do nothing
return 0;
}
////////////////////////////////////////////////////////////
void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize)
{
// Create an activity states (will keep us in the know, about events we care)

View File

@ -62,9 +62,6 @@ struct ActivityStates
std::vector<Event> pendingEvents;
int (*processEvent)(int fd, int events, void* data);
void (*enableSensors)();
void (*disableSensors)();
std::map<int, Vector2i> touchEvents;
Vector2i mousePosition;
bool isButtonPressed[Mouse::ButtonCount];

View File

@ -26,101 +26,8 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/JoystickImpl.hpp>
#include <SFML/System/Android/Activity.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Vector3.hpp>
#include <android/looper.h>
#include <android/sensor.h>
namespace
{
enum
{
Accelerometer,
Gyroscope,
Magnetometer,
UserAcceleration,
AbsoluteOrientation,
Count
};
static const int32_t updateInterval = (1000L/60)*1000;
ALooper* looper;
ASensorManager* sensorManager;
ASensorEventQueue* sensorEventQueue;
struct
{
const ASensor* device;
sf::Vector3f data;
} sensors[Count];
bool areSensorsEnabled;
int processSensorEvents(int fd, int events, void* data)
{
ASensorEvent event;
while (ASensorEventQueue_getEvents(sensorEventQueue, &event, 1) > 0)
{
// Cache the latest data
switch (event.sensor)
{
case ASENSOR_TYPE_ACCELEROMETER:
sensors[Accelerometer].data.x = event.acceleration.x;
sensors[Accelerometer].data.y = event.acceleration.y;
sensors[Accelerometer].data.z = event.acceleration.z;
break;
case ASENSOR_TYPE_GYROSCOPE:
sensors[Gyroscope].data.x = event.vector.x;
sensors[Gyroscope].data.y = event.vector.y;
sensors[Gyroscope].data.z = event.vector.z;
break;
case ASENSOR_TYPE_MAGNETIC_FIELD:
sensors[Magnetometer].data.x = event.magnetic.x;
sensors[Magnetometer].data.y = event.magnetic.y;
sensors[Magnetometer].data.z = event.magnetic.z;
break;
}
}
return 1;
}
void enableSensors()
{
// (Re)start monitoring sensors with 60 events per second
for (unsigned int i = 0; i < Count; ++i)
{
if (sensors[i].device != NULL)
{
ASensorEventQueue_enableSensor(sensorEventQueue, sensors[i].device);
ASensorEventQueue_setEventRate(sensorEventQueue, sensors[i].device, updateInterval);
}
}
areSensorsEnabled = true;
}
void disableSensors()
{
// Stop monitoring sensors (it avoids consuming battery)
for (unsigned int i = 0; i < Count; ++i)
{
if (sensors[i].device != NULL)
{
ASensorEventQueue_disableSensor(sensorEventQueue, sensors[i].device);
}
}
areSensorsEnabled = false;
}
}
namespace sf
{
namespace priv
@ -128,46 +35,7 @@ namespace priv
////////////////////////////////////////////////////////////
void JoystickImpl::initialize()
{
// Register callbacks to pause sensors when the device is in standby mode
ActivityStates* states = getActivity(NULL);
{
Lock lock(states->mutex);
states->enableSensors = enableSensors;
states->disableSensors = disableSensors;
}
// Get the unique sensor manager
sensorManager = ASensorManager_getInstance();
// Prepare available sensors
sensors[Accelerometer].device = ASensorManager_getDefaultSensor(sensorManager,
ASENSOR_TYPE_ACCELEROMETER);
sensors[Gyroscope].device = ASensorManager_getDefaultSensor(sensorManager,
ASENSOR_TYPE_GYROSCOPE);
sensors[Magnetometer].device = ASensorManager_getDefaultSensor(sensorManager,
ASENSOR_TYPE_MAGNETIC_FIELD);
// User acceleration and absolute orientation sensors are unavailable on Android
// (at least, unavailable from the android C API)
sensors[UserAcceleration].device = NULL;
sensors[AbsoluteOrientation].device = NULL;
// Get the looper associated with this thread
looper = ALooper_forThread();
// Create the sensor events queue and attach it to the looper
sensorEventQueue = ASensorManager_createEventQueue(sensorManager, looper,
1, &processSensorEvents, NULL);
// Set the event rate (not to consume too much battery)
ASensorEventQueue_setEventRate(sensorEventQueue, sensors[Accelerometer].device, updateInterval);
ASensorEventQueue_setEventRate(sensorEventQueue, sensors[Gyroscope].device, updateInterval);
ASensorEventQueue_setEventRate(sensorEventQueue, sensors[Magnetometer].device, updateInterval);
// Start monitoring sensors
enableSensors();
// To implement
}
@ -175,33 +43,22 @@ void JoystickImpl::initialize()
////////////////////////////////////////////////////////////
void JoystickImpl::cleanup()
{
// Stop monitoring sensors
disableSensors();
// Detach the sensor events queue from the looper and destroy it
ASensorManager_destroyEventQueue(sensorManager, sensorEventQueue);
// To implement
}
////////////////////////////////////////////////////////////
bool JoystickImpl::isConnected(unsigned int index)
{
// If sensors aren't paused and the requested sensor available
return (areSensorsEnabled && sensors[index].device);
// To implement
return false;
}
////////////////////////////////////////////////////////////
bool JoystickImpl::open(unsigned int index)
{
// Save the index if sensor is available
if(sensors[index].device)
{
m_index = index;
return true;
}
// To implement
return false;
}
@ -209,41 +66,23 @@ bool JoystickImpl::open(unsigned int index)
////////////////////////////////////////////////////////////
void JoystickImpl::close()
{
// Nothing to do
// To implement
}
////////////////////////////////////////////////////////////
JoystickCaps JoystickImpl::getCapabilities() const
{
JoystickCaps caps;
// All the connected joysticks have (X, Y, Z) axes
caps.axes[Joystick::X] = true;
caps.axes[Joystick::Y] = true;
caps.axes[Joystick::Z] = true;
return caps;
// To implement
return JoystickCaps();
}
////////////////////////////////////////////////////////////
JoystickState JoystickImpl::update()
{
JoystickState state;
// Poll latest sensor events
ALooper_pollAll(0, NULL, NULL, NULL);
// Always connected
state.connected = sensors[m_index].device ? true : false;
// Use our cache
state.axes[Joystick::X] = sensors[m_index].data.x;
state.axes[Joystick::Y] = sensors[m_index].data.y;
state.axes[Joystick::Z] = sensors[m_index].data.z;
return state;
// To implement
return JoystickState();
}
} // namespace priv

View File

@ -28,8 +28,19 @@
#include <SFML/Window/SensorImpl.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Time.hpp>
#include <SFML/System/Android/Activity.hpp>
#include <android/looper.h>
namespace
{
ALooper* looper;
ASensorManager* sensorManager;
ASensorEventQueue* sensorEventQueue;
std::queue<sf::Sensor::Data> sensorData[sf::Sensor::Count];
}
namespace sf
{
namespace priv
@ -37,21 +48,55 @@ namespace priv
////////////////////////////////////////////////////////////
void SensorImpl::initialize()
{
// To implement
// Get the looper associated with this thread
looper = ALooper_forThread();
// Get the unique sensor manager
sensorManager = ASensorManager_getInstance();
// Create the sensor events queue and attach it to the looper
sensorEventQueue = ASensorManager_createEventQueue(sensorManager, looper,
1, &processSensorEvents, NULL);
}
////////////////////////////////////////////////////////////
void SensorImpl::cleanup()
{
// To implement
{
// Detach the sensor events queue from the looper and destroy it
ASensorManager_destroyEventQueue(sensorManager, sensorEventQueue);
}
////////////////////////////////////////////////////////////
SensorCaps& SensorImpl::initialize(unsigned int type)
{
// To implement
SensorCaps capabilities;
capabilities.available = false;
// Get the default sensor matching the type
m_sensor = getDefaultSensor(type);
static SensorCaps capabilities;
if (!m_sensor)
{
// Sensor not available, stop here
capabilities.available = false;
return capabilities;
}
else
capabilities.available = true;
// Get the sensor resolution
capabilities.resolution = ASensor_getResolution(m_sensor);
// Get the minimum delay allowed between events
capabilities.minimumDelay = microseconds(ASensor_getMinDelay(m_sensor));
// To get the maximum range we'll need to use JNI since it's not available from C (todo)
capabilities.maximumRange = Vector2f();
// Initialize SensorState attributes
setRefreshRate(capabilities.minimumDelay); // Set the event rate (not to consume too much battery)
setEnable(false); // Disable the sensor by default (initialize SensorState on the fly)
m_state.pendingData = &sensorData[type];
return capabilities;
}
@ -59,34 +104,126 @@ SensorCaps& SensorImpl::initialize(unsigned int type)
////////////////////////////////////////////////////////////
void SensorImpl::terminate()
{
// To implement
// Nothing to do
}
////////////////////////////////////////////////////////////
SensorState& SensorImpl::update()
{
// To implement
static SensorState state;
return state;
// Update our pending sensor data lists
ALooper_pollAll(0, NULL, NULL, NULL);
return m_state;
}
////////////////////////////////////////////////////////////
bool SensorImpl::isEnable()
{
// To implement
return false;
return m_state.enabled;
}
////////////////////////////////////////////////////////////
void SensorImpl::setEnable(bool enable)
{
// To implement
if (enable)
ASensorEventQueue_enableSensor(sensorEventQueue, m_sensor);
else
ASensorEventQueue_disableSensor(sensorEventQueue, m_sensor);
m_state.enabled = enable;
}
////////////////////////////////////////////////////////////
void SensorImpl::setRefreshRate(const Time& rate)
{
// To implement
ASensorEventQueue_setEventRate(sensorEventQueue, m_sensor, rate.asMicroseconds());
m_state.refreshRate = rate;
}
////////////////////////////////////////////////////////////
ASensor const* SensorImpl::getDefaultSensor(unsigned int type)
{
int sensorType = 0;
switch(type)
{
case Sensor::Accelerometer:
sensorType = ASENSOR_TYPE_ACCELEROMETER;
break;
case Sensor::Magnetometer:
sensorType = ASENSOR_TYPE_MAGNETIC_FIELD;
break;
case Sensor::Gyroscope:
sensorType = ASENSOR_TYPE_GYROSCOPE;
break;
case Sensor::Light:
sensorType = ASENSOR_TYPE_LIGHT;
break;
case Sensor::Proximity:
sensorType = ASENSOR_TYPE_PROXIMITY;
break;
default:
// The other sensors are unavailable on Android from the android C API
return NULL;
}
return ASensorManager_getDefaultSensor(sensorManager, sensorType);
}
////////////////////////////////////////////////////////////
int SensorImpl::processSensorEvents(int fd, int events, void* data)
{
ASensorEvent event;
while (ASensorEventQueue_getEvents(sensorEventQueue, &event, 1) > 0)
{
Sensor::Data data;
Sensor::Type type;
switch (event.sensor)
{
case ASENSOR_TYPE_ACCELEROMETER:
type = Sensor::Accelerometer;
data.acceleration.x = event.acceleration.x;
data.acceleration.y = event.acceleration.y;
data.acceleration.z = event.acceleration.z;
break;
case ASENSOR_TYPE_GYROSCOPE:
type = Sensor::Gyroscope;
data.vector.x = event.vector.x;
data.vector.y = event.vector.y;
data.vector.z = event.vector.z;
break;
case ASENSOR_TYPE_MAGNETIC_FIELD:
type = Sensor::Magnetometer;
data.magnetic.x = event.magnetic.x;
data.magnetic.y = event.magnetic.y;
data.magnetic.z = event.magnetic.z;
break;
case ASENSOR_TYPE_LIGHT:
type = Sensor::Light;
data.light = event.light;
break;
case ASENSOR_TYPE_PROXIMITY:
type = Sensor::Proximity;
break;
}
sensorData[type].push(data);
}
return 1;
}
} // namespace priv

View File

@ -25,6 +25,10 @@
#ifndef SFML_SENSORIMPLANDROID_HPP
#define SFML_SENSORIMPLANDROID_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <android/sensor.h>
namespace sf
{
@ -97,7 +101,36 @@ public :
///
////////////////////////////////////////////////////////////
void setRefreshRate(const Time& rate);
private:
////////////////////////////////////////////////////////////
/// \brief Get the default Android sensor matching the sensor type
///
/// \param type Type of the sensor
///
/// \return The default Android sensor, NULL otherwise
///
////////////////////////////////////////////////////////////
ASensor const* getDefaultSensor(unsigned int type);
////////////////////////////////////////////////////////////
/// \brief Process the pending sensor data available and add them to our lists
///
/// \param fd File descriptor
/// \param events Bitmask of the poll events that were triggered
/// \param data Data pointer supplied
///
/// \return Whether it should continue (1) or unregister the callback (0)
///
////////////////////////////////////////////////////////////
static int processSensorEvents(int fd, int events, void* data);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
const ASensor* m_sensor; ///< Android sensor structure
unsigned int m_index; ///< Index of the sensor
SensorState m_state; ///< Sensor state
};
} // namespace priv

View File

@ -189,7 +189,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
{
if (AInputQueue_preDispatchEvent(states->inputQueue, _event))
return 1;
int32_t handled = 0;
int32_t type = AInputEvent_getType(_event);