1b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler/*
2b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Copyright (C) 2015 The Android Open Source Project
3b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler *
4b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Licensed under the Apache License, Version 2.0 (the "License");
5b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * you may not use this file except in compliance with the License.
6b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * You may obtain a copy of the License at
7b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler *
8b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler *      http://www.apache.org/licenses/LICENSE-2.0
9b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler *
10b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Unless required by applicable law or agreed to in writing, software
11b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * distributed under the License is distributed on an "AS IS" BASIS,
12b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * See the License for the specific language governing permissions and
14b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * limitations under the License.
15b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler */
16b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler
17b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerpackage com.android.ahat;
18b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler
19b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport com.android.tools.perflib.heap.ClassObj;
20b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport com.android.tools.perflib.heap.Instance;
21b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport java.net.URI;
22b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler
23b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler/**
24b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Class to render an hprof value to a DocString.
25b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler */
26b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerclass Value {
27b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler
2877ff54b5055ec55806069c8d026b102df29857b5Richard Uhler  // For string literals, we limit the number of characters we show to
2977ff54b5055ec55806069c8d026b102df29857b5Richard Uhler  // kMaxChars in case the string is really long.
3077ff54b5055ec55806069c8d026b102df29857b5Richard Uhler  private static int kMaxChars = 200;
3177ff54b5055ec55806069c8d026b102df29857b5Richard Uhler
32b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler  /**
33b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler   * Create a DocString representing a summary of the given instance.
34b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler   */
3538f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler  private static DocString renderInstance(AhatSnapshot snapshot, Instance inst) {
3638f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler    DocString formatted = new DocString();
37b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    if (inst == null) {
3838f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler      formatted.append("(null)");
3938f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler      return formatted;
4038f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler    }
4138f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler
4238f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler    // Annotate roots as roots.
4338f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler    if (snapshot.isRoot(inst)) {
4438f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler      formatted.append("(root) ");
45b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    }
46b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler
4738f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler
48b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    // Annotate classes as classes.
4938f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler    DocString link = new DocString();
50b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    if (inst instanceof ClassObj) {
51b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler      link.append("class ");
52b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    }
53b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler
54b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    link.append(inst.toString());
5538f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler
56b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler    URI objTarget = DocString.formattedUri("object?id=%d", inst.getId());
5738f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler    formatted.appendLink(objTarget, link);
58b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler
59b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    // Annotate Strings with their values.
6077ff54b5055ec55806069c8d026b102df29857b5Richard Uhler    String stringValue = InstanceUtils.asString(inst, kMaxChars);
61b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    if (stringValue != null) {
62b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler      formatted.appendFormat(" \"%s", stringValue);
63b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler      formatted.append(kMaxChars == stringValue.length() ? "..." : "\"");
64b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler    }
65b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler
66b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler    // Annotate Reference with its referent
67b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler    Instance referent = InstanceUtils.getReferent(inst);
68b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler    if (referent != null) {
69b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler      formatted.append(" for ");
70b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler
71b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler      // It should not be possible for a referent to refer back to the
72b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler      // reference object, even indirectly, so there shouldn't be any issues
73b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler      // with infinite recursion here.
7438f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler      formatted.append(renderInstance(snapshot, referent));
75b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    }
76b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler
77b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    // Annotate DexCache with its location.
7877ff54b5055ec55806069c8d026b102df29857b5Richard Uhler    String dexCacheLocation = InstanceUtils.getDexCacheLocation(inst, kMaxChars);
79b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    if (dexCacheLocation != null) {
80b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler      formatted.appendFormat(" for %s", dexCacheLocation);
8177ff54b5055ec55806069c8d026b102df29857b5Richard Uhler      if (kMaxChars == dexCacheLocation.length()) {
82b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler        formatted.append("...");
8377ff54b5055ec55806069c8d026b102df29857b5Richard Uhler      }
84b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    }
85b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler
86b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler
87b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    // Annotate bitmaps with a thumbnail.
88b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    Instance bitmap = InstanceUtils.getAssociatedBitmapInstance(inst);
89b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    String thumbnail = "";
90b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    if (bitmap != null) {
91c21e4e67861f38e2ebce3cce633d01fcb8de5f1fRichard Uhler      URI uri = DocString.formattedUri("bitmap?id=%d", bitmap.getId());
92b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler      formatted.appendThumbnail(uri, "bitmap image");
93b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    }
94b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    return formatted;
95b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler  }
96b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler
97b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler  /**
98b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler   * Create a DocString summarizing the given value.
99b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler   */
10038f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler  public static DocString render(AhatSnapshot snapshot, Object val) {
101b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    if (val instanceof Instance) {
10238f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler      return renderInstance(snapshot, (Instance)val);
103b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    } else {
104c21e4e67861f38e2ebce3cce633d01fcb8de5f1fRichard Uhler      return DocString.format("%s", val);
105b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler    }
106b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler  }
107b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler}
108