• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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 
17 package com.android.ide.eclipse.ddms.views;
18 
19 import com.android.ddmlib.AndroidDebugBridge;
20 import com.android.ddmlib.AndroidDebugBridge.IClientChangeListener;
21 import com.android.ddmlib.Client;
22 import com.android.ddmlib.ClientData;
23 import com.android.ddmlib.ClientData.IHprofDumpHandler;
24 import com.android.ddmlib.ClientData.MethodProfilingStatus;
25 import com.android.ddmlib.DdmPreferences;
26 import com.android.ddmlib.IDevice;
27 import com.android.ddmlib.SyncException;
28 import com.android.ddmlib.SyncService;
29 import com.android.ddmlib.SyncService.ISyncProgressMonitor;
30 import com.android.ddmlib.TimeoutException;
31 import com.android.ddmuilib.DevicePanel;
32 import com.android.ddmuilib.DevicePanel.IUiSelectionListener;
33 import com.android.ddmuilib.ImageLoader;
34 import com.android.ddmuilib.ScreenShotDialog;
35 import com.android.ddmuilib.SyncProgressHelper;
36 import com.android.ddmuilib.SyncProgressHelper.SyncRunnable;
37 import com.android.ddmuilib.handler.BaseFileHandler;
38 import com.android.ddmuilib.handler.MethodProfilingHandler;
39 import com.android.ide.eclipse.ddms.DdmsPlugin;
40 import com.android.ide.eclipse.ddms.IDebuggerConnector;
41 import com.android.ide.eclipse.ddms.i18n.Messages;
42 import com.android.ide.eclipse.ddms.preferences.PreferenceInitializer;
43 
44 import org.eclipse.core.filesystem.EFS;
45 import org.eclipse.core.filesystem.IFileStore;
46 import org.eclipse.core.resources.ResourcesPlugin;
47 import org.eclipse.core.runtime.IAdaptable;
48 import org.eclipse.core.runtime.Path;
49 import org.eclipse.jface.action.Action;
50 import org.eclipse.jface.action.IAction;
51 import org.eclipse.jface.action.IMenuManager;
52 import org.eclipse.jface.action.IToolBarManager;
53 import org.eclipse.jface.action.Separator;
54 import org.eclipse.jface.dialogs.MessageDialog;
55 import org.eclipse.jface.preference.IPreferenceStore;
56 import org.eclipse.jface.resource.ImageDescriptor;
57 import org.eclipse.swt.widgets.Composite;
58 import org.eclipse.swt.widgets.Display;
59 import org.eclipse.swt.widgets.Shell;
60 import org.eclipse.ui.IActionBars;
61 import org.eclipse.ui.ISharedImages;
62 import org.eclipse.ui.IWorkbench;
63 import org.eclipse.ui.IWorkbenchPage;
64 import org.eclipse.ui.IWorkbenchWindow;
65 import org.eclipse.ui.PartInitException;
66 import org.eclipse.ui.PlatformUI;
67 import org.eclipse.ui.WorkbenchException;
68 import org.eclipse.ui.ide.IDE;
69 import org.eclipse.ui.part.ViewPart;
70 
71 import java.io.File;
72 import java.io.IOException;
73 
74 public class DeviceView extends ViewPart implements IUiSelectionListener, IClientChangeListener {
75 
76     private final static boolean USE_SELECTED_DEBUG_PORT = true;
77 
78     public static final String ID = "com.android.ide.eclipse.ddms.views.DeviceView"; //$NON-NLS-1$
79 
80     private static DeviceView sThis;
81 
82     private Shell mParentShell;
83     private DevicePanel mDeviceList;
84 
85     private Action mResetAdbAction;
86     private Action mCaptureAction;
87     private Action mUpdateThreadAction;
88     private Action mUpdateHeapAction;
89     private Action mGcAction;
90     private Action mKillAppAction;
91     private Action mDebugAction;
92     private Action mHprofAction;
93     private Action mTracingAction;
94 
95     private ImageDescriptor mTracingStartImage;
96     private ImageDescriptor mTracingStopImage;
97 
98     public class HProfHandler extends BaseFileHandler implements IHprofDumpHandler {
99         public final static String ACTION_SAVE = "hprof.save"; //$NON-NLS-1$
100         public final static String ACTION_OPEN = "hprof.open"; //$NON-NLS-1$
101 
102         public final static String DOT_HPROF = ".hprof"; //$NON-NLS-1$
103 
HProfHandler(Shell parentShell)104         HProfHandler(Shell parentShell) {
105             super(parentShell);
106         }
107 
108         @Override
getDialogTitle()109         protected String getDialogTitle() {
110             return Messages.DeviceView_HPROF_Error;
111         }
112 
113         @Override
onEndFailure(final Client client, final String message)114         public void onEndFailure(final Client client, final String message) {
115             mParentShell.getDisplay().asyncExec(new Runnable() {
116                 @Override
117                 public void run() {
118                     try {
119                         displayErrorFromUiThread(
120                                 Messages.DeviceView_Unable_Create_HPROF_For_Application,
121                                 client.getClientData().getClientDescription(),
122                                 message != null ? message + "\n\n" : ""); //$NON-NLS-1$ //$NON-NLS-2$
123                     } finally {
124                         // this will make sure the dump hprof button is
125                         // re-enabled for the
126                         // current selection. as the client is finished dumping
127                         // an hprof file
128                         doSelectionChanged(mDeviceList.getSelectedClient());
129                     }
130                 }
131             });
132         }
133 
134         @Override
onSuccess(final String remoteFilePath, final Client client)135         public void onSuccess(final String remoteFilePath, final Client client) {
136             mParentShell.getDisplay().asyncExec(new Runnable() {
137                 @Override
138                 public void run() {
139                     final IDevice device = client.getDevice();
140                     try {
141                         // get the sync service to pull the HPROF file
142                         final SyncService sync = client.getDevice().getSyncService();
143                         if (sync != null) {
144                             // get from the preference what action to take
145                             IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore();
146                             String value = store.getString(PreferenceInitializer.ATTR_HPROF_ACTION);
147 
148                             if (ACTION_OPEN.equals(value)) {
149                                 File temp = File.createTempFile("android", DOT_HPROF); //$NON-NLS-1$
150                                 final String tempPath = temp.getAbsolutePath();
151                                 SyncProgressHelper.run(new SyncRunnable() {
152 
153                                     @Override
154                                     public void run(ISyncProgressMonitor monitor)
155                                                 throws SyncException, IOException,
156                                                 TimeoutException {
157                                         sync.pullFile(remoteFilePath, tempPath, monitor);
158                                     }
159 
160                                     @Override
161                                     public void close() {
162                                         sync.close();
163                                     }
164                                 },
165                                         String.format(Messages.DeviceView_Pulling_From_Device,
166                                                 remoteFilePath),
167                                         mParentShell);
168 
169                                 open(tempPath);
170                             } else {
171                                 // default action is ACTION_SAVE
172                                 promptAndPull(sync,
173                                         client.getClientData().getClientDescription() + DOT_HPROF,
174                                         remoteFilePath, Messages.DeviceView_Save_HPROF_File);
175 
176                             }
177                         } else {
178                             displayErrorFromUiThread(
179                                     Messages.DeviceView_Unable_Download_HPROF_From_Device_One_Param_First_Message,
180                                     device.getSerialNumber());
181                         }
182                     } catch (SyncException e) {
183                         if (e.wasCanceled() == false) {
184                             displayErrorFromUiThread(
185                                     Messages.DeviceView_Unable_Download_HPROF_From_Device_Two_Param,
186                                     device.getSerialNumber(), e.getMessage());
187                         }
188                     } catch (Exception e) {
189                         displayErrorFromUiThread(
190                                 Messages.DeviceView_Unable_Download_HPROF_From_Device_One_Param_Second_Message,
191                                 device.getSerialNumber());
192 
193                     } finally {
194                         // this will make sure the dump hprof button is
195                         // re-enabled for the
196                         // current selection. as the client is finished dumping
197                         // an hprof file
198                         doSelectionChanged(mDeviceList.getSelectedClient());
199                     }
200                 }
201             });
202         }
203 
204         @Override
onSuccess(final byte[] data, final Client client)205         public void onSuccess(final byte[] data, final Client client) {
206             mParentShell.getDisplay().asyncExec(new Runnable() {
207                 @Override
208                 public void run() {
209                     // get from the preference what action to take
210                     IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore();
211                     String value = store.getString(PreferenceInitializer.ATTR_HPROF_ACTION);
212 
213                     if (ACTION_OPEN.equals(value)) {
214                         try {
215                             // no need to give an extension since we're going to
216                             // convert the
217                             // file anyway after.
218                             File tempFile = saveTempFile(data, null /* extension */);
219                             open(tempFile.getAbsolutePath());
220                         } catch (Exception e) {
221                             String errorMsg = e.getMessage();
222                             displayErrorFromUiThread(
223                                     Messages.DeviceView_Failed_To_Save_HPROF_Data,
224                                     errorMsg != null ? ":\n" + errorMsg : "."); //$NON-NLS-1$ //$NON-NLS-2$
225                         }
226                     } else {
227                         // default action is ACTION_SAVE
228                         promptAndSave(client.getClientData().getClientDescription() + DOT_HPROF,
229                                 data, Messages.DeviceView_Save_HPROF_File);
230                     }
231                 }
232             });
233         }
234 
open(String path)235         private void open(String path) throws IOException, InterruptedException, PartInitException {
236             // make a temp file to convert the hprof into something
237             // readable by normal tools
238             File temp = File.createTempFile("android", DOT_HPROF); //$NON-NLS-1$
239             String tempPath = temp.getAbsolutePath();
240 
241             String[] command = new String[3];
242             command[0] = DdmsPlugin.getHprofConverter();
243             command[1] = path;
244             command[2] = tempPath;
245 
246             Process p = Runtime.getRuntime().exec(command);
247             p.waitFor();
248 
249             IFileStore fileStore = EFS.getLocalFileSystem().getStore(new Path(tempPath));
250             if (!fileStore.fetchInfo().isDirectory() && fileStore.fetchInfo().exists()) {
251                 // before we open the file in an editor window, we make sure the
252                 // current
253                 // workbench page has an editor area (typically the ddms
254                 // perspective doesn't).
255                 IWorkbench workbench = PlatformUI.getWorkbench();
256                 IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
257                 IWorkbenchPage page = window.getActivePage();
258                 if (page.isEditorAreaVisible() == false) {
259                     IAdaptable input;
260                     if (page != null)
261                         input = page.getInput();
262                     else
263                         input = ResourcesPlugin.getWorkspace().getRoot();
264                     try {
265                         workbench.showPerspective("org.eclipse.debug.ui.DebugPerspective", //$NON-NLS-1$
266                                 window, input);
267                     } catch (WorkbenchException e) {
268                     }
269                 }
270 
271                 IDE.openEditorOnFileStore(page, fileStore);
272             }
273         }
274     }
275 
DeviceView()276     public DeviceView() {
277         // the view is declared with allowMultiple="false" so we
278         // can safely do this.
279         sThis = this;
280     }
281 
getInstance()282     public static DeviceView getInstance() {
283         return sThis;
284     }
285 
286     @Override
createPartControl(Composite parent)287     public void createPartControl(Composite parent) {
288         mParentShell = parent.getShell();
289 
290         ImageLoader loader = ImageLoader.getDdmUiLibLoader();
291 
292         mDeviceList = new DevicePanel(USE_SELECTED_DEBUG_PORT);
293         mDeviceList.createPanel(parent);
294         mDeviceList.addSelectionListener(this);
295 
296         DdmsPlugin plugin = DdmsPlugin.getDefault();
297         mDeviceList.addSelectionListener(plugin);
298         plugin.setListeningState(true);
299 
300         mCaptureAction = new Action(Messages.DeviceView_Screen_Capture) {
301             @Override
302             public void run() {
303                 ScreenShotDialog dlg = new ScreenShotDialog(
304                         DdmsPlugin.getDisplay().getActiveShell());
305                 dlg.open(mDeviceList.getSelectedDevice());
306             }
307         };
308         mCaptureAction.setToolTipText(Messages.DeviceView_Screen_Capture_Tooltip);
309         mCaptureAction.setImageDescriptor(loader.loadDescriptor("capture.png")); //$NON-NLS-1$
310 
311         mResetAdbAction = new Action(Messages.DeviceView_Reset_ADB) {
312             @Override
313             public void run() {
314                 AndroidDebugBridge bridge = AndroidDebugBridge.getBridge();
315                 if (bridge != null) {
316                     if (bridge.restart() == false) {
317                         // get the current Display
318                         final Display display = DdmsPlugin.getDisplay();
319 
320                         // dialog box only run in ui thread..
321                         display.asyncExec(new Runnable() {
322                             @Override
323                             public void run() {
324                                 Shell shell = display.getActiveShell();
325                                 MessageDialog.openError(shell, Messages.DeviceView_ADB_Error,
326                                         Messages.DeviceView_ADB_Failed_Restart);
327                             }
328                         });
329                     }
330                 }
331             }
332         };
333         mResetAdbAction.setToolTipText(Messages.DeviceView_Reset_ADB_Host_Deamon);
334         mResetAdbAction.setImageDescriptor(PlatformUI.getWorkbench()
335                 .getSharedImages().getImageDescriptor(
336                         ISharedImages.IMG_OBJS_WARN_TSK));
337 
338         mKillAppAction = new Action() {
339             @Override
340             public void run() {
341                 mDeviceList.killSelectedClient();
342             }
343         };
344 
345         mKillAppAction.setText(Messages.DeviceView_Stop_Process);
346         mKillAppAction.setToolTipText(Messages.DeviceView_Stop_Process_Tooltip);
347         mKillAppAction.setImageDescriptor(loader.loadDescriptor(DevicePanel.ICON_HALT));
348 
349         mGcAction = new Action() {
350             @Override
351             public void run() {
352                 mDeviceList.forceGcOnSelectedClient();
353             }
354         };
355 
356         mGcAction.setText(Messages.DeviceView_Cause_GC);
357         mGcAction.setToolTipText(Messages.DeviceView_Cause_GC_Tooltip);
358         mGcAction.setImageDescriptor(loader.loadDescriptor(DevicePanel.ICON_GC));
359 
360         mHprofAction = new Action() {
361             @Override
362             public void run() {
363                 mDeviceList.dumpHprof();
364                 doSelectionChanged(mDeviceList.getSelectedClient());
365             }
366         };
367         mHprofAction.setText(Messages.DeviceView_Dump_HPROF_File);
368         mHprofAction.setToolTipText(Messages.DeviceView_Dump_HPROF_File_Tooltip);
369         mHprofAction.setImageDescriptor(loader.loadDescriptor(DevicePanel.ICON_HPROF));
370 
371         mUpdateHeapAction = new Action(Messages.DeviceView_Update_Heap, IAction.AS_CHECK_BOX) {
372             @Override
373             public void run() {
374                 boolean enable = mUpdateHeapAction.isChecked();
375                 mDeviceList.setEnabledHeapOnSelectedClient(enable);
376             }
377         };
378         mUpdateHeapAction.setToolTipText(Messages.DeviceView_Update_Heap_Tooltip);
379         mUpdateHeapAction.setImageDescriptor(loader.loadDescriptor(DevicePanel.ICON_HEAP));
380 
381         mUpdateThreadAction = new Action(Messages.DeviceView_Threads, IAction.AS_CHECK_BOX) {
382             @Override
383             public void run() {
384                 boolean enable = mUpdateThreadAction.isChecked();
385                 mDeviceList.setEnabledThreadOnSelectedClient(enable);
386             }
387         };
388         mUpdateThreadAction.setToolTipText(Messages.DeviceView_Threads_Tooltip);
389         mUpdateThreadAction.setImageDescriptor(loader.loadDescriptor(DevicePanel.ICON_THREAD));
390 
391         mTracingAction = new Action() {
392             @Override
393             public void run() {
394                 mDeviceList.toggleMethodProfiling();
395             }
396         };
397         mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling);
398         mTracingAction.setToolTipText(Messages.DeviceView_Start_Method_Profiling_Tooltip);
399         mTracingStartImage = loader.loadDescriptor(DevicePanel.ICON_TRACING_START);
400         mTracingStopImage = loader.loadDescriptor(DevicePanel.ICON_TRACING_STOP);
401         mTracingAction.setImageDescriptor(mTracingStartImage);
402 
403         mDebugAction = new Action(Messages.DeviceView_Debug_Process) {
404             @Override
405             public void run() {
406                 if (DdmsPlugin.getDefault().hasDebuggerConnectors()) {
407                     Client currentClient = mDeviceList.getSelectedClient();
408                     if (currentClient != null) {
409                         ClientData clientData = currentClient.getClientData();
410 
411                         // make sure the client can be debugged
412                         switch (clientData.getDebuggerConnectionStatus()) {
413                             case ERROR: {
414                                 Display display = DdmsPlugin.getDisplay();
415                                 Shell shell = display.getActiveShell();
416                                 MessageDialog.openError(shell,
417                                         Messages.DeviceView_Debug_Process_Title,
418                                         Messages.DeviceView_Process_Debug_Already_In_Use);
419                                 return;
420                             }
421                             case ATTACHED: {
422                                 Display display = DdmsPlugin.getDisplay();
423                                 Shell shell = display.getActiveShell();
424                                 MessageDialog.openError(shell,
425                                         Messages.DeviceView_Debug_Process_Title,
426                                         Messages.DeviceView_Process_Already_Being_Debugged);
427                                 return;
428                             }
429                         }
430 
431                         // get the name of the client
432                         String packageName = clientData.getClientDescription();
433                         if (packageName != null) {
434 
435                             // try all connectors till one returns true.
436                             IDebuggerConnector[] connectors =
437                                     DdmsPlugin.getDefault().getDebuggerConnectors();
438 
439                             if (connectors != null) {
440                                 for (IDebuggerConnector connector : connectors) {
441                                     try {
442                                         if (connector.connectDebugger(packageName,
443                                                 currentClient.getDebuggerListenPort(),
444                                                 DdmPreferences.getSelectedDebugPort())) {
445                                             return;
446                                         }
447                                     } catch (Throwable t) {
448                                         // ignore, we'll just not use this
449                                         // implementation
450                                     }
451                                 }
452                             }
453 
454                             // if we get to this point, then we failed to find a
455                             // project
456                             // that matched the application to debug
457                             Display display = DdmsPlugin.getDisplay();
458                             Shell shell = display.getActiveShell();
459                             MessageDialog.openError(shell, Messages.DeviceView_Debug_Process_Title,
460                                     String.format(
461                                             Messages.DeviceView_Debug_Session_Failed,
462                                             packageName));
463                         }
464                     }
465                 }
466             }
467         };
468         mDebugAction.setToolTipText(Messages.DeviceView_Debug_Process_Tooltip);
469         mDebugAction.setImageDescriptor(loader.loadDescriptor("debug-attach.png")); //$NON-NLS-1$
470         mDebugAction.setEnabled(DdmsPlugin.getDefault().hasDebuggerConnectors());
471 
472         placeActions();
473 
474         // disabling all action buttons
475         selectionChanged(null, null);
476 
477         ClientData.setHprofDumpHandler(new HProfHandler(mParentShell));
478         AndroidDebugBridge.addClientChangeListener(this);
479         ClientData.setMethodProfilingHandler(new MethodProfilingHandler(mParentShell) {
480             @Override
481             protected void open(String tempPath) {
482                 if (DdmsPlugin.getDefault().launchTraceview(tempPath) == false) {
483                     super.open(tempPath);
484                 }
485             }
486         });
487     }
488 
489     @Override
setFocus()490     public void setFocus() {
491         mDeviceList.setFocus();
492     }
493 
494     /**
495      * Sent when a new {@link IDevice} and {@link Client} are selected.
496      *
497      * @param selectedDevice the selected device. If null, no devices are
498      *            selected.
499      * @param selectedClient The selected client. If null, no clients are
500      *            selected.
501      */
502     @Override
selectionChanged(IDevice selectedDevice, Client selectedClient)503     public void selectionChanged(IDevice selectedDevice, Client selectedClient) {
504         // update the buttons
505         doSelectionChanged(selectedClient);
506         doSelectionChanged(selectedDevice);
507     }
508 
doSelectionChanged(Client selectedClient)509     private void doSelectionChanged(Client selectedClient) {
510         // update the buttons
511         if (selectedClient != null) {
512             if (USE_SELECTED_DEBUG_PORT) {
513                 // set the client as the debug client
514                 selectedClient.setAsSelectedClient();
515             }
516 
517             mDebugAction.setEnabled(DdmsPlugin.getDefault().hasDebuggerConnectors());
518             mKillAppAction.setEnabled(true);
519             mGcAction.setEnabled(true);
520 
521             mUpdateHeapAction.setEnabled(true);
522             mUpdateHeapAction.setChecked(selectedClient.isHeapUpdateEnabled());
523 
524             mUpdateThreadAction.setEnabled(true);
525             mUpdateThreadAction.setChecked(selectedClient.isThreadUpdateEnabled());
526 
527             ClientData data = selectedClient.getClientData();
528 
529             if (data.hasFeature(ClientData.FEATURE_HPROF)) {
530                 mHprofAction.setEnabled(data.hasPendingHprofDump() == false);
531                 mHprofAction.setToolTipText(Messages.DeviceView_Dump_HPROF_File);
532             } else {
533                 mHprofAction.setEnabled(false);
534                 mHprofAction
535                         .setToolTipText(Messages.DeviceView_Dump_HPROF_File_Not_Supported_By_VM);
536             }
537 
538             if (data.hasFeature(ClientData.FEATURE_PROFILING)) {
539                 mTracingAction.setEnabled(true);
540                 if (data.getMethodProfilingStatus() == MethodProfilingStatus.ON) {
541                     mTracingAction
542                             .setToolTipText(Messages.DeviceView_Stop_Method_Profiling_Tooltip);
543                     mTracingAction.setText(Messages.DeviceView_Stop_Method_Profiling);
544                     mTracingAction.setImageDescriptor(mTracingStopImage);
545                 } else {
546                     mTracingAction
547                             .setToolTipText(Messages.DeviceView_Start_Method_Profiling_Tooltip);
548                     mTracingAction.setImageDescriptor(mTracingStartImage);
549                     mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling);
550                 }
551             } else {
552                 mTracingAction.setEnabled(false);
553                 mTracingAction.setImageDescriptor(mTracingStartImage);
554                 mTracingAction
555                         .setToolTipText(Messages.DeviceView_Start_Method_Profiling_Not_Suported_By_Vm);
556                 mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling);
557             }
558         } else {
559             if (USE_SELECTED_DEBUG_PORT) {
560                 // set the client as the debug client
561                 AndroidDebugBridge bridge = AndroidDebugBridge.getBridge();
562                 if (bridge != null) {
563                     bridge.setSelectedClient(null);
564                 }
565             }
566 
567             mDebugAction.setEnabled(false);
568             mKillAppAction.setEnabled(false);
569             mGcAction.setEnabled(false);
570             mUpdateHeapAction.setChecked(false);
571             mUpdateHeapAction.setEnabled(false);
572             mUpdateThreadAction.setEnabled(false);
573             mUpdateThreadAction.setChecked(false);
574             mHprofAction.setEnabled(false);
575 
576             mHprofAction.setEnabled(false);
577             mHprofAction.setToolTipText(Messages.DeviceView_Dump_HPROF_File);
578 
579             mTracingAction.setEnabled(false);
580             mTracingAction.setImageDescriptor(mTracingStartImage);
581             mTracingAction.setToolTipText(Messages.DeviceView_Start_Method_Profiling_Tooltip);
582             mTracingAction.setText(Messages.DeviceView_Start_Method_Profiling);
583         }
584     }
585 
doSelectionChanged(IDevice selectedDevice)586     private void doSelectionChanged(IDevice selectedDevice) {
587         mCaptureAction.setEnabled(selectedDevice != null);
588     }
589 
590     /**
591      * Place the actions in the ui.
592      */
placeActions()593     private final void placeActions() {
594         IActionBars actionBars = getViewSite().getActionBars();
595 
596         // first in the menu
597         IMenuManager menuManager = actionBars.getMenuManager();
598         menuManager.removeAll();
599         menuManager.add(mDebugAction);
600         menuManager.add(new Separator());
601         menuManager.add(mUpdateHeapAction);
602         menuManager.add(mHprofAction);
603         menuManager.add(mGcAction);
604         menuManager.add(new Separator());
605         menuManager.add(mUpdateThreadAction);
606         menuManager.add(mTracingAction);
607         menuManager.add(new Separator());
608         menuManager.add(mKillAppAction);
609         menuManager.add(new Separator());
610         menuManager.add(mCaptureAction);
611         menuManager.add(new Separator());
612         menuManager.add(mResetAdbAction);
613 
614         // and then in the toolbar
615         IToolBarManager toolBarManager = actionBars.getToolBarManager();
616         toolBarManager.removeAll();
617         toolBarManager.add(mDebugAction);
618         toolBarManager.add(new Separator());
619         toolBarManager.add(mUpdateHeapAction);
620         toolBarManager.add(mHprofAction);
621         toolBarManager.add(mGcAction);
622         toolBarManager.add(new Separator());
623         toolBarManager.add(mUpdateThreadAction);
624         toolBarManager.add(mTracingAction);
625         toolBarManager.add(new Separator());
626         toolBarManager.add(mKillAppAction);
627         toolBarManager.add(new Separator());
628         toolBarManager.add(mCaptureAction);
629     }
630 
631     @Override
clientChanged(final Client client, int changeMask)632     public void clientChanged(final Client client, int changeMask) {
633         if ((changeMask & Client.CHANGE_METHOD_PROFILING_STATUS) == Client.CHANGE_METHOD_PROFILING_STATUS) {
634             if (mDeviceList.getSelectedClient() == client) {
635                 mParentShell.getDisplay().asyncExec(new Runnable() {
636                     @Override
637                     public void run() {
638                         // force refresh of the button enabled state.
639                         doSelectionChanged(client);
640                     }
641                 });
642             }
643         }
644     }
645 }
646