Android: Detect the accelerometer and gyro instead of assuming them

SYSPROP_HAS_ACCELEROMETER was true for every phone and tablet, whether or
not it had the sensor. The activity now tells the native side what the
sensor manager found, which also answers the new SYSPROP_HAS_GYRO. VR
headsets still report neither. Every other platform returns false for the
gyro for now.

The "Use gyroscope" checkbox uses the new property instead of waiting for
gyro data to show up.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-21 12:20:20 +02:00
1 parent 010a9c7e2a
commit fbf0cc2df4
6 files changed
+21 -9

No files matched your search

+1
View File
@@ -163,6 +163,7 @@ enum SystemProperty {
SYSPROP_HAS_KEYBOARD,
SYSPROP_KEYBOARD_IS_SOFT,
SYSPROP_HAS_ACCELEROMETER, // Used to enable/disable tilt input settings
SYSPROP_HAS_GYRO,
SYSPROP_HAS_OPEN_DIRECTORY,
SYSPROP_HAS_LOGIN_DIALOG,
SYSPROP_HAS_TEXT_CLIPBOARD,
-4
View File
@@ -371,10 +371,6 @@ bool GyroActive() {
return g_seenGyro && time_now_d() - g_lastGyroArrival < 0.2;
}
bool HasSeenGyro() {
return g_seenGyro;
}
void ResetTiltEvents() {
// Reset the buttons we have marked pressed.
__CtrlUpdateButtons(0, tiltButtonsDown);
-2
View File
@@ -16,8 +16,6 @@ void ProcessAccelerometerForFusion(float x, float y, float z);
bool ProcessGyro(float x, float y, float z, double timestamp, Lin::Vec3 *gravity);
// True if gyro data arrived recently, in which case the accelerometer shouldn't drive tilt directly.
bool GyroActive();
// Whether we've ever seen gyro data, to decide whether to show the gyro setting.
bool HasSeenGyro();
float GetCurrentYAngle();
+2 -1
View File
@@ -22,6 +22,7 @@
#include "Common/Math/math_util.h"
#include "Common/Log.h"
#include "Common/System/System.h"
#include "Common/Data/Text/I18n.h"
#include "Common/UI/ScrollView.h"
#include "Common/UI/PopupScreens.h"
@@ -113,7 +114,7 @@ void TiltAnalogSettingsScreen::CreateSettingsViews(UI::ViewGroup *settings) {
RecreateViews();
});
typeChoice->SetEnabledPtr(&g_Config.bTiltInputEnabled);
if (TiltEventProcessor::HasSeenGyro()) {
if (System_GetPropertyBool(SYSPROP_HAS_GYRO)) {
settings->Add(new CheckBox(&g_Config.bTiltUseGyro, co->T("Use gyroscope")))->SetEnabledPtr(&g_Config.bTiltInputEnabled);
}
settings->Add(new ItemHeader(co->T("Calibration")));
+12 -1
View File
@@ -164,6 +164,8 @@ static float g_safeInsetRight = 0.0;
static float g_safeInsetTop = 0.0;
static float g_safeInsetBottom = 0.0;
static bool g_hasCameraCutout = false;
static bool g_hasAccelerometer = false;
static bool g_hasGyro = false;
// Global ref. Written on the UI thread under g_activityLock. Other threads go through Android_GetActivity.
static jobject ppssppActivity;
@@ -465,7 +467,10 @@ bool System_GetPropertyBool(SystemProperty prop) {
case SYSPROP_HAS_KEYBOARD:
return deviceType != DEVICE_TYPE_VR;
case SYSPROP_HAS_ACCELEROMETER:
return deviceType == DEVICE_TYPE_MOBILE;
// A headset has the sensors, but tilting it isn't tilt control.
return g_hasAccelerometer && deviceType != DEVICE_TYPE_VR;
case SYSPROP_HAS_GYRO:
return g_hasGyro && deviceType != DEVICE_TYPE_VR;
case SYSPROP_CAN_CREATE_SHORTCUT:
return false; // We can't create shortcuts directly from game code, but we can from the Android UI.
case SYSPROP_DISPLAY_HAS_CAMERA_CUTOUT:
@@ -1299,6 +1304,12 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendMessageFromJava(JNI
g_safeInsetBottom = (float)bottom;
g_hasCameraCutout = cutout != 0;
}
} else if (msg == "sensors") {
int accelerometer, gyro;
if (2 == sscanf(prm.c_str(), "%d:%d", &accelerometer, &gyro)) {
g_hasAccelerometer = accelerometer != 0;
g_hasGyro = gyro != 0;
}
} else if (msg == "inputDeviceConnectedID") {
nextInputDeviceID = (InputDeviceID)parseLong(prm);
} else if (msg == "inputDeviceConnected") {
@@ -726,6 +726,9 @@ public class PpssppActivity extends AppCompatActivity implements SensorEventList
mSensorManager = (SensorManager)getSystemService(Activity.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
String sensors = (mAccelerometer != null ? "1" : "0") + ":" + (mGyroscope != null ? "1" : "0");
Log.i(TAG, "Sensors (accelerometer:gyro): " + sensors);
NativeApp.sendMessageFromJava("sensors", sensors);
surfaceManager = new NativeSurfaceManager(this);
TextRenderer.init(this);
@@ -1067,7 +1070,9 @@ public class PpssppActivity extends AppCompatActivity implements SensorEventList
NativeApp.resume();
}
updateAudioFocus(this.audioManager, this.audioFocusChangeListener);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
if (mAccelerometer != null) {
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
}
if (mGyroscope != null) {
mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME);
}