Home | History | Annotate | Download | only in systrace
      1 /*
      2  * Copyright (C) 2012 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.systrace;
     18 
     19 import org.eclipse.jface.dialogs.TitleAreaDialog;
     20 import org.eclipse.swt.SWT;
     21 import org.eclipse.swt.events.ModifyEvent;
     22 import org.eclipse.swt.events.ModifyListener;
     23 import org.eclipse.swt.events.SelectionAdapter;
     24 import org.eclipse.swt.events.SelectionEvent;
     25 import org.eclipse.swt.layout.GridData;
     26 import org.eclipse.swt.layout.GridLayout;
     27 import org.eclipse.swt.widgets.Button;
     28 import org.eclipse.swt.widgets.Composite;
     29 import org.eclipse.swt.widgets.Control;
     30 import org.eclipse.swt.widgets.FileDialog;
     31 import org.eclipse.swt.widgets.Group;
     32 import org.eclipse.swt.widgets.Label;
     33 import org.eclipse.swt.widgets.Shell;
     34 import org.eclipse.swt.widgets.Text;
     35 
     36 import java.io.File;
     37 
     38 public class SystraceOptionsDialogV1 extends TitleAreaDialog implements ISystraceOptionsDialog {
     39     private static final String TITLE = "Android System Trace";
     40     private static final String DEFAULT_MESSAGE =
     41             "Settings to use while capturing system level trace";
     42     private static final String DEFAULT_TRACE_FNAME = "trace.html"; //$NON-NLS-1$
     43 
     44     private Text mDestinationText;
     45     private String mDestinationPath;
     46     private Text mTraceDurationText;
     47     private Text mTraceBufferSizeText;
     48 
     49     private static String sSaveToFolder = System.getProperty("user.home"); //$NON-NLS-1$
     50     private static String sTraceDuration = "";
     51     private static String sTraceBufferSize = "";
     52 
     53     private Button mTraceCpuFreqBtn;
     54     private Button mTraceCpuIdleBtn;
     55     private Button mTraceCpuLoadBtn;
     56     private Button mTraceDiskIoBtn;
     57     private Button mTraceKernelWorkqueuesBtn;
     58     private Button mTraceCpuSchedulerBtn;
     59 
     60     private static boolean sTraceCpuFreq;
     61     private static boolean sTraceCpuIdle;
     62     private static boolean sTraceCpuLoad;
     63     private static boolean sTraceDiskIo;
     64     private static boolean sTraceKernelWorkqueues;
     65     private static boolean sTraceCpuScheduler;
     66 
     67     private Button mGfxTagBtn;
     68     private Button mInputTagBtn;
     69     private Button mViewTagBtn;
     70     private Button mWebViewTagBtn;
     71     private Button mWmTagBtn;
     72     private Button mAmTagBtn;
     73     private Button mSyncTagBtn;
     74     private Button mAudioTagBtn;
     75     private Button mVideoTagBtn;
     76     private Button mCameraTagBtn;
     77 
     78     private static boolean sGfxTag;
     79     private static boolean sInputTag;
     80     private static boolean sViewTag;
     81     private static boolean sWebViewTag;
     82     private static boolean sWmTag;
     83     private static boolean sAmTag;
     84     private static boolean sSyncTag;
     85     private static boolean sAudioTag;
     86     private static boolean sVideoTag;
     87     private static boolean sCameraTag;
     88 
     89     private final SystraceOptions mOptions = new SystraceOptions();
     90 
     91     public SystraceOptionsDialogV1(Shell parentShell) {
     92         super(parentShell);
     93     }
     94 
     95     @Override
     96     protected Control createDialogArea(Composite parent) {
     97         setTitle(TITLE);
     98         setMessage(DEFAULT_MESSAGE);
     99 
    100         Composite c = new Composite(parent, SWT.BORDER);
    101         c.setLayout(new GridLayout(3, false));
    102         c.setLayoutData(new GridData(GridData.FILL_BOTH));
    103 
    104         Label l = new Label(c, SWT.NONE);
    105         l.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
    106         l.setText("Destination File: ");
    107 
    108         mDestinationText = new Text(c, SWT.BORDER);
    109         mDestinationText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
    110         mDestinationText.setText(sSaveToFolder + File.separator + DEFAULT_TRACE_FNAME);
    111 
    112         final Button browse = new Button(c, SWT.NONE);
    113         browse.setText("Browse...");
    114         browse.addSelectionListener(new SelectionAdapter() {
    115             @Override
    116             public void widgetSelected(SelectionEvent e) {
    117                 String path = openBrowseDialog(browse.getShell());
    118                 if (path != null) mDestinationText.setText(path);
    119             }
    120         });
    121 
    122         Label lblTraceDurationseconds = new Label(c, SWT.NONE);
    123         lblTraceDurationseconds.setLayoutData(
    124                 new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
    125         lblTraceDurationseconds.setText("Trace duration (seconds): ");
    126 
    127         mTraceDurationText = new Text(c, SWT.BORDER);
    128         mTraceDurationText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
    129         mTraceDurationText.setText(sTraceDuration);
    130 
    131         Label lblTraceBufferSize = new Label(c, SWT.NONE);
    132         lblTraceBufferSize.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
    133         lblTraceBufferSize.setText("Trace Buffer Size (kb): ");
    134 
    135         mTraceBufferSizeText = new Text(c, SWT.BORDER);
    136         mTraceBufferSizeText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
    137         mTraceBufferSizeText.setText(sTraceBufferSize);
    138 
    139         Label separator = new Label(c, SWT.SEPARATOR | SWT.HORIZONTAL);
    140         GridData gd = new GridData(GridData.FILL_HORIZONTAL);
    141         gd.horizontalSpan = 3;
    142         separator.setLayoutData(gd);
    143 
    144         Group grpTraceEvents = new Group(c, SWT.BORDER);
    145         grpTraceEvents.setLayout(new GridLayout(3, false));
    146         grpTraceEvents.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1));
    147         grpTraceEvents.setText("Trace Events");
    148 
    149         mTraceCpuFreqBtn = new Button(grpTraceEvents, SWT.CHECK);
    150         mTraceCpuFreqBtn.setText("CPU Frequency Changes");
    151         mTraceCpuFreqBtn.setSelection(sTraceCpuFreq);
    152 
    153         mTraceCpuIdleBtn = new Button(grpTraceEvents, SWT.CHECK);
    154         mTraceCpuIdleBtn.setText("CPU Idle Events");
    155         mTraceCpuIdleBtn.setSelection(sTraceCpuIdle);
    156 
    157         mTraceCpuLoadBtn = new Button(grpTraceEvents, SWT.CHECK);
    158         mTraceCpuLoadBtn.setText("CPU Load");
    159         mTraceCpuLoadBtn.setSelection(sTraceCpuLoad);
    160 
    161         mTraceCpuSchedulerBtn = new Button(grpTraceEvents, SWT.CHECK);
    162         mTraceCpuSchedulerBtn.setText("CPU Scheduler");
    163         mTraceCpuSchedulerBtn.setSelection(sTraceCpuScheduler);
    164 
    165         Group grpTraceRootEvents = new Group(c, SWT.BORDER);
    166         grpTraceRootEvents.setLayout(new GridLayout(2, false));
    167         grpTraceRootEvents.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1));
    168         grpTraceRootEvents.setText("Trace Events that require root privileges on device");
    169 
    170         mTraceDiskIoBtn = new Button(grpTraceRootEvents, SWT.CHECK);
    171         mTraceDiskIoBtn.setText("Disk I/O");
    172         mTraceDiskIoBtn.setSelection(sTraceDiskIo);
    173 
    174         mTraceKernelWorkqueuesBtn = new Button(grpTraceRootEvents, SWT.CHECK);
    175         mTraceKernelWorkqueuesBtn.setText("Kernel Workqueues (requires root)");
    176         mTraceKernelWorkqueuesBtn.setSelection(sTraceKernelWorkqueues);
    177 
    178         Group grpTraceTags = new Group(c, SWT.BORDER);
    179         grpTraceTags.setLayout(new GridLayout(5, false));
    180         grpTraceTags.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 3, 1));
    181         grpTraceTags.setText("Trace Tags");
    182 
    183         mGfxTagBtn = new Button(grpTraceTags, SWT.CHECK);
    184         mGfxTagBtn.setText("gfx");
    185         mGfxTagBtn.setSelection(sGfxTag);
    186 
    187         mInputTagBtn = new Button(grpTraceTags, SWT.CHECK);
    188         mInputTagBtn.setText("input");
    189         mInputTagBtn.setSelection(sInputTag);
    190 
    191         mViewTagBtn = new Button(grpTraceTags, SWT.CHECK);
    192         mViewTagBtn.setText("view");
    193         mViewTagBtn.setSelection(sViewTag);
    194 
    195         mWebViewTagBtn = new Button(grpTraceTags, SWT.CHECK);
    196         mWebViewTagBtn.setText("webview");
    197         mWebViewTagBtn.setSelection(sWebViewTag);
    198 
    199         mWmTagBtn = new Button(grpTraceTags, SWT.CHECK);
    200         mWmTagBtn.setText("wm");
    201         mWmTagBtn.setSelection(sWmTag);
    202 
    203         mAmTagBtn = new Button(grpTraceTags, SWT.CHECK);
    204         mAmTagBtn.setText("am");
    205         mAmTagBtn.setSelection(sAmTag);
    206 
    207         mSyncTagBtn = new Button(grpTraceTags, SWT.CHECK);
    208         mSyncTagBtn.setText("sync");
    209         mSyncTagBtn.setSelection(sSyncTag);
    210 
    211         mAudioTagBtn = new Button(grpTraceTags, SWT.CHECK);
    212         mAudioTagBtn.setText("audio");
    213         mAudioTagBtn.setSelection(sAudioTag);
    214 
    215         mVideoTagBtn = new Button(grpTraceTags, SWT.CHECK);
    216         mVideoTagBtn.setText("video");
    217         mVideoTagBtn.setSelection(sVideoTag);
    218 
    219         mCameraTagBtn = new Button(grpTraceTags, SWT.CHECK);
    220         mCameraTagBtn.setText("camera");
    221         mCameraTagBtn.setSelection(sCameraTag);
    222 
    223         Label lblTraceTagsWarning = new Label(grpTraceTags, SWT.NONE);
    224         lblTraceTagsWarning.setText(
    225                 "Changes to trace tags will likely need a restart of the Android framework to take effect:\n"
    226                 + "    $ adb shell stop\n"
    227                 + "    $ adb shell start");
    228         lblTraceTagsWarning.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 5, 1));
    229 
    230         ModifyListener m = new ModifyListener() {
    231             @Override
    232             public void modifyText(ModifyEvent e) {
    233                 validateFields();
    234             }
    235         };
    236 
    237         mDestinationText.addModifyListener(m);
    238         mTraceBufferSizeText.addModifyListener(m);
    239         mTraceDurationText.addModifyListener(m);
    240 
    241         return c;
    242     }
    243 
    244     private void validateFields() {
    245         // validate trace destination path
    246         String msg = validatePath(mDestinationText.getText());
    247         if (msg != null) {
    248             setErrorMessage(msg);
    249             getButton(OK).setEnabled(false);
    250             return;
    251         }
    252 
    253         // validate the trace duration
    254         if (!validateInteger(mTraceDurationText.getText())) {
    255             setErrorMessage("Trace Duration should be a valid integer (seconds)");
    256             getButton(OK).setEnabled(false);
    257             return;
    258         }
    259 
    260         // validate the trace buffer size
    261         if (!validateInteger(mTraceBufferSizeText.getText())) {
    262             setErrorMessage("Trace Buffer Size should be a valid integer (kilobytes)");
    263             getButton(OK).setEnabled(false);
    264             return;
    265         }
    266 
    267         getButton(OK).setEnabled(true);
    268         setErrorMessage(null);
    269     }
    270 
    271     private boolean validateInteger(String text) {
    272         if (text == null || text.isEmpty()) {
    273             return true;
    274         }
    275 
    276         try {
    277             Integer.parseInt(text);
    278             return true;
    279         } catch (NumberFormatException e) {
    280             return false;
    281         }
    282     }
    283 
    284     private String validatePath(String path) {
    285         if (path == null || path.isEmpty()) {
    286             return null;
    287         }
    288 
    289         File f = new File(path);
    290         if (f.isDirectory()) {
    291             return String.format("The path '%s' points to a folder", path);
    292         }
    293 
    294         if (!f.exists()) { // if such a file doesn't exist, make sure the parent folder is valid
    295             if (!f.getParentFile().isDirectory()) {
    296                 return String.format("That path '%s' is not a valid folder.", f.getParent());
    297             }
    298         }
    299 
    300         return null;
    301     }
    302 
    303     private String openBrowseDialog(Shell parentShell) {
    304         FileDialog fd = new FileDialog(parentShell, SWT.SAVE);
    305 
    306         fd.setText("Save To");
    307         fd.setFileName(DEFAULT_TRACE_FNAME);
    308 
    309         fd.setFilterPath(sSaveToFolder);
    310         fd.setFilterExtensions(new String[] { "*.html" }); //$NON-NLS-1$
    311 
    312         String fname = fd.open();
    313         if (fname == null || fname.trim().length() == 0) {
    314             return null;
    315         }
    316 
    317         sSaveToFolder = fd.getFilterPath();
    318         return fname;
    319     }
    320 
    321     @Override
    322     protected void okPressed() {
    323         mDestinationPath = mDestinationText.getText().trim();
    324 
    325         sTraceDuration = mTraceDurationText.getText();
    326         if (!sTraceDuration.isEmpty()) {
    327             mOptions.mTraceDuration = Integer.parseInt(sTraceDuration);
    328         }
    329 
    330         sTraceBufferSize = mTraceBufferSizeText.getText();
    331         if (!sTraceBufferSize.isEmpty()) {
    332             mOptions.mTraceBufferSize = Integer.parseInt(sTraceBufferSize);
    333         }
    334 
    335         mOptions.mTraceCpuFreq = mTraceCpuFreqBtn.getSelection();
    336         mOptions.mTraceCpuIdle = mTraceCpuIdleBtn.getSelection();
    337         mOptions.mTraceCpuLoad = mTraceCpuLoadBtn.getSelection();
    338         mOptions.mTraceDiskIo = mTraceDiskIoBtn.getSelection();
    339         mOptions.mTraceKernelWorkqueues = mTraceKernelWorkqueuesBtn.getSelection();
    340         mOptions.mTraceCpuScheduler = mTraceCpuSchedulerBtn.getSelection();
    341 
    342         if (mGfxTagBtn.getSelection()) mOptions.enableTag(SystraceOptions.TAG_GFX);
    343         if (mInputTagBtn.getSelection()) mOptions.enableTag(SystraceOptions.TAG_INPUT);
    344         if (mViewTagBtn.getSelection()) mOptions.enableTag(SystraceOptions.TAG_VIEW);
    345         if (mWebViewTagBtn.getSelection()) mOptions.enableTag(SystraceOptions.TAG_WEBVIEW);
    346         if (mWmTagBtn.getSelection()) mOptions.enableTag(SystraceOptions.TAG_WM);
    347         if (mAmTagBtn.getSelection()) mOptions.enableTag(SystraceOptions.TAG_AM);
    348         if (mSyncTagBtn.getSelection()) mOptions.enableTag(SystraceOptions.TAG_SYNC);
    349         if (mAudioTagBtn.getSelection()) mOptions.enableTag(SystraceOptions.TAG_AUDIO);
    350         if (mVideoTagBtn.getSelection()) mOptions.enableTag(SystraceOptions.TAG_VIDEO);
    351         if (mCameraTagBtn.getSelection()) mOptions.enableTag(SystraceOptions.TAG_CAMERA);
    352 
    353         // save current selections to be restored if the dialog is invoked again
    354         sTraceCpuFreq = mTraceCpuFreqBtn.getSelection();
    355         sTraceCpuIdle = mTraceCpuIdleBtn.getSelection();
    356         sTraceCpuLoad = mTraceCpuLoadBtn.getSelection();
    357         sTraceDiskIo = mTraceDiskIoBtn.getSelection();
    358         sTraceKernelWorkqueues = mTraceKernelWorkqueuesBtn.getSelection();
    359         sTraceCpuScheduler = mTraceCpuSchedulerBtn.getSelection();
    360 
    361         sGfxTag = mGfxTagBtn.getSelection();
    362         sInputTag = mInputTagBtn.getSelection();
    363         sViewTag = mViewTagBtn.getSelection();
    364         sWebViewTag = mWebViewTagBtn.getSelection();
    365         sWmTag = mWmTagBtn.getSelection();
    366         sAmTag = mAmTagBtn.getSelection();
    367         sSyncTag = mSyncTagBtn.getSelection();
    368         sAudioTag = mAudioTagBtn.getSelection();
    369         sVideoTag = mVideoTagBtn.getSelection();
    370         sCameraTag = mCameraTagBtn.getSelection();
    371 
    372         super.okPressed();
    373     }
    374 
    375     @Override
    376     public SystraceOptions getSystraceOptions() {
    377         return mOptions;
    378     }
    379 
    380     @Override
    381     public String getTraceFilePath() {
    382         return mDestinationPath;
    383     }
    384 
    385     private class SystraceOptions implements ISystraceOptions {
    386         // This list is based on the tags in frameworks/native/include/utils/Trace.h
    387         private static final int TAG_GFX = 1 << 1;
    388         private static final int TAG_INPUT = 1 << 2;
    389         private static final int TAG_VIEW = 1 << 3;
    390         private static final int TAG_WEBVIEW = 1 << 4;
    391         private static final int TAG_WM = 1 << 5;
    392         private static final int TAG_AM = 1 << 6;
    393         private static final int TAG_SYNC = 1 << 7;
    394         private static final int TAG_AUDIO = 1 << 8;
    395         private static final int TAG_VIDEO = 1 << 9;
    396         private static final int TAG_CAMERA = 1 << 10;
    397 
    398         private int mTraceBufferSize;
    399         private int mTraceDuration;
    400 
    401         private boolean mTraceCpuFreq;
    402         private boolean mTraceCpuIdle;
    403         private boolean mTraceCpuLoad;
    404         private boolean mTraceDiskIo;
    405         private boolean mTraceKernelWorkqueues;
    406         private boolean mTraceCpuScheduler;
    407 
    408         private int mTag;
    409 
    410         private void enableTag(int tag) {
    411             mTag |= tag;
    412         }
    413 
    414         @Override
    415         public String getTags() {
    416             return mTag == 0 ? null : "0x" + Integer.toHexString(mTag);
    417         }
    418 
    419         @Override
    420         public String getOptions() {
    421             StringBuilder sb = new StringBuilder(20);
    422 
    423             if (mTraceCpuFreq) sb.append("-f "); //$NON-NLS-1$
    424             if (mTraceCpuIdle) sb.append("-i "); //$NON-NLS-1$
    425             if (mTraceCpuLoad) sb.append("-l "); //$NON-NLS-1$
    426             if (mTraceDiskIo) sb.append("-d ");  //$NON-NLS-1$
    427             if (mTraceKernelWorkqueues) sb.append("-w "); //$NON-NLS-1$
    428             if (mTraceCpuScheduler) sb.append("-s "); //$NON-NLS-1$
    429 
    430             if (mTraceDuration > 0) {
    431                 sb.append("-t");    //$NON-NLS-1$
    432                 sb.append(mTraceDuration);
    433                 sb.append(' ');
    434             }
    435 
    436             if (mTraceBufferSize > 0) {
    437                 sb.append("-b ");	//$NON-NLS-1$
    438                 sb.append(mTraceBufferSize);
    439                 sb.append(' ');
    440             }
    441 
    442             return sb.toString().trim();
    443         }
    444     }
    445 }
    446