• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.content.Context;
21 import android.content.res.Resources;
22 import android.net.Uri;
23 import android.os.Bundle;
24 import android.os.UserManager;
25 import android.os.storage.DiskInfo;
26 import android.os.storage.StorageEventListener;
27 import android.os.storage.StorageManager;
28 import android.os.storage.VolumeInfo;
29 import android.os.storage.VolumeRecord;
30 import android.provider.DocumentsContract;
31 import android.support.v7.preference.Preference;
32 import android.support.v7.preference.PreferenceScreen;
33 import android.text.TextUtils;
34 import android.text.format.Formatter;
35 import android.text.format.Formatter.BytesResult;
36 import android.view.View;
37 import android.view.ViewGroup;
38 import android.widget.Button;
39 
40 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
41 import com.android.internal.util.Preconditions;
42 import com.android.settings.R;
43 import com.android.settings.SettingsPreferenceFragment;
44 import com.android.settings.deviceinfo.StorageSettings.MountTask;
45 import com.android.settings.deviceinfo.StorageSettings.UnmountTask;
46 
47 import java.io.File;
48 import java.util.Objects;
49 
50 /**
51  * Panel showing summary and actions for a {@link VolumeInfo#TYPE_PUBLIC}
52  * storage volume.
53  */
54 public class PublicVolumeSettings extends SettingsPreferenceFragment {
55     // TODO: disable unmount when providing over MTP/PTP
56 
57     private StorageManager mStorageManager;
58 
59     private String mVolumeId;
60     private VolumeInfo mVolume;
61     private DiskInfo mDisk;
62 
63     private StorageSummaryPreference mSummary;
64 
65     private Preference mMount;
66     private Preference mFormatPublic;
67     private Preference mFormatPrivate;
68     private Button mUnmount;
69 
70     private boolean mIsPermittedToAdopt;
71 
isVolumeValid()72     private boolean isVolumeValid() {
73         return (mVolume != null) && (mVolume.getType() == VolumeInfo.TYPE_PUBLIC)
74                 && mVolume.isMountedReadable();
75     }
76 
77     @Override
getMetricsCategory()78     public int getMetricsCategory() {
79         return MetricsEvent.DEVICEINFO_STORAGE;
80     }
81 
82     @Override
onCreate(Bundle icicle)83     public void onCreate(Bundle icicle) {
84         super.onCreate(icicle);
85 
86         final Context context = getActivity();
87 
88         mIsPermittedToAdopt = UserManager.get(context).isAdminUser()
89                 && !ActivityManager.isUserAMonkey();
90 
91         mStorageManager = context.getSystemService(StorageManager.class);
92 
93         if (DocumentsContract.ACTION_DOCUMENT_ROOT_SETTINGS.equals(
94                 getActivity().getIntent().getAction())) {
95             final Uri rootUri = getActivity().getIntent().getData();
96             final String fsUuid = DocumentsContract.getRootId(rootUri);
97             mVolume = mStorageManager.findVolumeByUuid(fsUuid);
98         } else {
99             final String volId = getArguments().getString(VolumeInfo.EXTRA_VOLUME_ID);
100             if (volId != null) {
101                 mVolume = mStorageManager.findVolumeById(volId);
102             }
103         }
104 
105         if (!isVolumeValid()) {
106             getActivity().finish();
107             return;
108         }
109 
110         mDisk = mStorageManager.findDiskById(mVolume.getDiskId());
111         Preconditions.checkNotNull(mDisk);
112 
113         mVolumeId = mVolume.getId();
114 
115         addPreferencesFromResource(R.xml.device_info_storage_volume);
116         getPreferenceScreen().setOrderingAsAdded(true);
117 
118         mSummary = new StorageSummaryPreference(getPrefContext());
119 
120         mMount = buildAction(R.string.storage_menu_mount);
121         mUnmount = new Button(getActivity());
122         mUnmount.setText(R.string.storage_menu_unmount);
123         mUnmount.setOnClickListener(mUnmountListener);
124         mFormatPublic = buildAction(R.string.storage_menu_format);
125         if (mIsPermittedToAdopt) {
126             mFormatPrivate = buildAction(R.string.storage_menu_format_private);
127         }
128     }
129 
130     @Override
onActivityCreated(Bundle savedInstanceState)131     public void onActivityCreated(Bundle savedInstanceState) {
132         super.onActivityCreated(savedInstanceState);
133 
134         // If the volume isn't valid, we are not scaffolded to set up a view.
135         if (!isVolumeValid()) {
136             return;
137         }
138 
139         final Resources resources = getResources();
140         final int padding = resources.getDimensionPixelSize(
141                 R.dimen.unmount_button_padding);
142         final ViewGroup buttonBar = getButtonBar();
143         buttonBar.removeAllViews();
144         buttonBar.setPadding(padding, padding, padding, padding);
145         buttonBar.addView(mUnmount, new ViewGroup.LayoutParams(
146                 ViewGroup.LayoutParams.MATCH_PARENT,
147                 ViewGroup.LayoutParams.WRAP_CONTENT));
148     }
149 
update()150     public void update() {
151         if (!isVolumeValid()) {
152             getActivity().finish();
153             return;
154         }
155 
156         getActivity().setTitle(mStorageManager.getBestVolumeDescription(mVolume));
157 
158         final Context context = getActivity();
159         final PreferenceScreen screen = getPreferenceScreen();
160 
161         screen.removeAll();
162 
163         if (mVolume.isMountedReadable()) {
164             addPreference(mSummary);
165 
166             final File file = mVolume.getPath();
167             final long totalBytes = file.getTotalSpace();
168             final long freeBytes = file.getFreeSpace();
169             final long usedBytes = totalBytes - freeBytes;
170 
171             final BytesResult result = Formatter.formatBytes(getResources(), usedBytes, 0);
172             mSummary.setTitle(TextUtils.expandTemplate(getText(R.string.storage_size_large),
173                     result.value, result.units));
174             mSummary.setSummary(getString(R.string.storage_volume_used,
175                     Formatter.formatFileSize(context, totalBytes)));
176             mSummary.setPercent(usedBytes, totalBytes);
177         }
178 
179         if (mVolume.getState() == VolumeInfo.STATE_UNMOUNTED) {
180             addPreference(mMount);
181         }
182         if (mVolume.isMountedReadable()) {
183             getButtonBar().setVisibility(View.VISIBLE);
184         }
185         addPreference(mFormatPublic);
186         if (mDisk.isAdoptable() && mIsPermittedToAdopt) {
187             addPreference(mFormatPrivate);
188         }
189     }
190 
addPreference(Preference pref)191     private void addPreference(Preference pref) {
192         pref.setOrder(Preference.DEFAULT_ORDER);
193         getPreferenceScreen().addPreference(pref);
194     }
195 
buildAction(int titleRes)196     private Preference buildAction(int titleRes) {
197         final Preference pref = new Preference(getPrefContext());
198         pref.setTitle(titleRes);
199         return pref;
200     }
201 
202     @Override
onResume()203     public void onResume() {
204         super.onResume();
205 
206         // Refresh to verify that we haven't been formatted away
207         mVolume = mStorageManager.findVolumeById(mVolumeId);
208         if (!isVolumeValid()) {
209             getActivity().finish();
210             return;
211         }
212 
213         mStorageManager.registerListener(mStorageListener);
214         update();
215     }
216 
217     @Override
onPause()218     public void onPause() {
219         super.onPause();
220         mStorageManager.unregisterListener(mStorageListener);
221     }
222 
223     @Override
onPreferenceTreeClick(Preference pref)224     public boolean onPreferenceTreeClick(Preference pref) {
225         if (pref == mMount) {
226             new MountTask(getActivity(), mVolume).execute();
227         } else if (pref == mFormatPublic) {
228             StorageWizardFormatConfirm.showPublic(getActivity(), mDisk.getId());
229         } else if (pref == mFormatPrivate) {
230             StorageWizardFormatConfirm.showPrivate(getActivity(), mDisk.getId());
231         }
232 
233         return super.onPreferenceTreeClick(pref);
234     }
235 
236     private final View.OnClickListener mUnmountListener = new View.OnClickListener() {
237         @Override
238         public void onClick(View v) {
239             new UnmountTask(getActivity(), mVolume).execute();
240         }
241     };
242 
243     private final StorageEventListener mStorageListener = new StorageEventListener() {
244         @Override
245         public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
246             if (Objects.equals(mVolume.getId(), vol.getId())) {
247                 mVolume = vol;
248                 update();
249             }
250         }
251 
252         @Override
253         public void onVolumeRecordChanged(VolumeRecord rec) {
254             if (Objects.equals(mVolume.getFsUuid(), rec.getFsUuid())) {
255                 mVolume = mStorageManager.findVolumeById(mVolumeId);
256                 update();
257             }
258         }
259     };
260 }
261