summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStas Negara <snegara@google.com>2015-07-28 15:38:19 -0700
committerStas Negara <snegara@google.com>2015-07-28 15:38:19 -0700
commit7f7d4675da8a4f8b42adb085e5589604a543373d (patch)
tree4b474e4de53ebab353d30ed565fb87b1137920c0
parent25352a696d220f3258bf9029ea92d01b2487c2a2 (diff)
downloadtesting-7f7d4675da8a4f8b42adb085e5589604a543373d.tar.gz
Add intelligent VNC keep alive thread.
The thread will start VNC and will restart it when it crashes. Also, it will clean up after the user closes the VNC Viewer manually. Change-Id: I16e40e92fcfc2ab3e82ea8ef55765d485046261e
-rw-r--r--src/com/google/gct/testing/CloudConfigurationProviderImpl.java10
-rw-r--r--src/com/google/gct/testing/vnc/VncKeepAliveThreadImpl.java101
2 files changed, 106 insertions, 5 deletions
diff --git a/src/com/google/gct/testing/CloudConfigurationProviderImpl.java b/src/com/google/gct/testing/CloudConfigurationProviderImpl.java
index 23d7386..f0f04e7 100644
--- a/src/com/google/gct/testing/CloudConfigurationProviderImpl.java
+++ b/src/com/google/gct/testing/CloudConfigurationProviderImpl.java
@@ -25,7 +25,6 @@ import com.android.tools.idea.run.CloudConfiguration.Kind;
import com.android.tools.idea.run.CloudConfigurationProvider;
import com.android.tools.idea.sdk.IdeSdks;
import com.android.tools.idea.stats.UsageTracker;
-import com.glavsoft.viewer.Viewer;
import com.google.api.client.util.Maps;
import com.google.api.client.util.Sets;
import com.google.api.services.storage.Storage;
@@ -50,6 +49,7 @@ import com.google.gct.testing.results.GoogleCloudTestingResultParser;
import com.google.gct.testing.util.CloudTestingTracking;
import com.google.gct.testing.vnc.BlankVncViewer;
import com.google.gct.testing.vnc.BlankVncViewerCallback;
+import com.google.gct.testing.vnc.VncKeepAliveThreadImpl;
import com.intellij.execution.DefaultExecutionResult;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
@@ -362,7 +362,7 @@ public class CloudConfigurationProviderImpl extends CloudConfigurationProvider {
final long INITIAL_TIMEOUT = 10 * 60 * 1000; // 10 minutes
long stopTime = System.currentTimeMillis() + INITIAL_TIMEOUT;
String sdkPath = IdeSdks.getAndroidSdkPath().getAbsolutePath() + "/platform-tools";
- File dir = new File(sdkPath);
+ File workingDir = new File(sdkPath);
try {
while (System.currentTimeMillis() < stopTime) {
synchronized (ghostCloudDevices) {
@@ -391,7 +391,7 @@ public class CloudConfigurationProviderImpl extends CloudConfigurationProvider {
String deviceAddress = ipAddress + ":" + adbPort;
System.out.println("Device ready with IP address:port " + deviceAddress);
Runtime rt = Runtime.getRuntime();
- Process connect = rt.exec("./adb connect " + deviceAddress, null, dir);
+ Process connect = rt.exec("./adb connect " + deviceAddress, null, workingDir);
connect.waitFor();
serialNumberToConfigurationInstance.put(deviceAddress, configurationInstance);
// Do not wait for "finally" to remove the ghost device
@@ -401,11 +401,11 @@ public class CloudConfigurationProviderImpl extends CloudConfigurationProvider {
}
blankVncViewer.closeWindow();
// Make sure the device is unlocked.
- Process unlock = rt.exec("./adb -s " + deviceAddress + " wait-for-device shell input keyevent 82" , null, dir);
+ Process unlock = rt.exec("./adb -s " + deviceAddress + " wait-for-device shell input keyevent 82" , null, workingDir);
unlock.waitFor();
// Open the VNC window for the cloud device.
String[] viewerArgs = new String[]{"-port=" + vncPort, "-host=" + ipAddress, "-password=" + vncPassword, "-fullScreen=false"};
- Viewer.showViewer(viewerArgs, configurationName);
+ VncKeepAliveThreadImpl.startVnc(viewerArgs, configurationName, cloudProjectId, deviceId, deviceAddress, workingDir);
return;
}
Thread.sleep(POLLING_INTERVAL);
diff --git a/src/com/google/gct/testing/vnc/VncKeepAliveThreadImpl.java b/src/com/google/gct/testing/vnc/VncKeepAliveThreadImpl.java
new file mode 100644
index 0000000..8838237
--- /dev/null
+++ b/src/com/google/gct/testing/vnc/VncKeepAliveThreadImpl.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.gct.testing.vnc;
+
+import com.glavsoft.viewer.Viewer;
+import com.glavsoft.viewer.VncKeepAliveThread;
+import com.glavsoft.viewer.cli.Parser;
+
+import javax.swing.*;
+import java.io.File;
+
+import static com.google.gct.testing.launcher.CloudAuthenticator.getTest;
+
+public class VncKeepAliveThreadImpl extends VncKeepAliveThread {
+ private final Parser parser;
+ private final String configurationName;
+ private final String cloudProjectId;
+ private final String cloudDeviceId;
+ private final String deviceAddress;
+ private final File workingDir;
+ private volatile boolean hasCrashed = false;
+
+
+ public static void startVnc(String[] args, String configurationName, String cloudProjectId, String cloudDeviceId, String deviceAddress,
+ File workingDir) {
+ Parser parser = Viewer.prepareParser(args);
+ if (parser == null) {
+ return;
+ }
+ new VncKeepAliveThreadImpl(parser, configurationName, cloudProjectId, cloudDeviceId, deviceAddress, workingDir).start();
+ }
+
+ public VncKeepAliveThreadImpl(Parser parser, String configurationName, String cloudProjectId, String cloudDeviceId, String deviceAddress,
+ File workingDir) {
+ this.parser = parser;
+ this.configurationName = configurationName;
+ this.cloudProjectId = cloudProjectId;
+ this.cloudDeviceId = cloudDeviceId;
+ this.deviceAddress = deviceAddress;
+ this.workingDir = workingDir;
+ }
+
+ @Override
+ public void run() {
+ SwingUtilities.invokeLater(new Viewer(this, parser, configurationName));
+
+ while (!Thread.currentThread().isInterrupted() && deviceIsReady()) {
+ try {
+ getTest().projects().devices().keepalive(cloudProjectId, cloudDeviceId).execute();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ // Restart the viewer if it accidentally crashed.
+ if (hasCrashed) {
+ hasCrashed = false;
+ System.out.println("Restarting TightVNC Viewer");
+ SwingUtilities.invokeLater(new Viewer(this, parser, configurationName));
+ }
+ try {
+ Thread.sleep(1 * 1000); // 1 second
+ } catch (InterruptedException e) {
+ break;
+ }
+ }
+ try {
+ // Delete the cloud device after the viewer is closed.
+ getTest().projects().devices().delete(cloudProjectId, cloudDeviceId).execute();
+ // Disconnect adb from the deleted device (otherwise, it will keep showing the stale cloud device).
+ Runtime.getRuntime().exec("./adb disconnect " + deviceAddress, null, workingDir);
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ }
+
+ private boolean deviceIsReady() {
+ try {
+ return getTest().projects().devices().get(cloudProjectId, cloudDeviceId).execute().getState().equals("READY");
+ } catch (Exception e) {
+ return true; // Do not stop the keep alive thread for intermittent connection failures.
+ }
+ }
+
+ @Override
+ public void setCrashed() {
+ hasCrashed = true;
+ }
+
+}