public void dump(IndentingPrintWriter pw) { Map<String, CallEvent> pendingResponses = new HashMap<>(); pw.print("Call "); pw.print(mId); pw.print(" ["); pw.print(sDateFormat.format(new Date(mCall.getCreationTimeMillis()))); pw.print("]"); pw.println(mCall.isIncoming() ? "(MT - incoming)" : "(MO - outgoing)"); pw.increaseIndent(); pw.println("To address: " + piiHandle(mCall.getHandle())); for (CallEvent event : mEvents) { // We print out events in chronological order. During that process we look at each // event and see if it maps to a request on the Request-Response pairs map. If it // does, then we effectively start 'listening' for the response. We do that by // storing the response event ID in {@code pendingResponses}. When we find the // response in a later iteration of the loop, we grab the original request and // calculate the time it took to get a response. if (Events.requestResponsePairs.containsKey(event.eventId)) { // This event expects a response, so add that response to the maps // of pending events. String pendingResponse = Events.requestResponsePairs.get(event.eventId); pendingResponses.put(pendingResponse, event); } pw.print(sDateFormat.format(new Date(event.time))); pw.print(" - "); pw.print(event.eventId); if (event.data != null) { pw.print(" ("); Object data = event.data; if (data instanceof Call) { // If the data is another call, then change the data to the call's CallEvent // ID instead. CallEventRecord record = mCallEventRecordMap.get(data); if (record != null) { data = "Call " + record.mId; } } pw.print(data); pw.print(")"); } // If this event is a response event that we've been waiting for, calculate the time // it took for the response to complete and print that out as well. CallEvent requestEvent = pendingResponses.remove(event.eventId); if (requestEvent != null) { pw.print(", time since "); pw.print(requestEvent.eventId); pw.print(": "); pw.print(event.time - requestEvent.time); pw.print(" ms"); } pw.println(); } pw.decreaseIndent(); }