/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.ddmuilib.log.event; import com.android.ddmlib.log.EventContainer; import com.android.ddmlib.log.EventLogParser; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.AbstractXYItemRenderer; import org.jfree.chart.renderer.xy.XYBarRenderer; import org.jfree.data.time.RegularTimePeriod; import org.jfree.data.time.SimpleTimePeriod; import org.jfree.data.time.TimePeriodValues; import org.jfree.data.time.TimePeriodValuesCollection; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.TimeZone; public class DisplaySyncHistogram extends SyncCommon { Map<SimpleTimePeriod, Integer> mTimePeriodMap[]; // Information to graph for each authority private TimePeriodValues mDatasetsSyncHist[]; public DisplaySyncHistogram(String name) { super(name); } /** * Creates the UI for the event display. * @param parent the parent composite. * @param logParser the current log parser. * @return the created control (which may have children). */ @Override public Control createComposite(final Composite parent, EventLogParser logParser, final ILogColumnListener listener) { Control composite = createCompositeChart(parent, logParser, "Sync Histogram"); resetUI(); return composite; } /** * Resets the display. */ @Override void resetUI() { super.resetUI(); XYPlot xyPlot = mChart.getXYPlot(); AbstractXYItemRenderer br = new XYBarRenderer(); mDatasetsSyncHist = new TimePeriodValues[NUM_AUTHS+1]; mTimePeriodMap = new HashMap[NUM_AUTHS + 1]; TimePeriodValuesCollection tpvc = new TimePeriodValuesCollection(); xyPlot.setDataset(tpvc); xyPlot.setRenderer(br); for (int i = 0; i < NUM_AUTHS + 1; i++) { br.setSeriesPaint(i, AUTH_COLORS[i]); mDatasetsSyncHist[i] = new TimePeriodValues(AUTH_NAMES[i]); tpvc.addSeries(mDatasetsSyncHist[i]); mTimePeriodMap[i] = new HashMap<SimpleTimePeriod, Integer>(); } } /** * Callback to process a sync event. * * @param event The sync event * @param startTime Start time (ms) of events * @param stopTime Stop time (ms) of events * @param details Details associated with the event. * @param newEvent True if this event is a new sync event. False if this event * @param syncSource */ @Override void processSyncEvent(EventContainer event, int auth, long startTime, long stopTime, String details, boolean newEvent, int syncSource) { if (newEvent) { if (details.indexOf('x') >= 0 || details.indexOf('X') >= 0) { auth = ERRORS; } double delta = (stopTime - startTime) * 100. / 1000 / 3600; // Percent of hour addHistEvent(0, auth, delta); } else { // sync_details arrived for an event that has already been graphed. if (details.indexOf('x') >= 0 || details.indexOf('X') >= 0) { // Item turns out to be in error, so transfer time from old auth to error. double delta = (stopTime - startTime) * 100. / 1000 / 3600; // Percent of hour addHistEvent(0, auth, -delta); addHistEvent(0, ERRORS, delta); } } } /** * Helper to add an event to the data series. * Also updates error series if appropriate (x or X in details). * @param stopTime Time event ends * @param auth Sync authority * @param value Value to graph for event */ private void addHistEvent(long stopTime, int auth, double value) { SimpleTimePeriod hour = getTimePeriod(stopTime, mHistWidth); // Loop over all datasets to do the stacking. for (int i = auth; i <= ERRORS; i++) { addToPeriod(mDatasetsSyncHist, i, hour, value); } } private void addToPeriod(TimePeriodValues tpv[], int auth, SimpleTimePeriod period, double value) { int index; if (mTimePeriodMap[auth].containsKey(period)) { index = mTimePeriodMap[auth].get(period); double oldValue = tpv[auth].getValue(index).doubleValue(); tpv[auth].update(index, oldValue + value); } else { index = tpv[auth].getItemCount(); mTimePeriodMap[auth].put(period, index); tpv[auth].add(period, value); } } /** * Creates a multiple-hour time period for the histogram. * @param time Time in milliseconds. * @param numHoursWide: should divide into a day. * @return SimpleTimePeriod covering the number of hours and containing time. */ private SimpleTimePeriod getTimePeriod(long time, long numHoursWide) { Date date = new Date(time); TimeZone zone = RegularTimePeriod.DEFAULT_TIME_ZONE; Calendar calendar = Calendar.getInstance(zone); calendar.setTime(date); long hoursOfYear = calendar.get(Calendar.HOUR_OF_DAY) + calendar.get(Calendar.DAY_OF_YEAR) * 24; int year = calendar.get(Calendar.YEAR); hoursOfYear = (hoursOfYear / numHoursWide) * numHoursWide; calendar.clear(); calendar.set(year, 0, 1, 0, 0); // Jan 1 long start = calendar.getTimeInMillis() + hoursOfYear * 3600 * 1000; return new SimpleTimePeriod(start, start + numHoursWide * 3600 * 1000); } /** * Gets display type * * @return display type as an integer */ @Override int getDisplayType() { return DISPLAY_TYPE_SYNC_HIST; } }