Fix crash on stream disconnect on Android 7.0+ devices (root only)

This commit is contained in:
Cameron Gutman
2017-05-18 10:52:17 -07:00
parent 686490ba70
commit 44cbf8adc1
@@ -2,6 +2,7 @@ package com.limelight.binding.input.evdev;
import android.app.Activity; import android.app.Activity;
import android.os.Build; import android.os.Build;
import android.os.Looper;
import android.widget.Toast; import android.widget.Toast;
import com.limelight.LimeLog; import com.limelight.LimeLog;
@@ -198,6 +199,26 @@ public class EvdevCaptureProvider extends InputCaptureProvider {
}); });
} }
private void runInNetworkSafeContextSynchronously(Runnable runnable) {
// This function is used to avoid Android's strict NetworkOnMainThreadException.
// For our usage, it is highly unlikely to cause problems since we only do
// write operations and only to localhost sockets.
if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
Thread t = new Thread(runnable);
t.start();
try {
t.join();
} catch (InterruptedException e) {
// The main thread should never be interrupted
e.printStackTrace();
}
}
else {
// Run the runnable directly
runnable.run();
}
}
@Override @Override
public void enableCapture() { public void enableCapture() {
if (!started) { if (!started) {
@@ -207,6 +228,10 @@ public class EvdevCaptureProvider extends InputCaptureProvider {
started = true; started = true;
} }
else { else {
// This may be called on the main thread
runInNetworkSafeContextSynchronously(new Runnable() {
@Override
public void run() {
// Send a request to regrab if we're already capturing // Send a request to regrab if we're already capturing
if (!shutdown && evdevOut != null) { if (!shutdown && evdevOut != null) {
try { try {
@@ -216,10 +241,16 @@ public class EvdevCaptureProvider extends InputCaptureProvider {
} }
} }
} }
});
}
} }
@Override @Override
public void disableCapture() { public void disableCapture() {
// This may be called on the main thread
runInNetworkSafeContextSynchronously(new Runnable() {
@Override
public void run() {
if (started && !shutdown && evdevOut != null) { if (started && !shutdown && evdevOut != null) {
try { try {
evdevOut.write(UNGRAB_REQUEST); evdevOut.write(UNGRAB_REQUEST);
@@ -228,12 +259,16 @@ public class EvdevCaptureProvider extends InputCaptureProvider {
} }
} }
} }
});
}
@Override @Override
public void destroy() { public void destroy() {
// We need to stop the process in this context otherwise // We need to stop the process in this context otherwise
// we could get stuck waiting on output from the process // we could get stuck waiting on output from the process
// in order to terminate it. // in order to terminate it.
//
// This may be called on the main thread.
if (!started) { if (!started) {
return; return;
@@ -242,6 +277,9 @@ public class EvdevCaptureProvider extends InputCaptureProvider {
shutdown = true; shutdown = true;
handlerThread.interrupt(); handlerThread.interrupt();
runInNetworkSafeContextSynchronously(new Runnable() {
@Override
public void run() {
if (servSock != null) { if (servSock != null) {
try { try {
servSock.close(); servSock.close();
@@ -273,6 +311,8 @@ public class EvdevCaptureProvider extends InputCaptureProvider {
e.printStackTrace(); e.printStackTrace();
} }
} }
}
});
if (su != null) { if (su != null) {
su.destroy(); su.destroy();