Home | History | Annotate | Download | only in deletionhelper
      1 /*
      2  * Copyright (C) 2016 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.storagemanager.deletionhelper;
     18 
     19 import android.content.Context;
     20 import android.content.res.Resources;
     21 import android.graphics.Bitmap;
     22 import android.graphics.drawable.BitmapDrawable;
     23 import android.support.annotation.VisibleForTesting;
     24 import android.support.v7.preference.Preference;
     25 import android.text.format.Formatter;
     26 import android.util.AttributeSet;
     27 
     28 import com.android.internal.logging.MetricsLogger;
     29 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     30 import com.android.storagemanager.R;
     31 import com.android.storagemanager.utils.IconProvider;
     32 import com.android.storagemanager.utils.PreferenceListCache;
     33 
     34 import java.io.File;
     35 import java.util.Set;
     36 
     37 /**
     38  * DownloadsDeletionPreferenceGroup defines a checkable preference group which contains
     39  * downloads file deletion preferences.
     40  */
     41 public class DownloadsDeletionPreferenceGroup extends CollapsibleCheckboxPreferenceGroup
     42         implements DeletionType.FreeableChangedListener, Preference.OnPreferenceChangeListener {
     43     private DownloadsDeletionType mDeletionType;
     44     private DeletionType.FreeableChangedListener mListener;
     45     private IconProvider mIconProvider; // Purely for test.
     46 
     47     public DownloadsDeletionPreferenceGroup(Context context) {
     48         super(context);
     49         init();
     50     }
     51 
     52     public DownloadsDeletionPreferenceGroup(Context context, AttributeSet attrs) {
     53         super(context, attrs);
     54         init();
     55     }
     56 
     57     private void init() {
     58         setChecked(true);
     59         setOrderingAsAdded(false);
     60         setOnPreferenceChangeListener(this);
     61     }
     62 
     63     /**
     64      * Set up a deletion type to get info for the preference group.
     65      * @param type A {@link DownloadsDeletionType}.
     66      */
     67     public void registerDeletionService(DownloadsDeletionType type) {
     68         mDeletionType = type;
     69         mDeletionType.registerFreeableChangedListener(this);
     70     }
     71 
     72     /**
     73      * Registers a callback to be called when the amount of freeable space updates.
     74      * @param listener The callback listener.
     75      */
     76     public void registerFreeableChangedListener(DeletionType.FreeableChangedListener listener) {
     77         mListener = listener;
     78     }
     79 
     80     @Override
     81     public void onFreeableChanged(int numItems, long freeableBytes) {
     82         updatePreferenceText(numItems, freeableBytes, mDeletionType.getMostRecentLastModified());
     83         maybeUpdateListener(numItems, freeableBytes);
     84         switchSpinnerToCheckboxOrDisablePreference(freeableBytes, mDeletionType.getLoadingStatus());
     85         updateFiles();
     86     }
     87 
     88     @Override
     89     public boolean onPreferenceChange(Preference preference, Object newValue) {
     90         boolean checked = (boolean) newValue;
     91         if (!checked) {
     92             // Temporarily stop listening to avoid propagating the checked change to children.
     93             setOnPreferenceChangeListener(null);
     94             setChecked(false);
     95             setOnPreferenceChangeListener(this);
     96         }
     97 
     98         // If we have no deletion type, we have no files to toggle.
     99         if (mDeletionType == null) {
    100             return true;
    101         }
    102 
    103         // If the group checkbox changed, we need to toggle every child preference.
    104         if (preference == this) {
    105             for (int i = 0; i < getPreferenceCount(); i++) {
    106                 DownloadsFilePreference p = (DownloadsFilePreference) getPreference(i);
    107                 p.setOnPreferenceChangeListener(null);
    108                 mDeletionType.setFileChecked(p.getFile(), checked);
    109                 p.setChecked(checked);
    110                 p.setOnPreferenceChangeListener(this);
    111             }
    112             maybeUpdateListener(
    113                     mDeletionType.getFiles().size(),
    114                     mDeletionType.getFreeableBytes(DeletionHelperSettings.COUNT_CHECKED_ONLY));
    115             MetricsLogger.action(getContext(), MetricsEvent.ACTION_DELETION_SELECTION_DOWNLOADS,
    116                     checked);
    117             return true;
    118         }
    119 
    120         // If a single DownloadFilePreference changed, we need to toggle just itself.
    121         DownloadsFilePreference p = (DownloadsFilePreference) preference;
    122         mDeletionType.setFileChecked(p.getFile(), checked);
    123         maybeUpdateListener(
    124                 mDeletionType.getFiles().size(),
    125                 mDeletionType.getFreeableBytes(DeletionHelperSettings.COUNT_CHECKED_ONLY));
    126         return true;
    127     }
    128 
    129     @Override
    130     public void onClick() {
    131         super.onClick();
    132         MetricsLogger.action(
    133                 getContext(), MetricsEvent.ACTION_DELETION_DOWNLOADS_COLLAPSED, isCollapsed());
    134     }
    135 
    136     @VisibleForTesting
    137     void injectIconProvider(IconProvider iconProvider) {
    138         mIconProvider = iconProvider;
    139     }
    140 
    141     private void updatePreferenceText(int itemCount, long bytes, long mostRecent) {
    142         Context context = getContext();
    143         setTitle(context.getString(R.string.deletion_helper_downloads_title));
    144         // If there are no files to clear, show the empty text instead.
    145         if (itemCount != 0) {
    146             setSummary(context.getString(R.string.deletion_helper_downloads_category_summary,
    147                     Formatter.formatFileSize(context, bytes)));
    148         } else {
    149             setSummary(context.getString(R.string.deletion_helper_downloads_summary_empty,
    150                     Formatter.formatFileSize(context, bytes)));
    151         }
    152     }
    153 
    154     private void maybeUpdateListener(int numItems, long bytesFreeable) {
    155         if (mListener != null) {
    156             mListener.onFreeableChanged(numItems, bytesFreeable);
    157         }
    158     }
    159 
    160     private void updateFiles() {
    161         PreferenceListCache cache = new PreferenceListCache(this);
    162         Set<File> files = mDeletionType.getFiles();
    163         Context context = getContext();
    164         Resources res = context.getResources();
    165         IconProvider iconProvider =
    166                 mIconProvider == null ? new IconProvider(context) : mIconProvider;
    167         for (File file : files) {
    168             DownloadsFilePreference filePreference =
    169                     (DownloadsFilePreference) cache.getCachedPreference(file.getPath());
    170             if (filePreference == null) {
    171                 filePreference = new DownloadsFilePreference(context, file, iconProvider);
    172                 filePreference.setChecked(mDeletionType.isChecked(file));
    173                 filePreference.setOnPreferenceChangeListener(this);
    174                 Bitmap thumbnail = mDeletionType.getCachedThumbnail(file);
    175                 if (thumbnail != null) {
    176                     filePreference.setIcon(new BitmapDrawable(res, thumbnail));
    177                 }
    178             }
    179             addPreference(filePreference);
    180         }
    181         cache.removeCachedPrefs();
    182     }
    183 }
    184