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 */ 16 17 package com.android.providers.downloads; 18 19 import static android.app.DownloadManager.STATUS_FAILED; 20 import static android.app.DownloadManager.STATUS_SUCCESSFUL; 21 import static android.text.format.DateUtils.MINUTE_IN_MILLIS; 22 import static android.text.format.DateUtils.SECOND_IN_MILLIS; 23 24 import android.app.DownloadManager; 25 import android.content.ContentResolver; 26 import android.content.ContextWrapper; 27 import android.database.Cursor; 28 import android.net.Uri; 29 import android.os.Environment; 30 import android.os.ParcelFileDescriptor; 31 import android.os.SystemClock; 32 import android.util.Log; 33 34 import libcore.io.IoUtils; 35 import libcore.io.Streams; 36 37 import java.io.InputStream; 38 import java.net.MalformedURLException; 39 import java.net.UnknownHostException; 40 import java.util.concurrent.TimeoutException; 41 42 /** 43 * Code common to tests that use the download manager public API. 44 */ 45 public abstract class AbstractPublicApiTest extends AbstractDownloadProviderFunctionalTest { 46 47 class Download { 48 final long mId; 49 Download(long downloadId)50 private Download(long downloadId) { 51 this.mId = downloadId; 52 } 53 getStatus()54 public int getStatus() { 55 return (int) getLongField(DownloadManager.COLUMN_STATUS); 56 } 57 getReason()58 public int getReason() { 59 return (int) getLongField(DownloadManager.COLUMN_REASON); 60 } 61 getStatusIfExists()62 public int getStatusIfExists() { 63 Cursor cursor = mManager.query(new DownloadManager.Query().setFilterById(mId)); 64 try { 65 if (cursor.getCount() > 0) { 66 cursor.moveToFirst(); 67 return (int) cursor.getLong(cursor.getColumnIndexOrThrow( 68 DownloadManager.COLUMN_STATUS)); 69 } else { 70 // the row doesn't exist 71 return -1; 72 } 73 } finally { 74 cursor.close(); 75 } 76 } 77 getStringField(String field)78 String getStringField(String field) { 79 Cursor cursor = mManager.query(new DownloadManager.Query().setFilterById(mId)); 80 try { 81 assertEquals(1, cursor.getCount()); 82 cursor.moveToFirst(); 83 return cursor.getString(cursor.getColumnIndexOrThrow(field)); 84 } finally { 85 cursor.close(); 86 } 87 } 88 getLongField(String field)89 long getLongField(String field) { 90 Cursor cursor = mManager.query(new DownloadManager.Query().setFilterById(mId)); 91 try { 92 assertEquals(1, cursor.getCount()); 93 cursor.moveToFirst(); 94 return cursor.getLong(cursor.getColumnIndexOrThrow(field)); 95 } finally { 96 cursor.close(); 97 } 98 } 99 getRawContents()100 byte[] getRawContents() throws Exception { 101 ParcelFileDescriptor downloadedFile = mManager.openDownloadedFile(mId); 102 assertTrue("Invalid file descriptor: " + downloadedFile, 103 downloadedFile.getFileDescriptor().valid()); 104 final InputStream is = new ParcelFileDescriptor.AutoCloseInputStream( 105 downloadedFile); 106 try { 107 return Streams.readFully(is); 108 } finally { 109 IoUtils.closeQuietly(is); 110 } 111 } 112 getContents()113 String getContents() throws Exception { 114 return new String(getRawContents()); 115 } 116 runUntilStatus(int status)117 void runUntilStatus(int status) throws TimeoutException { 118 final long startMillis = mSystemFacade.currentTimeMillis(); 119 startDownload(mId); 120 waitForStatus(status, startMillis); 121 } 122 runUntilStatus(int status, long timeout)123 void runUntilStatus(int status, long timeout) throws TimeoutException { 124 final long startMillis = mSystemFacade.currentTimeMillis(); 125 startDownload(mId); 126 waitForStatus(status, startMillis, timeout); 127 } 128 waitForStatus(int expected, long afterMillis)129 void waitForStatus(int expected, long afterMillis) throws TimeoutException { 130 waitForStatus(expected, afterMillis, 15 * SECOND_IN_MILLIS); 131 } 132 waitForStatus(int expected, long afterMillis, long timeout)133 void waitForStatus(int expected, long afterMillis, long timeout) throws TimeoutException { 134 int actual = -1; 135 136 final long elapsedTimeout = SystemClock.elapsedRealtime() + timeout; 137 while (SystemClock.elapsedRealtime() < elapsedTimeout) { 138 if (getLongField(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP) >= afterMillis) { 139 actual = getStatus(); 140 if (actual == STATUS_SUCCESSFUL || actual == STATUS_FAILED) { 141 assertEquals(expected, actual); 142 return; 143 } else if (actual == expected) { 144 return; 145 } 146 147 if (timeout > MINUTE_IN_MILLIS) { 148 final int percent = (int) (100 149 * getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR) 150 / getLongField(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)); 151 Log.d(LOG_TAG, percent + "% complete"); 152 } 153 } 154 155 if (timeout > MINUTE_IN_MILLIS) { 156 SystemClock.sleep(SECOND_IN_MILLIS * 3); 157 } else { 158 SystemClock.sleep(100); 159 } 160 } 161 162 throw new TimeoutException("Expected status " + expected + "; only reached " + actual); 163 } 164 165 // max time to wait before giving up on the current download operation. 166 private static final int MAX_TIME_TO_WAIT_FOR_OPERATION = 5; 167 // while waiting for the above time period, sleep this long to yield to the 168 // download thread 169 private static final int TIME_TO_SLEEP = 1000; 170 171 // waits until progress_so_far is >= (progress)% runUntilProgress(int progress)172 boolean runUntilProgress(int progress) throws InterruptedException { 173 startDownload(mId); 174 175 int sleepCounter = MAX_TIME_TO_WAIT_FOR_OPERATION * 1000 / TIME_TO_SLEEP; 176 int numBytesReceivedSoFar = 0; 177 int totalBytes = 0; 178 for (int i = 0; i < sleepCounter; i++) { 179 Cursor cursor = mManager.query(new DownloadManager.Query().setFilterById(mId)); 180 try { 181 assertEquals(1, cursor.getCount()); 182 cursor.moveToFirst(); 183 numBytesReceivedSoFar = cursor.getInt( 184 cursor.getColumnIndexOrThrow( 185 DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)); 186 totalBytes = cursor.getInt( 187 cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)); 188 } finally { 189 cursor.close(); 190 } 191 Log.i(LOG_TAG, "in runUntilProgress, numBytesReceivedSoFar: " + 192 numBytesReceivedSoFar + ", totalBytes: " + totalBytes); 193 if (totalBytes == 0) { 194 fail("total_bytes should not be zero"); 195 return false; 196 } else { 197 if (numBytesReceivedSoFar * 100 / totalBytes >= progress) { 198 // progress_so_far is >= progress%. we are done 199 return true; 200 } 201 } 202 // download not done yet. sleep a while and try again 203 Thread.sleep(TIME_TO_SLEEP); 204 } 205 Log.i(LOG_TAG, "FAILED in runUntilProgress, numBytesReceivedSoFar: " + 206 numBytesReceivedSoFar + ", totalBytes: " + totalBytes); 207 return false; // failed 208 } 209 } 210 211 protected static final String PACKAGE_NAME = "my.package.name"; 212 protected static final String REQUEST_PATH = "/path"; 213 214 protected DownloadManager mManager; 215 AbstractPublicApiTest(FakeSystemFacade systemFacade)216 public AbstractPublicApiTest(FakeSystemFacade systemFacade) { 217 super(systemFacade); 218 } 219 220 @Override setUp()221 protected void setUp() throws Exception { 222 super.setUp(); 223 mManager = new DownloadManager(new ContextWrapper(mContext) { 224 @Override 225 public ContentResolver getContentResolver() { 226 return mResolver; 227 } 228 229 @Override 230 public String getPackageName() { 231 return PACKAGE_NAME; 232 } 233 }); 234 mManager.setAccessFilename(true); 235 } 236 getRequest()237 protected DownloadManager.Request getRequest() 238 throws MalformedURLException, UnknownHostException { 239 return getRequest(getServerUri(REQUEST_PATH)); 240 } 241 getRequestWithDestinationDownloadsDir()242 protected DownloadManager.Request getRequestWithDestinationDownloadsDir() 243 throws MalformedURLException, UnknownHostException { 244 final DownloadManager.Request request = getRequest(); 245 request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "testfile.txt"); 246 return request; 247 } 248 getRequest(String path)249 protected DownloadManager.Request getRequest(String path) { 250 return new DownloadManager.Request(Uri.parse(path)); 251 } 252 enqueueRequest(DownloadManager.Request request)253 protected Download enqueueRequest(DownloadManager.Request request) { 254 return new Download(mManager.enqueue(request)); 255 } 256 } 257