• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AppDeletionPreferenceGroup(Context context)41     public AppDeletionPreferenceGroup(Context context) {
42         this(context, null);
43     }
44 
AppDeletionPreferenceGroup(Context context, AttributeSet attrs)45     public AppDeletionPreferenceGroup(Context context, AttributeSet attrs) {
46         super(context, attrs);
47         setOnPreferenceChangeListener(this);
48         updateText();
49     }
50 
51     @Override
onAppRebuild(List<ApplicationsState.AppEntry> apps)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
onPreferenceChange(Preference preference, Object newValue)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
onClick()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      */
setDeletionType(AppDeletionType type)128     public void setDeletionType(AppDeletionType type) {
129         mBackend = type;
130     }
131 
updateText()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 
logAppToggle(boolean checked, String packageName)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