1dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey/*
2dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey * Copyright (C) 2014 The Android Open Source Project
3dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey *
4dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey * you may not use this file except in compliance with the License.
6dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey * You may obtain a copy of the License at
7dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey *
8dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey *
10dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
11dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey * See the License for the specific language governing permissions and
14dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey * limitations under the License.
15dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey */
16dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
17dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeypackage com.android.providers.downloads;
18dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
19dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport static android.app.DownloadManager.COLUMN_REASON;
20dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport static android.app.DownloadManager.ERROR_INSUFFICIENT_SPACE;
21dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport static android.app.DownloadManager.STATUS_FAILED;
22dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport static android.app.DownloadManager.STATUS_SUCCESSFUL;
23dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport static android.provider.Downloads.Impl.DESTINATION_CACHE_PARTITION;
24dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport static android.provider.Downloads.Impl.DESTINATION_SYSTEMCACHE_PARTITION;
25dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
26dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport android.app.DownloadManager;
27dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport android.content.pm.PackageManager;
28dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport android.os.Environment;
29dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport android.os.StatFs;
30dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport android.provider.Downloads.Impl;
318b36635d727451930ef4939aad25148c05c66b09Colin Crossimport android.system.ErrnoException;
325dcbf701c9077e62ca8c1ee0079b4cbffaf57d14Elliott Hughesimport android.system.Os;
338b36635d727451930ef4939aad25148c05c66b09Colin Crossimport android.system.StructStatVfs;
34dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport android.test.MoreAsserts;
35dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport android.util.Log;
36dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
37dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport com.android.providers.downloads.StorageUtils.ObserverLatch;
38dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport com.google.mockwebserver.MockResponse;
39dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport com.google.mockwebserver.SocketPolicy;
40dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
41dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport libcore.io.ForwardingOs;
42dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport libcore.io.IoUtils;
43dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
44dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport java.io.File;
45dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport java.io.FileDescriptor;
46dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport java.io.FileOutputStream;
47dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport java.io.IOException;
48dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport java.util.concurrent.TimeUnit;
49dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
50dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeypublic class StorageTest extends AbstractPublicApiTest {
51dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    private static final String TAG = "StorageTest";
52dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
53dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    private static final int DOWNLOAD_SIZE = 512 * 1024;
54dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    private static final byte[] DOWNLOAD_BODY;
55dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
56dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    static {
57dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        DOWNLOAD_BODY = new byte[DOWNLOAD_SIZE];
58dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        for (int i = 0; i < DOWNLOAD_SIZE; i++) {
59dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            DOWNLOAD_BODY[i] = (byte) (i % 32);
60dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        }
61dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    }
62dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
635dcbf701c9077e62ca8c1ee0079b4cbffaf57d14Elliott Hughes    private libcore.io.Os mOriginal;
64dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    private long mStealBytes;
65dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
66dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    public StorageTest() {
67dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        super(new FakeSystemFacade());
68dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    }
69dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
70dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    @Override
71dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    protected void setUp() throws Exception {
72dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        super.setUp();
73dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
74dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        StorageUtils.sForceFullEviction = true;
75dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        mStealBytes = 0;
76dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
775dcbf701c9077e62ca8c1ee0079b4cbffaf57d14Elliott Hughes        mOriginal = libcore.io.Libcore.os;
785dcbf701c9077e62ca8c1ee0079b4cbffaf57d14Elliott Hughes        libcore.io.Libcore.os = new ForwardingOs(mOriginal) {
79dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            @Override
80dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            public StructStatVfs statvfs(String path) throws ErrnoException {
81dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                return stealBytes(os.statvfs(path));
82dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            }
83dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
84dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            @Override
85dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            public StructStatVfs fstatvfs(FileDescriptor fd) throws ErrnoException {
86dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                return stealBytes(os.fstatvfs(fd));
87dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            }
88dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
89dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            private StructStatVfs stealBytes(StructStatVfs s) {
90dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                final long stealBlocks = (mStealBytes + (s.f_bsize - 1)) / s.f_bsize;
91dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                final long f_bavail = s.f_bavail - stealBlocks;
92dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                return new StructStatVfs(s.f_bsize, s.f_frsize, s.f_blocks, s.f_bfree, f_bavail,
93dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                        s.f_files, s.f_ffree, s.f_favail, s.f_fsid, s.f_flag, s.f_namemax);
94dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            }
95dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        };
96dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    }
97dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
98dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    @Override
99dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    protected void tearDown() throws Exception {
100dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        super.tearDown();
101dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
102dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        StorageUtils.sForceFullEviction = false;
103dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        mStealBytes = 0;
104dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
105dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        if (mOriginal != null) {
1065dcbf701c9077e62ca8c1ee0079b4cbffaf57d14Elliott Hughes            libcore.io.Libcore.os = mOriginal;
107dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        }
108dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    }
109dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
110dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    private enum CacheStatus { CLEAN, DIRTY }
111dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    private enum BodyType { COMPLETE, CHUNKED }
112dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
113dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    public void testDataDirtyComplete() throws Exception {
114dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        prepareAndRunDownload(DESTINATION_CACHE_PARTITION,
115dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                CacheStatus.DIRTY, BodyType.COMPLETE,
116dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                STATUS_SUCCESSFUL, -1);
117dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    }
118dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
119dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    public void testDataDirtyChunked() throws Exception {
120dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        prepareAndRunDownload(DESTINATION_CACHE_PARTITION,
121dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                CacheStatus.DIRTY, BodyType.CHUNKED,
122dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                STATUS_SUCCESSFUL, -1);
123dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    }
124dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
125dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    public void testDataCleanComplete() throws Exception {
126dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        prepareAndRunDownload(DESTINATION_CACHE_PARTITION,
127dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                CacheStatus.CLEAN, BodyType.COMPLETE,
128dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                STATUS_FAILED, ERROR_INSUFFICIENT_SPACE);
129dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    }
130dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
131dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    public void testDataCleanChunked() throws Exception {
132dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        prepareAndRunDownload(DESTINATION_CACHE_PARTITION,
133dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                CacheStatus.CLEAN, BodyType.CHUNKED,
134dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                STATUS_FAILED, ERROR_INSUFFICIENT_SPACE);
135dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    }
136dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
137dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    public void testCacheDirtyComplete() throws Exception {
138dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        prepareAndRunDownload(DESTINATION_SYSTEMCACHE_PARTITION,
139dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                CacheStatus.DIRTY, BodyType.COMPLETE,
140dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                STATUS_SUCCESSFUL, -1);
141dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    }
142dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
143dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    public void testCacheDirtyChunked() throws Exception {
144dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        prepareAndRunDownload(DESTINATION_SYSTEMCACHE_PARTITION,
145dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                CacheStatus.DIRTY, BodyType.CHUNKED,
146dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                STATUS_SUCCESSFUL, -1);
147dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    }
148dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
149dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    public void testCacheCleanComplete() throws Exception {
150dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        prepareAndRunDownload(DESTINATION_SYSTEMCACHE_PARTITION,
151dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                CacheStatus.CLEAN, BodyType.COMPLETE,
152dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                STATUS_FAILED, ERROR_INSUFFICIENT_SPACE);
153dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    }
154dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
155dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    public void testCacheCleanChunked() throws Exception {
156dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        prepareAndRunDownload(DESTINATION_SYSTEMCACHE_PARTITION,
157dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                CacheStatus.CLEAN, BodyType.CHUNKED,
158dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                STATUS_FAILED, ERROR_INSUFFICIENT_SPACE);
159dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    }
160dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
161dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    private void prepareAndRunDownload(
162dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            int dest, CacheStatus cache, BodyType body, int expectedStatus, int expectedReason)
163dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            throws Exception {
164dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
165dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        // Ensure that we've purged everything possible for destination
166dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        final File dirtyDir;
167dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        if (dest == DESTINATION_CACHE_PARTITION) {
168dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            final PackageManager pm = getContext().getPackageManager();
169dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            final ObserverLatch observer = new ObserverLatch();
170dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            pm.freeStorageAndNotify(Long.MAX_VALUE, observer);
171dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
172dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            try {
173dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                if (!observer.latch.await(30, TimeUnit.SECONDS)) {
174dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                    throw new IOException("Timeout while freeing disk space");
175dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                }
176dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            } catch (InterruptedException e) {
177dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                Thread.currentThread().interrupt();
178dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            }
179dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
180dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            dirtyDir = getContext().getCacheDir();
181dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
182dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        } else if (dest == DESTINATION_SYSTEMCACHE_PARTITION) {
183dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            IoUtils.deleteContents(Environment.getDownloadCacheDirectory());
184dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            dirtyDir = Environment.getDownloadCacheDirectory();
185dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
186dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        } else {
187dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            throw new IllegalArgumentException("Unknown destination");
188dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        }
189dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
190dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        // Allocate a cache file, if requested, making it large enough and old
191dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        // enough to clear.
192dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        final File dirtyFile;
193dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        if (cache == CacheStatus.DIRTY) {
194dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            dirtyFile = new File(dirtyDir, "cache_file.bin");
195dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            assertTrue(dirtyFile.createNewFile());
196dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            final FileOutputStream os = new FileOutputStream(dirtyFile);
197dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            final int dirtySize = (DOWNLOAD_SIZE * 3) / 2;
1985dcbf701c9077e62ca8c1ee0079b4cbffaf57d14Elliott Hughes            Os.posix_fallocate(os.getFD(), 0, dirtySize);
199dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            IoUtils.closeQuietly(os);
200dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
201dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            dirtyFile.setLastModified(
202dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                    System.currentTimeMillis() - (StorageUtils.MIN_DELETE_AGE * 2));
203dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        } else {
204dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            dirtyFile = null;
205dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        }
206dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
207dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        // At this point, hide all other disk space to make the download fail;
208dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        // if we have a dirty cache file it can be cleared to let us proceed.
209dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        final long targetFree = StorageUtils.RESERVED_BYTES + (DOWNLOAD_SIZE / 2);
210dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
211dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        final StatFs stat = new StatFs(dirtyDir.getAbsolutePath());
212dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        Log.d(TAG, "Available bytes (before steal): " + stat.getAvailableBytes());
213dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        mStealBytes = stat.getAvailableBytes() - targetFree;
214dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
215dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        stat.restat(dirtyDir.getAbsolutePath());
216dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        Log.d(TAG, "Available bytes (after steal): " + stat.getAvailableBytes());
217dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
218dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        final MockResponse resp = new MockResponse().setResponseCode(200)
219dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                .setHeader("Content-type", "text/plain")
220dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END);
221dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        if (body == BodyType.CHUNKED) {
222dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            resp.setChunkedBody(DOWNLOAD_BODY, 1021);
223dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        } else {
224dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            resp.setBody(DOWNLOAD_BODY);
225dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        }
226dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        enqueueResponse(resp);
227dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
228dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        final DownloadManager.Request req = getRequest();
229dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        if (dest == Impl.DESTINATION_SYSTEMCACHE_PARTITION) {
230dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            req.setDestinationToSystemCache();
231dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        }
232dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        final Download download = enqueueRequest(req);
233dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        download.runUntilStatus(expectedStatus);
234dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
235dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        if (expectedStatus == STATUS_SUCCESSFUL) {
236dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            MoreAsserts.assertEquals(DOWNLOAD_BODY, download.getRawContents());
237dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        }
238dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
239dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        if (expectedReason != -1) {
240dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            assertEquals(expectedReason, download.getLongField(COLUMN_REASON));
241dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        }
242dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
243dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        if (dirtyFile != null) {
244dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            assertFalse(dirtyFile.exists());
245dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        }
246dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey    }
247dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey}
248