android: Disable sensors when emulation is paused

This commit is contained in:
SachinVin 2020-06-13 23:00:45 +05:30 committed by bunnei
parent 337da335d6
commit 428b0910ef
5 changed files with 74 additions and 20 deletions

View File

@ -307,6 +307,10 @@ std::string GenerateAnalogParamPackage(int axis_id) {
return param.Serialize(); return param.Serialize();
} }
NDKMotionFactory* NDKMotionHandler() {
return motion.get();
}
void Init() { void Init() {
button = std::make_shared<ButtonFactory>(); button = std::make_shared<ButtonFactory>();
analog = std::make_shared<AnalogFactory>(); analog = std::make_shared<AnalogFactory>();

View File

@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "core/frontend/input.h" #include "core/frontend/input.h"
#include "jni/ndk_motion.h"
namespace InputManager { namespace InputManager {
@ -129,6 +130,9 @@ ButtonFactory* ButtonHandler();
/// Gets the gamepad analog device factory. /// Gets the gamepad analog device factory.
AnalogFactory* AnalogHandler(); AnalogFactory* AnalogHandler();
/// Gets the NDK Motion device factory.
NDKMotionFactory* NDKMotionHandler();
std::string GenerateButtonParamPackage(int type); std::string GenerateButtonParamPackage(int type);
std::string GenerateAnalogButtonParamPackage(int axis, float axis_val); std::string GenerateAnalogButtonParamPackage(int axis, float axis_val);

View File

@ -300,11 +300,13 @@ void Java_org_citra_citra_1emu_NativeLibrary_UnPauseEmulation(JNIEnv* env,
[[maybe_unused]] jclass clazz) { [[maybe_unused]] jclass clazz) {
pause_emulation = false; pause_emulation = false;
running_cv.notify_all(); running_cv.notify_all();
InputManager::NDKMotionHandler()->EnableSensors();
} }
void Java_org_citra_citra_1emu_NativeLibrary_PauseEmulation(JNIEnv* env, void Java_org_citra_citra_1emu_NativeLibrary_PauseEmulation(JNIEnv* env,
[[maybe_unused]] jclass clazz) { [[maybe_unused]] jclass clazz) {
pause_emulation = true; pause_emulation = true;
InputManager::NDKMotionHandler()->DisableSensors();
} }
void Java_org_citra_citra_1emu_NativeLibrary_StopEmulation(JNIEnv* env, void Java_org_citra_citra_1emu_NativeLibrary_StopEmulation(JNIEnv* env,

View File

@ -16,6 +16,8 @@ using Common::Vec3;
} }
class NDKMotion final : public Input::MotionDevice { class NDKMotion final : public Input::MotionDevice {
std::chrono::microseconds update_period;
ASensorManager* sensor_manager = nullptr; ASensorManager* sensor_manager = nullptr;
ALooper* looper = nullptr; ALooper* looper = nullptr;
ASensorEventQueue* event_queue; ASensorEventQueue* event_queue;
@ -60,7 +62,7 @@ class NDKMotion final : public Input::MotionDevice {
return out; return out;
} }
void Construct(std::chrono::microseconds update_period) { void Construct() {
sensor_manager = ASensorManager_getInstanceForPackage("org.citra.citra_emu"); sensor_manager = ASensorManager_getInstanceForPackage("org.citra.citra_emu");
looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
if (!sensor_manager || !looper) { if (!sensor_manager || !looper) {
@ -72,21 +74,8 @@ class NDKMotion final : public Input::MotionDevice {
LOG_ERROR(Input, "Could not create sensor event queue"); LOG_ERROR(Input, "Could not create sensor event queue");
return; return;
} }
const auto init_sensor = [this, update_period](int sensor_type) {
ASensorRef sensor = ASensorManager_getDefaultSensor(sensor_manager, sensor_type);
if (!sensor) {
LOG_ERROR(Input, "Could not find sensor of type {}", sensor_type);
return;
}
int error = ASensorEventQueue_registerSensor(
event_queue, sensor,
std::max(ASensor_getMinDelay(sensor), static_cast<int>(update_period.count())), 0);
if (error < 0)
LOG_ERROR(Input, "Registering sensor returned error code {}", error);
};
init_sensor(ASENSOR_TYPE_ACCELEROMETER); EnableSensors();
init_sensor(ASENSOR_TYPE_GYROSCOPE);
} }
void Destruct() { void Destruct() {
@ -117,10 +106,11 @@ class NDKMotion final : public Input::MotionDevice {
} }
public: public:
NDKMotion(std::chrono::microseconds update_period, bool asynchronous = false) { NDKMotion(std::chrono::microseconds update_period_, bool asynchronous = false)
: update_period(update_period_) {
if (asynchronous) { if (asynchronous) {
poll_thread = std::thread([this, update_period] { poll_thread = std::thread([this] {
Construct(update_period); Construct();
auto start = std::chrono::high_resolution_clock::now(); auto start = std::chrono::high_resolution_clock::now();
while (!stop_polling) { while (!stop_polling) {
Update(); Update();
@ -129,7 +119,7 @@ public:
Destruct(); Destruct();
}); });
} else { } else {
Construct(update_period); Construct();
} }
} }
@ -148,11 +138,59 @@ public:
} }
return {acceleration, rotation}; return {acceleration, rotation};
} }
void EnableSensors() {
const auto init_sensor = [this](int sensor_type) {
ASensorRef sensor = ASensorManager_getDefaultSensor(sensor_manager, sensor_type);
if (!sensor) {
LOG_ERROR(Input, "Could not find sensor of type {}", sensor_type);
return;
}
int error = ASensorEventQueue_registerSensor(
event_queue, sensor,
std::max(ASensor_getMinDelay(sensor), static_cast<int>(update_period.count())), 0);
if (error < 0)
LOG_ERROR(Input, "Registering sensor returned error code {}", error);
};
LOG_TRACE(Input, "Enabling sensors..");
init_sensor(ASENSOR_TYPE_ACCELEROMETER);
init_sensor(ASENSOR_TYPE_GYROSCOPE);
}
void DisableSensors() {
const auto disable_sensor = [this](int sensor_type) {
ASensorRef sensor = ASensorManager_getDefaultSensor(sensor_manager, sensor_type);
if (!sensor) {
LOG_ERROR(Input, "Could not find sensor of type {}", sensor_type);
return;
}
int error = ASensorEventQueue_disableSensor(event_queue, sensor);
if (error < 0)
LOG_ERROR(Input, "Disabling sensor returned error code {}", error);
};
LOG_TRACE(Input, "Disabling sensors..");
disable_sensor(ASENSOR_TYPE_ACCELEROMETER);
disable_sensor(ASENSOR_TYPE_GYROSCOPE);
}
}; };
std::unique_ptr<Input::MotionDevice> NDKMotionFactory::Create(const Common::ParamPackage& params) { std::unique_ptr<Input::MotionDevice> NDKMotionFactory::Create(const Common::ParamPackage& params) {
std::chrono::milliseconds update_period{params.Get("update_period", 4)}; std::chrono::milliseconds update_period{params.Get("update_period", 4)};
return std::make_unique<NDKMotion>(update_period); std::unique_ptr<NDKMotion> ndk_motion = std::make_unique<NDKMotion>(update_period);
ndk_motion_device = ndk_motion.get();
return std::move(ndk_motion);
}
void NDKMotionFactory::EnableSensors() {
if(ndk_motion_device)
ndk_motion_device->EnableSensors();
}
void NDKMotionFactory::DisableSensors() {
if(ndk_motion_device)
ndk_motion_device->DisableSensors();
} }
} // namespace InputManager } // namespace InputManager

View File

@ -18,5 +18,11 @@ public:
* Creates a motion device that obtains data from device sensors * Creates a motion device that obtains data from device sensors
*/ */
std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override; std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override;
void EnableSensors();
void DisableSensors();
private:
NDKMotion* ndk_motion_device;
}; };
} // namespace InputManager } // namespace InputManager