Use LastErrorException for native error handling

This commit is contained in:
Luiz Henrique Laurini 2021-05-04 19:16:52 -03:00 committed by Simon Chan
commit abedd0b478
No known key found for this signature in database
GPG key ID: A8B69F750B9BCEDD
3 changed files with 65 additions and 26 deletions

View file

@ -218,7 +218,7 @@ public class Controller {
try { try {
gameControllers.append(id, new GameController()); gameControllers.append(id, new GameController());
} catch (Exception e) { } catch (Exception e) {
Ln.e("It seems your phone doesn't support this feature without root. Game controllers will be disabled.", e); Ln.e("Failed to add new game controller. Game controllers will be disabled.", e);
gameControllersEnabled = false; gameControllersEnabled = false;
} }
break; break;

View file

@ -1,5 +1,6 @@
package com.genymobile.scrcpy; package com.genymobile.scrcpy;
import com.sun.jna.LastErrorException;
import com.sun.jna.Library; import com.sun.jna.Library;
import com.sun.jna.Native; import com.sun.jna.Native;
import com.sun.jna.Platform; import com.sun.jna.Platform;
@ -162,10 +163,10 @@ public abstract class UinputDevice {
private int fd = -1; private int fd = -1;
public interface LibC extends Library { public interface LibC extends Library {
int open(String pathname, int flags); int open(String pathname, int flags) throws LastErrorException;
int ioctl(int fd, long request, Object... args); int ioctl(int fd, long request, Object... args) throws LastErrorException;
long write(int fd, Pointer buf, long count); long write(int fd, Pointer buf, long count) throws LastErrorException;
int close(int fd); int close(int fd) throws LastErrorException;
} }
private static LibC libC; private static LibC libC;
@ -176,18 +177,27 @@ public abstract class UinputDevice {
} }
protected void setup() { protected void setup() {
fd = libC.open("/dev/uinput", O_WRONLY | O_NONBLOCK); try {
if (fd == -1) { fd = libC.open("/dev/uinput", O_WRONLY | O_NONBLOCK);
throw new RuntimeException("Couldn't open uinput device."); } catch (LastErrorException e) {
throw new UinputUnsupportedException(e);
} }
if (hasKeys()) { if (hasKeys()) {
libC.ioctl(fd, UI_SET_EVBIT, EV_KEY); try {
libC.ioctl(fd, UI_SET_EVBIT, EV_KEY);
} catch (LastErrorException e) {
throw new RuntimeException("Could not enable key events.", e);
}
setupKeys(); setupKeys();
} }
if (hasAbs()) { if (hasAbs()) {
libC.ioctl(fd, UI_SET_EVBIT, EV_ABS); try {
libC.ioctl(fd, UI_SET_EVBIT, EV_ABS);
} catch (LastErrorException e) {
throw new RuntimeException("Could not enable absolute events.", e);
}
setupAbs(); setupAbs();
} }
@ -198,21 +208,33 @@ public abstract class UinputDevice {
byte[] name = getName().getBytes(); byte[] name = getName().getBytes();
System.arraycopy(name, 0, usetup.name, 0, name.length); System.arraycopy(name, 0, usetup.name, 0, name.length);
if (libC.ioctl(fd, UI_DEV_SETUP, usetup) == -1) { try {
libC.ioctl(fd, UI_DEV_SETUP, usetup);
} catch (LastErrorException e) {
close(); close();
throw new RuntimeException("Couldn't setup uinput device."); throw new RuntimeException("Couldn't setup uinput device.", e);
} }
if (libC.ioctl(fd, UI_DEV_CREATE) == -1) { try {
libC.ioctl(fd, UI_DEV_CREATE);
} catch (LastErrorException e) {
close(); close();
throw new RuntimeException("Couldn't create uinput device."); throw new RuntimeException("Couldn't create uinput device.", e);
} }
} }
public void close() { public void close() {
if (fd != -1) { if (fd != -1) {
libC.ioctl(fd, UI_DEV_DESTROY); try {
libC.close(fd); libC.ioctl(fd, UI_DEV_DESTROY);
} catch (LastErrorException e) {
Ln.e("Could not destroy uinput device.", e);
}
try {
libC.close(fd);
} catch (LastErrorException e) {
Ln.e("Could not close uinput device.", e);
}
fd = -1; fd = -1;
} }
} }
@ -226,14 +248,18 @@ public abstract class UinputDevice {
protected abstract String getName(); protected abstract String getName();
protected void addKey(int key) { protected void addKey(int key) {
if (libC.ioctl(fd, UI_SET_KEYBIT, key) == -1) { try {
Ln.e("Could not add key event."); libC.ioctl(fd, UI_SET_KEYBIT, key);
} catch (LastErrorException e) {
Ln.e("Could not add key event.", e);
} }
} }
protected void addAbs(short code, int minimum, int maximum, int fuzz, int flat) { protected void addAbs(short code, int minimum, int maximum, int fuzz, int flat) {
if (libC.ioctl(fd, UI_SET_ABSBIT, code) == -1) { try {
Ln.e("Could not add absolute event."); libC.ioctl(fd, UI_SET_ABSBIT, code);
} catch (LastErrorException e) {
Ln.e("Could not add absolute event.", e);
} }
UinputAbsSetup absSetup = new UinputAbsSetup(); UinputAbsSetup absSetup = new UinputAbsSetup();
@ -244,8 +270,10 @@ public abstract class UinputDevice {
absSetup.absinfo.fuzz = fuzz; absSetup.absinfo.fuzz = fuzz;
absSetup.absinfo.flat = flat; absSetup.absinfo.flat = flat;
if (libC.ioctl(fd, UI_ABS_SETUP, absSetup) == -1) { try {
Ln.e("Could not set absolute event info."); libC.ioctl(fd, UI_ABS_SETUP, absSetup);
} catch (LastErrorException e) {
Ln.e("Could not set absolute event info.", e);
} }
} }
@ -274,10 +302,14 @@ public abstract class UinputDevice {
} }
private static void emit(int fd, short type, short code, int val) { private static void emit(int fd, short type, short code, int val) {
if (Platform.is64Bit()) { try {
emit64(fd, type, code, val); if (Platform.is64Bit()) {
} else { emit64(fd, type, code, val);
emit32(fd, type, code, val); } else {
emit32(fd, type, code, val);
}
} catch (LastErrorException e) {
Ln.e("Could not emit event.", e);
} }
} }

View file

@ -0,0 +1,7 @@
package com.genymobile.scrcpy;
public class UinputUnsupportedException extends RuntimeException {
public UinputUnsupportedException(Exception e) {
super("device does not support uinput without root", e);
}
}