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