From 5cb8998363a16e667faee4eaa7e5040bce7e702b Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Mon, 28 Nov 2016 13:15:10 -0800 Subject: [PATCH 1/3] Preload2: Abstract out UI Create IUI interface and move UI to SwingUI. Bug: 31961946 Test: manual Change-Id: If56347fdde8b441c0c01337a3f5eac002ea5b4f3 --- .../src/com/android/preload/Main.java | 17 +++++--- .../actions/ComputeThresholdAction.java | 7 +-- .../src/com/android/preload/ui/IUI.java | 43 +++++++++++++++++++ .../preload/ui/{UI.java => SwingUI.java} | 27 ++++++++++-- 4 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 tools/preload2/src/com/android/preload/ui/IUI.java rename tools/preload2/src/com/android/preload/ui/{UI.java => SwingUI.java} (94%) diff --git a/tools/preload2/src/com/android/preload/Main.java b/tools/preload2/src/com/android/preload/Main.java index ca5b0e005a1d2..cc54a8d9c7157 100644 --- a/tools/preload2/src/com/android/preload/Main.java +++ b/tools/preload2/src/com/android/preload/Main.java @@ -32,7 +32,8 @@ import com.android.preload.actions.ShowDataAction; import com.android.preload.classdataretrieval.ClassDataRetriever; import com.android.preload.classdataretrieval.hprof.Hprof; import com.android.preload.classdataretrieval.jdwp.JDWPClassDataRetriever; -import com.android.preload.ui.UI; +import com.android.preload.ui.IUI; +import com.android.preload.ui.SwingUI; import java.util.ArrayList; import java.util.Collection; @@ -66,7 +67,7 @@ public class Main { private DumpTableModel dataTableModel; private DefaultListModel clientListModel; - private UI ui; + private IUI ui; // Actions that need to be updated once a device is selected. private Collection deviceSpecificActions; @@ -89,13 +90,15 @@ public class Main { * @param args */ public static void main(String[] args) { - Main m = new Main(); + Main m = new Main(new SwingUI()); top = m; m.startUp(); } - public Main() { + public Main(IUI ui) { + this.ui = ui; + clientListModel = new DefaultListModel(); dataTableModel = new DumpTableModel(); @@ -124,11 +127,10 @@ public class Main { } } - ui = new UI(clientListModel, dataTableModel, actions); - ui.setVisible(true); + ui.prepare(clientListModel, dataTableModel, actions); } - public static UI getUI() { + public static IUI getUI() { return top.ui; } @@ -176,6 +178,7 @@ public class Main { new ReloadListAction(clientUtils, getDevice(), clientListModel).run(); getUI().hideWaitDialog(); + getUI().ready(); } private void initDevice() { diff --git a/tools/preload2/src/com/android/preload/actions/ComputeThresholdAction.java b/tools/preload2/src/com/android/preload/actions/ComputeThresholdAction.java index b524716fc2cb2..5d052ccc70723 100644 --- a/tools/preload2/src/com/android/preload/actions/ComputeThresholdAction.java +++ b/tools/preload2/src/com/android/preload/actions/ComputeThresholdAction.java @@ -32,7 +32,6 @@ import java.util.TreeSet; import java.util.regex.Pattern; import javax.swing.AbstractAction; -import javax.swing.JFileChooser; /** * Compute an intersection of classes from the given data. A class is in the intersection if it @@ -92,10 +91,8 @@ public class ComputeThresholdAction extends AbstractAction implements Runnable { boolean ret = Main.getUI().showConfirmDialog("Computed a set with " + result.size() + " classes, would you like to save to disk?", "Save?"); if (ret) { - JFileChooser jfc = new JFileChooser(); - int ret2 = jfc.showSaveDialog(Main.getUI()); - if (ret2 == JFileChooser.APPROVE_OPTION) { - File f = jfc.getSelectedFile(); + File f = Main.getUI().showSaveDialog(); + if (f != null) { saveSet(result, f); } } diff --git a/tools/preload2/src/com/android/preload/ui/IUI.java b/tools/preload2/src/com/android/preload/ui/IUI.java new file mode 100644 index 0000000000000..3c151d90ab0af --- /dev/null +++ b/tools/preload2/src/com/android/preload/ui/IUI.java @@ -0,0 +1,43 @@ +package com.android.preload.ui; + +import com.android.ddmlib.Client; +import java.io.File; +import java.util.List; +import javax.swing.Action; +import javax.swing.ListModel; +import javax.swing.table.TableModel; + +/** + * UI abstraction for the tool. This allows a graphical mode, command line mode, + * or silent mode. + */ +public interface IUI { + + void prepare(ListModel clientListModel, TableModel dataTableModel, + List actions); + + void ready(); + + Client getSelectedClient(); + + int getSelectedDataTableRow(); + + void showWaitDialog(); + + void updateWaitDialog(String s); + + void hideWaitDialog(); + + void showMessageDialog(String s); + + boolean showConfirmDialog(String title, String message); + + String showInputDialog(String message); + + T showChoiceDialog(String title, String message, T[] choices); + + File showSaveDialog(); + + File[] showOpenDialog(boolean multi); + +} diff --git a/tools/preload2/src/com/android/preload/ui/UI.java b/tools/preload2/src/com/android/preload/ui/SwingUI.java similarity index 94% rename from tools/preload2/src/com/android/preload/ui/UI.java rename to tools/preload2/src/com/android/preload/ui/SwingUI.java index 47174ddd0e075..1245f2c23d7e3 100644 --- a/tools/preload2/src/com/android/preload/ui/UI.java +++ b/tools/preload2/src/com/android/preload/ui/SwingUI.java @@ -41,7 +41,7 @@ import javax.swing.ListModel; import javax.swing.SwingUtilities; import javax.swing.table.TableModel; -public class UI extends JFrame { +public class SwingUI extends JFrame implements IUI { private JList clientList; private JTable dataTable; @@ -49,11 +49,13 @@ public class UI extends JFrame { // Shared file chooser, means the directory is retained. private JFileChooser jfc; - public UI(ListModel clientListModel, - TableModel dataTableModel, - List actions) { + public SwingUI() { super("Preloaded-classes computation"); + } + @Override + public void prepare(ListModel clientListModel, TableModel dataTableModel, + List actions) { getContentPane().add(new JScrollPane(clientList = new JList(clientListModel)), BorderLayout.WEST); clientList.setCellRenderer(new ClientListCellRenderer()); @@ -74,18 +76,27 @@ public class UI extends JFrame { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 800, 600); + + setVisible(true); } + @Override + public void ready() { + } + + @Override public Client getSelectedClient() { return clientList.getSelectedValue(); } + @Override public int getSelectedDataTableRow() { return dataTable.getSelectedRow(); } private JDialog currentWaitDialog = null; + @Override public void showWaitDialog() { if (currentWaitDialog == null) { currentWaitDialog = new JDialog(this, "Please wait...", true); @@ -111,6 +122,7 @@ public class UI extends JFrame { }); } + @Override public void updateWaitDialog(String s) { if (currentWaitDialog != null) { ((JLabel) currentWaitDialog.getContentPane().getComponent(0)).setText(s); @@ -124,6 +136,7 @@ public class UI extends JFrame { } } + @Override public void hideWaitDialog() { if (currentWaitDialog != null) { currentWaitDialog.setVisible(false); @@ -131,6 +144,7 @@ public class UI extends JFrame { } } + @Override public void showMessageDialog(String s) { // Hide the wait dialog... if (currentWaitDialog != null) { @@ -147,6 +161,7 @@ public class UI extends JFrame { } } + @Override public boolean showConfirmDialog(String title, String message) { // Hide the wait dialog... if (currentWaitDialog != null) { @@ -164,6 +179,7 @@ public class UI extends JFrame { } } + @Override public String showInputDialog(String message) { // Hide the wait dialog... if (currentWaitDialog != null) { @@ -180,6 +196,7 @@ public class UI extends JFrame { } } + @Override @SuppressWarnings("unchecked") public T showChoiceDialog(String title, String message, T[] choices) { // Hide the wait dialog... @@ -203,6 +220,7 @@ public class UI extends JFrame { } } + @Override public File showSaveDialog() { // Hide the wait dialog... if (currentWaitDialog != null) { @@ -228,6 +246,7 @@ public class UI extends JFrame { } } + @Override public File[] showOpenDialog(boolean multi) { // Hide the wait dialog... if (currentWaitDialog != null) { From 1c809a3d3240978ab393b48ec5501090ec5a0e57 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Mon, 28 Nov 2016 15:04:25 -0800 Subject: [PATCH 2/3] Preload2: Fix action inheritance Use AbstractThreadedAction as a base. Bug: 31961946 Test: manual Change-Id: I5a05b65d753be775c8b8382bb1a81e869c388f8d --- .../android/preload/actions/ComputeThresholdAction.java | 4 ++-- .../src/com/android/preload/actions/ExportAction.java | 7 ++----- .../src/com/android/preload/actions/ImportAction.java | 4 ++-- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/tools/preload2/src/com/android/preload/actions/ComputeThresholdAction.java b/tools/preload2/src/com/android/preload/actions/ComputeThresholdAction.java index 5d052ccc70723..3a7f7f74d755c 100644 --- a/tools/preload2/src/com/android/preload/actions/ComputeThresholdAction.java +++ b/tools/preload2/src/com/android/preload/actions/ComputeThresholdAction.java @@ -38,7 +38,7 @@ import javax.swing.AbstractAction; * appears in at least the number of threshold given packages. An optional blacklist can be * used to filter classes from the intersection. */ -public class ComputeThresholdAction extends AbstractAction implements Runnable { +public class ComputeThresholdAction extends AbstractThreadedAction { protected int threshold; private Pattern blacklist; private DumpTableModel dataTableModel; @@ -71,7 +71,7 @@ public class ComputeThresholdAction extends AbstractAction implements Runnable { return; } - new Thread(this).start(); + super.actionPerformed(e); } @Override diff --git a/tools/preload2/src/com/android/preload/actions/ExportAction.java b/tools/preload2/src/com/android/preload/actions/ExportAction.java index cb8b3df75b18a..848a568267884 100644 --- a/tools/preload2/src/com/android/preload/actions/ExportAction.java +++ b/tools/preload2/src/com/android/preload/actions/ExportAction.java @@ -19,14 +19,11 @@ package com.android.preload.actions; import com.android.preload.DumpDataIO; import com.android.preload.DumpTableModel; import com.android.preload.Main; - import java.awt.event.ActionEvent; import java.io.File; import java.io.PrintWriter; -import javax.swing.AbstractAction; - -public class ExportAction extends AbstractAction implements Runnable { +public class ExportAction extends AbstractThreadedAction { private File lastSaveFile; private DumpTableModel dataTableModel; @@ -39,7 +36,7 @@ public class ExportAction extends AbstractAction implements Runnable { public void actionPerformed(ActionEvent e) { lastSaveFile = Main.getUI().showSaveDialog(); if (lastSaveFile != null) { - new Thread(this).start(); + super.actionPerformed(e); } } diff --git a/tools/preload2/src/com/android/preload/actions/ImportAction.java b/tools/preload2/src/com/android/preload/actions/ImportAction.java index 5c1976580f944..bfeeb836fd458 100644 --- a/tools/preload2/src/com/android/preload/actions/ImportAction.java +++ b/tools/preload2/src/com/android/preload/actions/ImportAction.java @@ -27,7 +27,7 @@ import java.util.Collection; import javax.swing.AbstractAction; -public class ImportAction extends AbstractAction implements Runnable { +public class ImportAction extends AbstractThreadedAction { private File[] lastOpenFiles; private DumpTableModel dataTableModel; @@ -40,7 +40,7 @@ public class ImportAction extends AbstractAction implements Runnable { public void actionPerformed(ActionEvent e) { lastOpenFiles = Main.getUI().showOpenDialog(true); if (lastOpenFiles != null) { - new Thread(this).start(); + super.actionPerformed(e); } } From 3bf65c916ce65c06b0920ec4b8f68d3ef6c5e721 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Mon, 28 Nov 2016 15:06:35 -0800 Subject: [PATCH 3/3] Preload2: Add isSingleThreaded Expose whether a UI is single-threaded to avoid spawning threads in actions. Bug: 31961946 Test: manual Change-Id: I37c8daa6a00784e833bad53b8e83ab4417955df7 --- .../android/preload/actions/AbstractThreadedAction.java | 7 ++++++- .../src/com/android/preload/actions/RunMonkeyAction.java | 7 ++++++- tools/preload2/src/com/android/preload/ui/IUI.java | 2 ++ tools/preload2/src/com/android/preload/ui/SwingUI.java | 5 +++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/tools/preload2/src/com/android/preload/actions/AbstractThreadedAction.java b/tools/preload2/src/com/android/preload/actions/AbstractThreadedAction.java index fbf83d2e23399..5787d8507230b 100644 --- a/tools/preload2/src/com/android/preload/actions/AbstractThreadedAction.java +++ b/tools/preload2/src/com/android/preload/actions/AbstractThreadedAction.java @@ -16,6 +16,7 @@ package com.android.preload.actions; +import com.android.preload.Main; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; @@ -28,7 +29,11 @@ public abstract class AbstractThreadedAction extends AbstractAction implements R @Override public void actionPerformed(ActionEvent e) { - new Thread(this).start(); + if (Main.getUI().isSingleThreaded()) { + run(); + } else { + new Thread(this).start(); + } } } diff --git a/tools/preload2/src/com/android/preload/actions/RunMonkeyAction.java b/tools/preload2/src/com/android/preload/actions/RunMonkeyAction.java index 385e8577b1c8b..29464fc7abdfb 100644 --- a/tools/preload2/src/com/android/preload/actions/RunMonkeyAction.java +++ b/tools/preload2/src/com/android/preload/actions/RunMonkeyAction.java @@ -58,7 +58,12 @@ public class RunMonkeyAction extends AbstractAction implements DeviceSpecific { if (packages.isEmpty()) { packages = DEFAULT_MONKEY_PACKAGES; } - new Thread(new RunMonkeyRunnable(packages)).start(); + Runnable r = new RunMonkeyRunnable(packages); + if (Main.getUI().isSingleThreaded()) { + r.run(); + } else { + new Thread(r).start(); + } } private class RunMonkeyRunnable implements Runnable { diff --git a/tools/preload2/src/com/android/preload/ui/IUI.java b/tools/preload2/src/com/android/preload/ui/IUI.java index 3c151d90ab0af..9371463e9a790 100644 --- a/tools/preload2/src/com/android/preload/ui/IUI.java +++ b/tools/preload2/src/com/android/preload/ui/IUI.java @@ -18,6 +18,8 @@ public interface IUI { void ready(); + boolean isSingleThreaded(); + Client getSelectedClient(); int getSelectedDataTableRow(); diff --git a/tools/preload2/src/com/android/preload/ui/SwingUI.java b/tools/preload2/src/com/android/preload/ui/SwingUI.java index 1245f2c23d7e3..cab3744ad74c5 100644 --- a/tools/preload2/src/com/android/preload/ui/SwingUI.java +++ b/tools/preload2/src/com/android/preload/ui/SwingUI.java @@ -53,6 +53,11 @@ public class SwingUI extends JFrame implements IUI { super("Preloaded-classes computation"); } + @Override + public boolean isSingleThreaded() { + return false; + } + @Override public void prepare(ListModel clientListModel, TableModel dataTableModel, List actions) {