mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-28 15:55:22 +00:00
Ensure we release exclusive USB access to controllers when backgrounded. #15694
This commit is contained in:
@@ -21,6 +21,7 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
protected InputThread mInputThread;
|
||||
protected boolean mRunning;
|
||||
protected boolean mFrozen;
|
||||
protected boolean mClaimed;
|
||||
|
||||
public HIDDeviceUSB(HIDDeviceManager manager, UsbDevice usbDevice, int interface_index) {
|
||||
mManager = manager;
|
||||
@@ -29,6 +30,7 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
mInterface = mDevice.getInterface(mInterfaceIndex).getId();
|
||||
mDeviceId = manager.getDeviceIDForIdentifier(getIdentifier());
|
||||
mRunning = false;
|
||||
mClaimed = false;
|
||||
}
|
||||
|
||||
String getIdentifier() {
|
||||
@@ -114,6 +116,7 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
mClaimed = true;
|
||||
|
||||
// Find the endpoints
|
||||
for (int j = 0; j < iface.getEndpointCount(); j++) {
|
||||
@@ -137,6 +140,7 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
// back to the Android system gamepad functionality (and lose our paddles et al).
|
||||
if (mInputEndpoint == null) {
|
||||
Log.w(TAG, "Missing required endpoint on USB device " + getDeviceName());
|
||||
mConnection.releaseInterface(iface);
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
@@ -156,6 +160,11 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mClaimed) {
|
||||
Log.w(TAG, "writeReport() called but some other process currently owns the USB device");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (feature) {
|
||||
int res = -1;
|
||||
int offset = 0;
|
||||
@@ -212,6 +221,12 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
Log.w(TAG, "readReport() called with no device connection");
|
||||
return false;
|
||||
}
|
||||
if (!mClaimed) {
|
||||
if (feature) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (report_number == 0x0) {
|
||||
/* Offset the return buffer by 1, so that the report ID
|
||||
@@ -265,10 +280,13 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
mInputThread = null;
|
||||
}
|
||||
if (mConnection != null) {
|
||||
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
|
||||
mConnection.releaseInterface(iface);
|
||||
if (mClaimed) {
|
||||
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
|
||||
mConnection.releaseInterface(iface);
|
||||
}
|
||||
mConnection.close();
|
||||
mConnection = null;
|
||||
mClaimed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,6 +299,22 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
@Override
|
||||
public void setFrozen(boolean frozen) {
|
||||
mFrozen = frozen;
|
||||
|
||||
/* If we have a valid device connection and the claim state doesn't match what we want, try to correct that. */
|
||||
if (mConnection != null && mClaimed == mFrozen) {
|
||||
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
|
||||
if (frozen) {
|
||||
mClaimed = !mConnection.releaseInterface(iface);
|
||||
if (mClaimed) {
|
||||
Log.e(TAG, "Tried to release claim on USB device, but failed!");
|
||||
}
|
||||
} else {
|
||||
mClaimed = mConnection.claimInterface(iface, true);
|
||||
if (!mClaimed) {
|
||||
Log.e(TAG, "Tried to regain claim on USB device, but failed!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected class InputThread extends Thread {
|
||||
|
||||
@@ -545,7 +545,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
|
||||
if (mHIDDeviceManager != null) {
|
||||
mHIDDeviceManager.setFrozen(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mHasMultiWindow) {
|
||||
pauseNativeThread();
|
||||
}
|
||||
@@ -558,7 +559,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
|
||||
if (mHIDDeviceManager != null) {
|
||||
mHIDDeviceManager.setFrozen(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mHasMultiWindow) {
|
||||
resumeNativeThread();
|
||||
}
|
||||
@@ -631,6 +633,14 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
Log.v(TAG, "onWindowFocusChanged(): " + hasFocus);
|
||||
|
||||
// If we are gaining focus, we can always try to restore our USB devices. If we are losing focus,
|
||||
// only try to relinquish them if we don't have background events allowed (for multi-window Android setups).
|
||||
if (hasFocus || !SDLActivity.nativeGetHintBoolean("SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS", false)) {
|
||||
if (mHIDDeviceManager != null) {
|
||||
mHIDDeviceManager.setFrozen(!hasFocus);
|
||||
}
|
||||
}
|
||||
|
||||
if (SDLActivity.mBrokenLibraries) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user