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