Home | History | Annotate | Download | only in storage
      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.tv.settings.device.storage;
     18 
     19 import android.app.ActivityManager;
     20 import android.content.pm.PackageManager;
     21 import android.os.Bundle;
     22 import android.os.Environment;
     23 import android.os.storage.StorageManager;
     24 import android.os.storage.VolumeInfo;
     25 import android.support.v17.preference.LeanbackPreferenceFragment;
     26 import android.support.v7.preference.Preference;
     27 import android.support.v7.preference.PreferenceScreen;
     28 import android.text.TextUtils;
     29 import android.util.Log;
     30 
     31 import com.android.settingslib.deviceinfo.StorageMeasurement;
     32 import com.android.tv.settings.R;
     33 import com.android.tv.settings.device.apps.AppsFragment;
     34 
     35 import java.util.HashMap;
     36 import java.util.List;
     37 
     38 public class StorageFragment extends LeanbackPreferenceFragment {
     39     private static final String TAG = "StorageFragment";
     40 
     41     private static final String KEY_MIGRATE = "migrate";
     42     private static final String KEY_EJECT = "eject";
     43     private static final String KEY_ERASE = "erase";
     44     private static final String KEY_APPS_USAGE = "apps_usage";
     45     private static final String KEY_DCIM_USAGE = "dcim_usage";
     46     private static final String KEY_MUSIC_USAGE = "music_usage";
     47     private static final String KEY_DOWNLOADS_USAGE = "downloads_usage";
     48     private static final String KEY_CACHE_USAGE = "cache_usage";
     49     private static final String KEY_MISC_USAGE = "misc_usage";
     50     private static final String KEY_AVAILABLE = "available";
     51 
     52     private StorageManager mStorageManager;
     53     private PackageManager mPackageManager;
     54 
     55     private VolumeInfo mVolumeInfo;
     56 
     57     private StorageMeasurement mMeasure;
     58     private final StorageMeasurement.MeasurementReceiver mMeasurementReceiver =
     59             new MeasurementReceiver();
     60     private final StorageEventListener mStorageEventListener = new StorageEventListener();
     61 
     62     private Preference mMigratePref;
     63     private Preference mEjectPref;
     64     private Preference mErasePref;
     65     private StoragePreference mAppsUsagePref;
     66     private StoragePreference mDcimUsagePref;
     67     private StoragePreference mMusicUsagePref;
     68     private StoragePreference mDownloadsUsagePref;
     69     private StoragePreference mCacheUsagePref;
     70     private StoragePreference mMiscUsagePref;
     71     private StoragePreference mAvailablePref;
     72 
     73     public static void prepareArgs(Bundle bundle, VolumeInfo volumeInfo) {
     74         bundle.putString(VolumeInfo.EXTRA_VOLUME_ID, volumeInfo.getId());
     75     }
     76 
     77     @Override
     78     public void onCreate(Bundle savedInstanceState) {
     79         mStorageManager = getContext().getSystemService(StorageManager.class);
     80         mPackageManager = getContext().getPackageManager();
     81 
     82         mVolumeInfo = mStorageManager.findVolumeById(
     83                 getArguments().getString(VolumeInfo.EXTRA_VOLUME_ID));
     84 
     85         super.onCreate(savedInstanceState);
     86     }
     87 
     88     @Override
     89     public void onStart() {
     90         super.onStart();
     91         mStorageManager.registerListener(mStorageEventListener);
     92         startMeasurement();
     93     }
     94 
     95     @Override
     96     public void onResume() {
     97         super.onResume();
     98         mVolumeInfo = mStorageManager.findVolumeById(
     99                 getArguments().getString(VolumeInfo.EXTRA_VOLUME_ID));
    100         if (mVolumeInfo == null || !mVolumeInfo.isMountedReadable()) {
    101             getFragmentManager().popBackStack();
    102         } else {
    103             refresh();
    104         }
    105     }
    106 
    107     @Override
    108     public void onStop() {
    109         super.onStop();
    110         mStorageManager.unregisterListener(mStorageEventListener);
    111         stopMeasurement();
    112     }
    113 
    114     @Override
    115     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
    116         setPreferencesFromResource(R.xml.storage, null);
    117 
    118         final PreferenceScreen screen = getPreferenceScreen();
    119         screen.setTitle(mStorageManager.getBestVolumeDescription(mVolumeInfo));
    120 
    121         mMigratePref = findPreference(KEY_MIGRATE);
    122         mEjectPref = findPreference(KEY_EJECT);
    123         mErasePref = findPreference(KEY_ERASE);
    124 
    125         mAppsUsagePref = (StoragePreference) findPreference(KEY_APPS_USAGE);
    126         mDcimUsagePref = (StoragePreference) findPreference(KEY_DCIM_USAGE);
    127         mMusicUsagePref = (StoragePreference) findPreference(KEY_MUSIC_USAGE);
    128         mDownloadsUsagePref = (StoragePreference) findPreference(KEY_DOWNLOADS_USAGE);
    129         mCacheUsagePref = (StoragePreference) findPreference(KEY_CACHE_USAGE);
    130         mMiscUsagePref = (StoragePreference) findPreference(KEY_MISC_USAGE);
    131         mAvailablePref = (StoragePreference) findPreference(KEY_AVAILABLE);
    132     }
    133 
    134     private void refresh() {
    135         boolean showMigrate = false;
    136         final VolumeInfo currentExternal = mPackageManager.getPrimaryStorageCurrentVolume();
    137         // currentExternal will be null if the drive is not mounted. Don't offer the option to
    138         // migrate if so.
    139         if (currentExternal != null
    140                 && !TextUtils.equals(currentExternal.getId(), mVolumeInfo.getId())) {
    141             final List<VolumeInfo> candidates =
    142                     mPackageManager.getPrimaryStorageCandidateVolumes();
    143             for (final VolumeInfo candidate : candidates) {
    144                 if (TextUtils.equals(candidate.getId(), mVolumeInfo.getId())) {
    145                     showMigrate = true;
    146                     break;
    147                 }
    148             }
    149         }
    150 
    151         mMigratePref.setVisible(showMigrate);
    152         mMigratePref.setIntent(
    153                 MigrateStorageActivity.getLaunchIntent(getContext(), mVolumeInfo.getId(), true));
    154 
    155         final String description = mStorageManager.getBestVolumeDescription(mVolumeInfo);
    156 
    157         final boolean privateInternal = VolumeInfo.ID_PRIVATE_INTERNAL.equals(mVolumeInfo.getId());
    158         final boolean isPrivate = mVolumeInfo.getType() == VolumeInfo.TYPE_PRIVATE;
    159 
    160         mEjectPref.setVisible(!privateInternal);
    161         mEjectPref.setIntent(UnmountActivity.getIntent(getContext(), mVolumeInfo.getId(),
    162                 description));
    163         mErasePref.setVisible(!privateInternal);
    164         if (isPrivate) {
    165             mErasePref.setIntent(
    166                     FormatActivity.getFormatAsPublicIntent(getContext(), mVolumeInfo.getDiskId()));
    167             mErasePref.setTitle(R.string.storage_format_as_public);
    168         } else {
    169             mErasePref.setIntent(
    170                     FormatActivity.getFormatAsPrivateIntent(getContext(), mVolumeInfo.getDiskId()));
    171             mErasePref.setTitle(R.string.storage_format_as_private);
    172         }
    173 
    174         mAppsUsagePref.setVisible(isPrivate);
    175         mAppsUsagePref.setFragment(AppsFragment.class.getName());
    176         AppsFragment.prepareArgs(mAppsUsagePref.getExtras(), mVolumeInfo.fsUuid, description);
    177         mDcimUsagePref.setVisible(isPrivate);
    178         mMusicUsagePref.setVisible(isPrivate);
    179         mDownloadsUsagePref.setVisible(isPrivate);
    180         mCacheUsagePref.setVisible(isPrivate);
    181         mCacheUsagePref.setFragment(ConfirmClearCacheFragment.class.getName());
    182     }
    183 
    184     private void startMeasurement() {
    185         if (mVolumeInfo != null && mVolumeInfo.isMountedReadable()) {
    186             final VolumeInfo sharedVolume = mStorageManager.findEmulatedForPrivate(mVolumeInfo);
    187             mMeasure = new StorageMeasurement(getContext(), mVolumeInfo, sharedVolume);
    188             mMeasure.setReceiver(mMeasurementReceiver);
    189             mMeasure.forceMeasure();
    190         }
    191     }
    192 
    193     private void stopMeasurement() {
    194         if (mMeasure != null) {
    195             mMeasure.onDestroy();
    196         }
    197     }
    198 
    199     private void updateDetails(StorageMeasurement.MeasurementDetails details) {
    200         final int currentUser = ActivityManager.getCurrentUser();
    201         final long dcimSize = totalValues(details.mediaSize.get(currentUser),
    202                 Environment.DIRECTORY_DCIM,
    203                 Environment.DIRECTORY_MOVIES, Environment.DIRECTORY_PICTURES);
    204 
    205         final long musicSize = totalValues(details.mediaSize.get(currentUser),
    206                 Environment.DIRECTORY_MUSIC,
    207                 Environment.DIRECTORY_ALARMS, Environment.DIRECTORY_NOTIFICATIONS,
    208                 Environment.DIRECTORY_RINGTONES, Environment.DIRECTORY_PODCASTS);
    209 
    210         final long downloadsSize = totalValues(details.mediaSize.get(currentUser),
    211                 Environment.DIRECTORY_DOWNLOADS);
    212 
    213         mAvailablePref.setSize(details.availSize);
    214         mAppsUsagePref.setSize(details.appsSize.get(currentUser));
    215         mDcimUsagePref.setSize(dcimSize);
    216         mMusicUsagePref.setSize(musicSize);
    217         mDownloadsUsagePref.setSize(downloadsSize);
    218         mCacheUsagePref.setSize(details.cacheSize);
    219         mMiscUsagePref.setSize(details.miscSize.get(currentUser));
    220     }
    221 
    222     private static long totalValues(HashMap<String, Long> map, String... keys) {
    223         long total = 0;
    224         if (map != null) {
    225             for (String key : keys) {
    226                 if (map.containsKey(key)) {
    227                     total += map.get(key);
    228                 }
    229             }
    230         } else {
    231             Log.w(TAG,
    232                     "MeasurementDetails mediaSize array does not have key for current user " +
    233                             ActivityManager.getCurrentUser());
    234         }
    235         return total;
    236     }
    237 
    238     private class MeasurementReceiver implements StorageMeasurement.MeasurementReceiver {
    239 
    240         @Override
    241         public void onDetailsChanged(StorageMeasurement.MeasurementDetails details) {
    242             updateDetails(details);
    243         }
    244     }
    245 
    246     private class StorageEventListener extends android.os.storage.StorageEventListener {
    247         @Override
    248         public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
    249             mVolumeInfo = vol;
    250             if (isResumed()) {
    251                 if (mVolumeInfo.isMountedReadable()) {
    252                     refresh();
    253                 } else {
    254                     getFragmentManager().popBackStack();
    255                 }
    256             }
    257         }
    258     }
    259 }
    260