OSDN Git Service

Merge "Fix blank Battery Use screen due to changes in framework." into honeycomb-mr2
[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.AlertDialog;
20 import android.app.Dialog;
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.DialogInterface;
24 import android.content.DialogInterface.OnCancelListener;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.content.res.Resources;
28 import android.os.Bundle;
29 import android.os.Environment;
30 import android.os.IBinder;
31 import android.os.Parcelable;
32 import android.os.RemoteException;
33 import android.os.ServiceManager;
34 import android.os.storage.IMountService;
35 import android.os.storage.StorageEventListener;
36 import android.os.storage.StorageManager;
37 import android.os.storage.StorageVolume;
38 import android.preference.Preference;
39 import android.preference.PreferenceScreen;
40 import android.util.Log;
41 import android.widget.Toast;
42
43 import com.android.settings.R;
44 import com.android.settings.SettingsPreferenceFragment;
45
46 public class Memory extends SettingsPreferenceFragment implements OnCancelListener {
47     private static final String TAG = "MemorySettings";
48
49     private static final int DLG_CONFIRM_UNMOUNT = 1;
50     private static final int DLG_ERROR_UNMOUNT = 2;
51
52     private Resources mResources;
53
54     // The mountToggle Preference that has been clicked.
55     // The click event will be discarded if this value is not null. Reset to null after (un)mount.
56     private Preference mClickedMountToggle;
57     private String mClickedMountPoint;
58     
59     // Access using getMountService()
60     private IMountService mMountService = null;
61
62     private StorageManager mStorageManager = null;
63
64     private StorageVolumePreferenceCategory[] mStorageVolumePreferenceCategories;
65
66     @Override
67     public void onCreate(Bundle icicle) {
68         super.onCreate(icicle);
69
70         if (mStorageManager == null) {
71             mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
72             mStorageManager.registerListener(mStorageListener);
73         }
74
75         addPreferencesFromResource(R.xml.device_info_memory);
76
77         mResources = getResources();
78
79         try {
80             IMountService mountService = IMountService.Stub.asInterface(ServiceManager
81                     .getService("mount"));
82             Parcelable[] volumes = mountService.getVolumeList();
83             int length = volumes.length;
84             mStorageVolumePreferenceCategories = new StorageVolumePreferenceCategory[length];
85             for (int i = 0; i < length; i++) {
86                 StorageVolume storageVolume = (StorageVolume) volumes[i];
87                 StorageVolumePreferenceCategory storagePreferenceCategory =
88                     new StorageVolumePreferenceCategory(getActivity(), mResources, storageVolume,
89                             i == 0); // The first volume is the primary volume
90                 mStorageVolumePreferenceCategories[i] = storagePreferenceCategory;
91                 getPreferenceScreen().addPreference(storagePreferenceCategory);
92                 storagePreferenceCategory.init();
93             }
94         } catch (Exception e) {
95             Log.e(TAG, "couldn't talk to MountService", e);
96         }
97     }
98
99     @Override
100     public void onResume() {
101         super.onResume();
102         IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_STARTED);
103         intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
104         intentFilter.addDataScheme("file");
105         getActivity().registerReceiver(mMediaScannerReceiver, intentFilter);
106
107         for (int i = 0; i < mStorageVolumePreferenceCategories.length; i++) {
108             mStorageVolumePreferenceCategories[i].onResume();
109         }
110     }
111
112     StorageEventListener mStorageListener = new StorageEventListener() {
113         @Override
114         public void onStorageStateChanged(String path, String oldState, String newState) {
115             Log.i(TAG, "Received storage state changed notification that " +
116                     path + " changed state from " + oldState +
117                     " to " + newState);
118             for (int i = 0; i < mStorageVolumePreferenceCategories.length; i++) {
119                 StorageVolumePreferenceCategory svpc = mStorageVolumePreferenceCategories[i];
120                 if (path.equals(svpc.getMountPoint())) {
121                     svpc.onStorageStateChanged();
122                     break;
123                 }
124             }
125         }
126     };
127
128     @Override
129     public void onPause() {
130         super.onPause();
131         getActivity().unregisterReceiver(mMediaScannerReceiver);
132         for (int i = 0; i < mStorageVolumePreferenceCategories.length; i++) {
133             mStorageVolumePreferenceCategories[i].onPause();
134         }
135     }
136
137     @Override
138     public void onDestroy() {
139         if (mStorageManager != null && mStorageListener != null) {
140             mStorageManager.unregisterListener(mStorageListener);
141         }
142         super.onDestroy();
143     }
144
145     private synchronized IMountService getMountService() {
146        if (mMountService == null) {
147            IBinder service = ServiceManager.getService("mount");
148            if (service != null) {
149                mMountService = IMountService.Stub.asInterface(service);
150            } else {
151                Log.e(TAG, "Can't get mount service");
152            }
153        }
154        return mMountService;
155     }
156     
157     @Override
158     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
159         for (int i = 0; i < mStorageVolumePreferenceCategories.length; i++) {
160             StorageVolumePreferenceCategory svpc = mStorageVolumePreferenceCategories[i];
161             Intent intent = svpc.intentForClick(preference);
162             if (intent != null) {
163                 startActivity(intent);
164                 return true;
165             }
166
167             boolean mountToggleClicked = svpc.mountToggleClicked(preference);
168             if (mountToggleClicked && mClickedMountToggle == null) {
169                 mClickedMountToggle = preference;
170                 mClickedMountPoint = svpc.getMountPoint();
171                 String state = svpc.getStorageVolumeState();
172                 if (state.equals(Environment.MEDIA_MOUNTED) ||
173                         state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
174                     unmount();
175                 } else {
176                     mount();
177                 }
178                 return true;
179             }
180         }
181
182         return false;
183     }
184      
185     private final BroadcastReceiver mMediaScannerReceiver = new BroadcastReceiver() {
186         @Override
187         public void onReceive(Context context, Intent intent) {
188             for (int i = 0; i < mStorageVolumePreferenceCategories.length; i++) {
189                 mStorageVolumePreferenceCategories[i].onMediaScannerFinished();
190             }
191         }
192     };
193
194     @Override
195     public Dialog onCreateDialog(int id) {
196         switch (id) {
197         case DLG_CONFIRM_UNMOUNT:
198                 return new AlertDialog.Builder(getActivity())
199                     .setTitle(R.string.dlg_confirm_unmount_title)
200                     .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
201                         public void onClick(DialogInterface dialog, int which) {
202                             doUnmount();
203                         }})
204                     .setNegativeButton(R.string.cancel, null)
205                     .setMessage(R.string.dlg_confirm_unmount_text)
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             .create();
213         }
214         return null;
215     }
216
217     @Override
218     protected void showDialog(int id) {
219         super.showDialog(id);
220
221         switch (id) {
222             case DLG_CONFIRM_UNMOUNT:
223             case DLG_ERROR_UNMOUNT:
224                 setOnCancelListener(this);
225                 break;
226         }
227     }
228
229     private void doUnmount() {
230         // Present a toast here
231         Toast.makeText(getActivity(), R.string.unmount_inform_text, Toast.LENGTH_SHORT).show();
232         IMountService mountService = getMountService();
233         try {
234             mClickedMountToggle.setEnabled(false);
235             mClickedMountToggle.setTitle(mResources.getString(R.string.sd_ejecting_title));
236             mClickedMountToggle.setSummary(mResources.getString(R.string.sd_ejecting_summary));
237             mountService.unmountVolume(mClickedMountPoint, true);
238         } catch (RemoteException e) {
239             // Informative dialog to user that unmount failed.
240             showDialogInner(DLG_ERROR_UNMOUNT);
241         }
242         mClickedMountToggle = null;
243     }
244
245     private void showDialogInner(int id) {
246         removeDialog(id);
247         showDialog(id);
248     }
249
250     private boolean hasAppsAccessingStorage() throws RemoteException {
251         IMountService mountService = getMountService();
252         int stUsers[] = mountService.getStorageUsers(mClickedMountPoint);
253         if (stUsers != null && stUsers.length > 0) {
254             return true;
255         }
256         // TODO FIXME Parameterize with mountPoint and uncomment.
257         // On HC-MR2, no apps can be installed on sd and the emulated internal storage is not
258         // removable: application cannot interfere with unmount
259         /*
260         ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
261         List<ApplicationInfo> list = am.getRunningExternalApplications();
262         if (list != null && list.size() > 0) {
263             return true;
264         }
265         */
266         return false;
267     }
268
269     private void unmount() {
270         // Check if external media is in use.
271         try {
272            if (hasAppsAccessingStorage()) {
273                // Present dialog to user
274                showDialogInner(DLG_CONFIRM_UNMOUNT);
275            } else {
276                doUnmount();
277            }
278         } catch (RemoteException e) {
279             // Very unlikely. But present an error dialog anyway
280             Log.e(TAG, "Is MountService running?");
281             showDialogInner(DLG_ERROR_UNMOUNT);
282             mClickedMountToggle = null;
283         }
284     }
285
286     private void mount() {
287         IMountService mountService = getMountService();
288         try {
289             if (mountService != null) {
290                 mountService.mountVolume(mClickedMountPoint);
291             } else {
292                 Log.e(TAG, "Mount service is null, can't mount");
293             }
294         } catch (RemoteException ex) {
295             // Not much can be done
296         }
297         mClickedMountToggle = null;
298     }
299
300     public void onCancel(DialogInterface dialog) {
301         mClickedMountToggle = null;
302     }
303 }