• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.ide.eclipse.ddms;
17 
18 import com.android.ddmlib.AndroidDebugBridge;
19 import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener;
20 import com.android.ddmlib.IDevice;
21 import com.android.ddmlib.Log.LogLevel;
22 import com.android.ddmuilib.logcat.ILogCatMessageEventListener;
23 import com.android.ddmuilib.logcat.LogCatMessage;
24 import com.android.ddmuilib.logcat.LogCatReceiver;
25 import com.android.ddmuilib.logcat.LogCatReceiverFactory;
26 import com.android.ide.eclipse.ddms.views.LogCatView;
27 
28 import org.eclipse.jface.preference.IPreferenceStore;
29 import org.eclipse.jface.util.IPropertyChangeListener;
30 import org.eclipse.jface.util.PropertyChangeEvent;
31 import org.eclipse.swt.widgets.Display;
32 import org.eclipse.ui.IViewPart;
33 import org.eclipse.ui.IWorkbenchPage;
34 import org.eclipse.ui.IWorkbenchWindow;
35 import org.eclipse.ui.PartInitException;
36 import org.eclipse.ui.PlatformUI;
37 
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41 
42 /**
43  * LogCatMonitor helps in monitoring the logcat output from a set of devices.
44  * It scans through the received logcat messages, and activates the logcat view
45  * if any message is deemed important.
46  */
47 public class LogCatMonitor {
48     public static final String AUTO_MONITOR_PREFKEY = "ddms.logcat.automonitor";
49 
50     private IPreferenceStore mPrefStore;
51     private Map<String, DeviceData> mMonitoredDevices;
52     private IDebuggerConnector[] mConnectors;
53 
LogCatMonitor(IDebuggerConnector[] debuggerConnectors, IPreferenceStore prefStore)54     public LogCatMonitor(IDebuggerConnector[] debuggerConnectors, IPreferenceStore prefStore) {
55         mConnectors = debuggerConnectors;
56         mPrefStore = prefStore;
57 
58         mMonitoredDevices = new HashMap<String, DeviceData>();
59 
60         AndroidDebugBridge.addDeviceChangeListener(new IDeviceChangeListener() {
61             @Override
62             public void deviceDisconnected(IDevice device) {
63                 unmonitorDevice(device.getSerialNumber());
64                 mMonitoredDevices.remove(device.getSerialNumber());
65             }
66 
67             @Override
68             public void deviceConnected(IDevice device) {
69             }
70 
71             @Override
72             public void deviceChanged(IDevice device, int changeMask) {
73             }
74         });
75 
76         mPrefStore.addPropertyChangeListener(new IPropertyChangeListener() {
77             @Override
78             public void propertyChange(PropertyChangeEvent event) {
79                 if (AUTO_MONITOR_PREFKEY.equals(event.getProperty())
80                         && event.getNewValue().equals(false)) {
81                     unmonitorAllDevices();
82                 }
83             }
84         });
85     }
86 
unmonitorAllDevices()87     private void unmonitorAllDevices() {
88         for (String device : mMonitoredDevices.keySet()) {
89             unmonitorDevice(device);
90         }
91 
92         mMonitoredDevices.clear();
93     }
94 
unmonitorDevice(String deviceSerial)95     private void unmonitorDevice(String deviceSerial) {
96         DeviceData data = mMonitoredDevices.get(deviceSerial);
97         if (data == null) {
98             return;
99         }
100 
101         data.receiver.removeMessageReceivedEventListener(data.messageEventListener);
102     }
103 
monitorDevice(final IDevice device)104     public void monitorDevice(final IDevice device) {
105         if (!mPrefStore.getBoolean(AUTO_MONITOR_PREFKEY)) {
106             // do not monitor device if auto monitoring is off
107             return;
108         }
109 
110         if (mMonitoredDevices.keySet().contains(device.getSerialNumber())) {
111             // the device is already monitored
112             return;
113         }
114 
115         LogCatReceiver r = LogCatReceiverFactory.INSTANCE.newReceiver(device, mPrefStore);
116         ILogCatMessageEventListener l = new ILogCatMessageEventListener() {
117             @Override
118             public void messageReceived(List<LogCatMessage> receivedMessages) {
119                 checkMessages(receivedMessages, device);
120             }
121         };
122         r.addMessageReceivedEventListener(l);
123 
124         mMonitoredDevices.put(device.getSerialNumber(), new DeviceData(r, l));
125     }
126 
checkMessages(List<LogCatMessage> receivedMessages, IDevice device)127     private void checkMessages(List<LogCatMessage> receivedMessages, IDevice device) {
128         // check the received list of messages to see if any of them are
129         // significant enough to be seen by the user. If so, activate the logcat view
130         // to display those messages
131         for (LogCatMessage m : receivedMessages) {
132             if (isImportantMessage(m)) {
133                 focusLogCatView(device, m.getAppName());
134                 break;
135             }
136         }
137     }
138 
139     /**
140      * Check whether a message is "important". Currently, we assume that a message is important if
141      * it is of severity level error or higher, and it belongs to an app currently in the workspace.
142      */
isImportantMessage(LogCatMessage m)143     private boolean isImportantMessage(LogCatMessage m) {
144         if (m.getLogLevel().getPriority() < LogLevel.ERROR.getPriority()) {
145             return false;
146         }
147 
148         String app = m.getAppName();
149         for (IDebuggerConnector c : mConnectors) {
150             if (c.isWorkspaceApp(app)) {
151                 return true;
152             }
153         }
154 
155         return false;
156     }
157 
focusLogCatView(final IDevice device, final String appName)158     private void focusLogCatView(final IDevice device, final String appName) {
159         Display.getDefault().asyncExec(new Runnable() {
160             @Override
161             public void run() {
162                 IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
163                 if (window == null) {
164                     return;
165                 }
166 
167                 IWorkbenchPage page = window.getActivePage();
168                 if (page == null) {
169                     return;
170                 }
171 
172                 // display view
173                 final LogCatView v = displayLogCatView(page);
174                 if (v == null) {
175                     return;
176                 }
177 
178                 // select correct device
179                 v.selectionChanged(device);
180 
181                 // select appropriate filter
182                 v.selectTransientAppFilter(appName);
183             }
184 
185             private LogCatView displayLogCatView(IWorkbenchPage page) {
186                 // if the view is already in the page, just bring it to the front
187                 // without giving it focus.
188                 IViewPart view = page.findView(LogCatView.ID);
189                 if (view != null) {
190                     page.bringToTop(view);
191                     if (view instanceof LogCatView) {
192                         return (LogCatView)view;
193                     }
194                 }
195 
196                 // if the view is not in the page, then create and show it.
197                 try {
198                     return (LogCatView) page.showView(LogCatView.ID);
199                 } catch (PartInitException e) {
200                     return null;
201                 }
202             }
203         });
204     }
205 
206     private static class DeviceData {
207         public final LogCatReceiver receiver;
208         public final ILogCatMessageEventListener messageEventListener;
209 
DeviceData(LogCatReceiver r, ILogCatMessageEventListener l)210         public DeviceData(LogCatReceiver r, ILogCatMessageEventListener l) {
211             receiver = r;
212             messageEventListener = l;
213         }
214     }
215 }
216