OSDN Git Service

Bug 4539424: confirmation dialog always shown
[android-x86/packages-apps-Settings.git] / src / com / android / settings / deviceinfo / Memory.java
index c3df2d5..db60c37 100644 (file)
 
 package com.android.settings.deviceinfo;
 
-import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.deviceinfo.MemoryMeasurement.MeasurementReceiver;
-
-import android.app.ActivityManager;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.BroadcastReceiver;
@@ -28,129 +23,44 @@ import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.pm.ApplicationInfo;
 import android.content.res.Resources;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.shapes.RectShape;
-import android.graphics.drawable.shapes.RoundRectShape;
-import android.hardware.UsbManager;
 import android.os.Bundle;
 import android.os.Environment;
-import android.os.Handler;
 import android.os.IBinder;
-import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.storage.IMountService;
 import android.os.storage.StorageEventListener;
 import android.os.storage.StorageManager;
+import android.os.storage.StorageVolume;
 import android.preference.Preference;
-import android.preference.PreferenceGroup;
 import android.preference.PreferenceScreen;
-import android.text.format.Formatter;
 import android.util.Log;
 import android.widget.Toast;
 
-import java.util.List;
-
-public class Memory extends SettingsPreferenceFragment implements OnCancelListener,
-        MeasurementReceiver {
-    private static final String TAG = "Memory";
-    static final boolean localLOGV = false;
-
-    private static final String MEMORY_SD_SIZE = "memory_sd_size";
-
-    private static final String MEMORY_SD_AVAIL = "memory_sd_avail";
-
-    private static final String MEMORY_SD_MOUNT_TOGGLE = "memory_sd_mount_toggle";
-
-    private static final String MEMORY_SD_FORMAT = "memory_sd_format";
-
-    private static final String MEMORY_SD_GROUP = "memory_sd";
-
-    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";
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
 
-    private static final String MEMORY_INTERNAL_CHART = "memory_internal_chart";
+public class Memory extends SettingsPreferenceFragment {
+    private static final String TAG = "MemorySettings";
 
     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;
+    private Resources mResources;
 
-    boolean mSdMountToggleAdded = true;
+    // The mountToggle Preference that has last been clicked.
+    // Assumes no two successive unmount event on 2 different volumes are performed before the first
+    // one's preference is disabled
+    private Preference mLastClickedMountToggle;
+    private String mClickedMountPoint;
     
     // Access using getMountService()
     private IMountService mMountService = null;
 
     private StorageManager mStorageManager = null;
 
-    // Updates the memory usage bar graph.
-    private static final int MSG_UI_UPDATE_INTERNAL_APPROXIMATE = 1;
-
-    // Updates the memory usage bar graph.
-    private static final int MSG_UI_UPDATE_INTERNAL_EXACT = 2;
-
-    // Updates the memory usage stats for external.
-    private static final int MSG_UI_UPDATE_EXTERNAL_APPROXIMATE = 3;
-
-    private Handler mUpdateHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_UI_UPDATE_INTERNAL_APPROXIMATE: {
-                    Bundle bundle = msg.getData();
-                    final long totalSize = bundle.getLong(MemoryMeasurement.TOTAL_SIZE);
-                    final long availSize = bundle.getLong(MemoryMeasurement.AVAIL_SIZE);
-                    updateUiApproximate(totalSize, availSize);
-                    break;
-                }
-                case MSG_UI_UPDATE_INTERNAL_EXACT: {
-                    Bundle bundle = msg.getData();
-                    final long totalSize = bundle.getLong(MemoryMeasurement.TOTAL_SIZE);
-                    final long availSize = bundle.getLong(MemoryMeasurement.AVAIL_SIZE);
-                    final long mediaUsed = bundle.getLong(MemoryMeasurement.MEDIA_USED);
-                    final long appsUsed = bundle.getLong(MemoryMeasurement.APPS_USED);
-                    updateUiExact(totalSize, availSize, mediaUsed, appsUsed);
-                    break;
-                }
-                case MSG_UI_UPDATE_EXTERNAL_APPROXIMATE: {
-                    Bundle bundle = msg.getData();
-                    final long totalSize = bundle.getLong(MemoryMeasurement.TOTAL_SIZE);
-                    final long availSize = bundle.getLong(MemoryMeasurement.AVAIL_SIZE);
-                    updateExternalStorage(totalSize, availSize);
-                    break;
-                }
-            }
-        }
-    };
-
-    private MemoryMeasurement mMeasurement;
+    private StorageVolumePreferenceCategory[] mStorageVolumePreferenceCategories;
 
     @Override
     public void onCreate(Bundle icicle) {
@@ -163,63 +73,33 @@ 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);
-        mSdMountToggle = findPreference(MEMORY_SD_MOUNT_TOGGLE);
-        mSdFormat = findPreference(MEMORY_SD_FORMAT);
-        mSdMountPreferenceGroup = (PreferenceGroup)findPreference(MEMORY_SD_GROUP);
-
-        if (Environment.isExternalStorageEmulated()) {
-            getPreferenceScreen().removePreference(mSdMountPreferenceGroup);
+        mResources = getResources();
+
+        StorageVolume[] storageVolumes = mStorageManager.getVolumeList();
+        int length = storageVolumes.length;
+        mStorageVolumePreferenceCategories = new StorageVolumePreferenceCategory[length];
+        for (int i = 0; i < length; i++) {
+            StorageVolume storageVolume = storageVolumes[i];
+            StorageVolumePreferenceCategory storagePreferenceCategory =
+                new StorageVolumePreferenceCategory(getActivity(), mResources, storageVolume,
+                        mStorageManager, i == 0); // The first volume is the primary volume
+            mStorageVolumePreferenceCategories[i] = storagePreferenceCategory;
+            getPreferenceScreen().addPreference(storagePreferenceCategory);
+            storagePreferenceCategory.init();
         }
-
-        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);
-
-        float[] radius = new float[] {
-                5f, 5f, 5f, 5f, 5f, 5f, 5f, 5f
-        };
-        RoundRectShape shape1 = new RoundRectShape(radius, null, null);
-
-        ShapeDrawable mediaShape = new ShapeDrawable(shape1);
-        mediaShape.setIntrinsicWidth(32);
-        mediaShape.setIntrinsicHeight(32);
-        mediaShape.getPaint().setColor(mInternalMediaColor);
-        mInternalMediaUsage.setIcon(mediaShape);
-
-        ShapeDrawable appsShape = new ShapeDrawable(shape1);
-        appsShape.setIntrinsicWidth(32);
-        appsShape.setIntrinsicHeight(32);
-        appsShape.getPaint().setColor(mInternalAppsColor);
-        mInternalAppsUsage.setIcon(appsShape);
-
-        mInternalUsageChart = (UsageBarPreference) findPreference(MEMORY_INTERNAL_CHART);
-
-        mMeasurement = MemoryMeasurement.getInstance(getActivity());
-        mMeasurement.setReceiver(this);
     }
 
     @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);
