/** * 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; import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.widget.TextView; import android.widget.Toast; import com.google.android.diskusage.datasource.DataSource; import com.google.android.diskusage.datasource.DebugDataSourceBridge; import com.google.android.diskusage.datasource.fast.DefaultDataSource; import com.google.android.diskusage.entity.FileSystemEntry; public class SelectActivity extends Activity { private AlertDialog dialog; Map<String,Bundle> bundles = new TreeMap<String,Bundle>(); ArrayList<Runnable> actionList = new ArrayList<Runnable>(); private boolean expandRootMountPoints; // private static boolean debugUnhidden = true; private static boolean debugLoadedDump = false; private DataSource debugDataSource; private static DebugDataSourceBridge debugDataSourceBridge; static { try { Class<?> clazz = Class.forName( "com.google.android.diskusage.datasource.debug.DebugDataSourceBridgeImpl"); debugDataSourceBridge = (DebugDataSourceBridge) clazz.newInstance(); } catch (Throwable t) { Log.d("diskusage", "Debug is disabled"); } } private abstract class AbstractUsageAction implements Runnable { public void runAction(String key, String title, String rootKey, Class<?> viewer) { Intent i = new Intent(SelectActivity.this, viewer); i.putExtra(DiskUsage.TITLE_KEY, title); i.putExtra(DiskUsage.ROOT_KEY, rootKey); i.putExtra(DiskUsage.KEY_KEY, key); Bundle bundle = bundles.get(key); if (bundle != null) { i.putExtra(DiskUsage.STATE_KEY, bundle); } startActivityForResult(i, 0); } }; private class DiskUsageAction extends AbstractUsageAction { private final String title; private final MountPoint mountPoint; DiskUsageAction(String title, MountPoint mountPoint) { this.title = title; this.mountPoint = mountPoint; } public void run() { runAction(getKeyForStorage(mountPoint), title, mountPoint.root, DiskUsage.class); } }; private class AppUsageAction extends AbstractUsageAction { private final String title; public AppUsageAction(String title) { this.title = title; } public void run() { runAction(getKeyForApp(), title, "apps", AppUsage.class); } }; public String getKeyForApp() { return "app"; } public static String getKeyForStorage(MountPoint mountPoint) { return (mountPoint.rootRequired ? "rooted" : "storage:") + mountPoint.root; } private class ShowHideAction implements Runnable { public void run() { Intent i = new Intent(SelectActivity.this, ShowHideMountPointsActivity.class); startActivity(i); } } private class EnableDebugAction implements Runnable { public void run() { try { debugLoadedDump = false; debugDataSource = debugDataSourceBridge.initNewDump(SelectActivity.this); DataSource.override(debugDataSource); dialog.hide(); MountPoint.reset(); makeDialog(); } catch (IOException e) { Log.d("diskusage", "Failed to enable debug", e); Toast.makeText( SelectActivity.this, "Failed to enable debug " + e.getMessage(), Toast.LENGTH_LONG).show(); } } } private class DisableDebug implements Runnable { @Override public void run() { DataSource.override(new DefaultDataSource()); debugDataSource = null; // debugUnhidden = false; dialog.hide(); MountPoint.reset(); makeDialog(); } } private class LoadDumpAction implements Runnable { public void run() { try { debugDataSource = debugDataSourceBridge.loadDefaultDump(); debugLoadedDump = true; DataSource.override(debugDataSource); dialog.hide(); MountPoint.reset(); makeDialog(); } catch (IOException e) { Log.d("diskusage", "Failed to enable debug", e); Toast.makeText( SelectActivity.this, "Failed to enable debug " + e.getMessage(), Toast.LENGTH_LONG).show(); } } } private class SendBugReportAction implements Runnable { @Override public void run() { try { debugDataSourceBridge.saveDumpAndSendReport( debugDataSource, SelectActivity.this); } catch (IOException e) { Log.d("diskusage", "Failed to send bugreport", e); Toast.makeText( SelectActivity.this, "Failed to send bugreport: " + e.getMessage(), Toast.LENGTH_LONG).show(); } } } public Handler handler = new Handler(); public Runnable checkForMountsUpdates = new Runnable() { @Override public void run() { boolean reload = false; try { // BufferedReader reader = new BufferedReader(new InputStreamReader(getResources().openRawResource(R.raw.mounts_honeycomb), "UTF-8")); BufferedReader reader = DataSource.get().getProcReader(); String line; int checksum = 0; while ((line = reader.readLine()) != null) { checksum += line.length(); } reader.close(); if (checksum != MountPoint.checksum) { reload = true; } } catch (Throwable t) {} if (reload) { dialog.hide(); MountPoint.reset(); makeDialog(); } handler.postDelayed(this, 2000); } }; public void makeDialog() { ArrayList<String> options = new ArrayList<String>(); actionList.clear(); final String programStorage = getString(R.string.app_storage); if(MountPoint.getHoneycombSdcard(this) == null){ options.add(programStorage); actionList.add(new AppUsageAction(programStorage)); } for (MountPoint mountPoint : MountPoint.getMountPoints(this).values()) { options.add(mountPoint.title); actionList.add(new DiskUsageAction(mountPoint.title, mountPoint)); } if (/*debugUnhidden && */debugDataSourceBridge != null) { if (debugDataSource != null && !debugLoadedDump) { options.add("* Send bug report"); actionList.add(new SendBugReportAction()); } if (debugDataSource == null) { options.add("* Enable debug dump"); actionList.add(new EnableDebugAction()); if (debugDataSourceBridge.dumpExist()) { options.add("* Load dump"); actionList.add(new LoadDumpAction()); } } options.add("* Disable debug"); actionList.add(new DisableDebug()); } if (DataSource.get().isDeviceRooted()) { SharedPreferences prefs = getSharedPreferences("ignore_list", Context.MODE_PRIVATE); Map<String, ?> ignoreList = prefs.getAll(); if (!ignoreList.keySet().isEmpty()) { Set<String> ignores = ignoreList.keySet(); for (MountPoint mountPoint : MountPoint.getRootedMountPoints(this).values()) { if (ignores.contains(mountPoint.root)) continue; options.add(mountPoint.root); actionList.add(new DiskUsageAction(mountPoint.root, mountPoint)); } options.add("[Show/hide]"); actionList.add(new ShowHideAction()); } else if (expandRootMountPoints) { for (MountPoint mountPoint : MountPoint.getRootedMountPoints(this).values()) { options.add(mountPoint.root); actionList.add(new DiskUsageAction(mountPoint.root, mountPoint)); } options.add("[Show/hide]"); actionList.add(new ShowHideAction()); } else { options.add("[Root required]"); actionList.add(new Runnable() { @Override public void run() { expandRootMountPoints = true; makeDialog(); } }); } } final String[] optionsArray = options.toArray(new String[options.size()]); dialog = new AlertDialog.Builder(this) .setItems(optionsArray, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { actionList.get(which).run(); } }) .setTitle("View") .setOnCancelListener(new OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { finish(); } }).create(); /*try { if (debugDataSourceBridge != null) { dialog.getListView().setOnItemLongClickListener( new OnItemLongClickListener() { @Override public boolean onItemLongClick( AdapterView<?> arg0, View arg1, int arg2, long arg3) { debugUnhidden = true; dialog.hide(); makeDialog(); return true; } }); } } catch (Throwable t) { // api 3 }*/ dialog.show(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); FileSystemEntry.setupStrings(this); setContentView(new TextView(this)); // ActionBar bar = getActionBar(); // bar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_USE_LOGO); } @Override protected void onResume() { super.onResume(); // ActionBar actionBar = getActionBar(); // actionBar.setDisplayHomeAsUpEnabled(true); makeDialog(); handler.post(checkForMountsUpdates); } @Override protected void onPause() { if (dialog.isShowing()) dialog.dismiss(); handler.removeCallbacks(checkForMountsUpdates); super.onPause(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (data == null) return; Bundle state = data.getBundleExtra(DiskUsage.STATE_KEY); String key = data.getStringExtra(DiskUsage.KEY_KEY); bundles.put(key, state); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); for (Entry<String, Bundle> entry : bundles.entrySet()) { outState.putBundle(entry.getKey(), entry.getValue()); } String[] keys = bundles.keySet().toArray(new String[0]); outState.putStringArray(BUNDLE_KEYS, keys); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); for (String key : savedInstanceState.getStringArray(BUNDLE_KEYS)) { bundles.put(key, savedInstanceState.getBundle(key)); } } private static final String BUNDLE_KEYS = "keys"; }