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