1 /* 2 * Copyright (C) 2012 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 package com.android.loganalysis.item; 17 18 import org.json.JSONArray; 19 import org.json.JSONException; 20 import org.json.JSONObject; 21 22 import java.util.Arrays; 23 import java.util.Date; 24 import java.util.HashSet; 25 import java.util.LinkedList; 26 import java.util.List; 27 import java.util.Set; 28 29 /** 30 * An {@link IItem} used to store logcat info. 31 */ 32 public class LogcatItem extends GenericItem { 33 34 /** Constant for JSON output */ 35 public static final String START_TIME = "START_TIME"; 36 /** Constant for JSON output */ 37 public static final String STOP_TIME = "STOP_TIME"; 38 /** Constant for JSON output */ 39 public static final String EVENTS = "EVENTS"; 40 41 private static final Set<String> ATTRIBUTES = new HashSet<String>(Arrays.asList( 42 START_TIME, STOP_TIME, EVENTS)); 43 44 @SuppressWarnings("serial") 45 private class ItemList extends LinkedList<MiscLogcatItem> {} 46 47 /** 48 * The constructor for {@link LogcatItem}. 49 */ LogcatItem()50 public LogcatItem() { 51 super(ATTRIBUTES); 52 53 setAttribute(EVENTS, new ItemList()); 54 } 55 56 /** 57 * Get the start time of the logcat. 58 */ getStartTime()59 public Date getStartTime() { 60 return (Date) getAttribute(START_TIME); 61 } 62 63 /** 64 * Set the start time of the logcat. 65 */ setStartTime(Date time)66 public void setStartTime(Date time) { 67 setAttribute(START_TIME, time); 68 } 69 70 /** 71 * Get the stop time of the logcat. 72 */ getStopTime()73 public Date getStopTime() { 74 return (Date) getAttribute(STOP_TIME); 75 } 76 77 /** 78 * Set the stop time of the logcat. 79 */ setStopTime(Date time)80 public void setStopTime(Date time) { 81 setAttribute(STOP_TIME, time); 82 } 83 84 /** 85 * Get the list of all {@link MiscLogcatItem} events. 86 */ getEvents()87 public List<MiscLogcatItem> getEvents() { 88 return (ItemList) getAttribute(EVENTS); 89 } 90 91 /** 92 * Add an {@link MiscLogcatItem} event to the end of the list of events. 93 */ addEvent(MiscLogcatItem event)94 public void addEvent(MiscLogcatItem event) { 95 ((ItemList) getAttribute(EVENTS)).add(event); 96 } 97 98 /** 99 * Get the list of all {@link AnrItem} events. 100 */ getAnrs()101 public List<AnrItem> getAnrs() { 102 List<AnrItem> anrs = new LinkedList<AnrItem>(); 103 for (IItem item : getEvents()) { 104 if (item instanceof AnrItem) { 105 anrs.add((AnrItem) item); 106 } 107 } 108 return anrs; 109 } 110 111 /** 112 * Get the list of all {@link JavaCrashItem} events. 113 */ getJavaCrashes()114 public List<JavaCrashItem> getJavaCrashes() { 115 List<JavaCrashItem> jcs = new LinkedList<JavaCrashItem>(); 116 for (IItem item : getEvents()) { 117 if (item instanceof JavaCrashItem) { 118 jcs.add((JavaCrashItem) item); 119 } 120 } 121 return jcs; 122 } 123 124 /** 125 * Get the list of all {@link NativeCrashItem} events. 126 */ getNativeCrashes()127 public List<NativeCrashItem> getNativeCrashes() { 128 List<NativeCrashItem> ncs = new LinkedList<NativeCrashItem>(); 129 for (IItem item : getEvents()) { 130 if (item instanceof NativeCrashItem) { 131 ncs.add((NativeCrashItem) item); 132 } 133 } 134 return ncs; 135 } 136 137 /** 138 * Get the list of all {@link MiscLogcatItem} events for a cateogry. 139 */ getMiscEvents(String category)140 public List<MiscLogcatItem> getMiscEvents(String category) { 141 List<MiscLogcatItem> items = new LinkedList<MiscLogcatItem>(); 142 for (MiscLogcatItem item : getEvents()) { 143 if (item.getCategory().equals(category)) { 144 items.add(item); 145 } 146 } 147 return items; 148 } 149 150 /** 151 * {@inheritDoc} 152 */ 153 @Override merge(IItem other)154 public LogcatItem merge(IItem other) throws ConflictingItemException { 155 if (this == other) { 156 return this; 157 } 158 if (other == null || !(other instanceof LogcatItem)) { 159 throw new ConflictingItemException("Conflicting class types"); 160 } 161 162 LogcatItem logcat = (LogcatItem) other; 163 164 Date start = logcat.getStartTime().before(getStartTime()) ? 165 logcat.getStartTime() : getStartTime(); 166 Date stop = logcat.getStopTime().after(getStopTime()) ? 167 logcat.getStopTime() : getStopTime(); 168 Date overlapStart = logcat.getStartTime().after(getStartTime()) ? 169 logcat.getStartTime() : getStartTime(); 170 Date overlapStop = logcat.getStopTime().before(getStopTime()) ? 171 logcat.getStopTime() : getStopTime(); 172 173 // Make sure that all events in the overlapping span are 174 ItemList mergedEvents = new ItemList(); 175 for (MiscLogcatItem event : getEvents()) { 176 final Date eventTime = event.getEventTime(); 177 if (eventTime.after(overlapStart) && eventTime.before(overlapStop) && 178 !logcat.getEvents().contains(event)) { 179 throw new ConflictingItemException("Event in first logcat not contained in " + 180 "overlapping portion of other logcat."); 181 } 182 mergedEvents.add(event); 183 } 184 185 for (MiscLogcatItem event : logcat.getEvents()) { 186 final Date eventTime = event.getEventTime(); 187 if (eventTime.after(overlapStart) && eventTime.before(overlapStop)) { 188 if (!getEvents().contains(event)) { 189 throw new ConflictingItemException("Event in first logcat not contained in " + 190 "overlapping portion of other logcat."); 191 } 192 } else { 193 mergedEvents.add(event); 194 } 195 } 196 197 LogcatItem mergedLogcat = new LogcatItem(); 198 mergedLogcat.setStartTime(start); 199 mergedLogcat.setStopTime(stop); 200 mergedLogcat.setAttribute(EVENTS, mergedEvents); 201 return mergedLogcat; 202 } 203 204 /** 205 * {@inheritDoc} 206 */ 207 @Override toJson()208 public JSONObject toJson() { 209 JSONObject output = super.toJson(); 210 JSONArray events = new JSONArray(); 211 for (MiscLogcatItem event : getEvents()) { 212 events.put(event.toJson()); 213 } 214 215 try { 216 output.put(EVENTS, events); 217 } catch (JSONException e) { 218 // Ignore 219 } 220 return output; 221 } 222 } 223