diff options
Diffstat (limited to 'sdkmanager/libs/sdkuilib/src')
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) { |