19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.Serializable;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.BufferedReader;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.InputStreamReader;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.InputStream;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.OutputStream;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Arrays;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Memory usage information.
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass MemoryUsage implements Serializable {
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final long serialVersionUID = 0;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final MemoryUsage NOT_AVAILABLE = new MemoryUsage();
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static int errorCount = 0;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee    // These values are in 1kB increments (not 4kB like you'd expect).
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final int nativeSharedPages;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final int javaSharedPages;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final int otherSharedPages;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final int nativePrivatePages;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final int javaPrivatePages;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final int otherPrivatePages;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final int allocCount;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final int allocSize;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final int freedCount;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final int freedSize;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final long nativeHeapSize;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MemoryUsage(String line) {
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String[] parsed = line.split(",");
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nativeSharedPages = Integer.parseInt(parsed[1]);
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        javaSharedPages = Integer.parseInt(parsed[2]);
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        otherSharedPages = Integer.parseInt(parsed[3]);
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nativePrivatePages = Integer.parseInt(parsed[4]);
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        javaPrivatePages = Integer.parseInt(parsed[5]);
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        otherPrivatePages = Integer.parseInt(parsed[6]);
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        allocCount = Integer.parseInt(parsed[7]);
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        allocSize = Integer.parseInt(parsed[8]);
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        freedCount = Integer.parseInt(parsed[9]);
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        freedSize = Integer.parseInt(parsed[10]);
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nativeHeapSize = Long.parseLong(parsed[11]);
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    MemoryUsage() {
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nativeSharedPages = -1;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        javaSharedPages = -1;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        otherSharedPages = -1;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nativePrivatePages = -1;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        javaPrivatePages = -1;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        otherPrivatePages = -1;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        allocCount = -1;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        allocSize = -1;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        freedCount = -1;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        freedSize = -1;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nativeHeapSize = -1;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    MemoryUsage(int nativeSharedPages,
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int javaSharedPages,
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int otherSharedPages,
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int nativePrivatePages,
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int javaPrivatePages,
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int otherPrivatePages,
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int allocCount,
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int allocSize,
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int freedCount,
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int freedSize,
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long nativeHeapSize) {
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this.nativeSharedPages = nativeSharedPages;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this.javaSharedPages = javaSharedPages;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this.otherSharedPages = otherSharedPages;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this.nativePrivatePages = nativePrivatePages;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this.javaPrivatePages = javaPrivatePages;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this.otherPrivatePages = otherPrivatePages;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this.allocCount = allocCount;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this.allocSize = allocSize;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this.freedCount = freedCount;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this.freedSize = freedSize;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this.nativeHeapSize = nativeHeapSize;
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    MemoryUsage subtract(MemoryUsage baseline) {
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new MemoryUsage(
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                nativeSharedPages - baseline.nativeSharedPages,
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                javaSharedPages - baseline.javaSharedPages,
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                otherSharedPages - baseline.otherSharedPages,
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                nativePrivatePages - baseline.nativePrivatePages,
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                javaPrivatePages - baseline.javaPrivatePages,
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                otherPrivatePages - baseline.otherPrivatePages,
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                allocCount - baseline.allocCount,
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                allocSize - baseline.allocSize,
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                freedCount - baseline.freedCount,
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                freedSize - baseline.freedSize,
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                nativeHeapSize - baseline.nativeHeapSize);
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int javaHeapSize() {
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return allocSize - freedSize;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1269d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee    int totalHeap() {
1279d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee        return javaHeapSize() + (int) nativeHeapSize;
1289d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee    }
1299d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int javaPagesInK() {
1319d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee        return javaSharedPages + javaPrivatePages;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int nativePagesInK() {
1359d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee        return nativeSharedPages + nativePrivatePages;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int otherPagesInK() {
1389d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee        return otherSharedPages + otherPrivatePages;
1399d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee    }
1409d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee
1419d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee    int totalPages() {
1429d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee        return javaSharedPages + javaPrivatePages + nativeSharedPages +
1439d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee                nativePrivatePages + otherSharedPages + otherPrivatePages;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Was this information available?
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean isAvailable() {
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return nativeSharedPages != -1;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Measures baseline memory usage.
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static MemoryUsage baseline() {
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return forClass(null);
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String CLASS_PATH = "-Xbootclasspath"
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            + ":/system/framework/core.jar"
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            + ":/system/framework/ext.jar"
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            + ":/system/framework/framework.jar"
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            + ":/system/framework/framework-tests.jar"
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            + ":/system/framework/services.jar"
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            + ":/system/framework/loadclass.jar";
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String[] GET_DIRTY_PAGES = {
169e9fcaa0697dcb257d0288118347f721ce8806b55Jesse Wilson        "adb", "shell", "dalvikvm", CLASS_PATH, "LoadClass" };
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Measures memory usage for the given class.
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static MemoryUsage forClass(String className) {
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MeasureWithTimeout measurer = new MeasureWithTimeout(className);
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new Thread(measurer).start();
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (measurer) {
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (measurer.memoryUsage == null) {
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Wait up to 10s.
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    measurer.wait(30000);
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (InterruptedException e) {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.err.println("Interrupted waiting for measurement.");
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    e.printStackTrace();
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return NOT_AVAILABLE;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If it's still null.
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (measurer.memoryUsage == null) {
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.err.println("Timed out while measuring "
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + className + ".");
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return NOT_AVAILABLE;
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            System.err.println("Got memory usage for " + className + ".");
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return measurer.memoryUsage;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static class MeasureWithTimeout implements Runnable {
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String className;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MemoryUsage memoryUsage = null;
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MeasureWithTimeout(String className) {
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            this.className = className;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MemoryUsage measured = measure();
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                memoryUsage = measured;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notifyAll();
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private MemoryUsage measure() {
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String[] commands = GET_DIRTY_PAGES;
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (className != null) {
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                List<String> commandList = new ArrayList<String>(
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        GET_DIRTY_PAGES.length + 1);
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                commandList.addAll(Arrays.asList(commands));
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                commandList.add(className);
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                commands = commandList.toArray(new String[commandList.size()]);
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final Process process = Runtime.getRuntime().exec(commands);
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final InputStream err = process.getErrorStream();
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Send error output to stderr.
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Thread errThread = new Thread() {
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    @Override
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    public void run() {
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        copy(err, System.err);
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                };
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                errThread.setDaemon(true);
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                errThread.start();
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                BufferedReader in = new BufferedReader(
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        new InputStreamReader(process.getInputStream()));
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String line = in.readLine();
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (line == null || !line.startsWith("DECAFBAD,")) {
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.err.println("Got bad response for " + className
251e9fcaa0697dcb257d0288118347f721ce8806b55Jesse Wilson                            + ": " + line + "; command was " + Arrays.toString(commands));
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    errorCount += 1;
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return NOT_AVAILABLE;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                in.close();
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                err.close();
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                process.destroy();
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return new MemoryUsage(line);
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IOException e) {
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                System.err.println("Error getting stats for "
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + className + ".");
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                e.printStackTrace();
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return NOT_AVAILABLE;
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Copies from one stream to another.
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void copy(InputStream in, OutputStream out) {
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        byte[] buffer = new byte[1024];
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int read;
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while ((read = in.read(buffer)) > -1) {
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                out.write(buffer, 0, read);
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            e.printStackTrace();
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2859d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee
2869d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee    /** Measures memory usage information and stores it in the model. */
2879d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee    public static void main(String[] args) throws IOException,
2889d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee            ClassNotFoundException {
2899d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee        Root root = Root.fromFile(args[0]);
2909d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee        root.baseline = baseline();
2919d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee        for (LoadedClass loadedClass : root.loadedClasses.values()) {
2929d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee            if (loadedClass.systemClass) {
2939d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee                loadedClass.measureMemoryUsage();
2949d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee            }
2959d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee        }
2969d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee        root.toFile(args[0]);
2979d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee    }
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
299