OSDN Git Service

am e2fc49ac: am 5c2a4684: Merge "Supercalifragilisticexpialidocious." into gingerbread
[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 com.android.settings.R;
20 import com.android.settings.SettingsPreferenceFragment;
21
22 import android.app.ActivityManager;
23 import android.app.AlertDialog;
24 import android.app.Dialog;
25 import android.content.BroadcastReceiver;
26 import android.content.Context;
27 import android.content.DialogInterface;
28 import android.content.Intent;
29 import android.content.IntentFilter;
30 import android.content.DialogInterface.OnCancelListener;
31 import android.content.pm.ApplicationInfo;
32 import android.content.res.Resources;
33 import android.os.Bundle;
34 import android.hardware.Usb;
35 import android.os.Environment;
36 import android.os.IBinder;
37 import android.os.RemoteException;
38 import android.os.ServiceManager;
39 import android.os.StatFs;
40 import android.os.storage.IMountService;
41 import android.os.storage.StorageEventListener;
42 import android.os.storage.StorageManager;
43 import android.preference.CheckBoxPreference;
44 import android.preference.Preference;
45 import android.preference.PreferenceScreen;
46 import android.provider.Settings;
47 import android.text.format.Formatter;
48 import android.util.Log;
49 import android.widget.Toast;
50
51 import java.io.File;
52 import java.util.List;
53
54 public class Memory extends SettingsPreferenceFragment implements OnCancelListener {
55     private static final String TAG = "Memory";
56     private static final boolean localLOGV = false;
57
58     private static final String MEMORY_SD_SIZE = "memory_sd_size";
59
60     private static final String MEMORY_SD_AVAIL = "memory_sd_avail";
61
62     private static final String MEMORY_SD_MOUNT_TOGGLE = "memory_sd_mount_toggle";
63
64     private static final String MEMORY_SD_FORMAT = "memory_sd_format";
65
66     private static final String PTP_MODE_TOGGLE = "ptp_mode_toggle";
67
68     private static final int DLG_CONFIRM_UNMOUNT = 1;
69     private static final int DLG_ERROR_UNMOUNT = 2;
70
71     private Resources mRes;
72
73     private Preference mSdSize;
74     private Preference mSdAvail;
75     private Preference mSdMountToggle;
76     private Preference mSdFormat;
77     private CheckBoxPreference mPtpModeToggle;
78     
79     // Access using getMountService()
80     private IMountService mMountService = null;
81
82     private StorageManager mStorageManager = null;
83
84     @Override
85     public 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         mPtpModeToggle = (CheckBoxPreference)findPreference(PTP_MODE_TOGGLE);
102         if (Usb.isFunctionSupported(Usb.USB_FUNCTION_MTP)) {
103             mPtpModeToggle.setChecked(Settings.System.getInt(
104                     getContentResolver(),
105                     Settings.System.USE_PTP_INTERFACE, 0) != 0);
106         } else {
107             // hide the PTP mode toggle checkbox if MTP is not supported
108             getPreferenceScreen().removePreference(mPtpModeToggle);
109         }
110     }
111     
112     @Override
113     public void onResume() {
114         super.onResume();
115         
116         IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_STARTED);
117         intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
118         intentFilter.addDataScheme("file");
119         getActivity().registerReceiver(mReceiver, intentFilter);
120
121         updateMemoryStatus();
122     }
123
124     StorageEventListener mStorageListener = new StorageEventListener() {
125
126         @Override
127         public void onStorageStateChanged(String path, String oldState, String newState) {
128             Log.i(TAG, "Received storage state changed notification that " +
129                     path + " changed state from " + oldState +
130                     " to " + newState);
131             updateMemoryStatus();
132         }
133     };
134     
135     @Override
136     public void onPause() {
137         super.onPause();
138         getActivity().unregisterReceiver(mReceiver);
139     }
140
141     @Override
142     public void onDestroy() {
143         if (mStorageManager != null && mStorageListener != null) {
144             mStorageManager.unregisterListener(mStorageListener);
145         }
146         super.onDestroy();
147     }
148
149     private synchronized IMountService getMountService() {
150        if (mMountService == null) {
151            IBinder service = ServiceManager.getService("mount");
152            if (service != null) {
153                mMountService = IMountService.Stub.asInterface(service);
154            } else {
155                Log.e(TAG, "Can't get mount service");
156            }
157        }
158        return mMountService;
159     }
160     
161     @Override
162     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
163         if (preference == mSdMountToggle) {
164             String status = Environment.getExternalStorageState();
165             if (status.equals(Environment.MEDIA_MOUNTED)) {
166                 unmount();
167             } else {
168                 mount();
169             }
170             return true;
171         } else if (preference == mSdFormat) {
172             Intent intent = new Intent(Intent.ACTION_VIEW);
173             intent.setClass(getActivity(), com.android.settings.MediaFormat.class);
174             startActivity(intent);
175             return true;
176         } else if (preference == mPtpModeToggle) {
177             Settings.System.putInt(getContentResolver(),
178                     Settings.System.USE_PTP_INTERFACE,
179                     mPtpModeToggle.isChecked() ? 1 : 0);
180             return true;
181         }
182
183         return false;
184     }
185      
186     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
187         @Override
188         public void onReceive(Context context, Intent intent) {
189             updateMemoryStatus();
190         }
191     };
192
193     @Override
194     public Dialog onCreateDialog(int id) {
195         switch (id) {
196         case DLG_CONFIRM_UNMOUNT:
197                 return new AlertDialog.Builder(getActivity())
198                     .setTitle(R.string.dlg_confirm_unmount_title)
199                     .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
200                         public void onClick(DialogInterface dialog, int which) {
201                             doUnmount(true);
202                         }})
203                     .setNegativeButton(R.string.cancel, null)
204                     .setMessage(R.string.dlg_confirm_unmount_text)
205                     .setOnCancelListener(this)
206                     .create();
207         case DLG_ERROR_UNMOUNT:
208                 return new AlertDialog.Builder(getActivity())
209             .setTitle(R.string.dlg_error_unmount_title)
210             .setNeutralButton(R.string.dlg_ok, null)
211             .setMessage(R.string.dlg_error_unmount_text)
212             .setOnCancelListener(this)
213             .create();
214         }
215         return null;
216     }
217
218     private void doUnmount(boolean force) {
219         // Present a toast here
220         Toast.makeText(getActivity(), R.string.unmount_inform_text, Toast.LENGTH_SHORT).show();
221         IMountService mountService = getMountService();
222         String extStoragePath = Environment.getExternalStorageDirectory().toString();
223         try {
224             mSdMountToggle.setEnabled(false);
225             mSdMountToggle.setTitle(mRes.getString(R.string.sd_ejecting_title));
226             mSdMountToggle.setSummary(mRes.getString(R.string.sd_ejecting_summary));
227             mountService.unmountVolume(extStoragePath, force);
228         } catch (RemoteException e) {
229             // Informative dialog to user that
230             // unmount failed.
231             showDialogInner(DLG_ERROR_UNMOUNT);
232         }
233     }
234
235     private void showDialogInner(int id) {
236         removeDialog(id);
237         showDialog(id);
238     }
239
240     private boolean hasAppsAccessingStorage() throws RemoteException {
241         String extStoragePath = Environment.getExternalStorageDirectory().toString();
242         IMountService mountService = getMountService();
243         int stUsers[] = mountService.getStorageUsers(extStoragePath);
244         if (stUsers != null && stUsers.length > 0) {
245             return true;
246         }
247         ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
248         List<ApplicationInfo> list = am.getRunningExternalApplications();
249         if (list != null && list.size() > 0) {
250             return true;
251         }
252         return false;
253     }
254
255     private void unmount() {
256         // Check if external media is in use.
257         try {
258            if (hasAppsAccessingStorage()) {
259                if (localLOGV) Log.i(TAG, "Do have storage users accessing media");
260                // Present dialog to user
261                showDialogInner(DLG_CONFIRM_UNMOUNT);
262            } else {
263                doUnmount(true);
264            }
265         } catch (RemoteException e) {
266             // Very unlikely. But present an error dialog anyway
267             Log.e(TAG, "Is MountService running?");
268             showDialogInner(DLG_ERROR_UNMOUNT);
269         }
270     }
271
272     private void mount() {
273         IMountService mountService = getMountService();
274         try {
275             if (mountService != null) {
276                 mountService.mountVolume(Environment.getExternalStorageDirectory().toString());
277             } else {
278                 Log.e(TAG, "Mount service is null, can't mount");
279             }
280         } catch (RemoteException ex) {
281         }
282     }
283
284     private void updateMemoryStatus() {
285         String status = Environment.getExternalStorageState();
286         String readOnly = "";
287         if (status.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
288             status = Environment.MEDIA_MOUNTED;
289             readOnly = mRes.getString(R.string.read_only);
290         }
291  
292         mSdFormat.setEnabled(false);
293
294         if (status.equals(Environment.MEDIA_MOUNTED)) {
295             try {
296                 File path = Environment.getExternalStorageDirectory();
297                 StatFs stat = new StatFs(path.getPath());
298                 long blockSize = stat.getBlockSize();
299                 long totalBlocks = stat.getBlockCount();
300                 long availableBlocks = stat.getAvailableBlocks();
301                 
302                 mSdSize.setSummary(formatSize(totalBlocks * blockSize));
303                 mSdAvail.setSummary(formatSize(availableBlocks * blockSize) + readOnly);
304
305                 mSdMountToggle.setEnabled(true);
306                 mSdMountToggle.setTitle(mRes.getString(R.string.sd_eject));
307                 mSdMountToggle.setSummary(mRes.getString(R.string.sd_eject_summary));
308
309             } catch (IllegalArgumentException e) {
310                 // this can occur if the SD card is removed, but we haven't received the 
311                 // ACTION_MEDIA_REMOVED Intent yet.
312                 status = Environment.MEDIA_REMOVED;
313             }
314             
315         } else {
316             mSdSize.setSummary(mRes.getString(R.string.sd_unavailable));
317             mSdAvail.setSummary(mRes.getString(R.string.sd_unavailable));
318
319
320             if (status.equals(Environment.MEDIA_UNMOUNTED) ||
321                 status.equals(Environment.MEDIA_NOFS) ||
322                 status.equals(Environment.MEDIA_UNMOUNTABLE) ) {
323                 mSdFormat.setEnabled(true);
324                 mSdMountToggle.setEnabled(true);
325                 mSdMountToggle.setTitle(mRes.getString(R.string.sd_mount));
326                 mSdMountToggle.setSummary(mRes.getString(R.string.sd_mount_summary));
327             } else {
328                 mSdMountToggle.setEnabled(false);
329                 mSdMountToggle.setTitle(mRes.getString(R.string.sd_mount));
330                 mSdMountToggle.setSummary(mRes.getString(R.string.sd_insert_summary));
331             }
332         }
333
334         File path = Environment.getDataDirectory();
335         StatFs stat = new StatFs(path.getPath());
336         long blockSize = stat.getBlockSize();
337         long availableBlocks = stat.getAvailableBlocks();
338         findPreference("memory_internal_avail").setSummary(formatSize(availableBlocks * blockSize));
339     }
340     
341     private String formatSize(long size) {
342         return Formatter.formatFileSize(getActivity(), size);
343     }
344
345     public void onCancel(DialogInterface dialog) {
346         // TODO: Is this really required?
347         // finish();
348     }
349     
350 }