/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.storagemanager.deletionhelper; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; import android.text.format.Formatter; import android.util.AttributeSet; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.storagemanager.R; import com.android.storagemanager.utils.IconProvider; import com.android.storagemanager.utils.PreferenceListCache; import java.io.File; import java.util.Set; /** * DownloadsDeletionPreferenceGroup defines a checkable preference group which contains * downloads file deletion preferences. */ public class DownloadsDeletionPreferenceGroup extends CollapsibleCheckboxPreferenceGroup implements DeletionType.FreeableChangedListener, Preference.OnPreferenceChangeListener { private DownloadsDeletionType mDeletionType; private DeletionType.FreeableChangedListener mListener; private IconProvider mIconProvider; // Purely for test. public DownloadsDeletionPreferenceGroup(Context context) { super(context); init(); } public DownloadsDeletionPreferenceGroup(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { setChecked(true); setOrderingAsAdded(false); setOnPreferenceChangeListener(this); } /** * Set up a deletion type to get info for the preference group. * @param type A {@link DownloadsDeletionType}. */ public void registerDeletionService(DownloadsDeletionType type) { mDeletionType = type; mDeletionType.registerFreeableChangedListener(this); } /** * Registers a callback to be called when the amount of freeable space updates. * @param listener The callback listener. */ public void registerFreeableChangedListener(DeletionType.FreeableChangedListener listener) { mListener = listener; } @Override public void onFreeableChanged(int numItems, long freeableBytes) { updatePreferenceText(numItems, freeableBytes, mDeletionType.getMostRecentLastModified()); maybeUpdateListener(numItems, freeableBytes); switchSpinnerToCheckboxOrDisablePreference(freeableBytes, mDeletionType.getLoadingStatus()); updateFiles(); } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { boolean checked = (boolean) newValue; if (!checked) { // Temporarily stop listening to avoid propagating the checked change to children. setOnPreferenceChangeListener(null); setChecked(false); setOnPreferenceChangeListener(this); } // If we have no deletion type, we have no files to toggle. if (mDeletionType == null) { return true; } // If the group checkbox changed, we need to toggle every child preference. if (preference == this) { for (int i = 0; i < getPreferenceCount(); i++) { DownloadsFilePreference p = (DownloadsFilePreference) getPreference(i); p.setOnPreferenceChangeListener(null); mDeletionType.setFileChecked(p.getFile(), checked); p.setChecked(checked); p.setOnPreferenceChangeListener(this); } maybeUpdateListener( mDeletionType.getFiles().size(), mDeletionType.getFreeableBytes(DeletionHelperSettings.COUNT_CHECKED_ONLY)); MetricsLogger.action(getContext(), MetricsEvent.ACTION_DELETION_SELECTION_DOWNLOADS, checked); return true; } // If a single DownloadFilePreference changed, we need to toggle just itself. DownloadsFilePreference p = (DownloadsFilePreference) preference; mDeletionType.setFileChecked(p.getFile(), checked); maybeUpdateListener( mDeletionType.getFiles().size(), mDeletionType.getFreeableBytes(DeletionHelperSettings.COUNT_CHECKED_ONLY)); return true; } @Override public void onClick() { super.onClick(); MetricsLogger.action( getContext(), MetricsEvent.ACTION_DELETION_DOWNLOADS_COLLAPSED, isCollapsed()); } @VisibleForTesting void injectIconProvider(IconProvider iconProvider) { mIconProvider = iconProvider; } private void updatePreferenceText(int itemCount, long bytes, long mostRecent) { Context context = getContext(); setTitle(context.getString(R.string.deletion_helper_downloads_title)); // If there are no files to clear, show the empty text instead. if (itemCount != 0) { setSummary(context.getString(R.string.deletion_helper_downloads_category_summary, Formatter.formatFileSize(context, bytes))); } else { setSummary(context.getString(R.string.deletion_helper_downloads_summary_empty, Formatter.formatFileSize(context, bytes))); } } private void maybeUpdateListener(int numItems, long bytesFreeable) { if (mListener != null) { mListener.onFreeableChanged(numItems, bytesFreeable); } } private void updateFiles() { PreferenceListCache cache = new PreferenceListCache(this); Set files = mDeletionType.getFiles(); Context context = getContext(); Resources res = context.getResources(); IconProvider iconProvider = mIconProvider == null ? new IconProvider(context) : mIconProvider; for (File file : files) { DownloadsFilePreference filePreference = (DownloadsFilePreference) cache.getCachedPreference(file.getPath()); if (filePreference == null) { filePreference = new DownloadsFilePreference(context, file, iconProvider); filePreference.setChecked(mDeletionType.isChecked(file)); filePreference.setOnPreferenceChangeListener(this); Bitmap thumbnail = mDeletionType.getCachedThumbnail(file); if (thumbnail != null) { filePreference.setIcon(new BitmapDrawable(res, thumbnail)); } } addPreference(filePreference); } cache.removeCachedPrefs(); } }