public void addData(String hint, String text, DocNode node, int flag) { String plainText = node == null ? Util.stripHtml(text) : node.getText(); csvField(plainText); dbField(mColIdx, plainText); if (mColIdx == 0) { mRow = new TableRow(); mBody.add(mRow); if (mNextRowStyle != null) { mRow.setStyle(mNextRowStyle); mNextRowStyle = null; } if (mNextRowId != null) { mRow.setId(mNextRowId); mNextRowId = null; } } TableCell cell = new TableCell(hint, text, node); mRow.add(cell); Column c = mColumns.get(mColIdx); if (0 != (c.flag & FLAG_ALIGN_RIGHT)) { cell.addStyle("right"); } mColIdx = (mColIdx + 1) % mColumns.size(); if (mColIdx == 0) { csvEOL(); dbEOL(); } mEmpty = false; }
private int readFile(Section sl, String fileName, InputStream is, int limit) { int ret = READ_ALL; try { if (is == null) { // Check file size (only if not reading from stream) File f = new File(fileName); long size = f.length(); is = new FileInputStream(f); if (size > limit) { // Need to seek to "end - limit" Util.skip(is, size - limit); Util.skipToEol(is); printErr( 1, "File '" + fileName + "' is too long, loading only last " + (limit / Util.MB) + " megabyte(s)..."); ret = READ_PARTS; } } LineReader br = new LineReader(is); String line = null; while (null != (line = br.readLine())) { sl.addLine(line); } br.close(); is.close(); return ret; } catch (IOException e) { printErr(1, "Error reading file '" + fileName + "' (it will be ignored): " + e); return READ_FAILED; } }
private Packet parseAttrs(String log) { Packet pkt = new Packet(); log = Util.strip(log); // Extract prefix int idx = log.indexOf("IN="); if (idx > 0) { pkt.prefix = log.substring(0, idx); log = log.substring(idx); } pkt.hash = log.hashCode(); // Extract referenced packet idx = log.indexOf('['); if (idx > 0) { int idx2 = log.lastIndexOf(']'); if (idx2 > idx) { pkt.ref = parseAttrs(log.substring(idx + 1, idx2 - 1)); } log = log.substring(0, idx - 1); } // Split log line and extract attributes and flags String fields[] = log.split(" "); for (String f : fields) { if (f.contains("=")) { String kv[] = f.split("=", 2); pkt.put(kv[0], kv[1]); } else { pkt.addFlag(f); } } // Check parsed packet pkt.check(); return pkt; }
@Override public void generate(Module rep) { if (!mLoaded) return; BugReportModule br = (BugReportModule) rep; Chapter ch = br.findOrCreateChapter("Battery info/Kernel wakelocks"); addHelp(ch); long uptime = br.getUptime(); Table tg = new Table(Table.FLAG_SORT, ch); tg.setCSVOutput(rep, "kernel_wakelocks"); tg.setTableName(rep, "kernel_wakelocks"); tg.addColumn("Name", "The name of the wakelock as provided by the driver", 0, "name varchar"); tg.addColumn( "Count", "The number of times that the wakelock has been acquired.", Table.FLAG_ALIGN_RIGHT, "count int"); tg.addColumn( "Expire count", "The number of times that the wakelock has timed out. This indicates that some application has an input device open, but is not reading from it, which is a bug.", Table.FLAG_ALIGN_RIGHT, "expire_count int"); tg.addColumn( "Wake count", "The number of times that the wakelock was the first to be acquired in the resume path.", Table.FLAG_ALIGN_RIGHT, "wake_count int"); tg.addColumn( "Active since (ms)", "Tracks how long a wakelock has been held since it was last acquired, or zero if it is not currently held.", Table.FLAG_ALIGN_RIGHT, "active_since_ms int"); tg.addColumn( "Total time (ms)", "Accumulates the total amount of time that the corresponding wakelock has been held.", Table.FLAG_ALIGN_RIGHT, "total_time_ms int"); if (uptime > 0) { tg.addColumn( "Total time (%)", "Total time as percentage of uptime", Table.FLAG_ALIGN_RIGHT, "total_time_p int"); } tg.addColumn( "Average time (ms)", "Total time divided by Count.", Table.FLAG_ALIGN_RIGHT, "average_time_ms int"); tg.addColumn( "Sleep time (ms)", "The total time that the wakelock was held while the display was powered off.", Table.FLAG_ALIGN_RIGHT, "sleep_time_ms int"); tg.addColumn( "Max time (ms)", "The longest hold time for the wakelock. This allows finding cases where wakelocks are held for too long, but are eventually released. (In contrast, active_since is more useful in the held-forever case.)", Table.FLAG_ALIGN_RIGHT, "max_time_ms int"); tg.addColumn("Last change", "?", Table.FLAG_ALIGN_RIGHT, "last_change int"); tg.begin(); for (KernelWakelock lock : mLocks) { tg.addData(lock.name); tg.addData(lock.count); tg.addData(lock.expire_count); tg.addData(lock.wake_count); long activeSinceMs = lock.active_since / 1000000L; tg.addData(Util.formatTS(activeSinceMs), new ShadedValue(activeSinceMs)); long totalMs = lock.total_time / 1000000L; tg.addData(Util.formatTS(totalMs), new ShadedValue(totalMs)); if (uptime > 0) { tg.addData(lock.total_time / 10000000L / uptime); } long avgMs = (lock.count == 0) ? 0 : (lock.total_time / lock.count / 1000000L); tg.addData(Util.formatTS(avgMs), new ShadedValue(avgMs)); long sleepMs = lock.sleep_time / 1000000L; tg.addData(Util.formatTS(sleepMs), new ShadedValue(sleepMs)); long maxMs = lock.max_time / 1000000L; tg.addData(Util.formatTS(maxMs), new ShadedValue(maxMs)); tg.addData(lock.last_change); } tg.end(); }
/** Parse a log line from logs generated by crash */ private boolean parseFmtCrash(BugReportModule br, String line, LogLine prev) { if (line.length() <= 33) return false; // just some sane value... maybe it should be 23? // Do some initial verification boolean newLine = true; char c = line.charAt(8); if (c != '[') newLine = false; c = line.charAt(16); if (c != '.') newLine = false; c = line.charAt(23); if (c != ']') newLine = false; if (!newLine) { // Continuation of the previous one if (prev == null) { // No previous line, we cannot continue, ignore return false; } // Copy the important fields from the previous line level = prev.level; ts = prev.ts; pidS = prev.pidS; pidE = prev.pidE; pid = prev.pid; tagS = prev.tagS; tagE = prev.tagE; tag = prev.tag; msgS = prev.msgS; msgE = msgS + line.length(); msg = line; line = prev.line.substring(0, prev.msgS) + msg; this.line = line; } else { // This will hold the rebuilt line StringBuffer sb = new StringBuffer(); // Parse the level level = line.charAt(0); if (level == ' ') { level = line.charAt(2); } if (level == ' ') { level = line.charAt(3); } if (level == ' ') { level = 'I'; } // Parse the timestamp try { int sec = Integer.parseInt(Util.strip(line.substring(9, 16))); int usec = Integer.parseInt(Util.strip(line.substring(17, 23))); ts = sec * 1000 + usec / 1000; sb.append( String.format( "%02d:%02d:%02d.%03d ", (sec / 3600) % 24, (sec / 60) % 60, sec % 60, usec / 1000)); } catch (NumberFormatException e) { return false; // wrong ts? or wrong format? } // Parse pid pidS = line.indexOf('('); pidE = line.indexOf(':', pidS); if (pidS < 0 || pidE < 0) { return false; // wrong format? } pidS++; try { pid = Integer.parseInt(line.substring(pidS, pidE)); } catch (NumberFormatException t) { return false; // strange pid } // Parse tag tagS = line.indexOf(')'); if (tagS < 0) return false; tagS += 2; tagE = line.indexOf( " ", tagS); // This might not work for tags which actually contain a space, but there is no // more reliable way if (tagE < 0) return false; tag = line.substring(tagS, tagE); // This could be an event tag, extract the tag id int idx0 = tag.indexOf('('); int idx1 = tag.indexOf(')'); try { if (idx0 == -1 && idx1 == -1) { tagId = Integer.parseInt(tag); } else if (idx0 != -1 && idx1 != -1 && idx0 < idx1) { tagId = Integer.parseInt(tag.substring(idx0 + 1, idx1)); } } catch (NumberFormatException nfe) { /* ignore */ } // Read message int idx = tagE + 1; while (idx < line.length() && line.charAt(idx) == ' ') { idx++; } if (idx < line.length()) { msg = line.substring(idx); msgS = idx; msgE = line.length(); } else { msg = ""; msgS = msgE = line.length(); } // Finish reconstruction sb.append(level); sb.append('/'); tagS = sb.length(); sb.append(tag); tagE = sb.length(); sb.append('('); pidS = sb.length(); sb.append(pid); pidE = sb.length(); sb.append("): "); msgS = sb.length(); sb.append(msg); msgE = sb.length(); line = sb.toString(); this.line = line; } finishParse(br); // Override field parsing (Do some basic field parsing... very basic) if (msg != null) { fields = msg.split(","); for (int i = 0; i < fields.length; i++) { fields[i] = Util.strip(fields[i]); } } fmt = FMT_CRASH; return true; }
public void addColumn(String title, String hint, int flag, String dbSpec) { mColumns.add(new Column(title, hint, dbSpec, flag)); csvField(Util.stripHtml(title)); }