diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp index 873154dd5..cf2fc51ed 100644 --- a/src/SFML/Main/MainAndroid.cpp +++ b/src/SFML/Main/MainAndroid.cpp @@ -67,13 +67,9 @@ static void initializeMain(ActivityStates* states) ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); states->looper = looper; - // Prepare the sensor event queue - states->sensorEventQueue = ASensorManager_createEventQueue(states->sensorManager, states->looper, 2, NULL, (void*)&sf::priv::processSensorEvents); - // Get the default configuration states->config = AConfiguration_new(); AConfiguration_fromAssetManager(states->config, states->activity->assetManager); - } static void terminateMain(ActivityStates* states) @@ -277,23 +273,9 @@ static void onWindowFocusChanged(ANativeActivity* activity, int focused) // Retrieve our activity states from the activity instance sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); - if (focused) - { - // We start monitoring the accelerometer with 60 events per second - if (states->accelerometerSensor != NULL) - { - ASensorEventQueue_enableSensor(states->sensorEventQueue, states->accelerometerSensor); - ASensorEventQueue_setEventRate(states->sensorEventQueue, states->accelerometerSensor, (1000L/60)*1000); - } - } - else - { - // We stop monitoring the accelerometer (it avoids consuming battery) - if (states->accelerometerSensor != NULL) - { - ASensorEventQueue_disableSensor(states->sensorEventQueue, states->accelerometerSensor); - } - } + // 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) @@ -345,10 +327,6 @@ void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_ states->inputQueue = NULL; states->config = NULL; - states->sensorManager = ASensorManager_getInstance(); - states->accelerometerSensor = ASensorManager_getDefaultSensor(states->sensorManager, ASENSOR_TYPE_ACCELEROMETER); - states->sensorEventQueue = NULL; - states->display = eglCheck(eglGetDisplay(EGL_DEFAULT_DISPLAY)); // As the input queue will be created before the SFML window, we need to use diff --git a/src/SFML/System/Android/Activity.hpp b/src/SFML/System/Android/Activity.hpp index b05081d1b..69327edc8 100644 --- a/src/SFML/System/Android/Activity.hpp +++ b/src/SFML/System/Android/Activity.hpp @@ -51,10 +51,6 @@ struct ActivityStates AInputQueue* inputQueue; AConfiguration* config; - ASensorManager* sensorManager; - const ASensor* accelerometerSensor; - ASensorEventQueue* sensorEventQueue; - EGLDisplay display; EglContext* context; @@ -66,6 +62,9 @@ struct ActivityStates std::vector pendingEvents; int (*processEvent)(int fd, int events, void* data); + void (*enableSensors)(); + void (*disableSensors)(); + std::map touchEvents; bool mainOver; diff --git a/src/SFML/Window/Android/JoystickImpl.cpp b/src/SFML/Window/Android/JoystickImpl.cpp index a8437e68b..13fed1291 100644 --- a/src/SFML/Window/Android/JoystickImpl.cpp +++ b/src/SFML/Window/Android/JoystickImpl.cpp @@ -26,8 +26,101 @@ // Headers //////////////////////////////////////////////////////////// #include +#include +#include +#include +#include +#include +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 @@ -35,25 +128,80 @@ 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(); } + //////////////////////////////////////////////////////////// void JoystickImpl::cleanup() { + // Stop monitoring sensors + disableSensors(); + + // Detach the sensor events queue from the looper and destroy it + ASensorManager_destroyEventQueue(sensorManager, sensorEventQueue); } //////////////////////////////////////////////////////////// bool JoystickImpl::isConnected(unsigned int index) { - return false; + // If sensors aren't paused and the requested sensor available + return (areSensorsEnabled && sensors[index].device); } //////////////////////////////////////////////////////////// bool JoystickImpl::open(unsigned int index) { + // Save the index if sensor is available + if(sensors[index].device) + { + m_index = index; + + return true; + } + return false; } @@ -61,18 +209,41 @@ bool JoystickImpl::open(unsigned int index) //////////////////////////////////////////////////////////// void JoystickImpl::close() { + // Nothing to do } //////////////////////////////////////////////////////////// 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; } //////////////////////////////////////////////////////////// -JoystickState JoystickImpl::JoystickImpl::update() +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; } } // namespace priv