Merge "Power Widget: don't display toast in intermediate state"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index a7066e0..c986d3b 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -700,14 +700,6 @@
             </intent-filter>
         </activity>
 
-        <activity android:name="SdCardSettings" android:label="@string/sd_card_settings_label">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEVELOPMENT_PREFERENCE" />
-                <category android:name="android.intent.category.VOICE_LAUNCH" />
-            </intent-filter>
-        </activity>
-
         <activity android:name="ProxySelector" android:label="@string/proxy_settings_label"
                 android:theme="@android:style/Theme.Dialog">
             <intent-filter>
diff --git a/res/layout/sdcard_settings_screen.xml b/res/layout/sdcard_settings_screen.xml
deleted file mode 100644
index 3fa6c9a..0000000
--- a/res/layout/sdcard_settings_screen.xml
+++ /dev/null
@@ -1,132 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/Settings/res/layout/sdcard_settings_screen.xml
-**
-** Copyright 2007, 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.
-*/
--->
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <LinearLayout android:id="@+id/list"
-        android:orientation="vertical"
-        android:padding="10dip"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content">
-    
-        <LinearLayout android:id="@+id/usb"
-            android:orientation="vertical"
-            android:paddingBottom="10dip"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-            <CheckBox android:id="@+id/mass_storage"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" 
-                android:text="@string/sdcard_settings_screen_mass_storage_text">
-                <requestFocus/>
-            </CheckBox>
-            
-            <TextView android:text="@string/sdcard_changes_instructions" style="@style/info_small" />
-        </LinearLayout>
-        
-        <!-- divider line -->
-        <View android:background="#FF000000"
-            android:layout_width="match_parent"
-            android:layout_height="1dip" />
-    
-        <LinearLayout android:id="@+id/mounted" 
-            android:orientation="vertical" 
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingTop="10dip">
-            
-            <TextView android:id="@+id/read_only"
-                android:text="@string/sdcard_settings_read_only_status" 
-                style="@style/info_label" />
-            
-            <Button android:id="@+id/sdcard_unmount"
-                android:text="@string/sdcard_unmount" 
-                android:textSize="14sp"
-                android:layout_marginTop="8dip"
-                android:layout_width="wrap_content" android:layout_height="wrap_content" />
-
-            <Button android:id="@+id/sdcard_format"
-                android:text="@string/sdcard_format" 
-                android:textSize="14sp"
-                android:layout_marginTop="8dip"
-                android:layout_width="wrap_content" android:layout_height="wrap_content" />
-    
-            <TableLayout
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingTop="10dip">
-                <TableRow>
-                    <TextView android:text="@string/sdcard_settings_total_bytes_label" style="@style/info_label" />
-                    <TextView android:id="@+id/total" style="@style/info_value" />
-                </TableRow>
-                <TableRow>
-                    <TextView android:text="@string/sdcard_settings_used_bytes_label" style="@style/info_label" />
-                    <TextView android:id="@+id/used" style="@style/info_value" />
-                </TableRow>
-                <TableRow>
-                    <TextView android:text="@string/sdcard_settings_available_bytes_label" style="@style/info_label" />
-                    <TextView android:id="@+id/available" style="@style/info_value" />
-                </TableRow>
-            </TableLayout>
-    
-        </LinearLayout>
-    
-        <LinearLayout style="@style/entry_layout" 
-            android:id="@+id/scanning" 
-            android:paddingTop="10dip">
-            <TextView android:text="@string/sdcard_settings_scanning_status" style="@style/info_label" />
-        </LinearLayout>
-
-        <LinearLayout style="@style/entry_layout" 
-            android:id="@+id/removed" 
-            android:paddingTop="10dip">
-            <TextView android:text="@string/sdcard_settings_not_present_status" style="@style/info_label" />
-        </LinearLayout>
-
-        <LinearLayout android:id="@+id/shared" 
-            android:orientation="vertical" 
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content" 
-            android:paddingTop="10dip">
-        
-            <LinearLayout style="@style/entry_layout" >
-                <TextView android:text="@string/sdcard_settings_mass_storage_status" style="@style/info_label" />
-            </LinearLayout>
- 
-        </LinearLayout>
-
-        <LinearLayout style="@style/entry_layout" 
-            android:id="@+id/unmounted" 
-            android:paddingTop="10dip">
-            <TextView android:text="@string/sdcard_settings_unmounted_status" style="@style/info_label" />
-        </LinearLayout>
-
-        <LinearLayout style="@style/entry_layout" 
-            android:id="@+id/bad_removal" 
-            android:paddingTop="10dip">
-            <TextView android:text="@string/sdcard_settings_bad_removal_status" style="@style/info_label" />
-        </LinearLayout>
-    
-    </LinearLayout>
-</ScrollView>
-
diff --git a/res/values/strings.xml b/res/values/strings.xml
index bc19df5..4808a69 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1203,6 +1203,21 @@
     <string name="sd_unavailable">Unavailable</string>
     <!-- SD card status when it is mounted as read only  -->
     <string name="read_only">\u0020(Read-only)</string>
