Merge "Replace bluetooth pngs with vector drawables." into nyc-mr1-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4b5c071..333a106 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7604,7 +7604,7 @@
<string name="deletion_helper_downloads_title">Downloads (<xliff:g id="numItems" example="67">%1$d</xliff:g>)</string>
<!-- Summary of how much stale data can be cleared from the local download folder. [CHAR LIMIT=NONE]-->
- <string name="deletion_helper_downloads_summary"><xliff:g id="used" example="1.2GB">%1$s</xliff:g>, last modified <xliff:g id="days">%2$s</xliff:g></string>
+ <string name="deletion_helper_downloads_summary"><xliff:g id="used" example="1.2GB">%1$s</xliff:g> • last modified <xliff:g id="days">%2$s</xliff:g></string>
<!-- Summary for when when there is nothing in the downloads folder to clear. [CHAR LIMIT=NONE]-->
<string name="deletion_helper_downloads_summary_empty"><xliff:g id="used" example="1.2GB">%1$s</xliff:g></string>
diff --git a/res/xml/deletion_helper_list.xml b/res/xml/deletion_helper_list.xml
index ac5a851..64bd3b5 100644
--- a/res/xml/deletion_helper_list.xml
+++ b/res/xml/deletion_helper_list.xml
@@ -20,8 +20,9 @@
<com.android.settings.PhotosDeletionPreference
android:key="delete_photos" />
- <com.android.settings.deletionhelper.DownloadsDeletionPreference
- android:key="delete_downloads" />
+ <com.android.settings.deletionhelper.DownloadsDeletionPreferenceGroup
+ android:key="delete_downloads"
+ android:icon="@drawable/ic_keyboard_arrow_down_black_32"/>
<com.android.settings.CollapsibleCheckboxPreferenceGroup
android:key="apps_group"
diff --git a/src/com/android/settings/deletionhelper/DeletionHelperFragment.java b/src/com/android/settings/deletionhelper/DeletionHelperFragment.java
index 68144f8..85c1035 100644
--- a/src/com/android/settings/deletionhelper/DeletionHelperFragment.java
+++ b/src/com/android/settings/deletionhelper/DeletionHelperFragment.java
@@ -25,10 +25,7 @@
import android.util.ArraySet;
import android.util.Log;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.Button;
-import android.widget.LinearLayout;
-import com.android.settings.deletionhelper.DownloadsDeletionPreference;
import com.android.settings.CollapsibleCheckboxPreferenceGroup;
import com.android.settings.PhotosDeletionPreference;
import com.android.settings.SettingsPreferenceFragment;
@@ -70,7 +67,7 @@
private Button mCancel, mFree;
private CollapsibleCheckboxPreferenceGroup mApps;
private PhotosDeletionPreference mPhotoPreference;
- private DownloadsDeletionPreference mDownloadsPreference;
+ private DownloadsDeletionPreferenceGroup mDownloadsPreference;
private ApplicationsState mState;
private Session mSession;
@@ -96,7 +93,7 @@
mApps = (CollapsibleCheckboxPreferenceGroup) findPreference(KEY_APPS_GROUP);
mPhotoPreference = (PhotosDeletionPreference) findPreference(KEY_PHOTOS_VIDEOS_PREFERENCE);
mDownloadsPreference =
- (DownloadsDeletionPreference) findPreference(KEY_DOWNLOADS_PREFERENCE);
+ (DownloadsDeletionPreferenceGroup) findPreference(KEY_DOWNLOADS_PREFERENCE);
mProvider =
FeatureFactory.getFactory(app).getDeletionHelperFeatureProvider();
if (mProvider != null) {
@@ -155,14 +152,12 @@
super.onResume();
mSession.resume();
mDataUsageBridge.resume();
+ mDownloadsDeletion.onResume();
+ getLoaderManager().initLoader(DOWNLOADS_LOADER_ID, new Bundle(), mDownloadsDeletion);
if (mPhotoVideoDeletion != null) {
mPhotoVideoDeletion.onResume();
}
- if (mDownloadsDeletion != null) {
- mDownloadsDeletion.onResume();
- getLoaderManager().initLoader(DOWNLOADS_LOADER_ID, new Bundle(), mDownloadsDeletion);
- }
}
@@ -180,13 +175,11 @@
super.onPause();
mDataUsageBridge.pause();
mSession.pause();
+ mDownloadsDeletion.onPause();
if (mPhotoVideoDeletion != null) {
mPhotoVideoDeletion.onPause();
}
- if (mDownloadsDeletion != null) {
- mDownloadsDeletion.onPause();
- }
}
private void rebuild() {
@@ -316,6 +309,7 @@
if (mPhotoPreference != null && mPhotoPreference.isChecked()) {
mPhotoVideoDeletion.clearFreeableData();
}
+ mDownloadsDeletion.clearFreeableData();
ArraySet<String> apps = new ArraySet<>();
for (AppEntry entry : mAppEntries) {
@@ -351,9 +345,7 @@
if (mPhotoPreference != null) {
freeableSpace += mPhotoPreference.getFreeableBytes();
}
- if (mDownloadsPreference != null) {
- freeableSpace += mDownloadsPreference.getFreeableBytes();
- }
+ freeableSpace += mDownloadsDeletion.getFreeableBytes();
return freeableSpace;
}
diff --git a/src/com/android/settings/deletionhelper/DownloadsDeletionPreference.java b/src/com/android/settings/deletionhelper/DownloadsDeletionPreference.java
deleted file mode 100644
index 7cddf32..0000000
--- a/src/com/android/settings/deletionhelper/DownloadsDeletionPreference.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.settings.deletionhelper;
-
-import android.content.Context;
-import android.text.format.DateUtils;
-import android.util.AttributeSet;
-import android.text.format.Formatter;
-import com.android.settings.DeletionPreference;
-import com.android.settings.R;
-
-/**
- * Preference to handle the deletion of photos and videos in the Deletion Helper.
- */
-public class DownloadsDeletionPreference extends DeletionPreference {
- public DownloadsDeletionPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- updatePreferenceText(0, 0, Long.MAX_VALUE);
- }
-
- @Override
- public void onFreeableChanged(int numItems, long freeableBytes) {
- super.onFreeableChanged(numItems, freeableBytes);
- DownloadsDeletionType deletionService = (DownloadsDeletionType) getDeletionService();
- updatePreferenceText(numItems, freeableBytes, deletionService.getMostRecentLastModified());
- }
-
- private void updatePreferenceText(int items, long bytes, long mostRecent) {
- Context context = getContext();
- setTitle(context.getString(R.string.deletion_helper_downloads_title,
- items));
- // If there are no files to clear, show the empty text instead.
- if (mostRecent < Long.MAX_VALUE) {
- setSummary(context.getString(R.string.deletion_helper_downloads_summary,
- Formatter.formatFileSize(context, bytes),
- DateUtils.getRelativeTimeSpanString(mostRecent,
- System.currentTimeMillis(),
- DateUtils.DAY_IN_MILLIS,
- DateUtils.FORMAT_ABBREV_RELATIVE)));
- } else {
- setSummary(context.getString(R.string.deletion_helper_downloads_summary_empty,
- Formatter.formatFileSize(context, bytes)));
- }
- }
-
-}
diff --git a/src/com/android/settings/deletionhelper/DownloadsDeletionPreferenceGroup.java b/src/com/android/settings/deletionhelper/DownloadsDeletionPreferenceGroup.java
new file mode 100644
index 0000000..440b962
--- /dev/null
+++ b/src/com/android/settings/deletionhelper/DownloadsDeletionPreferenceGroup.java
@@ -0,0 +1,157 @@
+/*
+ * 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.settings.deletionhelper;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.text.format.DateUtils;
+import android.text.format.Formatter;
+import android.util.ArrayMap;
+import android.util.AttributeSet;
+import com.android.settings.CollapsibleCheckboxPreferenceGroup;
+import com.android.settings.R;
+
+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;
+
+ public DownloadsDeletionPreferenceGroup(Context context) {
+ this(context, null);
+ }
+
+ public DownloadsDeletionPreferenceGroup(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ 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);
+ 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 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.toggleFile(p.getFile(), checked);
+ p.setChecked(checked);
+ p.setOnPreferenceChangeListener(this);
+ }
+ maybeUpdateListener(mDeletionType.getFiles().size(), mDeletionType.getFreeableBytes());
+ return true;
+ }
+
+ // If a single DownloadFilePreference changed, we need to toggle just itself.
+ DownloadsFilePreference p = (DownloadsFilePreference) preference;
+ mDeletionType.toggleFile(p.getFile(), checked);
+ maybeUpdateListener(mDeletionType.getFiles().size(), mDeletionType.getFreeableBytes());
+ return true;
+ }
+
+
+ private void updatePreferenceText(int itemCount, long bytes, long mostRecent) {
+ Context context = getContext();
+ setTitle(context.getString(R.string.deletion_helper_downloads_title, itemCount));
+ // If there are no files to clear, show the empty text instead.
+ if (itemCount != 0) {
+ setSummary(context.getString(R.string.deletion_helper_downloads_summary,
+ Formatter.formatFileSize(context, bytes),
+ DateUtils.getRelativeTimeSpanString(mostRecent,
+ System.currentTimeMillis(),
+ DateUtils.DAY_IN_MILLIS,
+ DateUtils.FORMAT_ABBREV_RELATIVE)));
+ } 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() {
+ // TODO: Remove impl overlap with the cached preferences methods in
+ // SettingsPreferenceFragment.
+
+ // Cache the existing file preferences.
+ ArrayMap<String, Preference> cachedPreferences = new ArrayMap<>();
+ for (int i = 0; i < getPreferenceCount(); i++) {
+ Preference p = getPreference(i);
+ cachedPreferences.put(p.getKey(), p);
+ }
+
+ // Iterate over all of the files and re-use the old file preference, if it exists.
+ Set<File> files = mDeletionType.getFiles();
+ for (File file : files) {
+ DownloadsFilePreference filePreference =
+ (DownloadsFilePreference) cachedPreferences.remove(file.getPath());
+ if (filePreference == null) {
+ filePreference = new DownloadsFilePreference(getContext(), file);
+ filePreference.setChecked(isChecked());
+ filePreference.setOnPreferenceChangeListener(this);
+ }
+ addPreference(filePreference);
+ }
+
+ // Remove all of the unused preferences.
+ for (Preference p : cachedPreferences.values()) {
+ removePreference(p);
+ }
+ }
+}
diff --git a/src/com/android/settings/deletionhelper/DownloadsDeletionType.java b/src/com/android/settings/deletionhelper/DownloadsDeletionType.java
index 81293d6..3a251eb 100644
--- a/src/com/android/settings/deletionhelper/DownloadsDeletionType.java
+++ b/src/com/android/settings/deletionhelper/DownloadsDeletionType.java
@@ -22,26 +22,30 @@
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import com.android.settings.deletionhelper.FetchDownloadsLoader.DownloadsResult;
import java.io.File;
import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
* The DownloadsDeletionType provides stale download file information to the
- * {@link DownloadsDeletionPreference}.
+ * {@link DownloadsDeletionPreferenceGroup}.
*/
public class DownloadsDeletionType implements DeletionType, LoaderCallbacks<DownloadsResult> {
- private int mItems;
private long mBytes;
private long mMostRecent;
private FreeableChangedListener mListener;
- private FetchDownloadsLoader mTask;
- private ArrayList<File> mFiles;
private Context mContext;
+ private ArrayMap<File, Boolean> mFiles;
public DownloadsDeletionType(Context context) {
mContext = context;
+ mFiles = new ArrayMap<>();
}
@Override
@@ -66,8 +70,10 @@
AsyncTask.execute(new Runnable() {
@Override
public void run() {
- for (File file : mFiles) {
- file.delete();
+ for (Map.Entry<File, Boolean> entry : mFiles.entrySet()) {
+ if (entry.getValue()) {
+ entry.getKey().delete();
+ }
}
}
});
@@ -83,9 +89,13 @@
@Override
public void onLoadFinished(Loader<DownloadsResult> loader, DownloadsResult data) {
mMostRecent = data.youngestLastModified;
- mFiles = data.files;
+ for (File file : data.files) {
+ if (mFiles.containsKey(file)) {
+ continue;
+ }
+ mFiles.put(file, false);
+ }
mBytes = data.totalSize;
- mItems = mFiles.size();
maybeUpdateListener();
}
@@ -101,9 +111,39 @@
return mMostRecent;
}
+ /**
+ * Returns the files in the Downloads folder after the loader task finishes.
+ */
+ public Set<File> getFiles() {
+ if (mFiles == null) {
+ return null;
+ }
+ return mFiles.keySet();
+ }
+
+ /**
+ * Toggle if a file should be deleted when the service is asked to clear files.
+ */
+ public void toggleFile(File file, boolean checked) {
+ mFiles.put(file, checked);
+ }
+
+ /**
+ * Returns the number of bytes that would be cleared if the deletion tasks runs.
+ */
+ public long getFreeableBytes() {
+ long freedBytes = 0;
+ for (Map.Entry<File, Boolean> entry : mFiles.entrySet()) {
+ if (entry.getValue()) {
+ freedBytes += entry.getKey().length();
+ }
+ }
+ return freedBytes;
+ }
+
private void maybeUpdateListener() {
if (mListener != null) {
- mListener.onFreeableChanged(mItems, mBytes);
+ mListener.onFreeableChanged(mFiles.size(), mBytes);
}
}
}
diff --git a/src/com/android/settings/deletionhelper/DownloadsFilePreference.java b/src/com/android/settings/deletionhelper/DownloadsFilePreference.java
new file mode 100644
index 0000000..af8f6b6
--- /dev/null
+++ b/src/com/android/settings/deletionhelper/DownloadsFilePreference.java
@@ -0,0 +1,68 @@
+/*
+ * 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.settings.deletionhelper;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.CheckBoxPreference;
+import android.text.format.DateUtils;
+import android.text.format.Formatter;
+import com.android.settings.R;
+
+import java.io.File;
+
+/**
+ * DownloadsFilePreference is a preference representing a file in the Downloads folder
+ * with a checkbox that represents if the file should be deleted.
+ */
+public class DownloadsFilePreference extends CheckBoxPreference {
+ private File mFile;
+
+ public DownloadsFilePreference(Context context, File file) {
+ super(context);
+ mFile = file;
+ setKey(mFile.getPath());
+ setTitle(file.getName());
+ setSummary(context.getString(R.string.deletion_helper_downloads_summary,
+ Formatter.formatFileSize(getContext(), file.length()),
+ DateUtils.getRelativeTimeSpanString(mFile.lastModified(),
+ System.currentTimeMillis(),
+ DateUtils.DAY_IN_MILLIS,
+ DateUtils.FORMAT_ABBREV_RELATIVE)));
+ }
+
+ public File getFile() {
+ return mFile;
+ }
+
+ @Override
+ public int compareTo(Preference other) {
+ if (other == null) {
+ return 1;
+ }
+
+ if (other instanceof DownloadsFilePreference) {
+ DownloadsFilePreference preference = (DownloadsFilePreference) other;
+ return Long.compare(getFile().length(), preference.getFile().length());
+ } else {
+ // If a non-DownloadsFilePreference appears, consider ourselves to be greater.
+ // This means if a non-DownloadsFilePreference sneaks into a DownloadsPreferenceGroup
+ // then the DownloadsFilePreference will appear higher.
+ return 1;
+ }
+ }
+}