• 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.Manifest;
20 import android.app.Activity;
21 import android.content.pm.PackageManager;
22 import android.os.Bundle;
23 import android.support.v14.preference.PreferenceFragment;
24 import android.text.format.Formatter;
25 import android.view.Menu;
26 import android.view.MenuInflater;
27 import android.view.View;
28 import android.widget.Button;
29 import com.android.internal.logging.MetricsLogger;
30 import com.android.internal.logging.MetricsProto.MetricsEvent;
31 import com.android.settingslib.HelpUtils;
32 import com.android.storagemanager.ButtonBarProvider;
33 import com.android.storagemanager.R;
34 
35 import com.android.storagemanager.overlay.FeatureFactory;
36 import com.android.storagemanager.overlay.DeletionHelperFeatureProvider;
37 
38 import java.util.ArrayList;
39 import java.util.Collections;
40 import java.util.HashSet;
41 
42 /**
43  * Settings screen for the deletion helper, which manually removes data which is not recently used.
44  */
45 public class DeletionHelperSettings extends PreferenceFragment implements
46         DeletionType.FreeableChangedListener,
47         View.OnClickListener {
48     private static final String APPS_KEY = "apps_group";
49     private static final String KEY_DOWNLOADS_PREFERENCE = "delete_downloads";
50     private static final String KEY_PHOTOS_VIDEOS_PREFERENCE = "delete_photos";
51     private static final int DOWNLOADS_LOADER_ID = 1;
52 
53     private AppDeletionPreferenceGroup mApps;
54     private AppDeletionType mAppBackend;
55     private DownloadsDeletionPreferenceGroup mDownloadsPreference;
56     private DownloadsDeletionType mDownloadsDeletion;
57     private PhotosDeletionPreference mPhotoPreference;
58     private DeletionType mPhotoVideoDeletion;
59     private Button mCancel, mFree;
60     private DeletionHelperFeatureProvider mProvider;
61 
newInstance()62     public static DeletionHelperSettings newInstance() {
63         return new DeletionHelperSettings();
64     }
65 
66     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)67     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
68         addPreferencesFromResource(R.xml.deletion_helper_list);
69         mApps = (AppDeletionPreferenceGroup) findPreference(APPS_KEY);
70 
71         HashSet<String> checkedApplications = null;
72         if (savedInstanceState != null) {
73             checkedApplications =
74                     (HashSet<String>) savedInstanceState.getSerializable(
75                             AppDeletionType.EXTRA_CHECKED_SET);
76         }
77         mAppBackend = new AppDeletionType(getActivity().getApplication(), checkedApplications);
78         mAppBackend.registerView(mApps);
79         mAppBackend.registerFreeableChangedListener(this);
80         mApps.setDeletionType(mAppBackend);
81 
82         mPhotoPreference = (PhotosDeletionPreference) findPreference(KEY_PHOTOS_VIDEOS_PREFERENCE);
83         mProvider = FeatureFactory.getFactory(getActivity()).getDeletionHelperFeatureProvider();
84         if (mProvider != null) {
85             mPhotoVideoDeletion = mProvider.createPhotoVideoDeletionType(getContext());
86         }
87     }
88 
89     @Override
onActivityCreated(Bundle savedInstanceState)90     public void onActivityCreated(Bundle savedInstanceState) {
91         super.onActivityCreated(savedInstanceState);
92         initializeButtons();
93         setHasOptionsMenu(true);
94 
95         Activity activity = getActivity();
96         if (activity.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
97                 != PackageManager.PERMISSION_GRANTED) {
98             activity.requestPermissions(
99                     new String[] {Manifest.permission.READ_EXTERNAL_STORAGE},
100                     0);
101         }
102 
103         if (mProvider == null || mPhotoVideoDeletion == null) {
104             getPreferenceScreen().removePreference(mPhotoPreference);
105             mPhotoPreference = null;
106         } else {
107             mPhotoPreference.registerFreeableChangedListener(this);
108             mPhotoPreference.registerDeletionService(mPhotoVideoDeletion);
109         }
110 
111         String[] uncheckedFiles = null;
112         if (savedInstanceState != null) {
113             uncheckedFiles = savedInstanceState.getStringArray(
114                             DownloadsDeletionType.EXTRA_UNCHECKED_DOWNLOADS);
115         }
116         mDownloadsPreference =
117                 (DownloadsDeletionPreferenceGroup) findPreference(KEY_DOWNLOADS_PREFERENCE);
118         mDownloadsDeletion = new DownloadsDeletionType(getActivity(), uncheckedFiles);
119         mDownloadsPreference.registerFreeableChangedListener(this);
120         mDownloadsPreference.registerDeletionService(mDownloadsDeletion);
121         updateFreeButtonText();
122     }
123 
124     @Override
onResume()125     public void onResume() {
126         super.onResume();
127         mAppBackend.onResume();
128         mDownloadsDeletion.onResume();
129 
130         if (getActivity().checkSelfPermission(
131                 Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
132             getLoaderManager().initLoader(DOWNLOADS_LOADER_ID, new Bundle(), mDownloadsDeletion);
133         }
134 
135         if (mPhotoVideoDeletion != null) {
136             mPhotoVideoDeletion.onResume();
137         }
138     }
139 
140 
141     @Override
onPause()142     public void onPause() {
143         super.onPause();
144         mAppBackend.onPause();
145         mDownloadsDeletion.onPause();
146 
147         if (mPhotoVideoDeletion != null) {
148             mPhotoVideoDeletion.onPause();
149         }
150     }
151 
152     @Override
onSaveInstanceState(Bundle outState)153     public void onSaveInstanceState(Bundle outState) {
154         super.onSaveInstanceState(outState);
155         mAppBackend.onSaveInstanceStateBundle(outState);
156         mDownloadsDeletion.onSaveInstanceStateBundle(outState);
157     }
158 
159     @Override
onFreeableChanged(int numItems, long bytesFreeable)160     public void onFreeableChanged(int numItems, long bytesFreeable) {
161         // bytesFreeable is the number of bytes freed by a single deletion type. If it is non-zero,
162         // there is stuff to free and we can enable it. If it is zero, though, we still need to get
163         // getTotalFreeableSpace to check all deletion types.
164         mFree.setEnabled(bytesFreeable != 0 || getTotalFreeableSpace() != 0);
165         updateFreeButtonText();
166     }
167 
168     /**
169      * Clears out the selected apps and data from the device and closes the fragment.
170      */
clearData()171     protected void clearData() {
172         // This should be fine as long as there is only one extra deletion feature.
173         // In the future, this should be done in an async queue in order to not
174         // interfere with the simultaneous PackageDeletionTask.
175         if (mPhotoPreference != null && mPhotoPreference.isChecked()) {
176             mPhotoVideoDeletion.clearFreeableData(getActivity());
177         }
178         mDownloadsDeletion.clearFreeableData(getActivity());
179         mAppBackend.clearFreeableData(getActivity());
180     }
181 
182     @Override
onClick(View v)183     public void onClick(View v) {
184         if (v.getId() == R.id.next_button) {
185             ConfirmDeletionDialog dialog =
186                     ConfirmDeletionDialog.newInstance(getTotalFreeableSpace());
187             // The 0 is a placeholder for an optional result code.
188             dialog.setTargetFragment(this, 0);
189             dialog.show(getFragmentManager(), ConfirmDeletionDialog.TAG);
190             MetricsLogger.action(getContext(), MetricsEvent.ACTION_DELETION_HELPER_CLEAR);
191         } else {
192             MetricsLogger.action(getContext(), MetricsEvent.ACTION_DELETION_HELPER_CANCEL);
193             getActivity().finish();
194         }
195     }
196 
197     @Override
onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)198     public void onRequestPermissionsResult(int requestCode, String permissions[],
199                                            int[] grantResults) {
200         if (requestCode == 0) {
201             if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
202                 mDownloadsDeletion.onResume();
203                 getLoaderManager().initLoader(DOWNLOADS_LOADER_ID, new Bundle(),
204                         mDownloadsDeletion);
205             }
206         }
207     }
208 
209     @Override
onCreateOptionsMenu(Menu menu, MenuInflater menuInflater)210     public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
211         Activity activity = getActivity();
212         String mHelpUri = getResources().getString(R.string.help_uri_deletion_helper);
213         if (mHelpUri != null && activity != null) {
214             HelpUtils.prepareHelpMenuItem(activity, menu, mHelpUri, getClass().getName());
215         }
216     }
217 
initializeButtons()218     private void initializeButtons() {
219         ButtonBarProvider activity = (ButtonBarProvider) getActivity();
220         activity.getButtonBar().setVisibility(View.VISIBLE);
221 
222         mCancel = activity.getSkipButton();
223         mCancel.setText(R.string.cancel);
224         mCancel.setOnClickListener(this);
225         mCancel.setVisibility(View.VISIBLE);
226 
227         mFree = activity.getNextButton();
228         mFree.setText(R.string.storage_menu_free);
229         mFree.setOnClickListener(this);
230         mFree.setEnabled(false);
231     }
232 
updateFreeButtonText()233     private void updateFreeButtonText() {
234         mFree.setText(String.format(getActivity().getString(R.string.deletion_helper_free_button),
235                 Formatter.formatFileSize(getActivity(), getTotalFreeableSpace())));
236     }
237 
getTotalFreeableSpace()238     private long getTotalFreeableSpace() {
239         long freeableSpace = 0;
240         freeableSpace += mAppBackend.getTotalAppsFreeableSpace(false);
241         if (mPhotoPreference != null) {
242             freeableSpace += mPhotoPreference.getFreeableBytes();
243         }
244         freeableSpace += mDownloadsDeletion.getFreeableBytes();
245         return freeableSpace;
246     }
247 }