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.ddmuilib.log.event; 18 19 import com.android.ddmlib.log.EventContainer; 20 import com.android.ddmlib.log.EventLogParser; 21 22 import org.eclipse.swt.widgets.Composite; 23 import org.eclipse.swt.widgets.Control; 24 import org.jfree.chart.plot.XYPlot; 25 import org.jfree.chart.renderer.xy.AbstractXYItemRenderer; 26 import org.jfree.chart.renderer.xy.XYBarRenderer; 27 import org.jfree.data.time.RegularTimePeriod; 28 import org.jfree.data.time.SimpleTimePeriod; 29 import org.jfree.data.time.TimePeriodValues; 30 import org.jfree.data.time.TimePeriodValuesCollection; 31 32 import java.util.Calendar; 33 import java.util.Date; 34 import java.util.HashMap; 35 import java.util.Map; 36 import java.util.TimeZone; 37 38 public class DisplaySyncHistogram extends SyncCommon { 39 40 Map<SimpleTimePeriod, Integer> mTimePeriodMap[]; 41 42 // Information to graph for each authority 43 private TimePeriodValues mDatasetsSyncHist[]; 44 DisplaySyncHistogram(String name)45 public DisplaySyncHistogram(String name) { 46 super(name); 47 } 48 49 /** 50 * Creates the UI for the event display. 51 * @param parent the parent composite. 52 * @param logParser the current log parser. 53 * @return the created control (which may have children). 54 */ 55 @Override createComposite(final Composite parent, EventLogParser logParser, final ILogColumnListener listener)56 public Control createComposite(final Composite parent, EventLogParser logParser, 57 final ILogColumnListener listener) { 58 Control composite = createCompositeChart(parent, logParser, "Sync Histogram"); 59 resetUI(); 60 return composite; 61 } 62 63 /** 64 * Resets the display. 65 */ 66 @Override resetUI()67 void resetUI() { 68 super.resetUI(); 69 XYPlot xyPlot = mChart.getXYPlot(); 70 71 AbstractXYItemRenderer br = new XYBarRenderer(); 72 mDatasetsSyncHist = new TimePeriodValues[NUM_AUTHS+1]; 73 74 @SuppressWarnings("unchecked") 75 Map<SimpleTimePeriod, Integer> mTimePeriodMapTmp[] = new HashMap[NUM_AUTHS + 1]; 76 mTimePeriodMap = mTimePeriodMapTmp; 77 78 TimePeriodValuesCollection tpvc = new TimePeriodValuesCollection(); 79 xyPlot.setDataset(tpvc); 80 xyPlot.setRenderer(br); 81 82 for (int i = 0; i < NUM_AUTHS + 1; i++) { 83 br.setSeriesPaint(i, AUTH_COLORS[i]); 84 mDatasetsSyncHist[i] = new TimePeriodValues(AUTH_NAMES[i]); 85 tpvc.addSeries(mDatasetsSyncHist[i]); 86 mTimePeriodMap[i] = new HashMap<SimpleTimePeriod, Integer>(); 87 88 } 89 } 90 91 /** 92 * Callback to process a sync event. 93 * 94 * @param event The sync event 95 * @param startTime Start time (ms) of events 96 * @param stopTime Stop time (ms) of events 97 * @param details Details associated with the event. 98 * @param newEvent True if this event is a new sync event. False if this event 99 * @param syncSource 100 */ 101 @Override processSyncEvent(EventContainer event, int auth, long startTime, long stopTime, String details, boolean newEvent, int syncSource)102 void processSyncEvent(EventContainer event, int auth, long startTime, long stopTime, 103 String details, boolean newEvent, int syncSource) { 104 if (newEvent) { 105 if (details.indexOf('x') >= 0 || details.indexOf('X') >= 0) { 106 auth = ERRORS; 107 } 108 double delta = (stopTime - startTime) * 100. / 1000 / 3600; // Percent of hour 109 addHistEvent(0, auth, delta); 110 } else { 111 // sync_details arrived for an event that has already been graphed. 112 if (details.indexOf('x') >= 0 || details.indexOf('X') >= 0) { 113 // Item turns out to be in error, so transfer time from old auth to error. 114 double delta = (stopTime - startTime) * 100. / 1000 / 3600; // Percent of hour 115 addHistEvent(0, auth, -delta); 116 addHistEvent(0, ERRORS, delta); 117 } 118 } 119 } 120 121 /** 122 * Helper to add an event to the data series. 123 * Also updates error series if appropriate (x or X in details). 124 * @param stopTime Time event ends 125 * @param auth Sync authority 126 * @param value Value to graph for event 127 */ addHistEvent(long stopTime, int auth, double value)128 private void addHistEvent(long stopTime, int auth, double value) { 129 SimpleTimePeriod hour = getTimePeriod(stopTime, mHistWidth); 130 131 // Loop over all datasets to do the stacking. 132 for (int i = auth; i <= ERRORS; i++) { 133 addToPeriod(mDatasetsSyncHist, i, hour, value); 134 } 135 } 136 addToPeriod(TimePeriodValues tpv[], int auth, SimpleTimePeriod period, double value)137 private void addToPeriod(TimePeriodValues tpv[], int auth, SimpleTimePeriod period, 138 double value) { 139 int index; 140 if (mTimePeriodMap[auth].containsKey(period)) { 141 index = mTimePeriodMap[auth].get(period); 142 double oldValue = tpv[auth].getValue(index).doubleValue(); 143 tpv[auth].update(index, oldValue + value); 144 } else { 145 index = tpv[auth].getItemCount(); 146 mTimePeriodMap[auth].put(period, index); 147 tpv[auth].add(period, value); 148 } 149 } 150 151 /** 152 * Creates a multiple-hour time period for the histogram. 153 * @param time Time in milliseconds. 154 * @param numHoursWide: should divide into a day. 155 * @return SimpleTimePeriod covering the number of hours and containing time. 156 */ getTimePeriod(long time, long numHoursWide)157 private SimpleTimePeriod getTimePeriod(long time, long numHoursWide) { 158 Date date = new Date(time); 159 TimeZone zone = RegularTimePeriod.DEFAULT_TIME_ZONE; 160 Calendar calendar = Calendar.getInstance(zone); 161 calendar.setTime(date); 162 long hoursOfYear = calendar.get(Calendar.HOUR_OF_DAY) + 163 calendar.get(Calendar.DAY_OF_YEAR) * 24; 164 int year = calendar.get(Calendar.YEAR); 165 hoursOfYear = (hoursOfYear / numHoursWide) * numHoursWide; 166 calendar.clear(); 167 calendar.set(year, 0, 1, 0, 0); // Jan 1 168 long start = calendar.getTimeInMillis() + hoursOfYear * 3600 * 1000; 169 return new SimpleTimePeriod(start, start + numHoursWide * 3600 * 1000); 170 } 171 172 /** 173 * Gets display type 174 * 175 * @return display type as an integer 176 */ 177 @Override getDisplayType()178 int getDisplayType() { 179 return DISPLAY_TYPE_SYNC_HIST; 180 } 181 } 182