1 /* 2 * Copyright (C) 2015 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.ahat; 18 19 import com.android.ahat.heapdump.AhatInstance; 20 import com.android.ahat.heapdump.Site; 21 import com.android.ahat.heapdump.Value; 22 import java.net.URI; 23 24 /** 25 * Class for generating a DocString summary of an instance or value. 26 */ 27 class Summarizer { 28 29 // For string literals, we limit the number of characters we show to 30 // kMaxChars in case the string is really long. 31 private static int kMaxChars = 200; 32 33 /** 34 * Creates a DocString representing a summary of the given instance. 35 */ summarize(AhatInstance inst)36 public static DocString summarize(AhatInstance inst) { 37 DocString formatted = new DocString(); 38 if (inst == null) { 39 formatted.append("null"); 40 return formatted; 41 } 42 43 // Annotate new objects as new. 44 if (inst.getBaseline().isPlaceHolder()) { 45 formatted.append(DocString.added("new ")); 46 } 47 48 // Annotate deleted objects as deleted. 49 if (inst.isPlaceHolder()) { 50 formatted.append(DocString.removed("del ")); 51 } 52 53 // Annotate unreachable objects as such. 54 if (!inst.isReachable()) { 55 formatted.append("unreachable "); 56 } 57 58 // Annotate roots as roots. 59 if (inst.isRoot()) { 60 formatted.append("root "); 61 } 62 63 // Annotate classes as classes. 64 DocString linkText = new DocString(); 65 if (inst.isClassObj()) { 66 linkText.append("class "); 67 } 68 69 linkText.append(inst.toString()); 70 71 if (inst.isPlaceHolder()) { 72 // Don't make links to placeholder objects. 73 formatted.append(linkText); 74 } else { 75 URI objTarget = DocString.formattedUri("object?id=%d", inst.getId()); 76 formatted.appendLink(objTarget, linkText); 77 } 78 79 // Annotate Strings with their values. 80 String stringValue = inst.asString(kMaxChars); 81 if (stringValue != null) { 82 formatted.appendFormat(" \"%s", stringValue); 83 formatted.append(kMaxChars == stringValue.length() ? "..." : "\""); 84 } 85 86 // Annotate Reference with its referent 87 AhatInstance referent = inst.getReferent(); 88 if (referent != null) { 89 formatted.append(" for "); 90 91 // It should not be possible for a referent to refer back to the 92 // reference object, even indirectly, so there shouldn't be any issues 93 // with infinite recursion here. 94 formatted.append(summarize(referent)); 95 } 96 97 // Annotate DexCache with its location. 98 String dexCacheLocation = inst.getDexCacheLocation(kMaxChars); 99 if (dexCacheLocation != null) { 100 formatted.appendFormat(" for %s", dexCacheLocation); 101 if (kMaxChars == dexCacheLocation.length()) { 102 formatted.append("..."); 103 } 104 } 105 106 // Annotate bitmaps with a thumbnail. 107 AhatInstance bitmap = inst.getAssociatedBitmapInstance(); 108 String thumbnail = ""; 109 if (bitmap != null) { 110 URI uri = DocString.formattedUri("bitmap?id=%d", bitmap.getId()); 111 formatted.appendThumbnail(uri, "bitmap image"); 112 } 113 return formatted; 114 } 115 116 /** 117 * Creates a DocString summarizing the given value. 118 */ summarize(Value value)119 public static DocString summarize(Value value) { 120 if (value == null) { 121 return DocString.text("null"); 122 } 123 if (value.isAhatInstance()) { 124 return summarize(value.asAhatInstance()); 125 } 126 return DocString.text(value.toString()); 127 } 128 129 /** 130 * Creates a DocString summarizing the given site. 131 */ summarize(Site site)132 public static DocString summarize(Site site) { 133 DocString text = DocString.text(site.getMethodName()); 134 text.append(site.getSignature()); 135 text.append(" - "); 136 text.append(site.getFilename()); 137 if (site.getLineNumber() > 0) { 138 text.append(":").append(Integer.toString(site.getLineNumber())); 139 } 140 URI uri = DocString.formattedUri("site?id=%d&depth=%d", site.getId(), site.getDepth()); 141 return DocString.link(uri, text); 142 } 143 } 144