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