blob: 0010b05406e1d447a25cdb94469c253e86bf32ea [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 androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
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.PreferenceListCache;
import java.util.List;
/**
* AppDeletionPreferenceGroup is a collapsible checkbox preference group which contains many
* apps to be cleared in the Deletion Helper.
*/
public class AppDeletionPreferenceGroup extends CollapsibleCheckboxPreferenceGroup
implements AppDeletionType.AppListener, Preference.OnPreferenceChangeListener {
private static final int ORDER_OFFSET = 100;
private AppDeletionType mBackend;
@VisibleForTesting PreferenceScreen mScreen;
public AppDeletionPreferenceGroup(Context context) {
this(context, null);
}
public AppDeletionPreferenceGroup(Context context, AttributeSet attrs) {
super(context, attrs);
setOnPreferenceChangeListener(this);
updateText();
}
@Override
public void onAppRebuild(List<AppsAsyncLoader.PackageInfo> apps) {
int appCount = apps.size();
int currentUserId = getContext().getUserId();
PreferenceListCache cache = new PreferenceListCache(this);
for (int i = 0; i < appCount; i++) {
AppsAsyncLoader.PackageInfo app = apps.get(i);
if (app.userId != currentUserId) {
continue;
}
final String packageName = app.packageName;
AppDeletionPreference preference =
(AppDeletionPreference) cache.getCachedPreference(packageName);
if (preference == null) {
preference = new AppDeletionPreference(getContext(), app);
preference.setKey(packageName);
preference.setOnPreferenceChangeListener(this);
}
addThresholdDependentPreference(preference, isNoThreshold());
preference.setChecked(mBackend.isChecked(packageName));
preference.setOrder(i + ORDER_OFFSET);
preference.updateSummary();
}
cache.removeCachedPrefs();
updateText();
}
private void addThresholdDependentPreference(
AppDeletionPreference preference, boolean isThresholded) {
if (isNoThreshold()) {
addPreferenceToScreen(preference);
} else {
addPreference(preference);
}
}
private boolean isNoThreshold() {
return mBackend.getDeletionThreshold() == 0;
}
@VisibleForTesting
void addPreferenceToScreen(AppDeletionPreference preference) {
if (mScreen == null) {
mScreen = getPreferenceManager().getPreferenceScreen();
}
mScreen.addPreference(preference);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean isChecked = (boolean) newValue;
// If we have no AppDeletionType, we have no apps to toggle.
if (mBackend == null) {
return true;
}
if (preference == this) {
for (int i = 0; i < getPreferenceCount(); i++) {
AppDeletionPreference p = (AppDeletionPreference) getPreference(i);
p.setOnPreferenceChangeListener(null);
p.setChecked(isChecked);
mBackend.setChecked(p.getPackageName(), isChecked);
p.setOnPreferenceChangeListener(this);
}
updateText();
MetricsLogger.action(getContext(), MetricsEvent.ACTION_DELETION_SELECTION_ALL_APPS,
isChecked);
return true;
}
// If a single preference changed, we need to toggle just itself.
AppDeletionPreference p = (AppDeletionPreference) preference;
mBackend.setChecked(p.getPackageName(), isChecked);
logAppToggle(isChecked, p.getPackageName());
updateText();
return true;
}
@Override
public void onClick() {
super.onClick();
MetricsLogger.action(
getContext(), MetricsEvent.ACTION_DELETION_APPS_COLLAPSED, isCollapsed());
}
/**
* Initializes the PreferenceGroup with a source of apps to list.
*
* @param type The AppDeletionType which provides the app list.
*/
public void setDeletionType(AppDeletionType type) {
mBackend = type;
}
private void updateText() {
long freeableBytes = 0;
long deletionThreshold = AppsAsyncLoader.UNUSED_DAYS_DELETION_THRESHOLD;
if (mBackend != null) {
freeableBytes =
mBackend.getTotalAppsFreeableSpace(DeletionHelperSettings.COUNT_UNCHECKED);
deletionThreshold = mBackend.getDeletionThreshold();
switchSpinnerToCheckboxOrDisablePreference(freeableBytes, mBackend.getLoadingStatus());
}
Context app = getContext();
setTitle(app.getString(R.string.deletion_helper_apps_group_title));
setSummary(
app.getString(
R.string.deletion_helper_apps_group_summary,
Formatter.formatFileSize(app, freeableBytes),
deletionThreshold));
}
private void logAppToggle(boolean checked, String packageName) {
if (checked) {
MetricsLogger.action(
getContext(), MetricsEvent.ACTION_DELETION_SELECTION_APP_ON, packageName);
} else {
MetricsLogger.action(getContext(), MetricsEvent.ACTION_DELETION_SELECTION_APP_OFF,
packageName);
}
}
}