OSDN Git Service

merge from open-source master
[android-x86/packages-apps-Settings.git] / src / com / android / settings / deviceinfo / Memory.java
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.settings.deviceinfo;
18
19 import android.app.ActivityManager;
20 import android.app.AlertDialog;
21 import android.app.Dialog;
22 import android.content.BroadcastReceiver;
23 import android.content.Context;
24 import android.content.DialogInterface;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.content.DialogInterface.OnCancelListener;
28 import android.content.pm.ApplicationInfo;
29 import android.content.pm.PackageManager;
30 import android.content.pm.PackageManager.NameNotFoundException;
31 import android.content.res.Resources;
32 import android.os.Bundle;
33 import android.os.Handler;
34 import android.os.IBinder;
35 import android.os.Message;
36 import android.os.RemoteException;
37 import android.os.Environment;
38 import android.os.storage.IMountService;
39 import android.os.ServiceManager;
40 import android.os.StatFs;
41 import android.os.storage.StorageManager;
42 import android.os.storage.StorageEventListener;
43 import android.preference.Preference;
44 import android.preference.PreferenceActivity;
45 import android.preference.PreferenceScreen;
46 import android.text.format.Formatter;
47 import android.util.Log;
48 import android.widget.Toast;
49
50 import com.android.settings.R;
51
52 import java.io.File;
53 import java.util.HashSet;
54 import java.util.List;
55 import java.util.Set;
56
57 public class Memory extends PreferenceActivity implements OnCancelListener {
58     private static final String TAG = "Memory";
59     private static final boolean localLOGV = false;
60
61     private static final String MEMORY_SD_SIZE = "memory_sd_size";
62
63     private static final String MEMORY_SD_AVAIL = "memory_sd_avail";
64
65     private static final String MEMORY_SD_MOUNT_TOGGLE = "memory_sd_mount_toggle";
66
67     private static final String MEMORY_SD_FORMAT = "memory_sd_format";
68
69     private static final int DLG_CONFIRM_UNMOUNT = 1;
70     private static final int DLG_ERROR_UNMOUNT = 2;
71
72     private Resources mRes;
73
74     private Preference mSdSize;
75     private Preference mSdAvail;
76     private Preference mSdMountToggle;
77     private Preference mSdFormat;
78     
79     // Access using getMountService()
80     private IMountService mMountService = null;
81
82     private StorageManager mStorageManager = null;
83
84     @Override
85     protected void onCreate(Bundle icicle) {
86         super.onCreate(icicle);
87
88         if (mStorageManager == null) {
89             mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
90             mStorageManager.registerListener(mStorageListener);
91         }
92
93         addPreferencesFromResource(R.xml.device_info_memory);
94         
95         mRes = getResources();
96         mSdSize = findPreference(MEMORY_SD_SIZE);
97         mSdAvail = findPreference(MEMORY_SD_AVAIL);
98         mSdMountToggle = findPreference(MEMORY_SD_MOUNT_TOGGLE);
99         mSdFormat = findPreference(MEMORY_SD_FORMAT);
100     }
101     
102     @Override
103     protected void onResume() {
104         super.onResume();
105         
106         IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_STARTED);
107         intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
108         intentFilter.addDataScheme("file");
109         registerReceiver(mReceiver, intentFilter);
110
111         updateMemoryStatus();
112     }
113
114     StorageEventListener mStorageListener = new StorageEventListener() {
115
116         @Override
117         public void onStorageStateChanged(String path, String oldState, String newState) {
118             Log.i(TAG, "Received storage state changed notification that " +
119                     path + " changed state from " + oldState +
120                     " to " + newState);
121             updateMemoryStatus();
122         }
123     };
124     
125     @Override
126     protected void onPause() {
127         super.onPause();
128         unregisterReceiver(mReceiver);
129     }
130
131     @Override
132     protected void onDestroy() {
133         if (mStorageManager != null && mStorageListener != null) {
134             mStorageManager.unregisterListener(mStorageListener);
135         }
136         super.onDestroy();
137     }
138
139     private synchronized IMountService getMountService() {
140        if (mMountService == null) {
141            IBinder service = ServiceManager.getService("mount");
142            if (service != null) {
143                mMountService = IMountService.Stub.asInterface(service);
144            } else {
145                Log.e(TAG, "Can't get mount service");
146            }
147        }
148        return mMountService;
149     }
150     
151     @Override
152     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
153         if (preference == mSdMountToggle) {
154             String status = Environment.getExternalStorageState();
155             if (status.equals(Environment.MEDIA_MOUNTED)) {
156                 unmount();
157             } else {
158                 mount();
159             }
160             return true;
161         } else if (preference == mSdFormat) {
162             Intent intent = new Intent(Intent.ACTION_VIEW);
163             intent.setClass(this, com.android.settings.MediaFormat.class);
164             startActivity(intent);
165             return true;
166         }
167         
168         return false;
169     }
170      
171     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
172         @Override
173         public void onReceive(Context context, Intent intent) {
174             updateMemoryStatus();
175         }
176     };
177
178     @Override
179     public Dialog onCreateDialog(int id, Bundle args) {
180         switch (id) {
181         case DLG_CONFIRM_UNMOUNT:
182             return new AlertDialog.Builder(this)
183                     .setTitle(R.string.dlg_confirm_unmount_title)
184                     .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
185                         public void onClick(DialogInterface dialog, int which) {
186                             doUnmount(true);
187                         }})
188                     .setNegativeButton(R.string.cancel, null)
189                     .setMessage(R.string.dlg_confirm_unmount_text)
190                     .setOnCancelListener(this)
191                     .create();
192         case DLG_ERROR_UNMOUNT:
193             return new AlertDialog.Builder(this                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            )
194             .setTitle(R.string.dlg_error_unmount_title)
195             .setNeutralButton(R.string.dlg_ok, null)
196             .setMessage(R.string.dlg_error_unmount_text)
197             .setOnCancelListener(this)
198             .create();
199         }
200         return null;
201     }
202
203     private void doUnmount(boolean force) {
204         // Present a toast here
205         Toast.makeText(this, R.string.unmount_inform_text, Toast.LENGTH_SHORT).show();
206         IMountService mountService = getMountService();
207         String extStoragePath = Environment.getExternalStorageDirectory().toString();
208         try {
209             mSdMountToggle.setEnabled(false);
210             mSdMountToggle.setTitle(mRes.getString(R.string.sd_ejecting_title));
211             mSdMountToggle.setSummary(mRes.getString(R.string.sd_ejecting_summary));
212             mountService.unmountVolume(extStoragePath, force);
213         } catch (RemoteException e) {
214             // Informative dialog to user that
215             // unmount failed.
216             showDialogInner(DLG_ERROR_UNMOUNT);
217         }
218     }
219
220     private void showDialogInner(int id) {
221         removeDialog(id);
222         showDialog(id);
223     }
224
225     private boolean hasAppsAccessingStorage() throws RemoteException {
226         String extStoragePath = Environment.getExternalStorageDirectory().toString();
227         IMountService mountService = getMountService();
228         boolean showPidDialog = false;
229         int stUsers[] = mountService.getStorageUsers(extStoragePath);
230         if (stUsers != null && stUsers.length > 0) {
231             return true;
232         }
233         ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
234         List<ApplicationInfo> list = am.getRunningExternalApplications();
235         if (list != null && list.size() > 0) {
236             return true;
237         }
238         return false;
239     }
240
241     private void unmount() {
242         // Check if external media is in use.
243         try {
244            if (hasAppsAccessingStorage()) {
245                if (localLOGV) Log.i(TAG, "Do have storage users accessing media");
246                // Present dialog to user
247                showDialogInner(DLG_CONFIRM_UNMOUNT);
248            } else {
249                doUnmount(true);
250            }
251         } catch (RemoteException e) {
252             // Very unlikely. But present an error dialog anyway
253             Log.e(TAG, "Is MountService running?");
254             showDialogInner(DLG_ERROR_UNMOUNT);
255         }
256     }
257
258     private void mount() {
259         IMountService mountService = getMountService();
260         try {
261             if (mountService != null) {
262                 mountService.mountVolume(Environment.getExternalStorageDirectory().toString());
263             } else {
264                 Log.e(TAG, "Mount service is null, can't mount");
265             }
266         } catch (RemoteException ex) {
267         }
268     }
269
270     private void updateMemoryStatus() {
271         String status = Environment.getExternalStorageState();
272         String readOnly = "";
273         if (status.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
274             status = Environment.MEDIA_MOUNTED;
275             readOnly = mRes.getString(R.string.read_only);
276         }
277  
278         mSdFormat.setEnabled(false);
279
280         if (status.equals(Environment.MEDIA_MOUNTED)) {
281             try {
282                 File path = Environment.getExternalStorageDirectory();
283                 StatFs stat = new StatFs(path.getPath());
284                 long blockSize = stat.getBlockSize();
285                 long totalBlocks = stat.getBlockCount();
286                 long availableBlocks = stat.getAvailableBlocks();
287                 
288                 mSdSize.setSummary(formatSize(totalBlocks * blockSize));
289                 mSdAvail.setSummary(formatSize(availableBlocks * blockSize) + readOnly);
290
291                 mSdMountToggle.setEnabled(true);
292                 mSdMountToggle.setTitle(mRes.getString(R.string.sd_eject));
293                 mSdMountToggle.setSummary(mRes.getString(R.string.sd_eject_summary));
294
295             } catch (IllegalArgumentException e) {
296                 // this can occur if the SD card is removed, but we haven't received the 
297                 // ACTION_MEDIA_REMOVED Intent yet.
298                 status = Environment.MEDIA_REMOVED;
299             }
300             
301         } else {
302             mSdSize.setSummary(mRes.getString(R.string.sd_unavailable));
303             mSdAvail.setSummary(mRes.getString(R.string.sd_unavailable));
304
305
306             if (status.equals(Environment.MEDIA_UNMOUNTED) ||
307                 status.equals(Environment.MEDIA_NOFS) ||
308                 status.equals(Environment.MEDIA_UNMOUNTABLE) ) {
309                 mSdFormat.setEnabled(true);
310                 mSdMountToggle.setEnabled(true);
311                 mSdMountToggle.setTitle(mRes.getString(R.string.sd_mount));
312                 mSdMountToggle.setSummary(mRes.getString(R.string.sd_mount_summary));
313             } else {
314                 mSdMountToggle.setEnabled(false);
315                 mSdMountToggle.setTitle(mRes.getString(R.string.sd_mount));
316                 mSdMountToggle.setSummary(mRes.getString(R.string.sd_insert_summary));
317             }
318         }
319
320         File path = Environment.getDataDirectory();
321         StatFs stat = new StatFs(path.getPath());
322         long blockSize = stat.getBlockSize();
323         long availableBlocks = stat.getAvailableBlocks();
324         findPreference("memory_internal_avail").setSummary(formatSize(availableBlocks * blockSize));
325     }
326     
327     private String formatSize(long size) {
328         return Formatter.formatFileSize(this, size);
329     }
330
331     public void onCancel(DialogInterface dialog) {
332         finish();
333     }
334     
335 }