Home | History | Annotate | Download | only in src
      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    */
     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    */
    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    */
    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