Home | History | Annotate | Download | only in views
      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 
    104         HProfHandler(Shell parentShell) {
    105             super(parentShell);
    106         }
    107 
    108         @Override
    109         protected String getDialogTitle() {
    110             return Messages.DeviceView_HPROF_Error;
    111         }
    112 
    113         @Override
    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
    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
    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 
    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 
    276     public DeviceView() {
    277         // the view is declared with allowMultiple="false" so we
    278         // can safely do this.
    279         sThis = this;
    280     }
    281 
    282     public static DeviceView getInstance() {
    283         return sThis;
    284     }
    285 
    286     @Override
    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
    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
    503     public void selectionChanged(IDevice selectedDevice, Client selectedClient) {
    504         // update the buttons
    505         doSelectionChanged(selectedClient);
    506         doSelectionChanged(selectedDevice);
    507     }
    508 
    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 
    586     private void doSelectionChanged(IDevice selectedDevice) {
    587         mCaptureAction.setEnabled(selectedDevice != null);
    588     }
    589 
    590     /**
    591      * Place the actions in the ui.
    592      */
    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
    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