1 /* 2 * Copyright (C) 2009 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 com.android.ddmlib.log.InvalidTypeException; 22 23 import java.awt.Color; 24 25 abstract public class SyncCommon extends EventDisplay { 26 27 // State information while processing the event stream 28 private int mLastState; // 0 if event started, 1 if event stopped 29 private long mLastStartTime; // ms 30 private long mLastStopTime; //ms 31 private String mLastDetails; 32 private int mLastSyncSource; // poll, server, user, etc. 33 34 // Some common variables for sync display. These define the sync backends 35 //and how they should be displayed. 36 protected static final int CALENDAR = 0; 37 protected static final int GMAIL = 1; 38 protected static final int FEEDS = 2; 39 protected static final int CONTACTS = 3; 40 protected static final int ERRORS = 4; 41 protected static final int NUM_AUTHS = (CONTACTS + 1); 42 protected static final String AUTH_NAMES[] = {"Calendar", "Gmail", "Feeds", "Contacts", 43 "Errors"}; 44 protected static final Color AUTH_COLORS[] = {Color.MAGENTA, Color.GREEN, Color.BLUE, 45 Color.ORANGE, Color.RED}; 46 47 // Values from data/etc/event-log-tags 48 final int EVENT_SYNC = 2720; 49 final int EVENT_TICKLE = 2742; 50 final int EVENT_SYNC_DETAILS = 2743; 51 final int EVENT_CONTACTS_AGGREGATION = 2747; 52 SyncCommon(String name)53 protected SyncCommon(String name) { 54 super(name); 55 } 56 57 /** 58 * Resets the display. 59 */ 60 @Override resetUI()61 void resetUI() { 62 mLastStartTime = 0; 63 mLastStopTime = 0; 64 mLastState = -1; 65 mLastSyncSource = -1; 66 mLastDetails = ""; 67 } 68 69 /** 70 * Updates the display with a new event. This is the main entry point for 71 * each event. This method has the logic to tie together the start event, 72 * stop event, and details event into one graph item. The combined sync event 73 * is handed to the subclass via processSycnEvent. Note that the details 74 * can happen before or after the stop event. 75 * 76 * @param event The event 77 * @param logParser The parser providing the event. 78 */ 79 @Override newEvent(EventContainer event, EventLogParser logParser)80 void newEvent(EventContainer event, EventLogParser logParser) { 81 try { 82 if (event.mTag == EVENT_SYNC) { 83 int state = Integer.parseInt(event.getValueAsString(1)); 84 if (state == 0) { // start 85 mLastStartTime = (long) event.sec * 1000L + (event.nsec / 1000000L); 86 mLastState = 0; 87 mLastSyncSource = Integer.parseInt(event.getValueAsString(2)); 88 mLastDetails = ""; 89 } else if (state == 1) { // stop 90 if (mLastState == 0) { 91 mLastStopTime = (long) event.sec * 1000L + (event.nsec / 1000000L); 92 if (mLastStartTime == 0) { 93 // Log starts with a stop event 94 mLastStartTime = mLastStopTime; 95 } 96 int auth = getAuth(event.getValueAsString(0)); 97 processSyncEvent(event, auth, mLastStartTime, mLastStopTime, mLastDetails, 98 true, mLastSyncSource); 99 mLastState = 1; 100 } 101 } 102 } else if (event.mTag == EVENT_SYNC_DETAILS) { 103 mLastDetails = event.getValueAsString(3); 104 if (mLastState != 0) { // Not inside event 105 long updateTime = (long) event.sec * 1000L + (event.nsec / 1000000L); 106 if (updateTime - mLastStopTime <= 250) { 107 // Got details within 250ms after event, so delete and re-insert 108 // Details later than 250ms (arbitrary) are discarded as probably 109 // unrelated. 110 int auth = getAuth(event.getValueAsString(0)); 111 processSyncEvent(event, auth, mLastStartTime, mLastStopTime, mLastDetails, 112 false, mLastSyncSource); 113 } 114 } 115 } else if (event.mTag == EVENT_CONTACTS_AGGREGATION) { 116 long stopTime = (long) event.sec * 1000L + (event.nsec / 1000000L); 117 long startTime = stopTime - Long.parseLong(event.getValueAsString(0)); 118 String details; 119 int count = Integer.parseInt(event.getValueAsString(1)); 120 if (count < 0) { 121 details = "g" + (-count); 122 } else { 123 details = "G" + count; 124 } 125 processSyncEvent(event, CONTACTS, startTime, stopTime, details, 126 true /* newEvent */, mLastSyncSource); 127 } 128 } catch (InvalidTypeException e) { 129 } 130 } 131 132 /** 133 * Callback hook for subclass to process a sync event. newEvent has the logic 134 * to combine start and stop events and passes a processed event to the 135 * subclass. 136 * 137 * @param event The sync event 138 * @param auth The sync authority 139 * @param startTime Start time (ms) of events 140 * @param stopTime Stop time (ms) of events 141 * @param details Details associated with the event. 142 * @param newEvent True if this event is a new sync event. False if this event 143 * @param syncSource Poll, user, server, etc. 144 */ processSyncEvent(EventContainer event, int auth, long startTime, long stopTime, String details, boolean newEvent, int syncSource)145 abstract void processSyncEvent(EventContainer event, int auth, long startTime, long stopTime, 146 String details, boolean newEvent, int syncSource); 147 148 /** 149 * Converts authority name to auth number. 150 * 151 * @param authname "calendar", etc. 152 * @return number series number associated with the authority 153 */ getAuth(String authname)154 protected int getAuth(String authname) throws InvalidTypeException { 155 if ("calendar".equals(authname) || "cl".equals(authname) || 156 "com.android.calendar".equals(authname)) { 157 return CALENDAR; 158 } else if ("contacts".equals(authname) || "cp".equals(authname) || 159 "com.android.contacts".equals(authname)) { 160 return CONTACTS; 161 } else if ("subscribedfeeds".equals(authname)) { 162 return FEEDS; 163 } else if ("gmail-ls".equals(authname) || "mail".equals(authname)) { 164 return GMAIL; 165 } else if ("gmail-live".equals(authname)) { 166 return GMAIL; 167 } else if ("unknown".equals(authname)) { 168 return -1; // Unknown tickles; discard 169 } else { 170 throw new InvalidTypeException("Unknown authname " + authname); 171 } 172 } 173 } 174