/** * DiskUsage - displays sdcard usage on android. * Copyright (C) 2008-2011 Ivan Volosyuk * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package com.google.android.diskusage.entity; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import android.content.pm.ApplicationInfo; import android.util.Log; import com.google.android.diskusage.AppFilter; import com.google.android.diskusage.AppFilter.App2SD; import com.google.android.diskusage.datasource.AppStats; public class FileSystemPackage extends FileSystemEntry { public final String pkg; final long codeSize; final long dataSize; final long cacheSize; final long dalvikCacheSize; final int flags; // ApplicationInfo.FLAG_EXTERNAL_STORAGE private static final int SDCARD_FLAG = 0x40000; private File cacheFile(String pattern, Object... args) { return new File("/data/dalvik-cache/" + String.format(pattern, args)); } private File getDalvikCacheForSystemApp() { File cache = cacheFile("system@app@%s.apk@classes.dex", name); if (cache.exists()) return cache; return null; } private File getDalvikCacheForNumberedPackage(String pattern) { for (int i = 0; i < 10; i++) { File cache = cacheFile(pattern, pkg, i); if (cache.exists()) return cache; } return null; } private File getDalvikCacheForPkg(String pattern) { File cache = cacheFile(pattern, pkg); if (cache.exists()) return cache; return null; } private long guessDalvikCacheSize() { File cache = null; if (onSD()) { cache = getDalvikCacheForNumberedPackage( "mnt@asec@%s-%d@pkg.apk@classes.dex"); } else { // cache = getDalvikCacheForPkg("data@app@%s.apk@classes.dex"); // if (cache == null) // cache = getDalvikCacheForPkg("data@app-private@%s.apk@classes.dex"); // if (cache == null) // cache = getDalvikCacheForSystemApp(); // if (cache == null) // cache = getDalvikCacheForNumberedPackage( // "data@app@%s-%d.apk@classes.dex"); // if (cache == null) // cache = getDalvikCacheForNumberedPackage( // "data@app-private@%s-%d.apk@classes.dex"); } if (cache != null) { Log.d("diskusage", cache.getAbsolutePath() + ": " + cache.length()); return cache.length(); } else { // Log.d("diskusage", "can't guess dalvikCache for " + pkg); return 0; } } public FileSystemPackage( String name, String pkg, AppStats stats, int flags, Long hackApkSize, int blockSize) { super(null, name); this.pkg = pkg; long codeSize; this.cacheSize = stats.getCacheSize(); this.dataSize = stats.getDataSize(); this.flags = flags | (hackApkSize != null ? SDCARD_FLAG : 0); this.dalvikCacheSize = guessDalvikCacheSize(); if (onSD()) { if (hackApkSize != null) { codeSize = hackApkSize.intValue(); } else { codeSize = stats.getCodeSize(); } } else { codeSize = stats.getCodeSize() - this.dalvikCacheSize; } if ((flags & ApplicationInfo.FLAG_SYSTEM) != 0 && (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0) { codeSize = 0; } this.codeSize = codeSize; } public boolean onSD() { return (flags & SDCARD_FLAG) != 0; } private boolean select(App2SD selector, boolean isOnSD) { return selector == App2SD.BOTH || (isOnSD == (selector == App2SD.APPS2SD)); } public void applyFilter(AppFilter filter, int blockSize) { clearDrawingCache(); long blocks = 0; ArrayList<FileSystemEntry> entries = new ArrayList<FileSystemEntry>(); if (select(filter.apps, onSD())) { if (filter.showApk && select(filter.memory, onSD())) { entries.add(FileSystemEntry.makeNode(null, "apk") .initSizeInBytes(codeSize, blockSize)); } if (filter.showData && select(filter.memory, false)) { entries.add(FileSystemEntry.makeNode(null, "data") .initSizeInBytes(dataSize, blockSize)); } if (filter.showDalvikCache && select(filter.memory, false)) { entries.add(FileSystemEntry.makeNode(null, "dalvikCache") .initSizeInBytes(dalvikCacheSize, blockSize)); } if (filter.showCache && select(filter.memory, false)) { entries.add(FileSystemEntry.makeNode(null, "Cache") .initSizeInBytes(cacheSize, blockSize)); } } for (FileSystemEntry e : entries) { blocks += e.getSizeInBlocks(); } setSizeInBlocks(blocks, blockSize); if (filter.enableChildren) { for (FileSystemEntry e : entries) { e.parent = this; } children = entries.toArray(new FileSystemEntry[] {}); Arrays.sort(children, FileSystemEntry.COMPARE); } else { children = null; } } private FileSystemPackage( String name, String pkg, long codeSize, long dataSize, long cacheSize, long dalvikCacheSize, int flags) { super(null, name); this.pkg = pkg; this.codeSize = codeSize; this.dataSize = dataSize; this.cacheSize = cacheSize; this.dalvikCacheSize = dalvikCacheSize; this.flags = flags; } @Override public FileSystemEntry create() { return new FileSystemPackage(this.name, this.pkg, this.codeSize, this.dataSize, this.cacheSize, this.dalvikCacheSize, this.flags); } }