• 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             public void deviceDisconnected(IDevice device) {
62                 unmonitorDevice(device.getSerialNumber());
63                 mMonitoredDevices.remove(device.getSerialNumber());
64             }
65 
66             public void deviceConnected(IDevice device) {
67             }
68 
69             public void deviceChanged(IDevice device, int changeMask) {
70             }
71         });
72 
73         mPrefStore.addPropertyChangeListener(new IPropertyChangeListener() {
74             public void propertyChange(PropertyChangeEvent event) {
75                 if (AUTO_MONITOR_PREFKEY.equals(event.getProperty())
76                         && event.getNewValue().equals(false)) {
77                     unmonitorAllDevices();
78                 }
79             }
80         });
81     }
82 
unmonitorAllDevices()83     private void unmonitorAllDevices() {
84         for (String device : mMonitoredDevices.keySet()) {
85             unmonitorDevice(device);
86         }
87 
88         mMonitoredDevices.clear();
89     }
90 
unmonitorDevice(String deviceSerial)91     private void unmonitorDevice(String deviceSerial) {
92         DeviceData data = mMonitoredDevices.get(deviceSerial);
93         if (data == null) {
94             return;
95         }
96 
97         data.receiver.removeMessageReceivedEventListener(data.messageEventListener);
98     }
99 
monitorDevice(final IDevice device)100     public void monitorDevice(final IDevice device) {
101         if (!mPrefStore.getBoolean(AUTO_MONITOR_PREFKEY)) {
102             // do not monitor device if auto monitoring is off
103             return;
104         }
105 
106         if (mMonitoredDevices.keySet().contains(device.getSerialNumber())) {
107             // the device is already monitored
108             return;
109         }
110 
111         LogCatReceiver r = LogCatReceiverFactory.INSTANCE.newReceiver(device, mPrefStore);
112         ILogCatMessageEventListener l = new ILogCatMessageEventListener() {
113             public void messageReceived(List<LogCatMessage> receivedMessages) {
114                 checkMessages(receivedMessages, device);
115             }
116         };
117         r.addMessageReceivedEventListener(l);
118 
119         mMonitoredDevices.put(device.getSerialNumber(), new DeviceData(r, l));
120     }
121 
checkMessages(List<LogCatMessage> receivedMessages, IDevice device)122     private void checkMessages(List<LogCatMessage> receivedMessages, IDevice device) {
123         // check the received list of messages to see if any of them are
124         // significant enough to be seen by the user. If so, activate the logcat view
125         // to display those messages
126         for (LogCatMessage m : receivedMessages) {
127             if (isImportantMessage(m)) {
128                 focusLogCatView(device, m.getAppName());
129                 break;
130             }
131         }
132     }
133 
134     /**
135      * Check whether a message is "important". Currently, we assume that a message is important if
136      * it is of severity level error or higher, and it belongs to an app currently in the workspace.
137      */
isImportantMessage(LogCatMessage m)138     private boolean isImportantMessage(LogCatMessage m) {
139         if (m.getLogLevel().getPriority() < LogLevel.ERROR.getPriority()) {
140             return false;
141         }
142 
143         String app = m.getAppName();
144         for (IDebuggerConnector c : mConnectors) {
145             if (c.isWorkspaceApp(app)) {
146                 return true;
147             }
148         }
149 
150         return false;
151     }
152 
focusLogCatView(final IDevice device, final String appName)153     private void focusLogCatView(final IDevice device, final String appName) {
154         Display.getDefault().asyncExec(new Runnable() {
155             public void run() {
156                 IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
157                 if (window == null) {
158                     return;
159                 }
160 
161                 IWorkbenchPage page = window.getActivePage();
162                 if (page == null) {
163                     return;
164                 }
165 
166                 // display view
167                 final LogCatView v = displayLogCatView(page);
168                 if (v == null) {
169                     return;
170                 }
171 
172                 // select correct device
173                 v.selectionChanged(device);
174 
175                 // select appropriate filter
176                 v.selectTransientAppFilter(appName);
177             }
178 
179             private LogCatView displayLogCatView(IWorkbenchPage page) {
180                 // if the view is already in the page, just bring it to the front
181                 // without giving it focus.
182                 IViewPart view = page.findView(LogCatView.ID);
183                 if (view != null) {
184                     page.bringToTop(view);
185                     if (view instanceof LogCatView) {
186                         return (LogCatView)view;
187                     }
188                 }
189 
190                 // if the view is not in the page, then create and show it.
191                 try {
192                     return (LogCatView) page.showView(LogCatView.ID);
193                 } catch (PartInitException e) {
194                     return null;
195                 }
196             }
197         });
198     }
199 
200     private static class DeviceData {
201         public final LogCatReceiver receiver;
202         public final ILogCatMessageEventListener messageEventListener;
203 
DeviceData(LogCatReceiver r, ILogCatMessageEventListener l)204         public DeviceData(LogCatReceiver r, ILogCatMessageEventListener l) {
205             receiver = r;
206             messageEventListener = l;
207         }
208     }
209 }
210