+    <!-- SD card eject confirmation dialog title   -->
+    <string name="dlg_confirm_unmount_title">Unmount sdcard</string>
+    <!-- SD card eject confirmation dialog  -->
+    <string name="dlg_confirm_unmount_text">Some processes accessing data on sdcard will be killed. Do you want to continue?</string>
+    <!-- SD card eject error dialog title   -->
+    <string name="dlg_error_unmount_title">Unmount sdcard failed</string>
+    <!-- SD card eject error dialog text   -->
+    <string name="dlg_error_unmount_text">Cannot unmount sdcard. Try again later.</string>
+    <!-- SD card unmount informative text   -->
+    <string name="unmount_inform_text">Sdcard will be unmounted. Check the notification area for status.</string>
+    <!-- SD card eject progress title   -->
+    <string name="sd_ejecting_title">Unmounting</string>
+    <!-- SD card eject progress text   -->
+    <string name="sd_ejecting_summary">Unmount in progress</string>
+
     <!-- Phone info screen, section titles: -->
     <string name="battery_status_title">Battery status</string>
     <!-- Phone info screen, section titles: -->
diff --git a/src/com/android/settings/AccessibilitySettings.java b/src/com/android/settings/AccessibilitySettings.java
index 1d6db20..276a22f 100644
--- a/src/com/android/settings/AccessibilitySettings.java
+++ b/src/com/android/settings/AccessibilitySettings.java
@@ -105,8 +105,6 @@
         if (!accessibilityServices.isEmpty()) {
             if (serviceState == 1) {
                 mToggleCheckBox.setChecked(true);
-            } else {
-                setAccessibilityServicePreferencesState(false);
             }
             mToggleCheckBox.setEnabled(true);
         } else {
@@ -114,7 +112,6 @@
                 // no service and accessibility is enabled => disable
                 Settings.Secure.putInt(getContentResolver(),
                     Settings.Secure.ACCESSIBILITY_ENABLED, 0);
-                setAccessibilityServicePreferencesState(false);
             }
             mToggleCheckBox.setEnabled(false);
             // Notify user that they do not have any accessibility apps
@@ -130,26 +127,6 @@
         persistEnabledAccessibilityServices();
     }
 
-    /**
-     * Sets the state of the preferences for enabling/disabling AccessibilityServices.
-     *
-     * @param isEnabled If to enable or disable the preferences.
-     */
-    private void setAccessibilityServicePreferencesState(boolean isEnabled) {
-        if (mAccessibilityServicesCategory == null) {
-            return;
-        }
-
-        int count = mAccessibilityServicesCategory.getPreferenceCount();
-        for (int i = 0; i < count; i++) {
-            Preference pref = mAccessibilityServicesCategory.getPreference(i);
-            pref.setEnabled(isEnabled);
-            if (!isEnabled){
-               ((CheckBoxPreference) pref).setChecked(false);
-            }
-        }
-    }
-
     @Override
     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
         final String key = preference.getKey();
