Merge branch 'master' into root

This commit is contained in:
Cameron Gutman 2014-09-27 19:32:39 -07:00
commit 991407a2cf
6 changed files with 38 additions and 18 deletions

Binary file not shown.

View File

@ -287,7 +287,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
Dialog.closeDialogs(); Dialog.closeDialogs();
displayedFailureDialog = true; displayedFailureDialog = true;
conn.stop(); stopConnection();
int averageEndToEndLat = decoderRenderer.getAverageEndToEndLatency(); int averageEndToEndLat = decoderRenderer.getAverageEndToEndLatency();
int averageDecoderLat = decoderRenderer.getAverageDecoderLatency(); int averageDecoderLat = decoderRenderer.getAverageDecoderLatency();
@ -305,10 +305,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
if (message != null) { if (message != null) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show(); Toast.makeText(this, message, Toast.LENGTH_LONG).show();
} }
if (evdevWatcher != null) {
evdevWatcher.shutdown();
}
finish(); finish();
} }
@ -573,6 +569,19 @@ public class Game extends Activity implements SurfaceHolder.Callback,
@Override @Override
public void stageComplete(Stage stage) { public void stageComplete(Stage stage) {
} }
private void stopConnection() {
if (connecting || connected) {
conn.stop();
connecting = connected = false;
}
// Close the Evdev watcher to allow use of captured input devices
if (evdevWatcher != null) {
evdevWatcher.shutdown();
evdevWatcher = null;
}
}
@Override @Override
public void stageFailed(Stage stage) { public void stageFailed(Stage stage) {
@ -584,8 +593,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
if (!displayedFailureDialog) { if (!displayedFailureDialog) {
displayedFailureDialog = true; displayedFailureDialog = true;
Dialog.displayDialog(this, "Connection Error", "Starting "+stage.getName()+" failed", true); Dialog.displayDialog(this, "Connection Error", "Starting "+stage.getName()+" failed", true);
conn.stop(); stopConnection();
connecting = false;
} }
} }
@ -594,9 +602,9 @@ public class Game extends Activity implements SurfaceHolder.Callback,
if (!displayedFailureDialog) { if (!displayedFailureDialog) {
displayedFailureDialog = true; displayedFailureDialog = true;
e.printStackTrace(); e.printStackTrace();
Dialog.displayDialog(this, "Connection Terminated", "The connection failed unexpectedly", true); Dialog.displayDialog(this, "Connection Terminated", "The connection failed unexpectedly", true);
conn.stop(); stopConnection();
connected = false;
} }
} }
@ -658,8 +666,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
@Override @Override
public void surfaceDestroyed(SurfaceHolder holder) { public void surfaceDestroyed(SurfaceHolder holder) {
if (connected) { if (connected) {
conn.stop(); stopConnection();
connected = false;
} }
} }

View File

@ -6,6 +6,7 @@ import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import com.limelight.binding.PlatformBinding; import com.limelight.binding.PlatformBinding;
import com.limelight.binding.crypto.AndroidCryptoProvider;
import com.limelight.computers.ComputerManagerListener; import com.limelight.computers.ComputerManagerListener;
import com.limelight.computers.ComputerManagerService; import com.limelight.computers.ComputerManagerService;
import com.limelight.nvstream.http.ComputerDetails; import com.limelight.nvstream.http.ComputerDetails;
@ -60,6 +61,9 @@ public class PcView extends Activity {
// Start updates // Start updates
startComputerUpdates(); startComputerUpdates();
// Force a keypair to be generated early to avoid discovery delays
new AndroidCryptoProvider(PcView.this).getClientCertificate();
} }
}.start(); }.start();
} }

View File

