Commits

Christian Fischer  committed 45bc3bb

LogCat: multiple devices support: use serial numbers instead of device objects

  • Participants
  • Parent commits 69d5ede

Comments (0)

Files changed (1)

File logcat_multiple_devices.patch

 # HG changeset patch
 # Date 1309392817 -7200
-# Parent 20fb85cab183b91583c00d2ddcab6f86ef8e28a1
+# Parent df9ed72bb18c1d1d3e282d8a181f48065135f50b
 LogCat: Added support for multiple devices
 
-diff -r 20fb85cab183 logcat/src/org/nyerel/nbandroid/logcat/LogDevicesComboBoxSupport.java
+diff -r df9ed72bb18c logcat/src/org/nyerel/nbandroid/logcat/LogDevicesComboBoxSupport.java
 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-+++ b/logcat/src/org/nyerel/nbandroid/logcat/LogDevicesComboBoxSupport.java	Fri Jul 01 03:54:38 2011 +0200
-@@ -0,0 +1,245 @@
++++ b/logcat/src/org/nyerel/nbandroid/logcat/LogDevicesComboBoxSupport.java	Sun Jul 03 00:15:57 2011 +0200
+@@ -0,0 +1,325 @@
 +/*
 + * Licensed under the Apache License, Version 2.0 (the "License");
 + * you may not use this file except in compliance with the License.
 +
 +import com.android.ddmlib.AndroidDebugBridge;
 +import com.android.ddmlib.IDevice;
-+import java.awt.Color;
 +import java.awt.Component;
 +import java.beans.PropertyChangeEvent;
 +import java.beans.PropertyChangeListener;
 +import java.util.ArrayList;
++import java.util.HashMap;
 +import java.util.HashSet;
 +import java.util.List;
++import java.util.Map;
 +import java.util.Set;
 +import javax.swing.ComboBoxModel;
++import javax.swing.JComboBox;
 +import javax.swing.JLabel;
 +import javax.swing.JList;
 +import javax.swing.ListCellRenderer;
 +import org.netbeans.modules.android.core.ddm.AndroidDebugBridgeFactory;
 +import org.openide.util.WeakListeners;
 +
++
 +/**
++ * Support class for the list of logged devices.
++ * Implements a data model, cell renderer and a listener
++ * to handle attached and detached devices.
 + * @author Christian Fischer
 + */
 +public class LogDevicesComboBoxSupport
 +                AndroidDebugBridge.IDeviceChangeListener
 +{
 +    private Set<ListDataListener>   dataListeners   = new HashSet<ListDataListener>();
-+    private List<IDevice>           devices         = new ArrayList<IDevice>();
++    private List<String>            devices         = new ArrayList<String>();
++    private Map<String,String>      deviceLabels    = new HashMap<String,String>();
 +    private LogReader               reader;
++    private JComboBox               cmb;
 +
 +
 +    protected LogDevicesComboBoxSupport(LogReader reader) {
 +        
 +        update();
 +    }
++    
++    
++    /**
++     * Attaches this support class to a combo box.
++     * @param cmb 
++     */
++    public void attach(JComboBox cmb) {
++        this.cmb = cmb;
++        this.cmb.setModel(this);
++        this.cmb.setRenderer(this);
++        return;
++    }
++    
++    
++    /**
++     * Detach all listeners of this support class.
++     */
++    public void detach() {
++        AndroidDebugBridge.removeDeviceChangeListener(this);
++        
++        reader.removePropertyChangeListener(this);
++        
++        return;
++    }
 +
 +
++    /**
++     * Update the content of the list data model
++     * and add all currently logged and attached devices.
++     */
 +    private void update() {
 +        // add all logged devices
-+        for(IDevice device : reader.getLoggedDevices()) {
++        for(String device : reader.getLoggedDevices()) {
 +            add(device);
 +        }
 +
 +
 +        return;
 +    }
++    
++    /**
++     * Add a new device to the data model,
++     * or replace any existing.
++     */
++    private void add(IDevice device) {
++        String serial = device.getSerialNumber();
++        
++        do {
++            // for emulators use their virtual device name as label
++            String deviceAvdName = device.getAvdName();
++            if (deviceAvdName != null) {
++                deviceLabels.put(serial, deviceAvdName + " [" + serial + "]");
++                break;
++            }
 +
-+    private void add(IDevice device) {
++            // for real devices use their model name (something like '<vendor> <device>')
++            String deviceModelName = device.getProperty("ro.product.model");
++            if (deviceModelName != null) {
++                deviceLabels.put(serial, deviceModelName + " [" + serial + "]");
++                break;
++            }
++
++            // clear the last label, when no new label was found
++            deviceLabels.remove(serial);
++        }
++        while(false);
++
++        // finally, add the serial.
++        add(serial);
++    }
++
++    /**
++     * Add a new device serial to this data model, if it doesn't already exist.
++     */
++    private void add(String device) {
 +        int insertIndex = devices.size();
 +        
++        // check, if this serial already exists.
 +        for(int i=devices.size(); --i>=0;) {
-+            if (devices.get(i).getSerialNumber().equals(device.getSerialNumber())) {
-+                devices.remove(i);
++            if (devices.get(i).equals(device)) {
++                
++                // refresh this item (the label may changed)
 +                fireListDataEvent(ListDataEvent.INTERVAL_REMOVED, i);
++                fireListDataEvent(ListDataEvent.INTERVAL_ADDED, i);
 +                
-+                // replace this device
-+                insertIndex = i;
-+                
-+                break;
++                return;
 +            }
 +        }
 +        
 +
 +        return;
 +    }
++    
++    
++    /**
++     * Remove a device from the data model, except it has messages in the log cache.
++     */
++    private void remove(IDevice device) {
++        remove(device.getSerialNumber());
++    }
 +
-+    private void remove(IDevice device) {
-+       for(int i=devices.size(); --i>=0;) {
-+            if (devices.get(i).getSerialNumber().equals(device.getSerialNumber())) {
++    /**
++     * Remove a device from the data model, except it has messages in the log cache.
++     */
++    private void remove(String device) {
++        // do we have log events for this device?
++        if (reader.getLogEventsForDevice(device) != null) {
++            // if true, we want to keep it
++            return;
++        }
++        
++        for(int i=devices.size(); --i>=0;) {
++            if (devices.get(i).equals(device)) {
 +                devices.remove(i);
 +                fireListDataEvent(ListDataEvent.INTERVAL_REMOVED, i);
 +            }
 +
 +    @Override
 +    public void setSelectedItem(Object anItem) {
-+        if (anItem instanceof IDevice) {
-+            reader.setCurrentDevice((IDevice)anItem);
++        if (anItem instanceof String) {
++            reader.setCurrentDevice((String)anItem);
 +        }
 +
 +        return;
 +    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
 +        JLabel label;
 +        
-+        if (value != null && value instanceof IDevice) {
-+            IDevice device = (IDevice)value;
-+            String deviceName   = device.getAvdName();
-+            String deviceSerial = device.getSerialNumber();
-+            String deviceModel  = device.getProperty("ro.product.model");
-+            String deviceLabel;
++        if (value != null && value instanceof String) {
++            String deviceSerial = (String)value;
++            String deviceLabel  = deviceLabels.get(deviceSerial);
 +            
-+            if (deviceName != null) {
-+                deviceLabel = deviceName + " [" + deviceSerial + "]";
-+            }
-+            else if (deviceModel != null) {
-+                deviceLabel = deviceModel + " [" + deviceSerial + "]";
-+            }
-+            else {
++            // if we don't have a valid label for this device, just use the serial
++            if (deviceLabel == null) {
 +                deviceLabel = deviceSerial;
 +            }
 +            
 +            label = new JLabel(deviceLabel);
 +        }
 +        else {
-+            label = new JLabel();
++            // fallback, if there's something unexpected
++            label = new JLabel(String.valueOf(value));
 +        }
 +        
 +        if (isSelected) {
 +        // do nothing
 +    }
 +}
-diff -r 20fb85cab183 logcat/src/org/nyerel/nbandroid/logcat/LogReader.java
---- a/logcat/src/org/nyerel/nbandroid/logcat/LogReader.java	Thu Jun 30 21:54:42 2011 +0200
-+++ b/logcat/src/org/nyerel/nbandroid/logcat/LogReader.java	Fri Jul 01 03:54:38 2011 +0200
+diff -r df9ed72bb18c logcat/src/org/nyerel/nbandroid/logcat/LogReader.java
+--- a/logcat/src/org/nyerel/nbandroid/logcat/LogReader.java	Fri Jul 01 03:56:43 2011 +0200
++++ b/logcat/src/org/nyerel/nbandroid/logcat/LogReader.java	Sun Jul 03 00:15:57 2011 +0200
 @@ -22,6 +22,8 @@
  import com.android.ddmlib.MultiLineReceiver;
  import com.android.ddmlib.ShellCommandUnresponsiveException;
 -    private IDevice device;
 +    private PropertyChangeSupport changeSupprt;
 +    private IDevice currentDevice;
-+    private IDevice wantDevice;
++    private String requestedDeviceSerial;
      private LogCatOutputReceiver receiver;
      private LogEventInfo lastLogEventInfo;
      private static Pattern sLogPattern = Pattern.compile(
      
 -    private String lastDeviceSN;
 -    private Set<LogEvent> loggedEvents;
--    
-     private Map<IDevice,Map<Integer, String[]>> processNameCache
-             = new HashMap<IDevice, Map<Integer, String[]>>();
-+    
-+    private Map<IDevice,Set<LogEvent>> logEventCache
-+            = new HashMap<IDevice,Set<LogEvent>>();
++    private Map<String,Map<Integer, String[]>> processNameCache
++            = new HashMap<String, Map<Integer, String[]>>();
+     
+-    private Map<IDevice,Map<Integer, String[]>> processNameCache
+-            = new HashMap<IDevice, Map<Integer, String[]>>();
++    private Map<String,Set<LogEvent>> logEventCache
++            = new HashMap<String,Set<LogEvent>>();
  
  
      public LogReader() {
          
          adb = AndroidDebugBridgeFactory.getDefault();
          checkReadingStatusTimer = new Timer();
-@@ -94,17 +102,44 @@
+@@ -94,17 +102,53 @@
              }
          }, checkingPeriod, checkingPeriod);
      }
 +    
 +    
-+    public Set<IDevice> getLoggedDevices() {
++    public Set<String> getLoggedDevices() {
 +        return logEventCache.keySet();
 +    }
 +    
 +    
-+    public IDevice getCurrentDevice() {
-+        if (wantDevice != null) {
-+            return wantDevice;
++    public Set<LogEvent> getLogEventsForDevice(String device) {
++        return logEventCache.get(device);
++    }
++    
++    
++    public String getCurrentDevice() {
++        if (requestedDeviceSerial != null) {
++            return requestedDeviceSerial;
 +        }
 +        
-+        return currentDevice;
++        if (currentDevice != null) {
++            return currentDevice.getSerialNumber();
++        }
++        
++        return null;
 +    }
 +    
 +    
-+    public void setCurrentDevice(IDevice device) {
-+        if (this.wantDevice != device) {
++    public void setCurrentDevice(String device) {
++        if (device!=null && !device.equals(requestedDeviceSerial)) {
 +            // set new device
-+            this.wantDevice = device;
++            this.requestedDeviceSerial = device;
 +            
 +            // stop reading on current device
 +            stopReading();
                  gotIt = true;
              }
          }
-@@ -114,6 +149,19 @@
+@@ -114,6 +158,19 @@
          }
          return true;
      }
  
      public void addLogListener(LogListener listener) {
          listeners.add(listener);
-@@ -151,17 +199,19 @@
+@@ -151,17 +208,19 @@
  
      private final class LogCatOutputReceiver extends MultiLineReceiver {
  
              }
          }
  
-@@ -190,30 +240,26 @@
+@@ -190,30 +249,45 @@
      }
  
      private void reallyStartReading() {
 -            device = devs[0];
 -        } else {
 -            errorMessage("No devices found!");
--            return;
-+        if (wantDevice == null) {
-+            // need to connect to a new device
++        if (requestedDeviceSerial == null) {
++            // if no device was requested, select the first available
 +            IDevice[] devs = adb.getDevices();
 +            if (devs != null && devs.length > 0) {
-+                wantDevice = devs[0];
++                requestedDeviceSerial = devs[0].getSerialNumber();
 +            } else {
 +                errorMessage("No devices found!");
 +                return;
 +            }
++        }
++        
++        // select current device by requested serial
++        if (currentDevice == null || !currentDevice.getSerialNumber().equals(requestedDeviceSerial)) {
++            currentDevice =  null;
++            
++            IDevice[] devs = adb.getDevices();
++            if (devs != null) {
++                for(IDevice dev : devs) {
++                    if (dev.getSerialNumber().equals(requestedDeviceSerial)) {
++                        currentDevice = dev;
++                        break;
++                    }
++                }
++            }
++        }
++        
++        if (currentDevice == null) {
++            errorMessage("Device with serial " + requestedDeviceSerial + " not available.");
+             return;
          }
          
 -        if (device.isOnline()) {
 -            }
 -            
 -            receiver = new LogCatOutputReceiver();
-+        if (wantDevice.isOnline()) {
-+            currentDevice = wantDevice;
++        if (currentDevice.isOnline()) {
 +            receiver = new LogCatOutputReceiver(currentDevice);
              RequestProcessor.getDefault().post(new Runnable() {
  
                      } catch (TimeoutException e) {
                        LOG.log(Level.FINE, null, e);
                        reading = false;
-@@ -228,6 +274,11 @@
+@@ -228,6 +302,11 @@
                        reading = false;
                      } finally {
                          receiver = null;
 +                        
-+                        // when the device has changted, we restart the logging process
-+                        if (currentDevice != wantDevice) {
++                        // when the device has changed, we restart the logging process
++                        if (!currentDevice.getSerialNumber().equals(requestedDeviceSerial)) {
 +                            startReading();
 +                        }
                      }
                  }
              });
-@@ -237,7 +288,10 @@
+@@ -237,7 +316,10 @@
      }
  
      public void stopReading() {
          shouldBeReading = false;
      }
  
-@@ -248,7 +302,7 @@
+@@ -248,7 +330,7 @@
          return false;
      }
  
          for (String line : lines) {
              // ignore empty lines.
              if (line.length() > 0) {
-@@ -286,6 +340,16 @@
+@@ -286,6 +368,16 @@
                      }
                      
                      LogEvent event = new LogEvent(lastLogEventInfo, message);
 +                    
-+                    Set<LogEvent> loggedEvents = logEventCache.get(device);
++                    Set<LogEvent> loggedEvents = logEventCache.get(device.getSerialNumber());
 +                    if (loggedEvents == null) {
 +                        loggedEvents = new HashSet<LogEvent>();
-+                        logEventCache.put(device, loggedEvents);
++                        logEventCache.put(device.getSerialNumber(), loggedEvents);
 +                        
 +                        // notify listeners for the new device
 +                        firePropertyChange(PROPERTY_DEVICE_LIST, null, getLoggedDevices());
                      if(!loggedEvents.contains(event)) {
                          loggedEvents.add(event);
                          sendNewLogEvent(event);
-@@ -330,13 +394,4 @@
+@@ -306,10 +398,10 @@
+      *               or {@code null}, if the process couldn't be retrieved yet.
+      */
+     private String[] getProcessName(IDevice device, int pid) {
+-        Map<Integer, String[]> cache = processNameCache.get(device);
++        Map<Integer, String[]> cache = processNameCache.get(device.getSerialNumber());
+         if (cache == null) {
+             cache = new HashMap<Integer,String[]>();
+-            processNameCache.put(device, cache);
++            processNameCache.put(device.getSerialNumber(), cache);
+         }
+ 
+         String[] nameref = cache.get(pid);
+@@ -330,13 +422,4 @@
  
          return nameref;
      }
 -        loggedEvents.clear();
 -    }
  }
-diff -r 20fb85cab183 logcat/src/org/nyerel/nbandroid/logcat/LogTopComponent.form
---- a/logcat/src/org/nyerel/nbandroid/logcat/LogTopComponent.form	Thu Jun 30 21:54:42 2011 +0200
-+++ b/logcat/src/org/nyerel/nbandroid/logcat/LogTopComponent.form	Fri Jul 01 03:54:38 2011 +0200
+diff -r df9ed72bb18c logcat/src/org/nyerel/nbandroid/logcat/LogTopComponent.form
+--- a/logcat/src/org/nyerel/nbandroid/logcat/LogTopComponent.form	Fri Jul 01 03:56:43 2011 +0200
++++ b/logcat/src/org/nyerel/nbandroid/logcat/LogTopComponent.form	Sun Jul 03 00:15:57 2011 +0200
 @@ -171,12 +171,7 @@
  
        <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
            <Constraints>
              <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
                <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
-diff -r 20fb85cab183 logcat/src/org/nyerel/nbandroid/logcat/LogTopComponent.java
---- a/logcat/src/org/nyerel/nbandroid/logcat/LogTopComponent.java	Thu Jun 30 21:54:42 2011 +0200
-+++ b/logcat/src/org/nyerel/nbandroid/logcat/LogTopComponent.java	Fri Jul 01 03:54:38 2011 +0200
+diff -r df9ed72bb18c logcat/src/org/nyerel/nbandroid/logcat/LogTopComponent.java
+--- a/logcat/src/org/nyerel/nbandroid/logcat/LogTopComponent.java	Fri Jul 01 03:56:43 2011 +0200
++++ b/logcat/src/org/nyerel/nbandroid/logcat/LogTopComponent.java	Sun Jul 03 00:15:57 2011 +0200
 @@ -84,7 +84,9 @@
      
      private List<LogTableManager> tabManagers;
      public LogTopComponent() {
          initComponents();
          setName(NbBundle.getMessage(LogTopComponent.class, "CTL_LogTopComponent"));
-@@ -270,6 +272,10 @@
+@@ -151,6 +153,11 @@
+       if (reader != null) {
+         stopReading();
+       }
++      
++      if (cmbLogDevicesSupport != null) {
++          cmbLogDevicesSupport.detach();
++      }
++      
+       super.componentClosed();
+     }
+ 
+@@ -270,6 +277,9 @@
                  for (LogTableManager manager : tabManagers) {
                      reader.addLogListener(manager);
                  }
 +                
 +                cmbLogDevicesSupport = new LogDevicesComboBoxSupport(reader);
-+                cmbLogDevices.setModel(cmbLogDevicesSupport);
-+                cmbLogDevices.setRenderer(cmbLogDevicesSupport);
++                cmbLogDevicesSupport.attach(cmbLogDevices);
              }
              
              timer.schedule(new TimerTask() {
-@@ -316,7 +322,7 @@
+@@ -316,7 +326,7 @@
          autoScrollToggleButton = new javax.swing.JToggleButton();
          clearButton = new javax.swing.JButton();
          panFilterTools = new javax.swing.JPanel();
          txtFilterText = new javax.swing.JTextField();
          tbLogLevelSelect = new javax.swing.JToolBar();
          btLogLevelVerbose = new javax.swing.JToggleButton();
-@@ -412,8 +418,7 @@
+@@ -412,8 +422,7 @@
          add(tbLeft, gridBagConstraints);
  
          panFilterTools.setLayout(new java.awt.GridBagLayout());
  
          txtFilterText.setText(org.openide.util.NbBundle.getMessage(LogTopComponent.class, "LogTopComponent.txtFilterText.text")); // NOI18N
          txtFilterText.addKeyListener(new java.awt.event.KeyAdapter() {
-@@ -624,7 +629,7 @@
+@@ -624,7 +633,7 @@
      private javax.swing.JToggleButton btLogLevelVerbose;
      private javax.swing.JToggleButton btLogLevelWarn;
      private javax.swing.JButton clearButton;
      private javax.swing.JScrollPane jScrollPane1;
      private javax.swing.JTable jTable1;
      private javax.swing.JPanel panCenter;
-@@ -692,6 +697,9 @@
+@@ -692,6 +701,9 @@
                public void rowsInserted(int firstRow, int endRow) {
                  try {
                    super.rowsInserted(firstRow, endRow);