From 42283e61bbbfbe41726ff1c32f0ddd197574903f Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 18 Mar 2020 13:36:35 -0700 Subject: [PATCH] Update to SDL 2.0.12 --- NOTICE.md | 2 +- project/lib/sdl | 2 +- .../main/java/org/libsdl/app/HIDDevice.java | 3 + .../app/HIDDeviceBLESteamController.java | 22 +-- .../java/org/libsdl/app/HIDDeviceManager.java | 135 ++++++++--------- .../java/org/libsdl/app/HIDDeviceUSB.java | 35 +++-- .../main/java/org/libsdl/app/SDLActivity.java | 136 +++++++++++++----- 7 files changed, 196 insertions(+), 139 deletions(-) diff --git a/NOTICE.md b/NOTICE.md index 7979d4baf..e735e185b 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -46,7 +46,7 @@ This product bundles pixman 0.32.8, which is available under an This product bundles libpng 1.6.12, which is available under a "zlib" (BSD-style) license. For details, see [project/lib/png/](project/lib). -This product bundles SDL 2.10, which is available under a +This product bundles SDL 2.0.12, which is available under a "zlib" (BSD-style) license. For details, see [project/lib/sdl/](project/lib). This product bundles tinyfiledialogs 2.9.3, which is available under a diff --git a/project/lib/sdl b/project/lib/sdl index df0aae715..1bd71d9c1 160000 --- a/project/lib/sdl +++ b/project/lib/sdl @@ -1 +1 @@ -Subproject commit df0aae715053d50d02cd2e205ae98bc69b2a12ac +Subproject commit 1bd71d9c11fab90200566a2ad23c1a7274dad12f diff --git a/templates/android/template/app/src/main/java/org/libsdl/app/HIDDevice.java b/templates/android/template/app/src/main/java/org/libsdl/app/HIDDevice.java index aa358d1fc..955df5d14 100644 --- a/templates/android/template/app/src/main/java/org/libsdl/app/HIDDevice.java +++ b/templates/android/template/app/src/main/java/org/libsdl/app/HIDDevice.java @@ -1,5 +1,7 @@ package org.libsdl.app; +import android.hardware.usb.UsbDevice; + interface HIDDevice { public int getId(); @@ -9,6 +11,7 @@ interface HIDDevice public int getVersion(); public String getManufacturerName(); public String getProductName(); + public UsbDevice getDevice(); public boolean open(); public int sendFeatureReport(byte[] report); public int sendOutputReport(byte[] report); diff --git a/templates/android/template/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java b/templates/android/template/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java index 51538faed..94a28189b 100644 --- a/templates/android/template/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java +++ b/templates/android/template/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java @@ -9,6 +9,7 @@ import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothGattService; +import android.hardware.usb.UsbDevice; import android.os.Handler; import android.os.Looper; import android.util.Log; @@ -165,13 +166,13 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe mHandler = new Handler(Looper.getMainLooper()); mGatt = connectGatt(); - final HIDDeviceBLESteamController finalThis = this; - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - finalThis.checkConnectionForChromebookIssue(); - } - }, CHROMEBOOK_CONNECTION_CHECK_INTERVAL); + // final HIDDeviceBLESteamController finalThis = this; + // mHandler.postDelayed(new Runnable() { + // @Override + // public void run() { + // finalThis.checkConnectionForChromebookIssue(); + // } + // }, CHROMEBOOK_CONNECTION_CHECK_INTERVAL); } public String getIdentifier() { @@ -469,7 +470,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe // Only register controller with the native side once it has been fully configured if (!isRegistered()) { Log.v(TAG, "Registering Steam Controller with ID: " + getId()); - mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0); + mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0); setRegistered(); } } @@ -563,6 +564,11 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe return "Steam Controller"; } + @Override + public UsbDevice getDevice() { + return null; + } + @Override public boolean open() { return true; diff --git a/templates/android/template/app/src/main/java/org/libsdl/app/HIDDeviceManager.java b/templates/android/template/app/src/main/java/org/libsdl/app/HIDDeviceManager.java index 241775d46..56f677e66 100644 --- a/templates/android/template/app/src/main/java/org/libsdl/app/HIDDeviceManager.java +++ b/templates/android/template/app/src/main/java/org/libsdl/app/HIDDeviceManager.java @@ -19,8 +19,9 @@ import android.hardware.usb.*; import android.os.Handler; import android.os.Looper; -import java.util.HashMap; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; public class HIDDeviceManager { @@ -50,7 +51,6 @@ public class HIDDeviceManager { private Context mContext; private HashMap mDevicesById = new HashMap(); - private HashMap mUSBDevices = new HashMap(); private HashMap mBluetoothDevices = new HashMap(); private int mNextDeviceId = 0; private SharedPreferences mSharedPreferences = null; @@ -241,31 +241,20 @@ public class HIDDeviceManager { } } - private boolean isHIDDeviceUSB(UsbDevice usbDevice) { - for (int interface_number = 0; interface_number < usbDevice.getInterfaceCount(); ++interface_number) { - if (isHIDDeviceInterface(usbDevice, interface_number)) { - return true; - } - } - return false; - } - - private boolean isHIDDeviceInterface(UsbDevice usbDevice, int interface_number) { - UsbInterface usbInterface = usbDevice.getInterface(interface_number); + private boolean isHIDDeviceInterface(UsbDevice usbDevice, UsbInterface usbInterface) { if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_HID) { return true; } - if (interface_number == 0) { - if (isXbox360Controller(usbDevice, usbInterface) || isXboxOneController(usbDevice, usbInterface)) { - return true; - } + if (isXbox360Controller(usbDevice, usbInterface) || isXboxOneController(usbDevice, usbInterface)) { + return true; } return false; } private boolean isXbox360Controller(UsbDevice usbDevice, UsbInterface usbInterface) { final int XB360_IFACE_SUBCLASS = 93; - final int XB360_IFACE_PROTOCOL = 1; // Wired only + final int XB360_IFACE_PROTOCOL = 1; // Wired + final int XB360W_IFACE_PROTOCOL = 129; // Wireless final int[] SUPPORTED_VENDORS = { 0x0079, // GPD Win 2 0x044f, // Thrustmaster @@ -275,8 +264,9 @@ public class HIDDeviceManager { 0x06a3, // Saitek 0x0738, // Mad Catz 0x07ff, // Mad Catz - 0x0e6f, // Unknown + 0x0e6f, // PDP 0x0f0d, // Hori + 0x1038, // SteelSeries 0x11c9, // Nacon 0x12ab, // Unknown 0x1430, // RedOctane @@ -291,7 +281,8 @@ public class HIDDeviceManager { if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC && usbInterface.getInterfaceSubclass() == XB360_IFACE_SUBCLASS && - usbInterface.getInterfaceProtocol() == XB360_IFACE_PROTOCOL) { + (usbInterface.getInterfaceProtocol() == XB360_IFACE_PROTOCOL || + usbInterface.getInterfaceProtocol() == XB360W_IFACE_PROTOCOL)) { int vendor_id = usbDevice.getVendorId(); for (int supportedVid : SUPPORTED_VENDORS) { if (vendor_id == supportedVid) { @@ -308,13 +299,15 @@ public class HIDDeviceManager { final int[] SUPPORTED_VENDORS = { 0x045e, // Microsoft 0x0738, // Mad Catz - 0x0e6f, // Unknown + 0x0e6f, // PDP 0x0f0d, // Hori 0x1532, // Razer Wildcat 0x24c6, // PowerA + 0x2e24, // Hyperkin }; - if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC && + if (usbInterface.getId() == 0 && + usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC && usbInterface.getInterfaceSubclass() == XB1_IFACE_SUBCLASS && usbInterface.getInterfaceProtocol() == XB1_IFACE_PROTOCOL) { int vendor_id = usbDevice.getVendorId(); @@ -328,45 +321,45 @@ public class HIDDeviceManager { } private void handleUsbDeviceAttached(UsbDevice usbDevice) { - if (isHIDDeviceUSB(usbDevice)) { - connectHIDDeviceUSB(usbDevice); - } + connectHIDDeviceUSB(usbDevice); } private void handleUsbDeviceDetached(UsbDevice usbDevice) { - HIDDeviceUSB device = mUSBDevices.get(usbDevice); - if (device == null) - return; - - int id = device.getId(); - mUSBDevices.remove(usbDevice); - mDevicesById.remove(id); - device.shutdown(); - HIDDeviceDisconnected(id); + List devices = new ArrayList(); + for (HIDDevice device : mDevicesById.values()) { + if (usbDevice.equals(device.getDevice())) { + devices.add(device.getId()); + } + } + for (int id : devices) { + HIDDevice device = mDevicesById.get(id); + mDevicesById.remove(id); + device.shutdown(); + HIDDeviceDisconnected(id); + } } private void handleUsbDevicePermission(UsbDevice usbDevice, boolean permission_granted) { - HIDDeviceUSB device = mUSBDevices.get(usbDevice); - if (device == null) - return; - - boolean opened = false; - if (permission_granted) { - opened = device.open(); + for (HIDDevice device : mDevicesById.values()) { + if (usbDevice.equals(device.getDevice())) { + boolean opened = false; + if (permission_granted) { + opened = device.open(); + } + HIDDeviceOpenResult(device.getId(), opened); + } } - HIDDeviceOpenResult(device.getId(), opened); } private void connectHIDDeviceUSB(UsbDevice usbDevice) { synchronized (this) { - for (int interface_number = 0; interface_number < usbDevice.getInterfaceCount(); interface_number++) { - if (isHIDDeviceInterface(usbDevice, interface_number)) { - HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_number); + for (int interface_index = 0; interface_index < usbDevice.getInterfaceCount(); interface_index++) { + UsbInterface usbInterface = usbDevice.getInterface(interface_index); + if (isHIDDeviceInterface(usbDevice, usbInterface)) { + HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_index); int id = device.getId(); - mUSBDevices.put(usbDevice, device); mDevicesById.put(id, device); - HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), interface_number); - break; + HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol()); } } } @@ -563,33 +556,27 @@ public class HIDDeviceManager { ////////////////////////////////////////////////////////////////////////////////////////////////////// public boolean openDevice(int deviceID) { + Log.v(TAG, "openDevice deviceID=" + deviceID); + HIDDevice device = getDevice(deviceID); + if (device == null) { + HIDDeviceDisconnected(deviceID); + return false; + } + // Look to see if this is a USB device and we have permission to access it - for (HIDDeviceUSB device : mUSBDevices.values()) { - if (deviceID == device.getId()) { - UsbDevice usbDevice = device.getDevice(); - if (!mUsbManager.hasPermission(usbDevice)) { - HIDDeviceOpenPending(deviceID); - try { - mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), 0)); - } catch (Exception e) { - Log.v(TAG, "Couldn't request permission for USB device " + usbDevice); - HIDDeviceOpenResult(deviceID, false); - } - return false; - } - break; + UsbDevice usbDevice = device.getDevice(); + if (usbDevice != null && !mUsbManager.hasPermission(usbDevice)) { + HIDDeviceOpenPending(deviceID); + try { + mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), 0)); + } catch (Exception e) { + Log.v(TAG, "Couldn't request permission for USB device " + usbDevice); + HIDDeviceOpenResult(deviceID, false); } + return false; } try { - Log.v(TAG, "openDevice deviceID=" + deviceID); - HIDDevice device; - device = getDevice(deviceID); - if (device == null) { - HIDDeviceDisconnected(deviceID); - return false; - } - return device.open(); } catch (Exception e) { Log.e(TAG, "Got exception: " + Log.getStackTraceString(e)); @@ -599,7 +586,7 @@ public class HIDDeviceManager { public int sendOutputReport(int deviceID, byte[] report) { try { - Log.v(TAG, "sendOutputReport deviceID=" + deviceID + " length=" + report.length); + //Log.v(TAG, "sendOutputReport deviceID=" + deviceID + " length=" + report.length); HIDDevice device; device = getDevice(deviceID); if (device == null) { @@ -616,7 +603,7 @@ public class HIDDeviceManager { public int sendFeatureReport(int deviceID, byte[] report) { try { - Log.v(TAG, "sendFeatureReport deviceID=" + deviceID + " length=" + report.length); + //Log.v(TAG, "sendFeatureReport deviceID=" + deviceID + " length=" + report.length); HIDDevice device; device = getDevice(deviceID); if (device == null) { @@ -633,7 +620,7 @@ public class HIDDeviceManager { public boolean getFeatureReport(int deviceID, byte[] report) { try { - Log.v(TAG, "getFeatureReport deviceID=" + deviceID); + //Log.v(TAG, "getFeatureReport deviceID=" + deviceID); HIDDevice device; device = getDevice(deviceID); if (device == null) { @@ -672,7 +659,7 @@ public class HIDDeviceManager { private native void HIDDeviceRegisterCallback(); private native void HIDDeviceReleaseCallback(); - native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number); + native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol); native void HIDDeviceOpenPending(int deviceID); native void HIDDeviceOpenResult(int deviceID, boolean opened); native void HIDDeviceDisconnected(int deviceID); diff --git a/templates/android/template/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java b/templates/android/template/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java index c9fc58ece..33816e344 100644 --- a/templates/android/template/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java +++ b/templates/android/template/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java @@ -11,6 +11,7 @@ class HIDDeviceUSB implements HIDDevice { protected HIDDeviceManager mManager; protected UsbDevice mDevice; + protected int mInterfaceIndex; protected int mInterface; protected int mDeviceId; protected UsbDeviceConnection mConnection; @@ -20,16 +21,17 @@ class HIDDeviceUSB implements HIDDevice { protected boolean mRunning; protected boolean mFrozen; - public HIDDeviceUSB(HIDDeviceManager manager, UsbDevice usbDevice, int interface_number) { + public HIDDeviceUSB(HIDDeviceManager manager, UsbDevice usbDevice, int interface_index) { mManager = manager; mDevice = usbDevice; - mInterface = interface_number; + mInterfaceIndex = interface_index; + mInterface = mDevice.getInterface(mInterfaceIndex).getId(); mDeviceId = manager.getDeviceIDForIdentifier(getIdentifier()); mRunning = false; } public String getIdentifier() { - return String.format("%s/%x/%x", mDevice.getDeviceName(), mDevice.getVendorId(), mDevice.getProductId()); + return String.format("%s/%x/%x/%d", mDevice.getDeviceName(), mDevice.getVendorId(), mDevice.getProductId(), mInterfaceIndex); } @Override @@ -88,6 +90,7 @@ class HIDDeviceUSB implements HIDDevice { return result; } + @Override public UsbDevice getDevice() { return mDevice; } @@ -104,19 +107,15 @@ class HIDDeviceUSB implements HIDDevice { return false; } - // Force claim all interfaces - for (int i = 0; i < mDevice.getInterfaceCount(); i++) { - UsbInterface iface = mDevice.getInterface(i); - - if (!mConnection.claimInterface(iface, true)) { - Log.w(TAG, "Failed to claim interfaces on USB device " + getDeviceName()); - close(); - return false; - } + // Force claim our interface + UsbInterface iface = mDevice.getInterface(mInterfaceIndex); + if (!mConnection.claimInterface(iface, true)) { + Log.w(TAG, "Failed to claim interfaces on USB device " + getDeviceName()); + close(); + return false; } // Find the endpoints - UsbInterface iface = mDevice.getInterface(mInterface); for (int j = 0; j < iface.getEndpointCount(); j++) { UsbEndpoint endpt = iface.getEndpoint(j); switch (endpt.getDirection()) { @@ -166,7 +165,7 @@ class HIDDeviceUSB implements HIDDevice { UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_OUT, 0x09/*HID set_report*/, (3/*HID feature*/ << 8) | report_number, - 0, + mInterface, report, offset, length, 1000/*timeout millis*/); @@ -210,7 +209,7 @@ class HIDDeviceUSB implements HIDDevice { UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_IN, 0x01/*HID get_report*/, (3/*HID feature*/ << 8) | report_number, - 0, + mInterface, report, offset, length, 1000/*timeout millis*/); @@ -250,10 +249,8 @@ class HIDDeviceUSB implements HIDDevice { mInputThread = null; } if (mConnection != null) { - for (int i = 0; i < mDevice.getInterfaceCount(); i++) { - UsbInterface iface = mDevice.getInterface(i); - mConnection.releaseInterface(iface); - } + UsbInterface iface = mDevice.getInterface(mInterfaceIndex); + mConnection.releaseInterface(iface); mConnection.close(); mConnection = null; } diff --git a/templates/android/template/app/src/main/java/org/libsdl/app/SDLActivity.java b/templates/android/template/app/src/main/java/org/libsdl/app/SDLActivity.java index 3260e9282..67d746078 100644 --- a/templates/android/template/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/templates/android/template/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -284,10 +284,6 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh return; } - if (mHIDDeviceManager != null) { - mHIDDeviceManager.setFrozen(true); - } - SDLActivity.handleNativeState(); } @@ -299,10 +295,6 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh return; } - if (mHIDDeviceManager != null) { - mHIDDeviceManager.setFrozen(false); - } - SDLActivity.handleNativeState(); } @@ -311,6 +303,10 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh protected void onPause() { Log.v(TAG, "onPause()"); super.onPause(); + + if (mHIDDeviceManager != null) { + mHIDDeviceManager.setFrozen(true); + } if (!mHasMultiWindow) { pauseNativeThread(); } @@ -320,6 +316,10 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh protected void onResume() { Log.v(TAG, "onResume()"); super.onResume(); + + if (mHIDDeviceManager != null) { + mHIDDeviceManager.setFrozen(false); + } if (!mHasMultiWindow) { resumeNativeThread(); } @@ -454,7 +454,9 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh } // Default system back button behavior. - super.onBackPressed(); + if (!isFinishing()) { + super.onBackPressed(); + } } // Called by JNI from SDL. @@ -467,7 +469,9 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh runOnUiThread(new Runnable() { @Override public void run() { - SDLActivity.this.superOnBackPressed(); + if (!SDLActivity.this.isFinishing()) { + SDLActivity.this.superOnBackPressed(); + } } }); } @@ -634,6 +638,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh imm.hideSoftInputFromWindow(mTextEdit.getWindowToken(), 0); mScreenKeyboardShown = false; + + mSurface.requestFocus(); } break; case COMMAND_SET_KEEP_SCREEN_ON: @@ -725,7 +731,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh } } - if (bShouldWait) { + if (bShouldWait && (SDLActivity.getContext() != null)) { // We'll wait for the surfaceChanged() method, which will notify us // when called. That way, we know our current size is really the // size we need, instead of grabbing a size that's still got @@ -778,6 +784,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh public static native void nativeSetenv(String name, String value); public static native void onNativeOrientationChanged(int orientation); public static native void nativeAddTouch(int touchId, String name); + public static native void nativePermissionResult(int requestCode, boolean result); /** * This method is called by SDL using JNI. @@ -812,39 +819,62 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh */ public void setOrientationBis(int w, int h, boolean resizable, String hint) { - int orientation = -1; + int orientation_landscape = -1; + int orientation_portrait = -1; + /* If set, hint "explicitly controls which UI orientations are allowed". */ if (hint.contains("LandscapeRight") && hint.contains("LandscapeLeft")) { - orientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; + orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; } else if (hint.contains("LandscapeRight")) { - orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; + orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; } else if (hint.contains("LandscapeLeft")) { - orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; - } else if (hint.contains("Portrait") && hint.contains("PortraitUpsideDown")) { - orientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; - } else if (hint.contains("Portrait")) { - orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; - } else if (hint.contains("PortraitUpsideDown")) { - orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; + orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; } - /* no valid hint */ - if (orientation == -1) { + if (hint.contains("Portrait") && hint.contains("PortraitUpsideDown")) { + orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; + } else if (hint.contains("Portrait")) { + orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; + } else if (hint.contains("PortraitUpsideDown")) { + orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; + } + + boolean is_landscape_allowed = (orientation_landscape == -1 ? false : true); + boolean is_portrait_allowed = (orientation_portrait == -1 ? false : true); + int req = -1; /* Requested orientation */ + + /* No valid hint, nothing is explicitly allowed */ + if (!is_portrait_allowed && !is_landscape_allowed) { if (resizable) { - /* no fixed orientation */ + /* All orientations are allowed */ + req = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR; } else { - if (w > h) { - orientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; + /* Fixed window and nothing specified. Get orientation from w/h of created window */ + req = (w > h ? ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); + } + } else { + /* At least one orientation is allowed */ + if (resizable) { + if (is_portrait_allowed && is_landscape_allowed) { + /* hint allows both landscape and portrait, promote to full sensor */ + req = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR; } else { - orientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; + /* Use the only one allowed "orientation" */ + req = (is_landscape_allowed ? orientation_landscape : orientation_portrait); + } + } else { + /* Fixed window and both orientations are allowed. Choose one. */ + if (is_portrait_allowed && is_landscape_allowed) { + req = (w > h ? orientation_landscape : orientation_portrait); + } else { + /* Use the only one allowed "orientation" */ + req = (is_landscape_allowed ? orientation_landscape : orientation_portrait); } } } - Log.v("SDL", "setOrientation() orientation=" + orientation + " width=" + w +" height="+ h +" resizable=" + resizable + " hint=" + hint); - if (orientation != -1) { - mSingleton.setRequestedOrientation(orientation); - } + Log.v("SDL", "setOrientation() requestedOrientation=" + req + " width=" + w +" height="+ h +" resizable=" + resizable + " hint=" + hint); + mSingleton.setRequestedOrientation(req); } /** @@ -971,6 +1001,9 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh if (Build.MANUFACTURER.equals("Amlogic") && Build.MODEL.equals("X96-W")) { return true; } + if (Build.MANUFACTURER.equals("Amlogic") && Build.MODEL.startsWith("TV")) { + return true; + } return false; } @@ -980,6 +1013,9 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh public static boolean isTablet() { DisplayMetrics metrics = new DisplayMetrics(); Activity activity = (Activity)getContext(); + if (activity == null) { + return false; + } activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); double dWidthInches = metrics.widthPixels / (double)metrics.xdpi; @@ -995,6 +1031,9 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh * This method is called by SDL using JNI. */ public static boolean isChromebook() { + if (getContext() == null) { + return false; + } return getContext().getPackageManager().hasSystemFeature("org.chromium.arc.device_management"); } @@ -1566,6 +1605,32 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh } return true; } + + /** + * This method is called by SDL using JNI. + */ + public static void requestPermission(String permission, int requestCode) { + if (Build.VERSION.SDK_INT < 23) { + nativePermissionResult(requestCode, true); + return; + } + + Activity activity = (Activity)getContext(); + if (activity.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { + activity.requestPermissions(new String[]{permission}, requestCode); + } else { + nativePermissionResult(requestCode, true); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + nativePermissionResult(requestCode, true); + } else { + nativePermissionResult(requestCode, false); + } + } } /** @@ -1591,7 +1656,7 @@ class SDLMain implements Runnable { Log.v("SDL", "Finished main function"); - if (SDLActivity.mSingleton.isFinishing()) { + if (SDLActivity.mSingleton == null || SDLActivity.mSingleton.isFinishing()) { // Activity is already being destroyed } else { // Let's finish the Activity @@ -1826,10 +1891,9 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, if (source == InputDevice.SOURCE_UNKNOWN) { InputDevice device = InputDevice.getDevice(deviceId); - if ( device != null ) - { - source = device.getSources(); - } + if (device != null) { + source = device.getSources(); + } } if ((source & InputDevice.SOURCE_KEYBOARD) != 0) {