summaryrefslogtreecommitdiffstats
path: root/src/com/android/providers/downloads/StorageUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/providers/downloads/StorageUtils.java')
-rw-r--r--src/com/android/providers/downloads/StorageUtils.java170
1 files changed, 0 insertions, 170 deletions
diff --git a/src/com/android/providers/downloads/StorageUtils.java b/src/com/android/providers/downloads/StorageUtils.java
index d7a5c33b..4d332816 100644
--- a/src/com/android/providers/downloads/StorageUtils.java
+++ b/src/com/android/providers/downloads/StorageUtils.java
@@ -16,185 +16,24 @@
package com.android.providers.downloads;
-import static android.net.TrafficStats.MB_IN_BYTES;
-import static android.provider.Downloads.Impl.STATUS_INSUFFICIENT_SPACE_ERROR;
-import static android.text.format.DateUtils.DAY_IN_MILLIS;
-import static com.android.providers.downloads.Constants.TAG;
-
import android.app.DownloadManager;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.Context;
-import android.content.pm.IPackageDataObserver;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.os.Environment;
-import android.provider.Downloads;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructStat;
-import android.system.StructStatVfs;
-import android.text.TextUtils;
-import android.util.Slog;
-import com.android.internal.annotations.VisibleForTesting;
import com.google.android.collect.Lists;
-import com.google.android.collect.Sets;
-
-import libcore.io.IoUtils;
import java.io.File;
-import java.io.FileDescriptor;
-import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
/**
* Utility methods for managing storage space related to
* {@link DownloadManager}.
*/
public class StorageUtils {
-
- /**
- * Minimum age for a file to be considered for deletion.
- */
- static final long MIN_DELETE_AGE = DAY_IN_MILLIS;
-
- /**
- * Reserved disk space to avoid filling disk.
- */
- static final long RESERVED_BYTES = 32 * MB_IN_BYTES;
-
- @VisibleForTesting
- static boolean sForceFullEviction = false;
-
- /**
- * Ensure that requested free space exists on the partition backing the
- * given {@link FileDescriptor}. If not enough space is available, it tries
- * freeing up space as follows:
- * <ul>
- * <li>If backed by the data partition (including emulated external
- * storage), then ask {@link PackageManager} to free space from cache
- * directories.
- * <li>If backed by the cache partition, then try deleting older downloads
- * to free space.
- * </ul>
- */
- public static void ensureAvailableSpace(Context context, FileDescriptor fd, long bytes)
- throws IOException, StopRequestException {
-
- long availBytes = getAvailableBytes(fd);
- if (availBytes >= bytes) {
- // Underlying partition has enough space; go ahead
- return;
- }
-
- // Not enough space, let's try freeing some up. Start by tracking down
- // the backing partition.
- final long dev;
- try {
- dev = Os.fstat(fd).st_dev;
- } catch (ErrnoException e) {
- throw e.rethrowAsIOException();
- }
-
- // TODO: teach about evicting caches on adopted secondary storage devices
- final long dataDev = getDeviceId(Environment.getDataDirectory());
- final long cacheDev = getDeviceId(Environment.getDownloadCacheDirectory());
- final long externalDev = getDeviceId(Environment.getExternalStorageDirectory());
-
- if (dev == dataDev || (dev == externalDev && Environment.isExternalStorageEmulated())) {
- // File lives on internal storage; ask PackageManager to try freeing
- // up space from cache directories.
- final PackageManager pm = context.getPackageManager();
- final ObserverLatch observer = new ObserverLatch();
- pm.freeStorageAndNotify(sForceFullEviction ? Long.MAX_VALUE : bytes, observer);
-
- try {
- if (!observer.latch.await(30, TimeUnit.SECONDS)) {
- throw new IOException("Timeout while freeing disk space");
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
-
- } else if (dev == cacheDev) {
- // Try removing old files on cache partition
- freeCacheStorage(bytes);
- }
-
- // Did we free enough space?
- availBytes = getAvailableBytes(fd);
- if (availBytes < bytes) {
- throw new StopRequestException(STATUS_INSUFFICIENT_SPACE_ERROR,
- "Not enough free space; " + bytes + " requested, " + availBytes + " available");
- }
- }
-
- /**
- * Free requested space on cache partition, deleting oldest files first.
- * We're only focused on freeing up disk space, and rely on the next orphan
- * pass to clean up database entries.
- */
- private static void freeCacheStorage(long bytes) {
- // Only consider finished downloads
- final List<ConcreteFile> files = listFilesRecursive(
- Environment.getDownloadCacheDirectory(), Constants.DIRECTORY_CACHE_RUNNING,
- android.os.Process.myUid());
-
- Slog.d(TAG, "Found " + files.size() + " downloads on cache");
-
- Collections.sort(files, new Comparator<ConcreteFile>() {
- @Override
- public int compare(ConcreteFile lhs, ConcreteFile rhs) {
- return Long.compare(lhs.file.lastModified(), rhs.file.lastModified());
- }
- });
-
- final long now = System.currentTimeMillis();
- for (ConcreteFile file : files) {
- if (bytes <= 0) break;
-
- if (now - file.file.lastModified() < MIN_DELETE_AGE) {
- Slog.d(TAG, "Skipping recently modified " + file.file);
- } else {
- final long len = file.file.length();
- Slog.d(TAG, "Deleting " + file.file + " to reclaim " + len);
- bytes -= len;
- file.file.delete();
- }
- }
- }
-
- /**
- * Return number of available bytes on the filesystem backing the given
- * {@link FileDescriptor}, minus any {@link #RESERVED_BYTES} buffer.
- */
- private static long getAvailableBytes(FileDescriptor fd) throws IOException {
- try {
- final StructStatVfs stat = Os.fstatvfs(fd);
- return (stat.f_bavail * stat.f_bsize) - RESERVED_BYTES;
- } catch (ErrnoException e) {
- throw e.rethrowAsIOException();
- }
- }
-
- private static long getDeviceId(File file) {
- try {
- return Os.stat(file.getAbsolutePath()).st_dev;
- } catch (ErrnoException e) {
- // Safe since dev_t is uint
- return -1;
- }
- }
-
/**
* Return list of all normal files under the given directory, traversing
* directories recursively.
@@ -260,13 +99,4 @@ public class StorageUtils {
return false;
}
}
-
- static class ObserverLatch extends IPackageDataObserver.Stub {
- public final CountDownLatch latch = new CountDownLatch(1);
-
- @Override
- public void onRemoveCompleted(String packageName, boolean succeeded) {
- latch.countDown();
- }
- }
}