summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2010-12-02 17:59:04 -0800
committerKenny Root <kroot@google.com>2010-12-06 09:34:12 -0800
commit511c8cf103193fb41c915941b1b1d2a442a1ae12 (patch)
treeeb1aa1af5ae7f32b6a86c3f65e4aeb99b306f45e
parent71ac31906a5f933b82b58c706833b04a2c8ac13e (diff)
downloadpackages_apps_settings-511c8cf103193fb41c915941b1b1d2a442a1ae12.zip
packages_apps_settings-511c8cf103193fb41c915941b1b1d2a442a1ae12.tar.gz
packages_apps_settings-511c8cf103193fb41c915941b1b1d2a442a1ae12.tar.bz2
Add usage bar chart to storage preferences
Change-Id: Ic3c118ac9194e226e6384e01c9ea7e150b1d9521
-rw-r--r--res/layout/preference_memoryusage.xml26
-rw-r--r--res/values/colors.xml5
-rw-r--r--res/values/strings.xml6
-rw-r--r--res/xml/device_info_memory.xml17
-rw-r--r--src/com/android/settings/deviceinfo/Memory.java412
-rw-r--r--src/com/android/settings/deviceinfo/PercentageBarChart.java109
-rw-r--r--src/com/android/settings/deviceinfo/UsageBarPreference.java74
7 files changed, 571 insertions, 78 deletions
diff --git a/res/layout/preference_memoryusage.xml b/res/layout/preference_memoryusage.xml
new file mode 100644
index 0000000..7972de9
--- /dev/null
+++ b/res/layout/preference_memoryusage.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<com.android.settings.deviceinfo.PercentageBarChart
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:gravity="center_vertical"
+ android:id="@+id/percentage_bar_chart"
+ android:paddingRight="?android:attr/scrollbarSize"
+ android:textAppearance="?android:attr/textAppearanceMedium">
+</com.android.settings.deviceinfo.PercentageBarChart> \ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 193388c..8a2b68c 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -17,5 +17,10 @@
<resources>
<color name="black">#000</color>
<color name="red">#F00</color>
+
+ <color name="memory_avail">#333</color>
+ <color name="memory_media_usage">#F33</color>
+ <color name="memory_apps_usage">#3F3</color>
+ <color name="memory_used">#FFF</color>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7c09c71..4c62fe4 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1456,6 +1456,12 @@
<string name="memory_available">Available space</string>
<!-- SD card & phone storage settings screen heading. The total amount of storage space for some storage partition. For example, this is listed under both the "Internal phone storage" section and the "SD card" section -->
<string name="memory_size">Total space</string>
+ <!-- SD card & phone storage settings summary. Displayed when the total memory usage is being calculated. Will be replaced with a number like "12.3 GB" when finished calucating. -->
+ <string name="memory_calculating_size">Calculating…</string>
+ <!-- SD card & phone storage settings title. Displayed as a title when showing the total usage of applications installed. Below it will be a number like "123.4 MB" indicating used storage. [CHAR LIMIT=30] -->
+ <string name="memory_apps_usage">Application usage</string>
+ <!-- SD card & phone storage settings title. Displayed as a title when showing the total usage of media on the device. Below it will be a number like "123.4 MB" indicating used storage. [CHAR LIMIT=30] -->
+ <string name="memory_media_usage">Media usage</string>
<!-- SD card & phone storage settings item title that will result in the phone unmounting the SD card. This will be done before the user phyiscally removes the SD card from the phone. Kind of like the "Safely remove" on some operating systems. [CHAR LIMIT=25] -->
<string name="sd_eject" product="nosdcard">Unmount shared storage</string>
<!-- SD card & phone storage settings item title that will result in the phone unmounting the SD card. This will be done before the user phyiscally removes the SD card from the phone. Kind of like the "Safely remove" on some operating systems. -->
diff --git a/res/xml/device_info_memory.xml b/res/xml/device_info_memory.xml
index 56fe087..0c05213 100644
--- a/res/xml/device_info_memory.xml
+++ b/res/xml/device_info_memory.xml
@@ -36,8 +36,21 @@
</PreferenceCategory>
<PreferenceCategory android:title="@string/internal_memory">
- <Preference android:key="memory_internal_avail"
- style="?android:attr/preferenceInformationStyle"
+ <com.android.settings.deviceinfo.UsageBarPreference
+ android:key="memory_internal_chart" />
+ <Preference android:key="memory_internal_size"
+ android:title="@string/memory_size"
+ android:summary="00"/>
+ <Preference android:key="memory_internal_media"
+ android:icon="@color/memory_media_usage"
+ android:title="@string/memory_media_usage"
+ android:summary="@string/memory_calculating_size"/>
+ <Preference android:key="memory_internal_apps"
+ android:icon="@color/memory_apps_usage"
+ android:title="@string/memory_apps_usage"
+ android:summary="@string/memory_calculating_size"/>
+ <Preference android:key="memory_internal_avail"
+ android:icon="@color/memory_avail"
android:title="@string/memory_available"
android:summary="00"/>
<CheckBoxPreference android:key="ptp_mode_toggle"
diff --git a/src/com/android/settings/deviceinfo/Memory.java b/src/com/android/settings/deviceinfo/Memory.java
index 581121d..54c2a73 100644
--- a/src/com/android/settings/deviceinfo/Memory.java
+++ b/src/com/android/settings/deviceinfo/Memory.java
@@ -16,24 +16,35 @@
package com.android.settings.deviceinfo;
+import com.android.internal.app.IMediaContainerService;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
+import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.ServiceConnection;
import android.content.DialogInterface.OnCancelListener;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageStatsObserver;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageStats;
import android.content.res.Resources;
-import android.os.Bundle;
import android.hardware.Usb;
+import android.os.Bundle;
import android.os.Environment;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StatFs;
@@ -42,7 +53,6 @@ import android.os.storage.StorageEventListener;
import android.os.storage.StorageManager;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.provider.Settings;
@@ -51,6 +61,7 @@ import android.util.Log;
import android.widget.Toast;
import java.io.File;
+import java.util.ArrayList;
import java.util.List;
public class Memory extends SettingsPreferenceFragment implements OnCancelListener {
@@ -69,17 +80,47 @@ public class Memory extends SettingsPreferenceFragment implements OnCancelListen
private static final String PTP_MODE_TOGGLE = "ptp_mode_toggle";
+ private static final String MEMORY_INTERNAL_SIZE = "memory_internal_size";
+
+ private static final String MEMORY_INTERNAL_AVAIL = "memory_internal_avail";
+
+ private static final String MEMORY_INTERNAL_APPS = "memory_internal_apps";
+
+ private static final String MEMORY_INTERNAL_MEDIA = "memory_internal_media";
+
+ private static final String MEMORY_INTERNAL_CHART = "memory_internal_chart";
+
private static final int DLG_CONFIRM_UNMOUNT = 1;
private static final int DLG_ERROR_UNMOUNT = 2;
private Resources mRes;
+ // External storage preferences
private Preference mSdSize;
private Preference mSdAvail;
private Preference mSdMountToggle;
private Preference mSdFormat;
private PreferenceGroup mSdMountPreferenceGroup;
+ // Internal storage preferences
+ private Preference mInternalSize;
+ private Preference mInternalAvail;
+ private Preference mInternalMediaUsage;
+ private Preference mInternalAppsUsage;
+ private UsageBarPreference mInternalUsageChart;
+
+ // Internal storage chart colors
+ private int mInternalMediaColor;
+ private int mInternalAppsColor;
+ private int mInternalUsedColor;
+
+ // Internal memory fields
+ private long mInternalTotalSize;
+ private long mInternalUsedSize;
+ private long mInternalMediaSize;
+ private long mInternalAppsSize;
+ private boolean mMeasured = false;
+
boolean mSdMountToggleAdded = true;
private CheckBoxPreference mPtpModeToggle;
@@ -89,6 +130,243 @@ public class Memory extends SettingsPreferenceFragment implements OnCancelListen
private StorageManager mStorageManager = null;
+ // Updates the memory usage bar graph.
+ private static final int MSG_UI_UPDATE_APPROXIMATE = 1;
+
+ // Updates the memory usage bar graph.
+ private static final int MSG_UI_UPDATE_EXACT = 2;
+
+ private Handler mUpdateHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UI_UPDATE_APPROXIMATE:
+ updateUiApproximate();
+ break;
+ case MSG_UI_UPDATE_EXACT:
+ updateUiExact();
+ mMeasured = true;
+ break;
+ }
+ }
+ };
+
+ private static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
+
+ private static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
+ DEFAULT_CONTAINER_PACKAGE, "com.android.defcontainer.DefaultContainerService");
+
+ class MemoryMeasurementHandler extends Handler {
+ public static final int MSG_MEASURE_ALL = 1;
+
+ public static final int MSG_CONNECTED = 2;
+
+ public static final int MSG_DISCONNECTED = 3;
+
+ private List<String> mPendingApps = new ArrayList<String>();
+
+ private volatile boolean mBound = false;
+
+ private long mAppsSize = 0;
+
+ final private ServiceConnection mDefContainerConn = new ServiceConnection() {
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mBound = true;
+ IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(service);
+ mMeasurementHandler.sendMessage(mMeasurementHandler.obtainMessage(
+ MemoryMeasurementHandler.MSG_CONNECTED, imcs));
+ }
+
+ public void onServiceDisconnected(ComponentName name) {
+ mBound = false;
+ }
+ };
+
+ MemoryMeasurementHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_MEASURE_ALL: {
+ updateExternalStorage();
+ updateApproximateInternalStorage();
+
+ Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
+ getActivity().bindService(service, mDefContainerConn, Context.BIND_AUTO_CREATE);
+
+ mUpdateHandler.sendEmptyMessage(MSG_UI_UPDATE_APPROXIMATE);
+ break;
+ }
+ case MSG_CONNECTED: {
+ IMediaContainerService imcs = (IMediaContainerService) msg.obj;
+ updateExactInternalStorage(imcs);
+ }
+ }
+ }
+
+ public void cleanUp() {
+ if (mBound) {
+ getActivity().unbindService(mDefContainerConn);
+ }
+ }
+
+ public void queuePackageMeasurementLocked(String packageName) {
+ mPendingApps.add(packageName);
+ }
+
+ public void requestQueuedMeasurementsLocked() {
+ final Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
+
+ final PackageManager pm = activity.getPackageManager();
+ if (pm == null) {
+ return;
+ }
+
+ final int N = mPendingApps.size();
+ for (int i = 0; i < N; i++) {
+ pm.getPackageSizeInfo(mPendingApps.get(i), mStatsObserver);
+ }
+ }
+
+ final IPackageStatsObserver.Stub mStatsObserver = new IPackageStatsObserver.Stub() {
+ public void onGetStatsCompleted(PackageStats stats, boolean succeeded) {
+ if (succeeded) {
+ mAppsSize += stats.codeSize + stats.dataSize;
+ }
+
+ synchronized (mPendingApps) {
+ mPendingApps.remove(stats.packageName);
+
+ if (mPendingApps.size() == 0) {
+ mInternalAppsSize = mAppsSize;
+
+ mUpdateHandler.sendEmptyMessage(MSG_UI_UPDATE_EXACT);
+ }
+ }
+ }
+ };
+
+ private void updateApproximateInternalStorage() {
+ final File dataPath = Environment.getDataDirectory();
+ final StatFs stat = new StatFs(dataPath.getPath());
+ final long blockSize = stat.getBlockSize();
+ final long totalBlocks = stat.getBlockCount();
+ final long availableBlocks = stat.getAvailableBlocks();
+
+ final long totalSize = totalBlocks * blockSize;
+ final long availSize = availableBlocks * blockSize;
+ mInternalSize.setSummary(formatSize(totalSize));
+ mInternalAvail.setSummary(formatSize(availSize));
+
+ mInternalTotalSize = totalSize;
+ mInternalUsedSize = totalSize - availSize;
+ }
+
+ private void updateExactInternalStorage(IMediaContainerService imcs) {
+ long mediaSize;
+ try {
+ // TODO get these directories from somewhere
+ mediaSize = imcs.calculateDirectorySize("/data/media");
+ } catch (Exception e) {
+ Log.i(TAG, "Could not read memory from default container service");
+ return;
+ }
+
+ mInternalMediaSize = mediaSize;
+
+ // We have to get installd to measure the package sizes.
+ PackageManager pm = getPackageManager();
+ List<ApplicationInfo> apps = pm
+ .getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES
+ | PackageManager.GET_DISABLED_COMPONENTS);
+ if (apps != null) {
+ synchronized (mPendingApps) {
+ for (int i = 0; i < apps.size(); i++) {
+ final ApplicationInfo info = apps.get(i);
+ queuePackageMeasurementLocked(info.packageName);
+ }
+
+ requestQueuedMeasurementsLocked();
+ }
+ }
+ }
+
+ private void updateExternalStorage() {
+ if (Environment.isExternalStorageEmulated()) {
+ return;
+ }
+
+ String status = Environment.getExternalStorageState();
+ String readOnly = "";
+ if (status.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
+ status = Environment.MEDIA_MOUNTED;
+ readOnly = mRes.getString(R.string.read_only);
+ }
+
+ if (status.equals(Environment.MEDIA_MOUNTED)) {
+ if (!Environment.isExternalStorageRemovable()) {
+ // This device has built-in storage that is not removable.
+ // There is no reason for the user to unmount it.
+ if (mSdMountToggleAdded) {
+ mSdMountPreferenceGroup.removePreference(mSdMountToggle);
+ mSdMountToggleAdded = false;
+ }
+ }
+ try {
+ File path = Environment.getExternalStorageDirectory();
+ StatFs stat = new StatFs(path.getPath());
+ long blockSize = stat.getBlockSize();
+ long totalBlocks = stat.getBlockCount();
+ long availableBlocks = stat.getAvailableBlocks();
+
+ mSdSize.setSummary(formatSize(totalBlocks * blockSize));
+ mSdAvail.setSummary(formatSize(availableBlocks * blockSize) + readOnly);
+
+ mSdMountToggle.setEnabled(true);
+ mSdMountToggle.setTitle(mRes.getString(R.string.sd_eject));
+ mSdMountToggle.setSummary(mRes.getString(R.string.sd_eject_summary));
+
+ } catch (IllegalArgumentException e) {
+ // this can occur if the SD card is removed, but we haven't
+ // received the
+ // ACTION_MEDIA_REMOVED Intent yet.
+ status = Environment.MEDIA_REMOVED;
+ }
+ } else {
+ mSdSize.setSummary(mRes.getString(R.string.sd_unavailable));
+ mSdAvail.setSummary(mRes.getString(R.string.sd_unavailable));
+
+ if (!Environment.isExternalStorageRemovable()) {
+ if (status.equals(Environment.MEDIA_UNMOUNTED)) {
+ if (!mSdMountToggleAdded) {
+ mSdMountPreferenceGroup.addPreference(mSdMountToggle);
+ mSdMountToggleAdded = true;
+ }
+ }
+ }
+
+ if (status.equals(Environment.MEDIA_UNMOUNTED) ||
+ status.equals(Environment.MEDIA_NOFS) ||
+ status.equals(Environment.MEDIA_UNMOUNTABLE) ) {
+ mSdMountToggle.setEnabled(true);
+ mSdMountToggle.setTitle(mRes.getString(R.string.sd_mount));
+ mSdMountToggle.setSummary(mRes.getString(R.string.sd_mount_summary));
+ } else {
+ mSdMountToggle.setEnabled(false);
+ mSdMountToggle.setTitle(mRes.getString(R.string.sd_mount));
+ mSdMountToggle.setSummary(mRes.getString(R.string.sd_insert_summary));
+ }
+ }
+ }
+ }
+
+ private MemoryMeasurementHandler mMeasurementHandler;
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -99,7 +377,7 @@ public class Memory extends SettingsPreferenceFragment implements OnCancelListen
}
addPreferencesFromResource(R.xml.device_info_memory);
-
+
mRes = getResources();
mSdSize = findPreference(MEMORY_SD_SIZE);
mSdAvail = findPreference(MEMORY_SD_AVAIL);
@@ -107,6 +385,12 @@ public class Memory extends SettingsPreferenceFragment implements OnCancelListen
mSdFormat = findPreference(MEMORY_SD_FORMAT);
mSdMountPreferenceGroup = (PreferenceGroup)findPreference(MEMORY_SD_GROUP);
+ if (Environment.isExternalStorageEmulated()) {
+ mSdMountPreferenceGroup.removePreference(mSdSize);
+ mSdMountPreferenceGroup.removePreference(mSdAvail);
+ mSdMountPreferenceGroup.removePreference(mSdMountToggle);
+ }
+
mPtpModeToggle = (CheckBoxPreference)findPreference(PTP_MODE_TOGGLE);
if (Usb.isFunctionSupported(Usb.USB_FUNCTION_MTP)) {
mPtpModeToggle.setChecked(Settings.System.getInt(
@@ -116,35 +400,53 @@ public class Memory extends SettingsPreferenceFragment implements OnCancelListen
// hide the PTP mode toggle checkbox if MTP is not supported
getPreferenceScreen().removePreference(mPtpModeToggle);
}
+
+ mInternalSize = findPreference(MEMORY_INTERNAL_SIZE);
+ mInternalAvail = findPreference(MEMORY_INTERNAL_AVAIL);
+ mInternalMediaUsage = findPreference(MEMORY_INTERNAL_MEDIA);
+ mInternalAppsUsage = findPreference(MEMORY_INTERNAL_APPS);
+
+ mInternalMediaColor = mRes.getColor(R.color.memory_media_usage);
+ mInternalAppsColor = mRes.getColor(R.color.memory_apps_usage);
+ mInternalUsedColor = mRes.getColor(R.color.memory_used);
+
+ mInternalUsageChart = (UsageBarPreference) findPreference(MEMORY_INTERNAL_CHART);
+
+ // Start the thread that will measure the disk usage.
+ final HandlerThread t = new HandlerThread("MeasurementHandler");
+ t.start();
+ mMeasurementHandler = new MemoryMeasurementHandler(t.getLooper());
}
-
+
@Override
public void onResume() {
super.onResume();
-
+
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_STARTED);
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
intentFilter.addDataScheme("file");
getActivity().registerReceiver(mReceiver, intentFilter);
- updateMemoryStatus();
+ if (!mMeasured) {
+ mMeasurementHandler.sendEmptyMessage(MemoryMeasurementHandler.MSG_MEASURE_ALL);
+ }
}
StorageEventListener mStorageListener = new StorageEventListener() {
-
@Override
public void onStorageStateChanged(String path, String oldState, String newState) {
Log.i(TAG, "Received storage state changed notification that " +
path + " changed state from " + oldState +
" to " + newState);
- updateMemoryStatus();
+ mMeasurementHandler.sendEmptyMessage(MemoryMeasurementHandler.MSG_MEASURE_ALL);
}
};
-
+
@Override
public void onPause() {
super.onPause();
getActivity().unregisterReceiver(mReceiver);
+ mMeasurementHandler.removeMessages(MemoryMeasurementHandler.MSG_MEASURE_ALL);
}
@Override
@@ -152,6 +454,7 @@ public class Memory extends SettingsPreferenceFragment implements OnCancelListen
if (mStorageManager != null && mStorageListener != null) {
mStorageManager.unregisterListener(mStorageListener);
}
+ mMeasurementHandler.cleanUp();
super.onDestroy();
}
@@ -195,7 +498,7 @@ public class Memory extends SettingsPreferenceFragment implements OnCancelListen
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- updateMemoryStatus();
+ mMeasurementHandler.sendEmptyMessage(MemoryMeasurementHandler.MSG_MEASURE_ALL);
}
};
@@ -290,77 +593,35 @@ public class Memory extends SettingsPreferenceFragment implements OnCancelListen
}
}
- private void updateMemoryStatus() {
- String status = Environment.getExternalStorageState();
- String readOnly = "";
- if (status.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
- status = Environment.MEDIA_MOUNTED;
- readOnly = mRes.getString(R.string.read_only);
- }
-
- if (status.equals(Environment.MEDIA_MOUNTED)) {
- if (!Environment.isExternalStorageRemovable()) {
- // This device has built-in storage that is not removable.
- // There is no reason for the user to unmount it.
- if (mSdMountToggleAdded) {
- mSdMountPreferenceGroup.removePreference(mSdMountToggle);
- mSdMountToggleAdded = false;
- }
- }
- try {
- File path = Environment.getExternalStorageDirectory();
- StatFs stat = new StatFs(path.getPath());
- long blockSize = stat.getBlockSize();
- long totalBlocks = stat.getBlockCount();
- long availableBlocks = stat.getAvailableBlocks();
-
- mSdSize.setSummary(formatSize(totalBlocks * blockSize));
- mSdAvail.setSummary(formatSize(availableBlocks * blockSize) + readOnly);
-
- mSdMountToggle.setEnabled(true);
- mSdMountToggle.setTitle(mRes.getString(R.string.sd_eject));
- mSdMountToggle.setSummary(mRes.getString(R.string.sd_eject_summary));
-
- } catch (IllegalArgumentException e) {
- // this can occur if the SD card is removed, but we haven't received the
- // ACTION_MEDIA_REMOVED Intent yet.
- status = Environment.MEDIA_REMOVED;
- }
-
- } else {
- mSdSize.setSummary(mRes.getString(R.string.sd_unavailable));
- mSdAvail.setSummary(mRes.getString(R.string.sd_unavailable));
+ private void updateUiExact() {
+ final float totalSize = mInternalTotalSize;
+ final long mediaSize = mInternalMediaSize;
+ final long appsSize = mInternalAppsSize;
- if (!Environment.isExternalStorageRemovable()) {
- if (status.equals(Environment.MEDIA_UNMOUNTED)) {
- if (!mSdMountToggleAdded) {
- mSdMountPreferenceGroup.addPreference(mSdMountToggle);
- mSdMountToggleAdded = true;
- }
- }
- }
+ mInternalUsageChart.clear();
+ mInternalUsageChart.addEntry(mediaSize / totalSize, mInternalMediaColor);
+ mInternalUsageChart.addEntry(appsSize / totalSize, mInternalAppsColor);
- if (status.equals(Environment.MEDIA_UNMOUNTED) ||
- status.equals(Environment.MEDIA_NOFS) ||
- status.equals(Environment.MEDIA_UNMOUNTABLE) ) {
- mSdMountToggle.setEnabled(true);
- mSdMountToggle.setTitle(mRes.getString(R.string.sd_mount));
- mSdMountToggle.setSummary(mRes.getString(R.string.sd_mount_summary));
- } else {
- mSdMountToggle.setEnabled(false);
- mSdMountToggle.setTitle(mRes.getString(R.string.sd_mount));
- mSdMountToggle.setSummary(mRes.getString(R.string.sd_insert_summary));
- }
+ // There are other things that can take up storage, but we didn't
+ // measure it.
+ final long remaining = mInternalUsedSize - (mediaSize + appsSize);
+ if (remaining > 0) {
+ mInternalUsageChart.addEntry(remaining / totalSize, mInternalUsedColor);
}
+ mInternalUsageChart.commit();
- File path = Environment.getDataDirectory();
- StatFs stat = new StatFs(path.getPath());
- long blockSize = stat.getBlockSize();
- long availableBlocks = stat.getAvailableBlocks();
- findPreference("memory_internal_avail").setSummary(formatSize(availableBlocks * blockSize));
+ mInternalMediaUsage.setSummary(formatSize(mediaSize));
+ mInternalAppsUsage.setSummary(formatSize(appsSize));
}
-
+
+ private void updateUiApproximate() {
+ mInternalUsageChart.clear();
+ mInternalUsageChart.addEntry(mInternalUsedSize / (float) mInternalTotalSize, getResources()
+ .getColor(R.color.memory_used));
+ mInternalUsageChart.commit();
+ }
+
private String formatSize(long size) {
return Formatter.formatFileSize(getActivity(), size);
}
@@ -369,5 +630,4 @@ public class Memory extends SettingsPreferenceFragment implements OnCancelListen
// TODO: Is this really required?
// finish();
}
-
}
diff --git a/src/com/android/settings/deviceinfo/PercentageBarChart.java b/src/com/android/settings/deviceinfo/PercentageBarChart.java
new file mode 100644
index 0000000..e8fb62a
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/PercentageBarChart.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+
+import java.util.Collection;
+
+/**
+ *
+ */
+public class PercentageBarChart extends View {
+ private final Paint mBackgroundPaint = new Paint();
+
+ private Collection<Entry> mEntries;
+
+ public static class Entry {
+ public final float percentage;
+ public final Paint paint;
+
+ protected Entry(float percentage, Paint paint) {
+ this.percentage = percentage;
+ this.paint = paint;
+ }
+ }
+
+ public PercentageBarChart(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mBackgroundPaint.setARGB(255, 64, 64, 64);
+ mBackgroundPaint.setStyle(Paint.Style.FILL);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ final int width = getWidth();
+ final int height = getHeight();
+
+ canvas.drawPaint(mBackgroundPaint);
+
+ int lastX = 0;
+
+ if (mEntries != null) {
+ for (final Entry e : mEntries) {
+ final int entryWidth;
+ if (e.percentage == 0f) {
+ entryWidth = 0;
+ } else {
+ entryWidth = Math.max(1, (int) (width * e.percentage));
+ }
+
+ final int nextX = lastX + entryWidth;
+ if (nextX >= width) {
+ break;
+ }
+
+ canvas.drawRect(lastX, 0, nextX, height, e.paint);
+ lastX = nextX;
+ }
+ }
+ }
+
+ /**
+ * Sets the background for this chart. Callers are responsible for later
+ * calling {@link #invalidate()}.
+ */
+ public void setBackgroundColor(int color) {
+ mBackgroundPaint.setColor(color);
+ }
+
+ /**
+ * Adds a new slice to the percentage bar chart. Callers are responsible for
+ * later calling {@link #invalidate()}.
+ *
+ * @param percentage the total width that
+ * @param color the color to draw the entry
+ */
+ public static Entry createEntry(float percentage, int color) {
+ final Paint p = new Paint();
+ p.setColor(color);
+ p.setStyle(Paint.Style.FILL);
+
+ return new Entry(percentage, p);
+ }
+
+ public void setEntries(Collection<Entry> entries) {
+ mEntries = entries;
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/UsageBarPreference.java b/src/com/android/settings/deviceinfo/UsageBarPreference.java
new file mode 100644
index 0000000..e9909f1
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/UsageBarPreference.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo;
+
+import com.android.settings.R;
+
+import android.content.Context;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Creates a percentage bar chart inside a preference.
+ */
+public class UsageBarPreference extends Preference {
+ private PercentageBarChart mChart = null;
+
+ private final Collection<PercentageBarChart.Entry> mEntries = new ArrayList<PercentageBarChart.Entry>();
+
+ public UsageBarPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ setWidgetLayoutResource(R.layout.preference_memoryusage);
+ }
+
+ public UsageBarPreference(Context context) {
+ super(context);
+ setWidgetLayoutResource(R.layout.preference_memoryusage);
+ }
+
+ public UsageBarPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setWidgetLayoutResource(R.layout.preference_memoryusage);
+ }
+
+ public void addEntry(float percentage, int color) {
+ mEntries.add(PercentageBarChart.createEntry(percentage, color));
+ }
+
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+
+ mChart = (PercentageBarChart) view.findViewById(R.id.percentage_bar_chart);
+
+ mChart.setEntries(mEntries);
+ }
+
+ public void commit() {
+ if (mChart != null) {
+ mChart.invalidate();
+ }
+ }
+
+ public void clear() {
+ mEntries.clear();
+ }
+}