+        getActivity().registerReceiver(mMediaScannerReceiver, intentFilter);
 
-        mMeasurement.invalidate();
-        if (!Environment.isExternalStorageEmulated()) {
-            mMeasurement.measureExternal();
+        for (int i = 0; i < mStorageVolumePreferenceCategories.length; i++) {
+            mStorageVolumePreferenceCategories[i].onResume();
         }
-        mMeasurement.measureInternal();
     }
 
     StorageEventListener mStorageListener = new StorageEventListener() {
@@ -228,8 +108,12 @@ public class Memory extends SettingsPreferenceFragment implements OnCancelListen
             Log.i(TAG, "Received storage state changed notification that " +
                     path + " changed state from " + oldState +
                     " to " + newState);
-            if (!Environment.isExternalStorageEmulated()) {
-                mMeasurement.measureExternal();
+            for (int i = 0; i < mStorageVolumePreferenceCategories.length; i++) {
+                StorageVolumePreferenceCategory svpc = mStorageVolumePreferenceCategories[i];
+                if (path.equals(svpc.getStorageVolume().getPath())) {
+                    svpc.onStorageStateChanged();
+                    break;
+                }
             }
         }
     };
@@ -237,8 +121,10 @@ public class Memory extends SettingsPreferenceFragment implements OnCancelListen
     @Override
     public void onPause() {
         super.onPause();
-        getActivity().unregisterReceiver(mReceiver);
-        mMeasurement.cleanUp();
+        getActivity().unregisterReceiver(mMediaScannerReceiver);
+        for (int i = 0; i < mStorageVolumePreferenceCategories.length; i++) {
+            mStorageVolumePreferenceCategories[i].onPause();
+        }
     }
 
     @Override
@@ -263,39 +149,38 @@ public class Memory extends SettingsPreferenceFragment implements OnCancelListen
     
     @Override
     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
