Skip to content

Commit

Permalink
Android: Update Android files for SDL3
Browse files Browse the repository at this point in the history
  • Loading branch information
Ghabry committed Dec 22, 2024
1 parent f2a8c4e commit 00a6a56
Show file tree
Hide file tree
Showing 11 changed files with 854 additions and 915 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ interface HIDDevice
public String getProductName();
public UsbDevice getDevice();
public boolean open();
public int sendFeatureReport(byte[] report);
public int sendOutputReport(byte[] report);
public boolean getFeatureReport(byte[] report);
public int writeReport(byte[] report, boolean feature);
public boolean readReport(byte[] report, boolean feature);
public void setFrozen(boolean frozen);
public void close();
public void shutdown();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic
//Log.v(TAG, "onCharacteristicRead status=" + status + " uuid=" + characteristic.getUuid());

if (characteristic.getUuid().equals(reportCharacteristic) && !mFrozen) {
mManager.HIDDeviceFeatureReport(getId(), characteristic.getValue());
mManager.HIDDeviceReportResponse(getId(), characteristic.getValue());
}

finishCurrentGattOperation();
Expand Down Expand Up @@ -575,50 +575,45 @@ public boolean open() {
}

@Override
public int sendFeatureReport(byte[] report) {
public int writeReport(byte[] report, boolean feature) {
if (!isRegistered()) {
Log.e(TAG, "Attempted sendFeatureReport before Steam Controller is registered!");
Log.e(TAG, "Attempted writeReport before Steam Controller is registered!");
if (mIsConnected) {
probeService(this);
}
return -1;
}

// We need to skip the first byte, as that doesn't go over the air
byte[] actual_report = Arrays.copyOfRange(report, 1, report.length - 1);
//Log.v(TAG, "sendFeatureReport " + HexDump.dumpHexString(actual_report));
writeCharacteristic(reportCharacteristic, actual_report);
return report.length;
}

@Override
public int sendOutputReport(byte[] report) {
if (!isRegistered()) {
Log.e(TAG, "Attempted sendOutputReport before Steam Controller is registered!");
if (mIsConnected) {
probeService(this);
}
return -1;
if (feature) {
// We need to skip the first byte, as that doesn't go over the air
byte[] actual_report = Arrays.copyOfRange(report, 1, report.length - 1);
//Log.v(TAG, "writeFeatureReport " + HexDump.dumpHexString(actual_report));
writeCharacteristic(reportCharacteristic, actual_report);
return report.length;
} else {
//Log.v(TAG, "writeOutputReport " + HexDump.dumpHexString(report));
writeCharacteristic(reportCharacteristic, report);
return report.length;
}

//Log.v(TAG, "sendFeatureReport " + HexDump.dumpHexString(report));
writeCharacteristic(reportCharacteristic, report);
return report.length;
}

@Override
public boolean getFeatureReport(byte[] report) {
public boolean readReport(byte[] report, boolean feature) {
if (!isRegistered()) {
Log.e(TAG, "Attempted getFeatureReport before Steam Controller is registered!");
Log.e(TAG, "Attempted readReport before Steam Controller is registered!");
if (mIsConnected) {
probeService(this);
}
return false;
}

//Log.v(TAG, "getFeatureReport");
readCharacteristic(reportCharacteristic);
return true;
if (feature) {
readCharacteristic(reportCharacteristic);
return true;
} else {
// Not implemented
return false;
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,11 @@ private void initializeUSB() {
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
filter.addAction(HIDDeviceManager.ACTION_USB_PERMISSION);
mContext.registerReceiver(mUsbBroadcast, filter);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
mContext.registerReceiver(mUsbBroadcast, filter, Context.RECEIVER_EXPORTED);
} else {
mContext.registerReceiver(mUsbBroadcast, filter);
}

for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) {
handleUsbDeviceAttached(usbDevice);
Expand Down Expand Up @@ -404,7 +408,11 @@ private void initializeBluetooth() {
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
mContext.registerReceiver(mBluetoothBroadcast, filter);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
mContext.registerReceiver(mBluetoothBroadcast, filter, Context.RECEIVER_EXPORTED);
} else {
mContext.registerReceiver(mBluetoothBroadcast, filter);
}

if (mIsChromebook) {
mHandler = new Handler(Looper.getMainLooper());
Expand Down Expand Up @@ -613,51 +621,34 @@ public boolean openDevice(int deviceID) {
return false;
}

public int sendOutputReport(int deviceID, byte[] report) {
try {
//Log.v(TAG, "sendOutputReport deviceID=" + deviceID + " length=" + report.length);
HIDDevice device;
device = getDevice(deviceID);
if (device == null) {
HIDDeviceDisconnected(deviceID);
return -1;
}

return device.sendOutputReport(report);
} catch (Exception e) {
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
}
return -1;
}

public int sendFeatureReport(int deviceID, byte[] report) {
public int writeReport(int deviceID, byte[] report, boolean feature) {
try {
//Log.v(TAG, "sendFeatureReport deviceID=" + deviceID + " length=" + report.length);
//Log.v(TAG, "writeReport deviceID=" + deviceID + " length=" + report.length);
HIDDevice device;
device = getDevice(deviceID);
if (device == null) {
HIDDeviceDisconnected(deviceID);
return -1;
}

return device.sendFeatureReport(report);
return device.writeReport(report, feature);
} catch (Exception e) {
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
}
return -1;
}

public boolean getFeatureReport(int deviceID, byte[] report) {
public boolean readReport(int deviceID, byte[] report, boolean feature) {
try {
//Log.v(TAG, "getFeatureReport deviceID=" + deviceID);
//Log.v(TAG, "readReport deviceID=" + deviceID);
HIDDevice device;
device = getDevice(deviceID);
if (device == null) {
HIDDeviceDisconnected(deviceID);
return false;
}

return device.getFeatureReport(report);
return device.readReport(report, feature);
} catch (Exception e) {
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
}
Expand Down Expand Up @@ -694,5 +685,5 @@ public void closeDevice(int deviceID) {
native void HIDDeviceDisconnected(int deviceID);

native void HIDDeviceInputReport(int deviceID, byte[] report);
native void HIDDeviceFeatureReport(int deviceID, byte[] report);
native void HIDDeviceReportResponse(int deviceID, byte[] report);
}
83 changes: 46 additions & 37 deletions builds/android/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,55 +153,64 @@ public boolean open() {
}

@Override
public int sendFeatureReport(byte[] report) {
int res = -1;
int offset = 0;
int length = report.length;
boolean skipped_report_id = false;
byte report_number = report[0];

if (report_number == 0x0) {
++offset;
--length;
skipped_report_id = true;
}

res = mConnection.controlTransfer(
UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_OUT,
0x09/*HID set_report*/,
(3/*HID feature*/ << 8) | report_number,
mInterface,
report, offset, length,
1000/*timeout millis*/);

if (res < 0) {
Log.w(TAG, "sendFeatureReport() returned " + res + " on device " + getDeviceName());
public int writeReport(byte[] report, boolean feature) {
if (mConnection == null) {
Log.w(TAG, "writeReport() called with no device connection");
return -1;
}

if (skipped_report_id) {
++length;
}
return length;
}
if (feature) {
int res = -1;
int offset = 0;
int length = report.length;
boolean skipped_report_id = false;
byte report_number = report[0];

if (report_number == 0x0) {
++offset;
--length;
skipped_report_id = true;
}

@Override
public int sendOutputReport(byte[] report) {
int r = mConnection.bulkTransfer(mOutputEndpoint, report, report.length, 1000);
if (r != report.length) {
Log.w(TAG, "sendOutputReport() returned " + r + " on device " + getDeviceName());
res = mConnection.controlTransfer(
UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_OUT,
0x09/*HID set_report*/,
(3/*HID feature*/ << 8) | report_number,
mInterface,
report, offset, length,
1000/*timeout millis*/);

if (res < 0) {
Log.w(TAG, "writeFeatureReport() returned " + res + " on device " + getDeviceName());
return -1;
}

if (skipped_report_id) {
++length;
}
return length;
} else {
int res = mConnection.bulkTransfer(mOutputEndpoint, report, report.length, 1000);
if (res != report.length) {
Log.w(TAG, "writeOutputReport() returned " + res + " on device " + getDeviceName());
}
return res;
}
return r;
}

@Override
public boolean getFeatureReport(byte[] report) {
public boolean readReport(byte[] report, boolean feature) {
int res = -1;
int offset = 0;
int length = report.length;
boolean skipped_report_id = false;
byte report_number = report[0];

if (mConnection == null) {
Log.w(TAG, "readReport() called with no device connection");
return false;
}

if (report_number == 0x0) {
/* Offset the return buffer by 1, so that the report ID
will remain in byte 0. */
Expand All @@ -213,7 +222,7 @@ public boolean getFeatureReport(byte[] report) {
res = mConnection.controlTransfer(
UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_IN,
0x01/*HID get_report*/,
(3/*HID feature*/ << 8) | report_number,
((feature ? 3/*HID feature*/ : 1/*HID Input*/) << 8) | report_number,
mInterface,
report, offset, length,
1000/*timeout millis*/);
Expand All @@ -234,7 +243,7 @@ public boolean getFeatureReport(byte[] report) {
} else {
data = Arrays.copyOfRange(report, 0, res);
}
mManager.HIDDeviceFeatureReport(mDeviceId, data);
mManager.HIDDeviceReportResponse(mDeviceId, data);

return true;
}
Expand Down
8 changes: 4 additions & 4 deletions builds/android/app/src/main/java/org/libsdl/app/SDL.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,21 @@ public static void loadLibrary(String libraryName, Context context) throws Unsat
}

try {
// Let's see if we have ReLinker available in the project. This is necessary for
// some projects that have huge numbers of local libraries bundled, and thus may
// Let's see if we have ReLinker available in the project. This is necessary for
// some projects that have huge numbers of local libraries bundled, and thus may
// trip a bug in Android's native library loader which ReLinker works around. (If
// loadLibrary works properly, ReLinker will simply use the normal Android method
// internally.)
//
// To use ReLinker, just add it as a dependency. For more information, see
// To use ReLinker, just add it as a dependency. For more information, see
// https://github.com/KeepSafe/ReLinker for ReLinker's repository.
//
Class<?> relinkClass = context.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker");
Class<?> relinkListenerClass = context.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker$LoadListener");
Class<?> contextClass = context.getClassLoader().loadClass("android.content.Context");
Class<?> stringClass = context.getClassLoader().loadClass("java.lang.String");

// Get a 'force' instance of the ReLinker, so we can ensure libraries are reinstalled if
// Get a 'force' instance of the ReLinker, so we can ensure libraries are reinstalled if
// they've changed during updates.
Method forceMethod = relinkClass.getDeclaredMethod("force");
Object relinkInstance = forceMethod.invoke(null);
Expand Down
Loading

0 comments on commit 00a6a56

Please sign in to comment.