Преглед изворни кода

Ensure we release exclusive USB access to controllers when backgrounded. #15694

Rachel Blackman пре 17 часа
родитељ
комит
ac177763aa

+ 36 - 2
android-project/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java

@@ -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 {

+ 12 - 2
android-project/app/src/main/java/org/libsdl/app/SDLActivity.java

@@ -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;
         }