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.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     protected 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             mVolume = mStorageManager.findVolumeById(volId);
    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
    130     public void onActivityCreated(Bundle savedInstanceState) {
    131         super.onActivityCreated(savedInstanceState);
    132         final Resources resources = getResources();
    133         final int padding = resources.getDimensionPixelSize(
    134                 R.dimen.unmount_button_padding);
    135         final ViewGroup buttonBar = getButtonBar();
    136         buttonBar.removeAllViews();
    137         buttonBar.setPadding(padding, padding, padding, padding);
    138         buttonBar.addView(mUnmount, new ViewGroup.LayoutParams(
    139                 ViewGroup.LayoutParams.MATCH_PARENT,
    140                 ViewGroup.LayoutParams.WRAP_CONTENT));
    141     }
    142 
    143     public void update() {
    144         if (!isVolumeValid()) {
    145             getActivity().finish();
    146             return;
    147         }
    148 
    149         getActivity().setTitle(mStorageManager.getBestVolumeDescription(mVolume));
    150 
    151         final Context context = getActivity();
    152         final PreferenceScreen screen = getPreferenceScreen();
    153 
    154         screen.removeAll();
    155 
    156         if (mVolume.isMountedReadable()) {
    157             addPreference(mSummary);
    158 
    159             final File file = mVolume.getPath();
    160             final long totalBytes = file.getTotalSpace();
    161             final long freeBytes = file.getFreeSpace();
    162             final long usedBytes = totalBytes - freeBytes;
    163 
    164             final BytesResult result = Formatter.formatBytes(getResources(), usedBytes, 0);
    165             mSummary.setTitle(TextUtils.expandTemplate(getText(R.string.storage_size_large),
    166                     result.value, result.units));
    167             mSummary.setSummary(getString(R.string.storage_volume_used,
    168                     Formatter.formatFileSize(context, totalBytes)));
    169             mSummary.setPercent((int) ((usedBytes * 100) / totalBytes));
    170         }
    171 
    172         if (mVolume.getState() == VolumeInfo.STATE_UNMOUNTED) {
    173             addPreference(mMount);
    174         }
    175         if (mVolume.isMountedReadable()) {
    176             getButtonBar().setVisibility(View.VISIBLE);
    177         }
    178         addPreference(mFormatPublic);
    179         if (mDisk.isAdoptable() && mIsPermittedToAdopt) {
    180             addPreference(mFormatPrivate);
    181         }
    182     }
    183 
    184     private void addPreference(Preference pref) {
    185         pref.setOrder(Preference.DEFAULT_ORDER);
    186         getPreferenceScreen().addPreference(pref);
    187     }
    188 
    189     private Preference buildAction(int titleRes) {
    190         final Preference pref = new Preference(getPrefContext());
    191         pref.setTitle(titleRes);
    192         return pref;
    193     }
    194 
    195     @Override
    196     public void onResume() {
    197         super.onResume();
    198 
    199         // Refresh to verify that we haven't been formatted away
    200         mVolume = mStorageManager.findVolumeById(mVolumeId);
    201         if (!isVolumeValid()) {
    202             getActivity().finish();
    203             return;
    204         }
    205 
    206         mStorageManager.registerListener(mStorageListener);
    207         update();
    208     }
    209 
    210     @Override
    211     public void onPause() {
    212         super.onPause();
    213         mStorageManager.unregisterListener(mStorageListener);
    214     }
    215 
    216     @Override
    217     public boolean onPreferenceTreeClick(Preference pref) {
    218         final Context context = getActivity();
    219         if (pref == mMount) {
    220             new MountTask(context, mVolume).execute();
    221         } else if (pref == mFormatPublic) {
    222             final Intent intent = new Intent(context, StorageWizardFormatConfirm.class);
    223             intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
    224             intent.putExtra(StorageWizardFormatConfirm.EXTRA_FORMAT_PRIVATE, false);
    225             startActivity(intent);
    226         } else if (pref == mFormatPrivate) {
    227             final Intent intent = new Intent(context, StorageWizardFormatConfirm.class);
    228             intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
    229             intent.putExtra(StorageWizardFormatConfirm.EXTRA_FORMAT_PRIVATE, true);
    230             startActivity(intent);
    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