@ -51,6 +51,8 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
private RSAPrivateKey key; private RSAPrivateKey key;
private byte[] pemCertBytes; private byte[] pemCertBytes;
private static Object globalCryptoLock = new Object();
static { static {
// Install the Bouncy Castle provider // Install the Bouncy Castle provider
Security.addProvider(new BouncyCastleProvider()); Security.addProvider(new BouncyCastleProvider());
@ -208,7 +210,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
public X509Certificate getClientCertificate() { public X509Certificate getClientCertificate() {
// Use a lock here to ensure only one guy will be generating or loading // Use a lock here to ensure only one guy will be generating or loading
// the certificate and key at a time // the certificate and key at a time
synchronized (this) { synchronized (globalCryptoLock) {
// Return a loaded cert if we have one // Return a loaded cert if we have one
if (cert != null) { if (cert != null) {
return cert; return cert;
@ -235,7 +237,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
public RSAPrivateKey getClientPrivateKey() { public RSAPrivateKey getClientPrivateKey() {
// Use a lock here to ensure only one guy will be generating or loading // Use a lock here to ensure only one guy will be generating or loading
// the certificate and key at a time // the certificate and key at a time
synchronized (this) { synchronized (globalCryptoLock) {
// Return a loaded key if we have one // Return a loaded key if we have one
if (key != null) { if (key != null) {
return key; return key;
@ -260,7 +262,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
} }
public byte[] getPemEncodedClientCertificate() { public byte[] getPemEncodedClientCertificate() {
synchronized (this) { synchronized (globalCryptoLock) {
// Call our helper function to do the cert loading/generation for us // Call our helper function to do the cert loading/generation for us
getClientCertificate(); getClientCertificate();

View File

@ -38,6 +38,7 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
private int cpuCount = Runtime.getRuntime().availableProcessors(); private int cpuCount = Runtime.getRuntime().availableProcessors();
@SuppressWarnings("unused")
private int findOptimalPerformanceLevel() { private int findOptimalPerformanceLevel() {
StringBuilder cpuInfo = new StringBuilder(); StringBuilder cpuInfo = new StringBuilder();
BufferedReader br = null; BufferedReader br = null;
@ -93,7 +94,7 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
public boolean setup(int width, int height, int redrawRate, Object renderTarget, int drFlags) { public boolean setup(int width, int height, int redrawRate, Object renderTarget, int drFlags) {
this.targetFps = redrawRate; this.targetFps = redrawRate;
int perfLevel = findOptimalPerformanceLevel(); int perfLevel = LOW_PERF; //findOptimalPerformanceLevel();
int threadCount; int threadCount;
int avcFlags = 0; int avcFlags = 0;

View File

@ -342,7 +342,7 @@ public class ComputerManagerService extends Service {
polledDetails = tryPollIp(details.remoteIp); polledDetails = tryPollIp(details.remoteIp);
} }
if (polledDetails == null) { if (polledDetails == null && !details.localIp.equals(details.remoteIp)) {
// Failed, so let's try the fallback // Failed, so let's try the fallback
if (!localFirst) { if (!localFirst) {
polledDetails = tryPollIp(details.localIp); polledDetails = tryPollIp(details.localIp);
@ -356,7 +356,8 @@ public class ComputerManagerService extends Service {
polledDetails.reachability = !localFirst ? ComputerDetails.Reachability.LOCAL : polledDetails.reachability = !localFirst ? ComputerDetails.Reachability.LOCAL :
ComputerDetails.Reachability.REMOTE; ComputerDetails.Reachability.REMOTE;
} }
} else { }
else if (polledDetails != null) {
polledDetails.reachability = localFirst ? ComputerDetails.Reachability.LOCAL : polledDetails.reachability = localFirst ? ComputerDetails.Reachability.LOCAL :
ComputerDetails.Reachability.REMOTE; ComputerDetails.Reachability.REMOTE;
} }
@ -401,7 +402,12 @@ public class ComputerManagerService extends Service {
public void run() { public void run() {
boolean newPc = (details.name == null); boolean newPc = (details.name == null);
if (stopped) { // This is called from addComputerManually() where we don't
// want to block the initial poll if polling is disabled, so
// we explicitly let this through if we've never seen this
// PC before. This path won't be triggered normally when polling
// is disabled because the mDNS discovery is stopped.
if (stopped && !newPc) {
return; return;
} }