-        if (preference == mSdMountToggle) {
-            String status = Environment.getExternalStorageState();
-            if (status.equals(Environment.MEDIA_MOUNTED)) {
-                unmount();
-            } else {
-                mount();
+        for (int i = 0; i < mStorageVolumePreferenceCategories.length; i++) {
+            StorageVolumePreferenceCategory svpc = mStorageVolumePreferenceCategories[i];
+            Intent intent = svpc.intentForClick(preference);
+            if (intent != null) {
+                startActivity(intent);
+                return true;
+            }
+
+            if (svpc.mountToggleClicked(preference)) {
+                mLastClickedMountToggle = preference;
+                final StorageVolume storageVolume = svpc.getStorageVolume();
+                mClickedMountPoint = storageVolume.getPath();
+                String state = mStorageManager.getVolumeState(storageVolume.getPath());
+                if (Environment.MEDIA_MOUNTED.equals(state) ||
+                        Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
+                    unmount();
+                } else {
+                    mount();
+                }
+                return true;
             }
-            return true;
-        } else if (preference == mSdFormat) {
-            Intent intent = new Intent(Intent.ACTION_VIEW);
-            intent.setClass(getActivity(), com.android.settings.MediaFormat.class);
-            startActivity(intent);
-            return true;
-        } else if (preference == mInternalAppsUsage) {
-            Intent intent = new Intent(Intent.ACTION_MANAGE_PACKAGE_STORAGE);
-            intent.setClass(getActivity(),
-                    com.android.settings.Settings.ManageApplicationsActivity.class);
-            startActivity(intent);
-            return true;
         }
 
         return false;
     }
      
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+    private final BroadcastReceiver mMediaScannerReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            mMeasurement.invalidate();
-
-            if (!Environment.isExternalStorageEmulated()) {
-                mMeasurement.measureExternal();
+            for (int i = 0; i < mStorageVolumePreferenceCategories.length; i++) {
+                mStorageVolumePreferenceCategories[i].onMediaScannerFinished();
             }
-            mMeasurement.measureInternal();
         }
     };
 
@@ -307,36 +192,32 @@ public class Memory extends SettingsPreferenceFragment implements OnCancelListen
                     .setTitle(R.string.dlg_confirm_unmount_title)
                     .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
                         public void onClick(DialogInterface dialog, int which) {
-                            doUnmount(true);
+                            doUnmount();
                         }})
                     .setNegativeButton(R.string.cancel, null)
                     .setMessage(R.string.dlg_confirm_unmount_text)
-                    .setOnCancelListener(this)
                     .create();
         case DLG_ERROR_UNMOUNT:
                 return new AlertDialog.Builder(getActivity())
             .setTitle(R.string.dlg_error_unmount_title)
             .setNeutralButton(R.string.dlg_ok, null)
             .setMessage(R.string.dlg_error_unmount_text)
-            .setOnCancelListener(this)
             .create();
         }
         return null;
     }
 
