aboutsummaryrefslogtreecommitdiffstats
path: root/sdkmanager/libs/sdkuilib/src
diff options
context:
space:
mode:
Diffstat (limited to 'sdkmanager/libs/sdkuilib/src')
-rwxr-xr-xsdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTask.java49
-rwxr-xr-xsdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTaskFactory.java4
-rw-r--r--sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java167
3 files changed, 128 insertions, 92 deletions
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTask.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTask.java
index 42d5558..2563a5f 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTask.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTask.java
@@ -27,21 +27,48 @@ import org.eclipse.swt.widgets.Shell;
*/
public final class ProgressTask extends TaskMonitorImpl {
+ private final String mTitle;
private final ProgressTaskDialog mDialog;
- private boolean mAutomaticallyCloseOnTaskCompletion = true;
+ private volatile boolean mAutoClose = true;
/**
* Creates a new {@link ProgressTask} with the given title.
- * The given task will execute in a separate thread (not the UI thread).
- *
- * This blocks till the thread ends.
+ * This does NOT start the task. The caller must invoke {@link #start(ITask)}.
*/
- public ProgressTask(Shell parent, String title, ITask task) {
+ public ProgressTask(Shell parent, String title) {
super(new ProgressTaskDialog(parent));
+ mTitle = title;
mDialog = (ProgressTaskDialog) getUiProvider();
- mDialog.setText(title);
- mDialog.open(createTaskThread(title, task));
+ mDialog.setText(mTitle);
+ }
+
+ /**
+ * Execute the given task in a separate thread (not the UI thread).
+ * This blocks till the thread ends.
+ * <p/>
+ * The {@link ProgressTask} must not be reused after this call.
+ */
+ public void start(ITask task) {
+ assert mDialog != null;
+ mDialog.open(createTaskThread(mTitle, task));
+ }
+
+ /**
+ * Changes the auto-close behavior of the dialog on task completion.
+ *
+ * @param autoClose True if the dialog should be closed automatically when the task
+ * has completed.
+ */
+ public void setAutoClose(boolean autoClose) {
+ if (autoClose != mAutoClose) {
+ if (autoClose) {
+ mDialog.setAutoCloseRequested();
+ } else {
+ mDialog.setManualCloseRequested();
+ }
+ mAutoClose = autoClose;
+ }
}
/**
@@ -56,7 +83,7 @@ public final class ProgressTask extends TaskMonitorImpl {
@Override
public void run() {
task.run(ProgressTask.this);
- if (mAutomaticallyCloseOnTaskCompletion) {
+ if (mAutoClose) {
mDialog.setAutoCloseRequested();
} else {
mDialog.setManualCloseRequested();
@@ -68,12 +95,14 @@ public final class ProgressTask extends TaskMonitorImpl {
}
/**
- * Sets the dialog to not auto-close since we want the user to see the error.
* {@inheritDoc}
+ * <p/>
+ * Sets the dialog to not auto-close since we want the user to see the error
+ * (this is equivalent to calling {@code setAutoClose(false)}).
*/
@Override
public void logError(String format, Object...args) {
- mAutomaticallyCloseOnTaskCompletion = false;
+ setAutoClose(false);
super.logError(format, args);
}
}
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTaskFactory.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTaskFactory.java
index ac0bc30..bd2cc14 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTaskFactory.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTaskFactory.java
@@ -43,8 +43,8 @@ public final class ProgressTaskFactory implements ITaskFactory {
public void start(String title, ITaskMonitor parentMonitor, ITask task) {
if (parentMonitor == null) {
- new ProgressTask(mShell, title, task);
-
+ ProgressTask p = new ProgressTask(mShell, title);
+ p.start(task);
} else {
// Use all the reminder of the parent monitor.
if (parentMonitor.getProgressMax() == 0) {
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java
index e2e148b..8c0057b 100644
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java
@@ -26,6 +26,9 @@ import com.android.sdklib.internal.avd.AvdInfo.AvdStatus;
import com.android.sdklib.internal.avd.AvdManager;
import com.android.sdklib.internal.repository.ITask;
import com.android.sdklib.internal.repository.ITaskMonitor;
+import com.android.sdklib.util.GrabProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.Wait;
import com.android.sdkuilib.internal.repository.SettingsController;
import com.android.sdkuilib.internal.repository.icons.ImageFactory;
import com.android.sdkuilib.internal.tasks.ProgressTask;
@@ -55,10 +58,8 @@ import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
-import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
-import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@@ -1081,93 +1082,99 @@ public final class AvdSelector {
final String[] command = list.toArray(new String[list.size()]);
// launch the emulator
- new ProgressTask(mTable.getShell(),
- "Starting Android Emulator",
- new ITask() {
- @Override
- public void run(ITaskMonitor monitor) {
- try {
- monitor.setDescription(
- "Starting emulator for AVD '%1$s'",
- avdName);
- int n = 10;
- monitor.setProgressMax(n);
- Process process = Runtime.getRuntime().exec(command);
- grabEmulatorOutput(process, monitor);
-
- // This small wait prevents the dialog from closing too fast:
- // When it works, the emulator returns immediately, even if
- // no UI is shown yet. And when it fails (because the AVD is
- // locked/running)
- // if we don't have a wait we don't capture the error for
- // some reason.
- for (int i = 0; i < n; i++) {
- try {
- Thread.sleep(100);
- monitor.incProgress(1);
- } catch (InterruptedException e) {
- // ignore
+ final ProgressTask progress = new ProgressTask(mTable.getShell(),
+ "Starting Android Emulator");
+ progress.start(new ITask() {
+ ITaskMonitor mMonitor = null;
+
+ @Override
+ public void run(final ITaskMonitor monitor) {
+ mMonitor = monitor;
+ try {
+ monitor.setDescription(
+ "Starting emulator for AVD '%1$s'",
+ avdName);
+ monitor.log("Starting emulator for AVD '%1$s'", avdName);
+
+ // we'll wait 100ms*100 = 10s. The emulator sometimes seem to
+ // start mostly OK just to crash a few seconds later. 10 seconds
+ // seems a good wait for that case.
+ int n = 100;
+ monitor.setProgressMax(n);
+
+ Process process = Runtime.getRuntime().exec(command);
+ GrabProcessOutput.grabProcessOutput(
+ process,
+ Wait.ASYNC,
+ new IProcessOutput() {
+ @Override
+ public void out(String line) {
+ if (line != null) {
+ filterStdOut(line);
+ }
}
- }
- } catch (IOException e) {
- monitor.logError("Failed to start emulator: %1$s",
- e.getMessage());
+
+ @Override
+ public void err(String line) {
+ if (line != null) {
+ filterStdErr(line);
+ }
+ }
+ });
+
+ // This small wait prevents the dialog from closing too fast:
+ // When it works, the emulator returns immediately, even if
+ // no UI is shown yet. And when it fails (because the AVD is
+ // locked/running) this allows us to have time to capture the
+ // error and display it.
+ for (int i = 0; i < n; i++) {
+ try {
+ Thread.sleep(100);
+ monitor.incProgress(1);
+ } catch (InterruptedException e) {
+ // ignore
}
}
- });
- }
- }
+ } catch (Exception e) {
+ monitor.logError("Failed to start emulator: %1$s",
+ e.getMessage());
+ } finally {
+ mMonitor = null;
+ }
+ }
- /**
- * Get the stderr/stdout outputs of a process and return when the process is done.
- * Both <b>must</b> be read or the process will block on windows.
- * @param process The process to get the output from.
- * @param monitor An {@link ITaskMonitor} to capture errors. Cannot be null.
- */
- private void grabEmulatorOutput(final Process process, final ITaskMonitor monitor) {
- // read the lines as they come. if null is returned, it's because the process finished
- new Thread("emu-stderr") { //$NON-NLS-1$
- @Override
- public void run() {
- // create a buffer to read the stderr output
- InputStreamReader is = new InputStreamReader(process.getErrorStream());
- BufferedReader errReader = new BufferedReader(is);
-
- try {
- while (true) {
- String line = errReader.readLine();
- if (line != null) {
- monitor.logError("%1$s", line); //$NON-NLS-1$
- } else {
- break;
- }
+ private void filterStdOut(String line) {
+ // Skip some non-useful messages.
+ if (line.indexOf("NSQuickDrawView") != -1) { //$NON-NLS-1$
+ // Discard the MacOS warning:
+ // "This application, or a library it uses, is using NSQuickDrawView,
+ // which has been deprecated. Apps should cease use of QuickDraw and move
+ // to Quartz."
+ return;
+ }
+
+ if (line.toLowerCase().indexOf("error") != -1 || //$NON-NLS-1$
+ line.indexOf("qemu: fatal") != -1) { //$NON-NLS-1$
+ // Sometimes the emulator seems to output errors on stdout. Catch these.
+ mMonitor.logError("%1$s", line); //$NON-NLS-1$
+ return;
}
- } catch (IOException e) {
- // do nothing.
+
+ mMonitor.log("%1$s", line); //$NON-NLS-1$
}
- }
- }.start();
- new Thread("emu-stdout") { //$NON-NLS-1$
- @Override
- public void run() {
- InputStreamReader is = new InputStreamReader(process.getInputStream());
- BufferedReader outReader = new BufferedReader(is);
-
- try {
- while (true) {
- String line = outReader.readLine();
- if (line != null) {
- monitor.log("%1$s", line); //$NON-NLS-1$
- } else {
- break;
- }
+ private void filterStdErr(String line) {
+ if (line.indexOf("emulator: device") != -1 || //$NON-NLS-1$
+ line.indexOf("HAX is working") != -1) { //$NON-NLS-1$
+ // These are not errors. Output them as regular stdout messages.
+ mMonitor.log("%1$s", line); //$NON-NLS-1$
+ return;
}
- } catch (IOException e) {
- // do nothing.
+
+ mMonitor.logError("%1$s", line); //$NON-NLS-1$
}
- }
- }.start();
+ });
+ }
}
private boolean isAvdRepairable(AvdStatus avdStatus) {