Home | History | Annotate | Download | only in preload
      1 /*
      2  * Copyright (C) 2008 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 import java.util.List;
     18 import java.util.ArrayList;
     19 import java.util.LinkedList;
     20 import java.util.Map;
     21 import java.util.HashMap;
     22 import java.io.Serializable;
     23 
     24 /**
     25  * A Dalvik process.
     26  */
     27 class Proc implements Serializable {
     28 
     29     private static final long serialVersionUID = 0;
     30 
     31     /** Parent process. */
     32     final Proc parent;
     33 
     34     /** Process ID. */
     35     final int id;
     36 
     37     /**
     38      * Name of this process. We may not have the correct name at first, i.e.
     39      * some classes could have been loaded before the process name was set.
     40      */
     41     String name;
     42 
     43     /** Child processes. */
     44     final List<Proc> children = new ArrayList<Proc>();
     45 
     46     /** Maps thread ID to operation stack. */
     47     transient final Map<Integer, LinkedList<Operation>> stacks
     48             = new HashMap<Integer, LinkedList<Operation>>();
     49 
     50     /** Number of operations. */
     51     int operationCount;
     52 
     53     /** Sequential list of operations that happened in this process. */
     54     final List<Operation> operations = new ArrayList<Operation>();
     55 
     56     /** List of past process names. */
     57     final List<String> nameHistory = new ArrayList<String>();
     58 
     59     /** Constructs a new process. */
     60     Proc(Proc parent, int id) {
     61         this.parent = parent;
     62         this.id = id;
     63     }
     64 
     65     /** Sets name of this process. */
     66     void setName(String name) {
     67         if (!name.equals(this.name)) {
     68             if (this.name != null) {
     69                 nameHistory.add(this.name);
     70             }
     71             this.name = name;
     72         }
     73     }
     74 
     75     /**
     76      * Returns true if this process comes from the zygote.
     77      */
     78     public boolean fromZygote() {
     79         return parent != null && parent.name.equals("zygote")
     80                 && !name.equals("com.android.development");
     81     }
     82 
     83     /**
     84      * Starts an operation.
     85      *
     86      * @param threadId thread the operation started in
     87      * @param loadedClass class operation happened to
     88      * @param time the operation started
     89      */
     90     void startOperation(int threadId, LoadedClass loadedClass, long time,
     91             Operation.Type type) {
     92         Operation o = new Operation(
     93                 this, loadedClass, time, operationCount++, type);
     94         operations.add(o);
     95 
     96         LinkedList<Operation> stack = stacks.get(threadId);
     97         if (stack == null) {
     98             stack = new LinkedList<Operation>();
     99             stacks.put(threadId, stack);
    100         }
    101 
    102         if (!stack.isEmpty()) {
    103             stack.getLast().subops.add(o);
    104         }
    105 
    106         stack.add(o);
    107     }
    108 
    109     /**
    110      * Ends an operation.
    111      *
    112      * @param threadId thread the operation ended in
    113      * @param loadedClass class operation happened to
    114      * @param time the operation ended
    115      */
    116     Operation endOperation(int threadId, String className,
    117             LoadedClass loadedClass, long time) {
    118         LinkedList<Operation> stack = stacks.get(threadId);
    119 
    120         if (stack == null || stack.isEmpty()) {
    121             didNotStart(className);
    122             return null;
    123         }
    124 
    125         Operation o = stack.getLast();
    126         if (loadedClass != o.loadedClass) {
    127             didNotStart(className);
    128             return null;
    129         }
    130 
    131         stack.removeLast();
    132 
    133         o.endTimeNanos = time;
    134         return o;
    135     }
    136 
    137     /**
    138      * Prints an error indicating that we saw the end of an operation but not
    139      * the start. A bug in the logging framework which results in dropped logs
    140      * causes this.
    141      */
    142     private static void didNotStart(String name) {
    143         System.err.println("Warning: An operation ended on " + name
    144             + " but it never started!");
    145     }
    146 
    147     /**
    148      * Prints this process tree to stdout.
    149      */
    150     void print() {
    151         print("");
    152     }
    153 
    154     /**
    155      * Prints a child proc to standard out.
    156      */
    157     private void print(String prefix) {
    158         System.out.println(prefix + "id=" + id + ", name=" + name);
    159         for (Proc child : children) {
    160             child.print(prefix + "    ");
    161         }
    162     }
    163 
    164     @Override
    165     public String toString() {
    166         return this.name;
    167     }
    168 }
    169