• 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.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