blob: 82131706b59b6248ef7620ff23e17152cd303b19 [file] [log] [blame]
/*
* 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<File> 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();
}
}