-    private void doUnmount(boolean force) {
+    private void doUnmount() {
         // Present a toast here
         Toast.makeText(getActivity(), R.string.unmount_inform_text, Toast.LENGTH_SHORT).show();
         IMountService mountService = getMountService();
-        String extStoragePath = Environment.getExternalStorageDirectory().toString();
         try {
-            mSdMountToggle.setEnabled(false);
-            mSdMountToggle.setTitle(mRes.getString(R.string.sd_ejecting_title));
-            mSdMountToggle.setSummary(mRes.getString(R.string.sd_ejecting_summary));
-            mountService.unmountVolume(extStoragePath, force);
+            mLastClickedMountToggle.setEnabled(false);
+            mLastClickedMountToggle.setTitle(mResources.getString(R.string.sd_ejecting_title));
+            mLastClickedMountToggle.setSummary(mResources.getString(R.string.sd_ejecting_summary));
+            mountService.unmountVolume(mClickedMountPoint, true);
         } catch (RemoteException e) {
-            // Informative dialog to user that
-            // unmount failed.
+            // Informative dialog to user that unmount failed.
             showDialogInner(DLG_ERROR_UNMOUNT);
         }
     }
@@ -347,29 +228,33 @@ public class Memory extends SettingsPreferenceFragment implements OnCancelListen
     }
 
     private boolean hasAppsAccessingStorage() throws RemoteException {
-        String extStoragePath = Environment.getExternalStorageDirectory().toString();
         IMountService mountService = getMountService();
-        int stUsers[] = mountService.getStorageUsers(extStoragePath);
+        int stUsers[] = mountService.getStorageUsers(mClickedMountPoint);
         if (stUsers != null && stUsers.length > 0) {
             return true;
         }
+        // TODO FIXME Parameterize with mountPoint and uncomment.
+        // On HC-MR2, no apps can be installed on sd and the emulated internal storage is not
+        // removable: application cannot interfere with unmount
+        /*
         ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
         List<ApplicationInfo> list = am.getRunningExternalApplications();
         if (list != null && list.size() > 0) {
             return true;
         }
-        return false;
+        */
+        // Better safe than sorry. Assume the storage is used to ask for confirmation.
+        return true;
     }
 
     private void unmount() {
         // Check if external media is in use.
         try {
            if (hasAppsAccessingStorage()) {
-               if (localLOGV) Log.i(TAG, "Do have storage users accessing media");
                // Present dialog to user
                showDialogInner(DLG_CONFIRM_UNMOUNT);
            } else {
-               doUnmount(true);
+               doUnmount();
            }
         } catch (RemoteException e) {
             // Very unlikely. But present an error dialog anyway
@@ -382,130 +267,12 @@ public class Memory extends SettingsPreferenceFragment implements OnCancelListen
         IMountService mountService = getMountService();
         try {
             if (mountService != null) {
-                mountService.mountVolume(Environment.getExternalStorageDirectory().toString());
+                mountService.mountVolume(mClickedMountPoint);
             } else {
                 Log.e(TAG, "Mount service is null, can't mount");
             }
         } catch (RemoteException ex) {
+            // Not much can be done
         }
     }
-
-    private void updateUiExact(long totalSize, long availSize, long mediaSize, long appsSize) {
-        mInternalSize.setSummary(formatSize(totalSize));
-        mInternalAvail.setSummary(formatSize(availSize));
-        mInternalMediaUsage.setSummary(formatSize(mediaSize));
-        mInternalAppsUsage.setSummary(formatSize(appsSize));
-
-        mInternalUsageChart.clear();
-        mInternalUsageChart.addEntry(mediaSize / (float) totalSize, mInternalMediaColor);
-        mInternalUsageChart.addEntry(appsSize / (float) totalSize, mInternalAppsColor);
-
-        final long usedSize = totalSize - availSize;
-
-        // There are other things that can take up storage, but we didn't
-        // measure it.
-        final long remaining = usedSize - (mediaSize + appsSize);
-        if (remaining > 0) {
-            mInternalUsageChart.addEntry(remaining / (float) totalSize, mInternalUsedColor);
-        }
-        mInternalUsageChart.commit();
-    }
-
-    private void updateUiApproximate(long totalSize, long availSize) {
-        mInternalSize.setSummary(formatSize(totalSize));
-        mInternalAvail.setSummary(formatSize(availSize));
-
-        final long usedSize = totalSize - availSize;
-
-        mInternalUsageChart.clear();
-        mInternalUsageChart.addEntry(usedSize / (float) totalSize, mInternalUsedColor);
-        mInternalUsageChart.commit();
-    }
-
-    private void updateExternalStorage(long totalSize, long availSize) {
-        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 {
-                mSdSize.setSummary(formatSize(totalSize));
-                mSdAvail.setSummary(formatSize(availSize) + 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 String formatSize(long size) {
-        return Formatter.formatFileSize(getActivity(), size);
-    }
-
-    public void onCancel(DialogInterface dialog) {
-        // TODO: Is this really required?
-        // finish();
-    }
-
-    @Override
-    public void updateApproximateExternal(Bundle bundle) {
-        final Message message = mUpdateHandler.obtainMessage(MSG_UI_UPDATE_EXTERNAL_APPROXIMATE);
-        message.setData(bundle);
-        mUpdateHandler.sendMessage(message);
-    }
-
-    @Override
-    public void updateApproximateInternal(Bundle bundle) {
-        final Message message = mUpdateHandler.obtainMessage(MSG_UI_UPDATE_INTERNAL_APPROXIMATE);
-        message.setData(bundle);
-        mUpdateHandler.sendMessage(message);
-    }
-
-    @Override
-    public void updateExactInternal(Bundle bundle) {
-        final Message message = mUpdateHandler.obtainMessage(MSG_UI_UPDATE_INTERNAL_EXACT);
-        message.setData(bundle);
-        mUpdateHandler.sendMessage(message);
-    }
 }