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.support.v7.preference.Preference;
     21 import android.text.format.Formatter;
     22 import android.util.AttributeSet;
     23 import android.view.View;
     24 import com.android.internal.logging.MetricsLogger;
     25 import com.android.internal.logging.MetricsProto.MetricsEvent;
     26 import com.android.settingslib.applications.ApplicationsState;
     27 import com.android.storagemanager.deletionhelper.AppStateUsageStatsBridge.UsageStatsState;
     28 import com.android.storagemanager.PreferenceListCache;
     29 import com.android.storagemanager.R;
     30 
     31 import java.util.List;
     32 
     33 /**
     34  * AppDeletionPreferenceGroup is a collapsible checkbox preference group which contains many
     35  * apps to be cleared in the Deletion Helper.
     36  */
     37 public class AppDeletionPreferenceGroup extends CollapsibleCheckboxPreferenceGroup
     38         implements AppDeletionType.AppListener, Preference.OnPreferenceChangeListener {
     39     private AppDeletionType mBackend;
     40 
     41     public AppDeletionPreferenceGroup(Context context) {
     42         this(context, null);
     43     }
     44 
     45     public AppDeletionPreferenceGroup(Context context, AttributeSet attrs) {
     46         super(context, attrs);
     47         setOnPreferenceChangeListener(this);
     48         updateText();
     49     }
     50 
     51     @Override
     52     public void onAppRebuild(List<ApplicationsState.AppEntry> apps) {
     53         int entryCount = apps.size();
     54         int currentUserId = getContext().getUserId();
     55         PreferenceListCache cache = new PreferenceListCache(this);
     56         for (int i = 0; i < entryCount; i++) {
     57             ApplicationsState.AppEntry entry = apps.get(i);
     58 
     59             // If it's a different user's app, skip it.
     60             UsageStatsState extraData = (UsageStatsState) entry.extraInfo;
     61             if (extraData.userId != currentUserId) {
     62                 continue;
     63             }
     64 
     65             final String packageName;
     66             synchronized (entry) {
     67                 packageName = entry.info.packageName;
     68             }
     69             AppDeletionPreference preference =
     70                     (AppDeletionPreference) cache.getCachedPreference(packageName);
     71             if (preference == null) {
     72                 preference = new AppDeletionPreference(getContext(), entry);
     73                 preference.setKey(packageName);
     74                 preference.setOnPreferenceChangeListener(this);
     75             }
     76 
     77             addPreference(preference);
     78             preference.setChecked(mBackend.isChecked(packageName));
     79             preference.setOrder(i);
     80             preference.updateSummary();
     81         }
     82         cache.removeCachedPrefs();
     83         updateText();
     84     }
     85 
     86     @Override
     87     public boolean onPreferenceChange(Preference preference, Object newValue) {
     88         boolean isChecked = (boolean) newValue;
     89 
     90         // If we have no AppDeletionType, we have no apps to toggle.
     91         if (mBackend == null) {
     92             return true;
     93         }
     94 
     95         if (preference == this) {
     96             for (int i = 0; i < getPreferenceCount(); i++) {
     97                 AppDeletionPreference p = (AppDeletionPreference) getPreference(i);
     98                 p.setOnPreferenceChangeListener(null);
     99                 p.setChecked(isChecked);
    100                 mBackend.setChecked(p.getPackageName(), isChecked);
    101                 p.setOnPreferenceChangeListener(this);
    102             }
    103             updateText();
    104             MetricsLogger.action(getContext(), MetricsEvent.ACTION_DELETION_SELECTION_ALL_APPS,
    105                     isChecked);
    106             return true;
    107         }
    108 
    109         // If a single preference changed, we need to toggle just itself.
    110         AppDeletionPreference p = (AppDeletionPreference) preference;
    111         mBackend.setChecked(p.getPackageName(), isChecked);
    112         logAppToggle(isChecked, p.getPackageName());
    113         updateText();
    114         return true;
    115     }
    116 
    117     @Override
    118     public void onClick() {
    119         super.onClick();
    120         MetricsLogger.action(getContext(), MetricsEvent.ACTION_DELETION_APPS_COLLAPSED,
    121                 isCollapsed());
    122     }
    123 
    124     /**
    125      * Initializes the PreferenceGroup with a source of apps to list.
    126      * @param type The AppDeletionType which provides the app list.
    127      */
    128     public void setDeletionType(AppDeletionType type) {
    129         mBackend = type;
    130     }
    131 
    132     private void updateText() {
    133         int eligibleApps = 0;
    134         long freeableBytes = 0;
    135         if (mBackend != null) {
    136             eligibleApps = mBackend.getEligibleApps();
    137             freeableBytes = mBackend.getTotalAppsFreeableSpace(true);
    138         }
    139         Context app = getContext();
    140         setTitle(app.getString(R.string.deletion_helper_apps_group_title, eligibleApps));
    141         setSummary(app.getString(R.string.deletion_helper_apps_group_summary,
    142                 Formatter.formatFileSize(app, freeableBytes),
    143                 AppStateUsageStatsBridge.UNUSED_DAYS_DELETION_THRESHOLD));
    144     }
    145 
    146     private void logAppToggle(boolean checked, String packageName) {
    147         if (checked) {
    148             MetricsLogger.action(getContext(), MetricsEvent.ACTION_DELETION_SELECTION_APP_ON,
    149                     packageName);
    150         } else {
    151             MetricsLogger.action(getContext(), MetricsEvent.ACTION_DELETION_SELECTION_APP_OFF,
    152                     packageName);
    153         }
    154     }
    155 }
    156