DownloadManagerTestApp.java revision a305d7229fb99a536293b5d52cdb9ce3c820d6c8
1/*
2 * Copyright (C) 2010 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 */
16package com.android.frameworks.downloadmanagertests;
17
18import android.app.DownloadManager;
19import android.app.DownloadManager.Request;
20import android.database.Cursor;
21import android.net.Uri;
22import android.os.Environment;
23import android.os.ParcelFileDescriptor;
24import android.util.Log;
25
26import java.io.DataInputStream;
27import java.io.DataOutputStream;
28import java.io.File;
29import java.io.FileInputStream;
30import java.io.FileOutputStream;
31import java.util.HashSet;
32
33/**
34 * Class to test downloading files from a real (not mock) external server.
35 */
36public class DownloadManagerTestApp extends DownloadManagerBaseTest {
37    protected static String DOWNLOAD_STARTED_FLAG = "DMTEST_DOWNLOAD_STARTED";
38    protected static String LOG_TAG =
39            "com.android.frameworks.downloadmanagertests.DownloadManagerTestApp";
40
41    protected static final String DOWNLOAD_FILENAME = "External93mb.apk";
42    protected static final long DOWNLOAD_FILESIZE = 95251708;
43
44    private static final String FILE_CONCURRENT_DOWNLOAD_FILE_PREFIX = "file";
45    private static final String FILE_CONCURRENT_DOWNLOAD_FILE_EXTENSION = ".bin";
46    protected static long CONCURRENT_DOWNLOAD_FILESIZE = 1000000;
47
48    // Values to be obtained from TestRunner
49    private String externalDownloadUriValue = null;
50    private String externalLargeDownloadUriValue = null;
51
52    /**
53     * {@inheritDoc }
54     */
55    @Override
56    public void setUp() throws Exception {
57        super.setUp();
58        DownloadManagerTestRunner mRunner = (DownloadManagerTestRunner)getInstrumentation();
59        externalDownloadUriValue = normalizeUri(mRunner.externalDownloadUriValue);
60        assertNotNull(externalDownloadUriValue);
61
62        externalLargeDownloadUriValue = normalizeUri(mRunner.externalDownloadUriValue);
63        assertNotNull(externalLargeDownloadUriValue);
64    }
65
66    /**
67     * Normalizes a uri to ensure it ends with a "/"
68     *
69     * @param uri The uri to normalize (or null)
70     * @return The normalized uri, or null if null was passed in
71     */
72    public String normalizeUri(String uri) {
73        if (uri != null && !uri.endsWith("/")) {
74            uri += "/";
75        }
76        return uri;
77    }
78
79    /**
80     * Gets the external URL of the file to download
81     *
82     * @return the Uri of the external file to download
83     */
84    private Uri getExternalFileUri(String file) {
85        return Uri.parse(externalDownloadUriValue + file);
86    }
87
88    /**
89     * Gets the path to the file that flags that a download has started. The file contains the
90     * DownloadManager id of the download being trackted between reboot sessions.
91     *
92     * @return The path of the file tracking that a download has started
93     * @throws InterruptedException if interrupted
94     * @throws Exception if timed out while waiting for SD card to mount
95     */
96    protected String getDownloadStartedFilePath() {
97        String path = Environment.getExternalStorageDirectory().getPath();
98        return path + File.separatorChar + DOWNLOAD_STARTED_FLAG;
99    }
100
101    /**
102     * Common setup steps for downloads.
103     *
104     * Note that these are not included in setUp, so that individual tests can control their own
105     * state between reboots, etc.
106     */
107    protected void doCommonDownloadSetup() throws Exception {
108        setWiFiStateOn(true);
109        setAirplaneModeOn(false);
110        waitForExternalStoreMount();
111        removeAllCurrentDownloads();
112    }
113
114    /**
115     * Initiates a download.
116     *
117     * Queues up a download to the download manager, and saves the DownloadManager's assigned
118     * download ID for this download to a file.
119     *
120     * @throws Exception if unsuccessful
121     */
122    public void initiateDownload() throws Exception {
123        String filename = DOWNLOAD_FILENAME;
124        mContext.deleteFile(DOWNLOAD_STARTED_FLAG);
125        FileOutputStream fileOutput = mContext.openFileOutput(DOWNLOAD_STARTED_FLAG, 0);
126        DataOutputStream outputFile = null;
127        doCommonDownloadSetup();
128
129        try {
130            long dlRequest = -1;
131
132            // Make sure there are no pending downloads currently going on
133            removeAllCurrentDownloads();
134
135            Uri remoteUri = getExternalFileUri(filename);
136            Request request = new Request(remoteUri);
137
138            dlRequest = mDownloadManager.enqueue(request);
139            waitForDownloadToStart(dlRequest);
140            assertTrue(dlRequest != -1);
141
142            // Store ID of download for later retrieval
143            outputFile = new DataOutputStream(fileOutput);
144            outputFile.writeLong(dlRequest);
145        } finally {
146            if (outputFile != null) {
147                outputFile.flush();
148                outputFile.close();
149            }
150        }
151    }
152
153    /**
154     * Waits for a previously-initiated download and verifies it has completed successfully.
155     *
156     * @throws Exception if unsuccessful
157     */
158    public void verifyFileDownloadSucceeded() throws Exception {
159        String filename = DOWNLOAD_FILENAME;
160        long filesize = DOWNLOAD_FILESIZE;
161        long dlRequest = -1;
162        boolean rebootMarkerValid = false;
163        DataInputStream dataInputFile = null;
164
165        setWiFiStateOn(true);
166        setAirplaneModeOn(false);
167
168        try {
169            FileInputStream inFile = mContext.openFileInput(DOWNLOAD_STARTED_FLAG);
170            dataInputFile = new DataInputStream(inFile);
171            dlRequest = dataInputFile.readLong();
172        } catch (Exception e) {
173            // The file was't valid so we just leave the flag false
174            Log.i(LOG_TAG, "Unable to determine initial download id.");
175            throw e;
176        } finally {
177            if (dataInputFile != null) {
178                dataInputFile.close();
179            }
180            mContext.deleteFile(DOWNLOAD_STARTED_FLAG);
181        }
182
183        assertTrue(dlRequest != -1);
184        Cursor cursor = getCursor(dlRequest);
185        ParcelFileDescriptor pfd = null;
186        try {
187            assertTrue("Unable to query last initiated download!", cursor.moveToFirst());
188
189            int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
190            int status = cursor.getInt(columnIndex);
191            int currentWaitTime = 0;
192
193            assertTrue(waitForDownload(dlRequest, 15 * 60 * 1000));
194
195            Log.i(LOG_TAG, "Verifying download information...");
196            // Verify specific info about the file (size, name, etc)...
197            pfd = mDownloadManager.openDownloadedFile(dlRequest);
198            verifyFileSize(pfd, filesize);
199        } catch (Exception e) {
200            Log.i(LOG_TAG, "error: " + e.toString());
201            throw e;
202        } finally {
203            // Clean up...
204            cursor.close();
205            mDownloadManager.remove(dlRequest);
206            if (pfd != null) {
207                pfd.close();
208            }
209        }
210    }
211
212    /**
213     * Tests downloading a large file over WiFi (~10 Mb).
214     *
215     * @throws Exception if unsuccessful
216     */
217    public void runLargeDownloadOverWiFi() throws Exception {
218        String filename = DOWNLOAD_FILENAME;
219        long filesize = DOWNLOAD_FILESIZE;
220        long dlRequest = -1;
221        doCommonDownloadSetup();
222
223        // Make sure there are no pending downloads currently going on
224        removeAllCurrentDownloads();
225
226        Uri remoteUri = getExternalFileUri(filename);
227        Request request = new Request(remoteUri);
228        request.setMimeType("application/vnd.android.package-archive");
229
230        dlRequest = mDownloadManager.enqueue(request);
231
232        // Rather large file, so wait up to 15 mins...
233        assertTrue(waitForDownload(dlRequest, 15 * 60 * 1000));
234
235        Cursor cursor = getCursor(dlRequest);
236        ParcelFileDescriptor pfd = null;
237        try {
238            Log.i(LOG_TAG, "Verifying download information...");
239            // Verify specific info about the file (size, name, etc)...
240            pfd = mDownloadManager.openDownloadedFile(dlRequest);
241            verifyFileSize(pfd, filesize);
242        } finally {
243            if (pfd != null) {
244                pfd.close();
245            }
246            mDownloadManager.remove(dlRequest);
247            cursor.close();
248        }
249    }
250
251    /**
252     * Tests that downloads resume when switching back and forth from having connectivity to
253     * having no connectivity using both WiFi and airplane mode.
254     *
255     * Note: Device has no mobile access when running this test.
256     *
257     * @throws Exception if unsuccessful
258     */
259    public void runDownloadMultipleSwitching() throws Exception {
260        String filename = DOWNLOAD_FILENAME;
261        long filesize = DOWNLOAD_FILESIZE;
262        doCommonDownloadSetup();
263
264        String localDownloadDirectory = Environment.getExternalStorageDirectory().getPath();
265        File downloadedFile = new File(localDownloadDirectory, filename);
266
267        long dlRequest = -1;
268        try {
269            downloadedFile.delete();
270
271            // Make sure there are no pending downloads currently going on
272            removeAllCurrentDownloads();
273
274            Uri remoteUri = getExternalFileUri(filename);
275            Request request = new Request(remoteUri);
276
277            // Local destination of downloaded file
278            Uri localUri = Uri.fromFile(downloadedFile);
279            Log.i(LOG_TAG, "setting localUri to: " + localUri.getPath());
280            request.setDestinationUri(localUri);
281
282            request.setAllowedNetworkTypes(Request.NETWORK_MOBILE | Request.NETWORK_WIFI);
283
284            dlRequest = mDownloadManager.enqueue(request);
285            waitForDownloadToStart(dlRequest);
286            // make sure we're starting to download some data...
287            waitToReceiveData(dlRequest);
288
289            // download disable
290            setWiFiStateOn(false);
291
292            // download disable
293            Log.i(LOG_TAG, "Turning on airplane mode...");
294            setAirplaneModeOn(true);
295            Thread.sleep(30 * 1000);  // wait 30 secs
296
297            // download disable
298            setWiFiStateOn(true);
299            Thread.sleep(30 * 1000);  // wait 30 secs
300
301            // download enable
302            Log.i(LOG_TAG, "Turning off airplane mode...");
303            setAirplaneModeOn(false);
304            Thread.sleep(5 * 1000);  // wait 5 seconds
305
306            // download disable
307            Log.i(LOG_TAG, "Turning off WiFi...");
308            setWiFiStateOn(false);
309            Thread.sleep(30 * 1000);  // wait 30 secs
310
311            // finally, turn WiFi back on and finish up the download
312            Log.i(LOG_TAG, "Turning on WiFi...");
313            setWiFiStateOn(true);
314            Log.i(LOG_TAG, "Waiting up to 3 minutes for download to complete...");
315            assertTrue(waitForDownload(dlRequest, 3 * 60 * 1000));
316            ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
317            verifyFileSize(pfd, filesize);
318        } finally {
319            Log.i(LOG_TAG, "Cleaning up files...");
320            if (dlRequest != -1) {
321                mDownloadManager.remove(dlRequest);
322            }
323            downloadedFile.delete();
324        }
325    }
326
327    /**
328     * Tests that downloads resume when switching on/off WiFi at various intervals.
329     *
330     * Note: Device has no mobile access when running this test.
331     *
332     * @throws Exception if unsuccessful
333     */
334    public void runDownloadMultipleWiFiEnableDisable() throws Exception {
335        String filename = DOWNLOAD_FILENAME;
336        long filesize = DOWNLOAD_FILESIZE;
337        doCommonDownloadSetup();
338
339        String localDownloadDirectory = Environment.getExternalStorageDirectory().getPath();
340        File downloadedFile = new File(localDownloadDirectory, filename);
341        long dlRequest = -1;
342        try {
343            downloadedFile.delete();
344
345            // Make sure there are no pending downloads currently going on
346            removeAllCurrentDownloads();
347
348            Uri remoteUri = getExternalFileUri(filename);
349            Request request = new Request(remoteUri);
350
351            // Local destination of downloaded file
352            Uri localUri = Uri.fromFile(downloadedFile);
353            Log.i(LOG_TAG, "setting localUri to: " + localUri.getPath());
354            request.setDestinationUri(localUri);
355
356            request.setAllowedNetworkTypes(Request.NETWORK_WIFI);
357
358            dlRequest = mDownloadManager.enqueue(request);
359            waitForDownloadToStart(dlRequest);
360            // are we making any progress?
361            waitToReceiveData(dlRequest);
362
363            // download disable
364            Log.i(LOG_TAG, "Turning off WiFi...");
365            setWiFiStateOn(false);
366            Thread.sleep(40 * 1000);  // wait 40 seconds
367
368            // enable download...
369            Log.i(LOG_TAG, "Turning on WiFi again...");
370            setWiFiStateOn(true);
371            waitToReceiveData(dlRequest);
372
373            // download disable
374            Log.i(LOG_TAG, "Turning off WiFi...");
375            setWiFiStateOn(false);
376            Thread.sleep(20 * 1000);  // wait 20 seconds
377
378            // enable download...
379            Log.i(LOG_TAG, "Turning on WiFi again...");
380            setWiFiStateOn(true);
381
382            Log.i(LOG_TAG, "Waiting up to 3 minutes for download to complete...");
383            assertTrue(waitForDownload(dlRequest, 3 * 60 * 1000));
384            ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
385            verifyFileSize(pfd, filesize);
386        } finally {
387            Log.i(LOG_TAG, "Cleaning up files...");
388            if (dlRequest != -1) {
389                mDownloadManager.remove(dlRequest);
390            }
391            downloadedFile.delete();
392        }
393    }
394
395    /**
396     * Tests that downloads resume when switching on/off Airplane mode numerous times at
397     * various intervals.
398     *
399     * Note: Device has no mobile access when running this test.
400     *
401     * @throws Exception if unsuccessful
402     */
403    public void runDownloadMultipleAirplaneModeEnableDisable() throws Exception {
404        String filename = DOWNLOAD_FILENAME;
405        long filesize = DOWNLOAD_FILESIZE;
406        // make sure WiFi is enabled, and airplane mode is not on
407        doCommonDownloadSetup();
408
409        String localDownloadDirectory = Environment.getExternalStorageDirectory().getPath();
410        File downloadedFile = new File(localDownloadDirectory, filename);
411        long dlRequest = -1;
412        try {
413            downloadedFile.delete();
414
415            // Make sure there are no pending downloads currently going on
416            removeAllCurrentDownloads();
417
418            Uri remoteUri = getExternalFileUri(filename);
419            Request request = new Request(remoteUri);
420
421            // Local destination of downloaded file
422            Uri localUri = Uri.fromFile(downloadedFile);
423            Log.i(LOG_TAG, "setting localUri to: " + localUri.getPath());
424            request.setDestinationUri(localUri);
425
426            request.setAllowedNetworkTypes(Request.NETWORK_WIFI);
427
428            dlRequest = mDownloadManager.enqueue(request);
429            waitForDownloadToStart(dlRequest);
430            // are we making any progress?
431            waitToReceiveData(dlRequest);
432
433            // download disable
434            Log.i(LOG_TAG, "Turning on Airplane mode...");
435            setAirplaneModeOn(true);
436            Thread.sleep(60 * 1000);  // wait 1 minute
437
438            // download enable
439            Log.i(LOG_TAG, "Turning off Airplane mode...");
440            setAirplaneModeOn(false);
441            // make sure we're starting to download some data...
442            waitToReceiveData(dlRequest);
443
444            // reenable the connection to start up the download again
445            Log.i(LOG_TAG, "Turning on Airplane mode again...");
446            setAirplaneModeOn(true);
447            Thread.sleep(20 * 1000);  // wait 20 seconds
448
449            // Finish up the download...
450            Log.i(LOG_TAG, "Turning off Airplane mode again...");
451            setAirplaneModeOn(false);
452
453            Log.i(LOG_TAG, "Waiting up to 3 minutes for donwload to complete...");
454            assertTrue(waitForDownload(dlRequest, 180 * 1000));  // wait up to 3 mins before timeout
455            ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
456            verifyFileSize(pfd, filesize);
457        } finally {
458            Log.i(LOG_TAG, "Cleaning up files...");
459            if (dlRequest != -1) {
460                mDownloadManager.remove(dlRequest);
461            }
462            downloadedFile.delete();
463        }
464    }
465
466    /**
467     * Tests 15 concurrent downloads of 1,000,000-byte files.
468     *
469     * @throws Exception if test failed
470     */
471    public void runDownloadMultipleSimultaneously() throws Exception {
472        final int TOTAL_DOWNLOADS = 15;
473        HashSet<Long> downloadIds = new HashSet<Long>(TOTAL_DOWNLOADS);
474
475        // Make sure there are no pending downloads currently going on
476        removeAllCurrentDownloads();
477
478        try {
479            for (int i = 0; i < TOTAL_DOWNLOADS; ++i) {
480                long dlRequest = -1;
481                String filename = FILE_CONCURRENT_DOWNLOAD_FILE_PREFIX + i
482                        + FILE_CONCURRENT_DOWNLOAD_FILE_EXTENSION;
483                Uri remoteUri = getExternalFileUri(filename);
484                Request request = new Request(remoteUri);
485                request.setTitle(filename);
486                dlRequest = mDownloadManager.enqueue(request);
487                assertTrue(dlRequest != -1);
488                downloadIds.add(dlRequest);
489            }
490
491            assertTrue(waitForMultipleDownloads(downloadIds, 15 * 60 * 2000));  // wait 15 mins max
492        } finally {
493            removeAllCurrentDownloads();
494        }
495    }
496}
497