@@ -173,7 +150,6 @@
         if (preference.isChecked()) {
             Settings.Secure.putInt(getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_ENABLED, 1);
-            setAccessibilityServicePreferencesState(true);
         } else {
             final CheckBoxPreference checkBoxPreference = preference;
             AlertDialog dialog = (new AlertDialog.Builder(this))
@@ -186,7 +162,6 @@
                         public void onClick(DialogInterface dialog, int which) {
                             Settings.Secure.putInt(getContentResolver(),
                                 Settings.Secure.ACCESSIBILITY_ENABLED, 0);
-                            setAccessibilityServicePreferencesState(false);
                         }
                 })
                 .setNegativeButton(android.R.string.cancel,
diff --git a/src/com/android/settings/SdCardIntentReceiver.java b/src/com/android/settings/SdCardIntentReceiver.java
deleted file mode 100644
index 9648ec1..0000000
--- a/src/com/android/settings/SdCardIntentReceiver.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2007 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;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.BroadcastReceiver;
-import android.util.Config;
-import android.util.Log;
-
-/**
- * 
- */
-public class SdCardIntentReceiver extends BroadcastReceiver {
-
-    private static final int SDCARD_STATUS = 1;
-    private static final String TAG = "SdCardIntentReceiver";
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        NotificationManager nm = (NotificationManager) context
-                .getSystemService(Context.NOTIFICATION_SERVICE);
-        String action = intent.getAction();
-        if (Config.LOGD) Log.d(TAG, "onReceiveIntent " + action);
-
-        if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
-            nm.cancel(SDCARD_STATUS);
-
-            Intent statusIntent = new Intent(Intent.ACTION_MAIN, null);
-            statusIntent.setClass(context, SdCardSettings.class);
-            nm.notify(SDCARD_STATUS, new Notification(context,
-                    android.R.drawable.stat_notify_sdcard,
-                    null,
-                    System.currentTimeMillis(),
-                    context.getText(R.string.sdcard_setting),
-                    null,
-                    statusIntent));
-        } else if (action.equals(Intent.ACTION_MEDIA_REMOVED)) {
-            nm.cancel(SDCARD_STATUS);
-        } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) {
-            nm.cancel(SDCARD_STATUS);
-
-            Intent statusIntent = new Intent(Intent.ACTION_MAIN, null);
-            statusIntent.setClass(context, SdCardSettings.class);
-            nm.notify(SDCARD_STATUS, new Notification(context,
-                    android.R.drawable.stat_notify_sdcard_usb,
-                    null,
-                    System.currentTimeMillis(),
-                    "SD Card",
-                    null,
-                    statusIntent));
-        }
-    }
-}
diff --git a/src/com/android/settings/SdCardSettings.java b/src/com/android/settings/SdCardSettings.java
deleted file mode 100644
index 87e8fb3..0000000
--- a/src/com/android/settings/SdCardSettings.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2007 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;
-
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.Environment;
-import android.os.ServiceManager;
-import android.os.StatFs;
-import android.os.storage.StorageManager;
-import android.os.storage.IMountService;
-import android.text.format.Formatter;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.TextView;
-
-import java.io.File;
-
-
-public class SdCardSettings extends Activity
-{
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        setContentView(R.layout.sdcard_settings_screen);
-
-        mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
-        mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
-
-        mRemovedLayout = findViewById(R.id.removed);
-        mMountedLayout = findViewById(R.id.mounted);
-        mUnmountedLayout = findViewById(R.id.unmounted);
-        mScanningLayout = findViewById(R.id.scanning);
-        mSharedLayout = findViewById(R.id.shared);
-        mBadRemovalLayout = findViewById(R.id.bad_removal);
-        mReadOnlyStatus = findViewById(R.id.read_only);
-
-        mMassStorage = (CheckBox)findViewById(R.id.mass_storage);
-        mMassStorage.setOnClickListener(mMassStorageListener);
-
-        Button unmountButton = (Button)findViewById(R.id.sdcard_unmount);
-        unmountButton.setOnClickListener(mUnmountButtonHandler);
-
-        Button formatButton = (Button)findViewById(R.id.sdcard_format);
-        formatButton.setOnClickListener(mFormatButtonHandler);
-
-        mTotalSize = (TextView)findViewById(R.id.total);
-        mUsedSize = (TextView)findViewById(R.id.used);
-        mAvailableSize = (TextView)findViewById(R.id.available);
-
-        // install an intent filter to receive SD card related events.
-        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_REMOVED);
-        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
-        intentFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
-        intentFilter.addAction(Intent.ACTION_MEDIA_SHARED);
-        intentFilter.addAction(Intent.ACTION_MEDIA_CHECKING);
-        intentFilter.addAction(Intent.ACTION_MEDIA_NOFS);
-        intentFilter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
-        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
-        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
-        intentFilter.addDataScheme("file");
-        registerReceiver(mReceiver, intentFilter);
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        update();
-    }
-
-    private void setLayout(View layout) {
-        mRemovedLayout.setVisibility(layout == mRemovedLayout ? View.VISIBLE : View.GONE);
-        mMountedLayout.setVisibility(layout == mMountedLayout ? View.VISIBLE : View.GONE);
-        mUnmountedLayout.setVisibility(layout == mUnmountedLayout ? View.VISIBLE : View.GONE);
-        mScanningLayout.setVisibility(layout == mScanningLayout ? View.VISIBLE : View.GONE);
-        mSharedLayout.setVisibility(layout == mSharedLayout ? View.VISIBLE : View.GONE);
-        mBadRemovalLayout.setVisibility(layout == mBadRemovalLayout ? View.VISIBLE : View.GONE);
-    }
-
-    private void update() {
-
-        try {
-            mMassStorage.setChecked(mStorageManager.isUsbMassStorageEnabled());
-        } catch (Exception ex) {
-        }
-
-        String status = Environment.getExternalStorageState();
-        boolean readOnly = false;
-
-        if (status.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
-            status = Environment.MEDIA_MOUNTED;
-            readOnly = true;
-        }
-
-        if (status.equals(Environment.MEDIA_MOUNTED)) {
-            try {
-                File path = Environment.getExternalStorageDirectory();
-                StatFs stat = new StatFs(path.getPath());
-                long blockSize = stat.getBlockSize();
-                long totalBlocks = stat.getBlockCount();
-                long availableBlocks = stat.getAvailableBlocks();
-
-                mTotalSize.setText(formatSize(totalBlocks * blockSize));
-                mUsedSize.setText(formatSize((totalBlocks - availableBlocks) * blockSize));
-                mAvailableSize.setText(formatSize(availableBlocks * blockSize));
-            } 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;
-            }
-
-            mReadOnlyStatus.setVisibility(readOnly ? View.VISIBLE : View.GONE);
-            setLayout(mMountedLayout);
-        } else if (status.equals(Environment.MEDIA_UNMOUNTED)) {
-            setLayout(mUnmountedLayout);
-        } else if (status.equals(Environment.MEDIA_REMOVED)) {
-            setLayout(mRemovedLayout);
-        } else if (status.equals(Environment.MEDIA_SHARED)) {
-            setLayout(mSharedLayout);
-        } else if (status.equals(Environment.MEDIA_BAD_REMOVAL)) {
-            setLayout(mBadRemovalLayout);
-        }
-    }
-
-    private String formatSize(long size) {
-        return Formatter.formatFileSize(this, size);
-    }
-
-    OnClickListener mMassStorageListener = new OnClickListener() {
-        public void onClick(View v) {
-            try {
-                if (mMassStorage.isChecked()) {
-                    mStorageManager.enableUsbMassStorage();
-                } else {
-                    mStorageManager.disableUsbMassStorage();
-                }
-            } catch (Exception ex) {
-            }
-        }
-    };
-
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            update();
-        }
-    };
-
-    OnClickListener mUnmountButtonHandler = new OnClickListener() {
-        public void onClick(View v) {
-            try {
-                mMountService.unmountVolume(Environment.getExternalStorageDirectory().toString(), false);
-            } catch (RemoteException ex) {
-            }
-        }
-    };
-
-    OnClickListener mFormatButtonHandler = new OnClickListener() {
-        public void onClick(View v) {
-            try {
-                mMountService.formatVolume(Environment.getExternalStorageDirectory().toString());
-            } catch (RemoteException ex) {
-            }
-        }
-    };
-
-    private StorageManager mStorageManager;
-    private IMountService mMountService;
-
-    private CheckBox    mMassStorage;
-
-    private TextView    mTotalSize;
-    private TextView    mUsedSize;
-    private TextView    mAvailableSize;
-
-    private View        mRemovedLayout;
-    private View        mMountedLayout;
-    private View        mUnmountedLayout;
-    private View        mScanningLayout;
-    private View        mSharedLayout;
-    private View        mBadRemovalLayout;
-    private View        mReadOnlyStatus;
-}
diff --git a/src/com/android/settings/deviceinfo/Memory.java b/src/com/android/settings/deviceinfo/Memory.java
index 53c641a..fa217ad 100644
--- a/src/com/android/settings/deviceinfo/Memory.java
+++ b/src/com/android/settings/deviceinfo/Memory.java
@@ -16,13 +16,19 @@
 
 package com.android.settings.deviceinfo;
 
