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 // Wait until download manager actually start downloading something 44 // Will wait for 1 MB to be downloaded. 45 private static final long EXPECTED_PROGRESS = 1024 * 1024; 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("download url is null", externalDownloadUriValue); 64 65 externalLargeDownloadUriValue = normalizeUri(mRunner.externalDownloadUriValue); 66 assertNotNull("large download url is null", 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("request id is -1 from download manager", 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("request id is -1 from download manager", 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 assertTrue("download not finished", waitForDownload(dlRequest, 15 * 60 * 1000)); 197 198 Log.i(LOG_TAG, "Verifying download information..."); 199 // Verify specific info about the file (size, name, etc)... 200 pfd = mDownloadManager.openDownloadedFile(dlRequest); 201 verifyFileSize(pfd, filesize); 202 } catch (Exception e) { 203 Log.i(LOG_TAG, "error: " + e.toString()); 204 throw e; 205 } finally { 206 // Clean up... 207 cursor.close(); 208 mDownloadManager.remove(dlRequest); 209 if (pfd != null) { 210 pfd.close(); 211 } 212 } 213 } 214 215 /** 216 * Tests downloading a large file over WiFi (~10 Mb). 217 * 218 * @throws Exception if unsuccessful 219 */ 220 public void runLargeDownloadOverWiFi() throws Exception { 221 String filename = DOWNLOAD_FILENAME; 222 long filesize = DOWNLOAD_FILESIZE; 223 long dlRequest = -1; 224 doCommonDownloadSetup(); 225 226 // Make sure there are no pending downloads currently going on 227 removeAllCurrentDownloads(); 228 229 Uri remoteUri = getExternalFileUri(filename); 230 Request request = new Request(remoteUri); 231 request.setMimeType("application/vnd.android.package-archive"); 232 233 dlRequest = mDownloadManager.enqueue(request); 234 235 // Rather large file, so wait up to 15 mins... 236 assertTrue("download not finished", waitForDownload(dlRequest, 15 * 60 * 1000)); 237 238 Cursor cursor = getCursor(dlRequest); 239 ParcelFileDescriptor pfd = null; 240 try { 241 Log.i(LOG_TAG, "Verifying download information..."); 242 // Verify specific info about the file (size, name, etc)... 243 pfd = mDownloadManager.openDownloadedFile(dlRequest); 244 verifyFileSize(pfd, filesize); 245 } finally { 246 if (pfd != null) { 247 pfd.close(); 248 } 249 mDownloadManager.remove(dlRequest); 250 cursor.close(); 251 } 252 } 253 254 /** 255 * Tests that downloads resume when switching back and forth from having connectivity to 256 * having no connectivity using both WiFi and airplane mode. 257 * 258 * Note: Device has no mobile access when running this test. 259 * 260 * @throws Exception if unsuccessful 261 */ 262 public void runDownloadMultipleSwitching() throws Exception { 263 String filename = DOWNLOAD_FILENAME; 264 long filesize = DOWNLOAD_FILESIZE; 265 doCommonDownloadSetup(); 266 267 String localDownloadDirectory = Environment.getExternalStorageDirectory().getPath(); 268 File downloadedFile = new File(localDownloadDirectory, filename); 269 270 long dlRequest = -1; 271 try { 272 downloadedFile.delete(); 273 274 // Make sure there are no pending downloads currently going on 275 removeAllCurrentDownloads(); 276 277 Uri remoteUri = getExternalFileUri(filename); 278 Request request = new Request(remoteUri); 279 280 // Local destination of downloaded file 281 Uri localUri = Uri.fromFile(downloadedFile); 282 Log.i(LOG_TAG, "setting localUri to: " + localUri.getPath()); 283 request.setDestinationUri(localUri); 284 285 request.setAllowedNetworkTypes(Request.NETWORK_MOBILE | Request.NETWORK_WIFI); 286 287 dlRequest = mDownloadManager.enqueue(request); 288 waitForDownloadToStart(dlRequest); 289 // make sure we're starting to download some data... 290 waitToReceiveData(dlRequest, EXPECTED_PROGRESS); 291 292 // download disable 293 setWiFiStateOn(false); 294 295 // download disable 296 Log.i(LOG_TAG, "Turning on airplane mode..."); 297 setAirplaneModeOn(true); 298 Thread.sleep(5 * 1000); // wait 5 secs 299 300 // download disable 301 setWiFiStateOn(true); 302 Thread.sleep(5 * 1000); // wait 5 secs 303 waitToReceiveData(dlRequest, EXPECTED_PROGRESS); 304 305 // download enable 306 Log.i(LOG_TAG, "Turning off airplane mode..."); 307 setAirplaneModeOn(false); 308 Thread.sleep(5 * 1000); // wait 5 seconds 309 waitToReceiveData(dlRequest, EXPECTED_PROGRESS); 310 311 // download disable 312 Log.i(LOG_TAG, "Turning off WiFi..."); 313 setWiFiStateOn(false); 314 Thread.sleep(5 * 1000); // wait 5 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 10 minutes for download to complete..."); 320 assertTrue("download not finished", waitForDownload(dlRequest, 10 * 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 waitToReceiveData(dlRequest, EXPECTED_PROGRESS); 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 waitToReceiveData(dlRequest, EXPECTED_PROGRESS); 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 10 minutes for download to complete..."); 388 assertTrue("download not finished", waitForDownload(dlRequest, 10 * 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 waitToReceiveData(dlRequest, EXPECTED_PROGRESS); 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 waitToReceiveData(dlRequest, EXPECTED_PROGRESS); 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 10 minutes for donwload to complete..."); 459 assertTrue("download not finished", waitForDownload(dlRequest, 10 * 60 * 1000)); // wait up to 10 mins 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 480 // Make sure there are no pending downloads currently going on 481 removeAllCurrentDownloads(); 482 483 try { 484 for (int i = 0; i < TOTAL_DOWNLOADS; ++i) { 485 long dlRequest = -1; 486 String filename = FILE_CONCURRENT_DOWNLOAD_FILE_PREFIX + i 487 + FILE_CONCURRENT_DOWNLOAD_FILE_EXTENSION; 488 Uri remoteUri = getExternalFileUri(filename); 489 Request request = new Request(remoteUri); 490 request.setTitle(filename); 491 dlRequest = mDownloadManager.enqueue(request); 492 assertTrue("request id is -1 from download manager", dlRequest != -1); 493 downloadIds.add(dlRequest); 494 } 495 496 assertTrue("download not finished", waitForMultipleDownloads(downloadIds, 15 * 60 * 2000)); // wait 15 mins max 497 } finally { 498 removeAllCurrentDownloads(); 499 } 500 } 501} 502