+import android.app.AlertDialog;
+import android.app.Dialog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.DialogInterface.OnCancelListener;
 import android.content.res.Resources;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Message;
 import android.os.RemoteException;
 import android.os.Environment;
 import android.os.storage.IMountService;
@@ -35,15 +41,15 @@
 import android.preference.PreferenceScreen;
 import android.text.format.Formatter;
 import android.util.Log;
+import android.widget.Toast;
 
 import com.android.settings.R;
 
 import java.io.File;
-import java.text.DecimalFormat;
 
-public class Memory extends PreferenceActivity {
-    
+public class Memory extends PreferenceActivity implements OnCancelListener {
     private static final String TAG = "Memory";
+    private static final boolean localLOGV = false;
 
     private static final String MEMORY_SD_SIZE = "memory_sd_size";
 
@@ -52,6 +58,10 @@
     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 int DLG_CONFIRM_UNMOUNT = 1;
+    private static final int DLG_ERROR_UNMOUNT = 2;
+
     private Resources mRes;
 
     private Preference mSdSize;
@@ -98,6 +108,9 @@
 
         @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();
         }
     };
@@ -107,7 +120,15 @@
         super.onPause();
         unregisterReceiver(mReceiver);
     }
-    
+
+    @Override
+    protected void onDestroy() {
+        if (mStorageManager != null && mStorageListener != null) {
+            mStorageManager.unregisterListener(mStorageListener);
+        }
+        super.onDestroy();
+    }
+
     private synchronized IMountService getMountService() {
        if (mMountService == null) {
            IBinder service = ServiceManager.getService("mount");
@@ -147,19 +168,80 @@
         }
     };
 
-    private void unmount() {
-        IMountService mountService = getMountService();
-        try {
-            if (mountService != null) {
-                mountService.unmountVolume(Environment.getExternalStorageDirectory().toString(), false);
-            } else {
-                Log.e(TAG, "Mount service is null, can't unmount");
-            }
-        } catch (RemoteException ex) {
+    @Override
+    public Dialog onCreateDialog(int id, Bundle args) {
+        switch (id) {
+        case DLG_CONFIRM_UNMOUNT:
+            return new AlertDialog.Builder(this)
+                    .setTitle(R.string.dlg_confirm_unmount_title)
+                    .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
+                        public void onClick(DialogInterface dialog, int which) {
+                            doUnmount(true);
+                        }})
+                    .setNegativeButton(R.string.cancel, null)
+                    .setMessage(R.string.dlg_confirm_unmount_text)
+                    .setOnCancelListener(this)
+                    .create();
+        case DLG_ERROR_UNMOUNT:
+            return new AlertDialog.Builder(this                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            )
+            .setTitle(R.string.dlg_error_unmount_title)
+            .setNeutralButton(R.string.dlg_ok, null)
+            .setMessage(R.string.dlg_error_unmount_text)
+            .setOnCancelListener(this)
+            .create();
         }
-        updateMemoryStatus();
+        return null;
     }
 
+    private void doUnmount(boolean force) {
+        // Present a toast here
+        Toast.makeText(this, 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);
+        } catch (RemoteException e) {
+            // Informative dialog to user that
+            // unmount failed.
+            showDialogInner(DLG_ERROR_UNMOUNT);
+        }
+    }
+
+    private void showDialogInner(int id) {
+        removeDialog(id);
+        showDialog(id);
+    }
+
+    private void unmount() {
+        // Check if the sdcard is being accessed by other processes
+        // and let the user decide if the sdcard should be ejected.
+        String extStoragePath = Environment.
+        getExternalStorageDirectory().toString();
+        IMountService mountService = getMountService();
+        int stUsers[] = null;
+        try {
+            stUsers = mountService.getStorageUsers(extStoragePath);
+        } catch (RemoteException e) {
+            // Very unlikely. But present an error dialog anyway
+            Log.e(TAG, "Is MountService running?");
+            showDialogInner(DLG_ERROR_UNMOUNT);
+        }
+        if (stUsers != null && stUsers.length > 0) {
+            if (localLOGV) Log.i(TAG, "Do have storage users accessing "
+                    + extStoragePath);
+            for (int pid : stUsers) {
+                if (localLOGV) Log.i(TAG, pid + " accessing file on sdcard");
+            }
+            // Present dialog to user
+            showDialogInner(DLG_CONFIRM_UNMOUNT);
+        } else {
+            doUnmount(true);
+        }
+}
+
     private void mount() {
         IMountService mountService = getMountService();
         try {
@@ -170,7 +252,6 @@
             }
         } catch (RemoteException ex) {
         }
-        updateMemoryStatus();
     }
 
     private void updateMemoryStatus() {
@@ -233,5 +314,9 @@
     private String formatSize(long size) {
         return Formatter.formatFileSize(this, size);
     }
+
+    public void onCancel(DialogInterface dialog) {
+        finish();
+    }
     
 }