140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen/* 240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Copyright (C) 2010 The Android Open Source Project 340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Licensed under the Apache License, Version 2.0 (the "License"); 540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * you may not use this file except in compliance with the License. 640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * You may obtain a copy of the License at 740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * http://www.apache.org/licenses/LICENSE-2.0 940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 1040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Unless required by applicable law or agreed to in writing, software 1140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * distributed under the License is distributed on an "AS IS" BASIS, 1240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * See the License for the specific language governing permissions and 1440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * limitations under the License. 1540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 1640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 1731fd85f39b554e09b2e6c1c2ccf5c186859880faSteve Howardpackage android.app; 1840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 1931fd85f39b554e09b2e6c1c2ccf5c186859880faSteve Howardimport android.app.DownloadManager.Query; 2031fd85f39b554e09b2e6c1c2ccf5c186859880faSteve Howardimport android.app.DownloadManager.Request; 2140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport android.content.BroadcastReceiver; 2240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport android.content.Context; 2340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport android.content.Intent; 2440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport android.content.IntentFilter; 2540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport android.database.Cursor; 2640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport android.net.ConnectivityManager; 2740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport android.net.NetworkInfo; 2831fd85f39b554e09b2e6c1c2ccf5c186859880faSteve Howardimport android.net.Uri; 2940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport android.net.wifi.WifiManager; 3040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport android.os.Environment; 3140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport android.os.ParcelFileDescriptor; 32c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tateimport android.os.UserHandle; 3340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport android.os.ParcelFileDescriptor.AutoCloseInputStream; 3482e891b3259350a92b55969a6380ca1240ee0829Vasu Noriimport android.os.SystemClock; 3540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport android.provider.Settings; 3640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport android.test.InstrumentationTestCase; 3740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport android.util.Log; 3840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 39b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkeyimport com.google.mockwebserver.MockResponse; 40b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkeyimport com.google.mockwebserver.MockWebServer; 41b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey 4240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport java.io.DataInputStream; 4340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport java.io.DataOutputStream; 4440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport java.io.File; 4540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport java.io.FileInputStream; 46b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkeyimport java.io.FileNotFoundException; 4740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport java.io.FileOutputStream; 4840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport java.io.IOException; 4940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport java.net.URL; 5082e891b3259350a92b55969a6380ca1240ee0829Vasu Noriimport java.util.ArrayList; 51df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyenimport java.util.Collections; 52df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyenimport java.util.HashSet; 5340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenimport java.util.Random; 54df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyenimport java.util.Set; 5582e891b3259350a92b55969a6380ca1240ee0829Vasu Noriimport java.util.concurrent.TimeoutException; 5640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 57b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkeyimport libcore.io.Streams; 58b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey 5940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen/** 6040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Base class for Instrumented tests for the Download Manager. 6140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 6240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyenpublic class DownloadManagerBaseTest extends InstrumentationTestCase { 636f35c0ecba6cb1ce5d7563a9962acf9557dbacedVasu Nori private static final String TAG = "DownloadManagerBaseTest"; 6440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected DownloadManager mDownloadManager = null; 65b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey private MockWebServer mServer = null; 6640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected String mFileType = "text/plain"; 6740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected Context mContext = null; 6863e5d79a163461651cd8bd89d3de691ef7649109Neal Nguyen protected MultipleDownloadsCompletedReceiver mReceiver = null; 6982e891b3259350a92b55969a6380ca1240ee0829Vasu Nori protected static final int DEFAULT_FILE_SIZE = 10 * 1024; // 10kb 7040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected static final int FILE_BLOCK_READ_SIZE = 1024 * 1024; 7140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 7240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected static final String LOG_TAG = "android.net.DownloadManagerBaseTest"; 7340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected static final int HTTP_OK = 200; 74df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen protected static final int HTTP_REDIRECT = 307; 7540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected static final int HTTP_PARTIAL_CONTENT = 206; 7640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected static final int HTTP_NOT_FOUND = 404; 7740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected static final int HTTP_SERVICE_UNAVAILABLE = 503; 7840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected String DEFAULT_FILENAME = "somefile.txt"; 7940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 8040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected static final int DEFAULT_MAX_WAIT_TIME = 2 * 60 * 1000; // 2 minutes 8140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected static final int DEFAULT_WAIT_POLL_TIME = 5 * 1000; // 5 seconds 8240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 8340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected static final int WAIT_FOR_DOWNLOAD_POLL_TIME = 1 * 1000; // 1 second 8440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected static final int MAX_WAIT_FOR_DOWNLOAD_TIME = 5 * 60 * 1000; // 5 minutes 85bd06f02d02e07ca15e420ee9e50e35253646ba64Neal Nguyen protected static final int MAX_WAIT_FOR_LARGE_DOWNLOAD_TIME = 15 * 60 * 1000; // 15 minutes 8640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 8782e891b3259350a92b55969a6380ca1240ee0829Vasu Nori protected static final int DOWNLOAD_TO_SYSTEM_CACHE = 1; 8882e891b3259350a92b55969a6380ca1240ee0829Vasu Nori protected static final int DOWNLOAD_TO_DOWNLOAD_CACHE_DIR = 2; 8982e891b3259350a92b55969a6380ca1240ee0829Vasu Nori 9040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // Just a few popular file types used to return from a download 9140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected enum DownloadFileType { 9240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen PLAINTEXT, 9340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen APK, 9440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen GIF, 9540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen GARBAGE, 9640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen UNRECOGNIZED, 9740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen ZIP 9840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 9940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 10040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected enum DataType { 10140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen TEXT, 10240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen BINARY 10340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 10440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 10540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen public static class LoggingRng extends Random { 10640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 10740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 10840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Constructor 10940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 11040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Creates RNG with self-generated seed value. 11140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 11240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen public LoggingRng() { 11340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen this(SystemClock.uptimeMillis()); 11440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 11540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 11640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 11740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Constructor 11840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 11940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Creats RNG with given initial seed value 12040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 12140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param seed The initial seed value 12240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 12340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen public LoggingRng(long seed) { 12440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen super(seed); 12540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Log.i(LOG_TAG, "Seeding RNG with value: " + seed); 12640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 12740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 12840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 12940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen public static class MultipleDownloadsCompletedReceiver extends BroadcastReceiver { 13040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen private volatile int mNumDownloadsCompleted = 0; 131df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen private Set<Long> downloadIds = Collections.synchronizedSet(new HashSet<Long>()); 13240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 13340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 13440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * {@inheritDoc} 13540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 13640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen @Override 13740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen public void onReceive(Context context, Intent intent) { 13840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen if (intent.getAction().equalsIgnoreCase(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) { 13963e5d79a163461651cd8bd89d3de691ef7649109Neal Nguyen synchronized(this) { 14065c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen long id = intent.getExtras().getLong(DownloadManager.EXTRA_DOWNLOAD_ID); 14165c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen Log.i(LOG_TAG, "Received Notification for download: " + id); 14265c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen if (!downloadIds.contains(id)) { 14365c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen ++mNumDownloadsCompleted; 14465c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen Log.i(LOG_TAG, "MultipleDownloadsCompletedReceiver got intent: " + 14565c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen intent.getAction() + " --> total count: " + mNumDownloadsCompleted); 14665c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen downloadIds.add(id); 14765c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen 14865c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen DownloadManager dm = (DownloadManager)context.getSystemService( 14965c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen Context.DOWNLOAD_SERVICE); 15065c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen 15165c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen Cursor cursor = dm.query(new Query().setFilterById(id)); 15265c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen try { 15365c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen if (cursor.moveToFirst()) { 15465c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen int status = cursor.getInt(cursor.getColumnIndex( 15565c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen DownloadManager.COLUMN_STATUS)); 15665c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen Log.i(LOG_TAG, "Download status is: " + status); 15765c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen } else { 15865c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen fail("No status found for completed download!"); 15965c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen } 16065c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen } finally { 16165c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen cursor.close(); 16265c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen } 16365c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen } else { 16465c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen Log.i(LOG_TAG, "Notification for id: " + id + " has already been made."); 16565c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen } 16663e5d79a163461651cd8bd89d3de691ef7649109Neal Nguyen } 16740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 16840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 16940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 17040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 17140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Gets the number of times the {@link #onReceive} callback has been called for the 17240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * {@link DownloadManager.ACTION_DOWNLOAD_COMPLETED} action, indicating the number of 17340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * downloads completed thus far. 17440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 17540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @return the number of downloads completed so far. 17640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 17740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen public int numDownloadsCompleted() { 17840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return mNumDownloadsCompleted; 17940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 180df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen 181df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen /** 182df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen * Gets the list of download IDs. 183df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen * @return A Set<Long> with the ids of the completed downloads. 184df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen */ 185df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen public Set<Long> getDownloadIds() { 186bd06f02d02e07ca15e420ee9e50e35253646ba64Neal Nguyen synchronized(this) { 187df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen Set<Long> returnIds = new HashSet<Long>(downloadIds); 188df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen return returnIds; 189df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen } 190df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen } 191df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen 19240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 19340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 19440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen public static class WiFiChangedReceiver extends BroadcastReceiver { 19540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen private Context mContext = null; 19640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 19740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 19840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Constructor 19940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 20040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Sets the current state of WiFi. 20140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 20240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param context The current app {@link Context}. 20340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 20440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen public WiFiChangedReceiver(Context context) { 20540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen mContext = context; 20640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 20740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 20840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 20940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * {@inheritDoc} 21040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 21140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen @Override 21240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen public void onReceive(Context context, Intent intent) { 21340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen if (intent.getAction().equalsIgnoreCase(ConnectivityManager.CONNECTIVITY_ACTION)) { 21440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Log.i(LOG_TAG, "ConnectivityManager state change: " + intent.getAction()); 21540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen synchronized (this) { 21640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen this.notify(); 21740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 21840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 21940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 22040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 22140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 22240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Gets the current state of WiFi. 22340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 22440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @return Returns true if WiFi is on, false otherwise. 22540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 22640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen public boolean getWiFiIsOn() { 22740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen ConnectivityManager connManager = (ConnectivityManager)mContext.getSystemService( 22840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Context.CONNECTIVITY_SERVICE); 22940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen NetworkInfo info = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); 230bd06f02d02e07ca15e420ee9e50e35253646ba64Neal Nguyen Log.i(LOG_TAG, "WiFi Connection state is currently: " + info.isConnected()); 23140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return info.isConnected(); 23240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 23340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 23440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 23540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 23640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * {@inheritDoc} 23740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 23840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen @Override 23940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen public void setUp() throws Exception { 24040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen mContext = getInstrumentation().getContext(); 24140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen mDownloadManager = (DownloadManager)mContext.getSystemService(Context.DOWNLOAD_SERVICE); 24240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen mServer = new MockWebServer(); 243b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey mServer.play(); 24463e5d79a163461651cd8bd89d3de691ef7649109Neal Nguyen mReceiver = registerNewMultipleDownloadsReceiver(); 24540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // Note: callers overriding this should call mServer.play() with the desired port # 24640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 24740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 24840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 249b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey * Helper to build a response from the MockWebServer with no body. 250df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen * 251df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen * @param status The HTTP status code to return for this response 252df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen * @return Returns the mock web server response that was queued (which can be modified) 253df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen */ 254b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey protected MockResponse buildResponse(int status) { 255b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey MockResponse response = new MockResponse().setResponseCode(status); 256b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey response.setHeader("Content-type", mFileType); 257b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey return response; 258df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen } 259df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen 260df7a865bbf45b57c60d294d5ac721e67e69a2dd6Neal Nguyen /** 261b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey * Helper to build a response from the MockWebServer. 26240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 26340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param status The HTTP status code to return for this response 26440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param body The body to return in this response 26540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @return Returns the mock web server response that was queued (which can be modified) 26640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 267b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey protected MockResponse buildResponse(int status, byte[] body) { 268b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey return buildResponse(status).setBody(body); 26940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 27040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 27140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 272b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey * Helper to build a response from the MockWebServer. 27340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 27440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param status The HTTP status code to return for this response 27540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param bodyFile The body to return in this response 27640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @return Returns the mock web server response that was queued (which can be modified) 27740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 278b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey protected MockResponse buildResponse(int status, File bodyFile) 279b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey throws FileNotFoundException, IOException { 280b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey final byte[] body = Streams.readFully(new FileInputStream(bodyFile)); 281b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey return buildResponse(status).setBody(body); 28240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 28340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 284b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey protected void enqueueResponse(MockResponse resp) { 285b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey mServer.enqueue(resp); 28640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 28740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 28840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 28940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to generate a random blob of bytes. 29040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 29140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param size The size of the data to generate 292b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey * @param type The type of data to generate: currently, one of {@link DataType#TEXT} or 293b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey * {@link DataType#BINARY}. 29440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @return The random data that is generated. 29540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 29640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected byte[] generateData(int size, DataType type) { 29740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return generateData(size, type, null); 29840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 29940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 30040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 30140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to generate a random blob of bytes using a given RNG. 30240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 30340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param size The size of the data to generate 304b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey * @param type The type of data to generate: currently, one of {@link DataType#TEXT} or 305b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey * {@link DataType#BINARY}. 30640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param rng (optional) The RNG to use; pass null to use 30740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @return The random data that is generated. 30840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 30940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected byte[] generateData(int size, DataType type, Random rng) { 31040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int min = Byte.MIN_VALUE; 31140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int max = Byte.MAX_VALUE; 31240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 31340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // Only use chars in the HTTP ASCII printable character range for Text 31440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen if (type == DataType.TEXT) { 31540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen min = 32; 31640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen max = 126; 31740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 31840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen byte[] result = new byte[size]; 31940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Log.i(LOG_TAG, "Generating data of size: " + size); 32040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 32140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen if (rng == null) { 32240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen rng = new LoggingRng(); 32340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 32440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 32540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen for (int i = 0; i < size; ++i) { 32640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen result[i] = (byte) (min + rng.nextInt(max - min + 1)); 32740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 32840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return result; 32940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 33040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 33140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 33240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to verify the size of a file. 33340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 33440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param pfd The input file to compare the size of 33540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param size The expected size of the file 33640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 33740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void verifyFileSize(ParcelFileDescriptor pfd, long size) { 33840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen assertEquals(pfd.getStatSize(), size); 33940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 34040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 34140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 34240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to verify the contents of a downloaded file versus a byte[]. 34340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 34440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param actual The file of whose contents to verify 34540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param expected The data we expect to find in the aforementioned file 34640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @throws IOException if there was a problem reading from the file 34740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 34840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void verifyFileContents(ParcelFileDescriptor actual, byte[] expected) 34940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen throws IOException { 35040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen AutoCloseInputStream input = new ParcelFileDescriptor.AutoCloseInputStream(actual); 35140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen long fileSize = actual.getStatSize(); 35240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 35340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen assertTrue(fileSize <= Integer.MAX_VALUE); 35440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen assertEquals(expected.length, fileSize); 35540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 35640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen byte[] actualData = new byte[expected.length]; 35740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen assertEquals(input.read(actualData), fileSize); 35840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen compareByteArrays(actualData, expected); 35940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 36040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 36140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 36240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to compare 2 byte arrays. 36340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 36440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param actual The array whose data we want to verify 36540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param expected The array of data we expect to see 36640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 36740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void compareByteArrays(byte[] actual, byte[] expected) { 36840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen assertEquals(actual.length, expected.length); 36940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int length = actual.length; 37040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen for (int i = 0; i < length; ++i) { 37140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // assert has a bit of overhead, so only do the assert when the values are not the same 37240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen if (actual[i] != expected[i]) { 37340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen fail("Byte arrays are not equal."); 37440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 37540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 37640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 37740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 37840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 37940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Verifies the contents of a downloaded file versus the contents of a File. 38040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 38140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param pfd The file whose data we want to verify 38240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param file The file containing the data we expect to see in the aforementioned file 38340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @throws IOException If there was a problem reading either of the two files 38440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 38540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void verifyFileContents(ParcelFileDescriptor pfd, File file) throws IOException { 38640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen byte[] actual = new byte[FILE_BLOCK_READ_SIZE]; 38740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen byte[] expected = new byte[FILE_BLOCK_READ_SIZE]; 38840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 38940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen AutoCloseInputStream input = new ParcelFileDescriptor.AutoCloseInputStream(pfd); 39040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 39140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen assertEquals(file.length(), pfd.getStatSize()); 39240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 39340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen DataInputStream inFile = new DataInputStream(new FileInputStream(file)); 39440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int actualRead = 0; 39540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int expectedRead = 0; 39640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 39740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen while (((actualRead = input.read(actual)) != -1) && 39840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen ((expectedRead = inFile.read(expected)) != -1)) { 39940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen assertEquals(actualRead, expectedRead); 40040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen compareByteArrays(actual, expected); 40140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 40240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 40340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 40440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 40540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Sets the MIME type of file that will be served from the mock server 40640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 40740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param type The MIME type to return from the server 40840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 40940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void setServerMimeType(DownloadFileType type) { 41040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen mFileType = getMimeMapping(type); 41140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 41240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 41340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 41440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Gets the MIME content string for a given type 41540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 41640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param type The MIME type to return 41740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @return the String representation of that MIME content type 41840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 41940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected String getMimeMapping(DownloadFileType type) { 42040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen switch (type) { 42140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen case APK: 42240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return "application/vnd.android.package-archive"; 42340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen case GIF: 42440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return "image/gif"; 42540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen case ZIP: 42640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return "application/x-zip-compressed"; 42740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen case GARBAGE: 42840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return "zip\\pidy/doo/da"; 42940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen case UNRECOGNIZED: 43040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return "application/new.undefined.type.of.app"; 43140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 43240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return "text/plain"; 43340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 43440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 43540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 43640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Gets the Uri that should be used to access the mock server 43740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 43840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param filename The name of the file to try to retrieve from the mock server 43940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @return the Uri to use for access the file on the mock server 44040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 44140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected Uri getServerUri(String filename) throws Exception { 44240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen URL url = mServer.getUrl("/" + filename); 44340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return Uri.parse(url.toString()); 44440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 44540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 44640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 44740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Gets the Uri that should be used to access the mock server 44840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 44940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param filename The name of the file to try to retrieve from the mock server 45040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @return the Uri to use for access the file on the mock server 45140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 45240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void logDBColumnData(Cursor cursor, String column) { 45340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int index = cursor.getColumnIndex(column); 45440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Log.i(LOG_TAG, "columnName: " + column); 45540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Log.i(LOG_TAG, "columnValue: " + cursor.getString(index)); 45640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 45740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 45840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 45940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to create and register a new MultipleDownloadCompletedReciever 46040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 46140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * This is used to track many simultaneous downloads by keeping count of all the downloads 46240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * that have completed. 46340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 46440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @return A new receiver that records and can be queried on how many downloads have completed. 46540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 46640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected MultipleDownloadsCompletedReceiver registerNewMultipleDownloadsReceiver() { 46740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen MultipleDownloadsCompletedReceiver receiver = new MultipleDownloadsCompletedReceiver(); 46840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen mContext.registerReceiver(receiver, new IntentFilter( 46940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen DownloadManager.ACTION_DOWNLOAD_COMPLETE)); 47040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return receiver; 47140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 47240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 47340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 47440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to verify a standard single-file download from the mock server, and clean up after 47540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * verification 47640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 47740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Note that this also calls the Download manager's remove, which cleans up the file from cache. 47840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 47940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param requestId The id of the download to remove 48040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param fileData The data to verify the file contains 48140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 48240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void verifyAndCleanupSingleFileDownload(long requestId, byte[] fileData) 48340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen throws Exception { 48440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int fileSize = fileData.length; 48540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(requestId); 48640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Cursor cursor = mDownloadManager.query(new Query().setFilterById(requestId)); 48740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 48840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen try { 48940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen assertEquals(1, cursor.getCount()); 49040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen assertTrue(cursor.moveToFirst()); 49140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 49240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen verifyFileSize(pfd, fileSize); 49340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen verifyFileContents(pfd, fileData); 49440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } finally { 49540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen pfd.close(); 49640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen cursor.close(); 49740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen mDownloadManager.remove(requestId); 49840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 49940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 50040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 50140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 50240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Enables or disables WiFi. 50340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 50440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Note: Needs the following permissions: 50540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * android.permission.ACCESS_WIFI_STATE 50640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * android.permission.CHANGE_WIFI_STATE 50740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param enable true if it should be enabled, false if it should be disabled 50840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 50940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void setWiFiStateOn(boolean enable) throws Exception { 510bd06f02d02e07ca15e420ee9e50e35253646ba64Neal Nguyen Log.i(LOG_TAG, "Setting WiFi State to: " + enable); 51140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen WifiManager manager = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE); 51240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 51340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen manager.setWifiEnabled(enable); 51440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 51540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen String timeoutMessage = "Timed out waiting for Wifi to be " 51640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen + (enable ? "enabled!" : "disabled!"); 51740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 51840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen WiFiChangedReceiver receiver = new WiFiChangedReceiver(mContext); 51940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen mContext.registerReceiver(receiver, new IntentFilter( 52040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen ConnectivityManager.CONNECTIVITY_ACTION)); 52140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 52240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen synchronized (receiver) { 52340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen long timeoutTime = SystemClock.elapsedRealtime() + DEFAULT_MAX_WAIT_TIME; 52440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen boolean timedOut = false; 52540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 52640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen while (receiver.getWiFiIsOn() != enable && !timedOut) { 52740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen try { 528bd06f02d02e07ca15e420ee9e50e35253646ba64Neal Nguyen receiver.wait(DEFAULT_WAIT_POLL_TIME); 52940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 53040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen if (SystemClock.elapsedRealtime() > timeoutTime) { 53140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen timedOut = true; 53240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 53340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 53440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen catch (InterruptedException e) { 53540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // ignore InterruptedExceptions 53640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 53740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 53840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen if (timedOut) { 53940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen fail(timeoutMessage); 54040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 54140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 54240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen assertEquals(enable, receiver.getWiFiIsOn()); 54340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 54440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 54540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 54640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to enables or disables airplane mode. If successful, it also broadcasts an intent 54740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * indicating that the mode has changed. 54840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 54940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Note: Needs the following permission: 55040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * android.permission.WRITE_SETTINGS 55140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param enable true if airplane mode should be ON, false if it should be OFF 55240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 55340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void setAirplaneModeOn(boolean enable) throws Exception { 55440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int state = enable ? 1 : 0; 55540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 55640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // Change the system setting 557c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 55840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen state); 55940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 56040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen String timeoutMessage = "Timed out waiting for airplane mode to be " + 56140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen (enable ? "enabled!" : "disabled!"); 56240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 56340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // wait for airplane mode to change state 56440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int currentWaitTime = 0; 565c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate while (Settings.Global.getInt(mContext.getContentResolver(), 566c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate Settings.Global.AIRPLANE_MODE_ON, -1) != state) { 56740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen timeoutWait(currentWaitTime, DEFAULT_WAIT_POLL_TIME, DEFAULT_MAX_WAIT_TIME, 56840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen timeoutMessage); 56940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 57040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 57140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // Post the intent 57240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); 57340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen intent.putExtra("state", true); 574c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 57540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 57640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 57740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 57840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to create a large file of random data on the SD card. 57940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 58040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param filename (optional) The name of the file to create on the SD card; pass in null to 58140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * use a default temp filename. 58240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param type The type of file to create 58340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param subdirectory If not null, the subdirectory under the SD card where the file should go 58440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @return The File that was created 58540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @throws IOException if there was an error while creating the file. 58640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 58740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected File createFileOnSD(String filename, long fileSize, DataType type, 58840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen String subdirectory) throws IOException { 58940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 59040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // Build up the file path and name 59140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen String sdPath = Environment.getExternalStorageDirectory().getPath(); 59240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen StringBuilder fullPath = new StringBuilder(sdPath); 59340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen if (subdirectory != null) { 59440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen fullPath.append(File.separatorChar).append(subdirectory); 59540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 59640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 59740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen File file = null; 59840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen if (filename == null) { 59940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen file = File.createTempFile("DMTEST_", null, new File(fullPath.toString())); 60040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 60140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen else { 60240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen fullPath.append(File.separatorChar).append(filename); 60340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen file = new File(fullPath.toString()); 60440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen file.createNewFile(); 60540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 60640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 60740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // Fill the file with random data 60840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen DataOutputStream output = new DataOutputStream(new FileOutputStream(file)); 60940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen final int CHUNK_SIZE = 1000000; // copy random data in 1000000-char chunks 61040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen long remaining = fileSize; 61140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int nextChunkSize = CHUNK_SIZE; 61240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen byte[] randomData = null; 61340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Random rng = new LoggingRng(); 6146f35c0ecba6cb1ce5d7563a9962acf9557dbacedVasu Nori byte[] chunkSizeData = generateData(nextChunkSize, type, rng); 61540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 61640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen try { 61740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen while (remaining > 0) { 61840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen if (remaining < CHUNK_SIZE) { 61940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen nextChunkSize = (int)remaining; 62040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen remaining = 0; 6216f35c0ecba6cb1ce5d7563a9962acf9557dbacedVasu Nori randomData = generateData(nextChunkSize, type, rng); 62240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 62340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen else { 62440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen remaining -= CHUNK_SIZE; 6256f35c0ecba6cb1ce5d7563a9962acf9557dbacedVasu Nori randomData = chunkSizeData; 62640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 62740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen output.write(randomData); 6286f35c0ecba6cb1ce5d7563a9962acf9557dbacedVasu Nori Log.i(TAG, "while creating " + fileSize + " file, " + 6296f35c0ecba6cb1ce5d7563a9962acf9557dbacedVasu Nori "remaining bytes to be written: " + remaining); 63040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 63140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } catch (IOException e) { 63240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Log.e(LOG_TAG, "Error writing to file " + file.getAbsolutePath()); 63340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen file.delete(); 63440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen throw e; 63540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } finally { 63640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen output.close(); 63740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 63840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return file; 63940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 64040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 64140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 64240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to wait for a particular download to finish, or else a timeout to occur 64340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 64465c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * Does not wait for a receiver notification of the download. 64565c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * 64640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param id The download id to query on (wait for) 64740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 64865c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen protected void waitForDownloadOrTimeout_skipNotification(long id) throws TimeoutException, 64940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen InterruptedException { 65040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen waitForDownloadOrTimeout(id, WAIT_FOR_DOWNLOAD_POLL_TIME, MAX_WAIT_FOR_DOWNLOAD_TIME); 65140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 65240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 65340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 65440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to wait for a particular download to finish, or else a timeout to occur 65540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 65665c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * Also guarantees a notification has been posted for the download. 65765c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * 65865c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * @param id The download id to query on (wait for) 65965c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen */ 66065c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen protected void waitForDownloadOrTimeout(long id) throws TimeoutException, 66165c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen InterruptedException { 66265c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen waitForDownloadOrTimeout_skipNotification(id); 66365c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen waitForReceiverNotifications(1); 66465c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen } 66565c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen 66665c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen /** 66765c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * Helper to wait for a particular download to finish, or else a timeout to occur 66865c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * 66965c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * Also guarantees a notification has been posted for the download. 67065c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * 67140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param id The download id to query on (wait for) 67240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param poll The amount of time to wait 67340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param timeoutMillis The max time (in ms) to wait for the download(s) to complete 67440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 67540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void waitForDownloadOrTimeout(long id, long poll, long timeoutMillis) 67640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen throws TimeoutException, InterruptedException { 67740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen doWaitForDownloadsOrTimeout(new Query().setFilterById(id), poll, timeoutMillis); 67865c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen waitForReceiverNotifications(1); 67940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 68040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 68140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 68240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to wait for all downloads to finish, or else a specified timeout to occur 68340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 68465c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * Makes no guaranee that notifications have been posted for all downloads. 68565c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * 68640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param poll The amount of time to wait 68740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param timeoutMillis The max time (in ms) to wait for the download(s) to complete 68840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 68940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void waitForDownloadsOrTimeout(long poll, long timeoutMillis) throws TimeoutException, 69040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen InterruptedException { 69140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen doWaitForDownloadsOrTimeout(new Query(), poll, timeoutMillis); 69240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 69340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 69440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 69540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to wait for all downloads to finish, or else a timeout to occur, but does not throw 69640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 69765c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * Also guarantees a notification has been posted for the download. 69865c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * 69940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param id The id of the download to query against 70040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param poll The amount of time to wait 70140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param timeoutMillis The max time (in ms) to wait for the download(s) to complete 70240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @return true if download completed successfully (didn't timeout), false otherwise 70340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 70440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected boolean waitForDownloadOrTimeoutNoThrow(long id, long poll, long timeoutMillis) { 70540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen try { 70640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen doWaitForDownloadsOrTimeout(new Query().setFilterById(id), poll, timeoutMillis); 70765c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen waitForReceiverNotifications(1); 70840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } catch (TimeoutException e) { 70940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return false; 71040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 71140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return true; 71240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 71340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 71440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 71540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper function to synchronously wait, or timeout if the maximum threshold has been exceeded. 71640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 71740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param currentTotalWaitTime The total time waited so far 71840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param poll The amount of time to wait 71940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param maxTimeoutMillis The total wait time threshold; if we've waited more than this long, 72040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * we timeout and fail 72140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param timedOutMessage The message to display in the failure message if we timeout 72240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @return The new total amount of time we've waited so far 72340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @throws TimeoutException if timed out waiting for SD card to mount 72440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 72540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected int timeoutWait(int currentTotalWaitTime, long poll, long maxTimeoutMillis, 72640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen String timedOutMessage) throws TimeoutException { 72740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen long now = SystemClock.elapsedRealtime(); 72840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen long end = now + poll; 72940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 73040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // if we get InterruptedException's, ignore them and just keep sleeping 73140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen while (now < end) { 73240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen try { 73340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Thread.sleep(end - now); 73440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } catch (InterruptedException e) { 73540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // ignore interrupted exceptions 73640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 73740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen now = SystemClock.elapsedRealtime(); 73840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 73940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 74040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen currentTotalWaitTime += poll; 74140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen if (currentTotalWaitTime > maxTimeoutMillis) { 74240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen throw new TimeoutException(timedOutMessage); 74340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 74440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return currentTotalWaitTime; 74540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 74640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 74740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 74840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to wait for all downloads to finish, or else a timeout to occur 74940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 75040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param query The query to pass to the download manager 75140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param poll The poll time to wait between checks 75240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param timeoutMillis The max amount of time (in ms) to wait for the download(s) to complete 75340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 75440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void doWaitForDownloadsOrTimeout(Query query, long poll, long timeoutMillis) 75540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen throws TimeoutException { 75640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int currentWaitTime = 0; 75740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen while (true) { 75840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen query.setFilterByStatus(DownloadManager.STATUS_PENDING | DownloadManager.STATUS_PAUSED 75940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen | DownloadManager.STATUS_RUNNING); 76040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Cursor cursor = mDownloadManager.query(query); 76140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 76240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen try { 76365c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen if (cursor.getCount() == 0) { 76465c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen Log.i(LOG_TAG, "All downloads should be done..."); 76540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen break; 76640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 76740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen currentWaitTime = timeoutWait(currentWaitTime, poll, timeoutMillis, 76840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen "Timed out waiting for all downloads to finish"); 76940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } finally { 77040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen cursor.close(); 77140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 77240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 77340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 77440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 77540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 77640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Synchronously waits for external store to be mounted (eg: SD Card). 77740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 77840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @throws InterruptedException if interrupted 77940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @throws Exception if timed out waiting for SD card to mount 78040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 78140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void waitForExternalStoreMount() throws Exception { 78240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen String extStorageState = Environment.getExternalStorageState(); 78340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int currentWaitTime = 0; 78440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen while (!extStorageState.equals(Environment.MEDIA_MOUNTED)) { 78540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Log.i(LOG_TAG, "Waiting for SD card..."); 78640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen currentWaitTime = timeoutWait(currentWaitTime, DEFAULT_WAIT_POLL_TIME, 78740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen DEFAULT_MAX_WAIT_TIME, "Timed out waiting for SD Card to be ready!"); 78840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen extStorageState = Environment.getExternalStorageState(); 78940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 79040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 79140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 79240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 79340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Synchronously waits for a download to start. 79440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 79540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param dlRequest the download request id used by Download Manager to track the download. 79640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @throws Exception if timed out while waiting for SD card to mount 79740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 79840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void waitForDownloadToStart(long dlRequest) throws Exception { 79940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Cursor cursor = getCursor(dlRequest); 80040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen try { 80140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS); 80240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int value = cursor.getInt(columnIndex); 80340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int currentWaitTime = 0; 80440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 80540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen while (value != DownloadManager.STATUS_RUNNING && 80640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen (value != DownloadManager.STATUS_FAILED) && 80740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen (value != DownloadManager.STATUS_SUCCESSFUL)) { 80840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Log.i(LOG_TAG, "Waiting for download to start..."); 80940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME, 81040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for download to start!"); 81140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen cursor.requery(); 81240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen assertTrue(cursor.moveToFirst()); 81340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS); 81440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen value = cursor.getInt(columnIndex); 81540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 81640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen assertFalse("Download failed immediately after start", 81740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen value == DownloadManager.STATUS_FAILED); 81840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } finally { 81940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen cursor.close(); 82040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 82140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 82240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 82340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 82465c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * Convenience function to wait for just 1 notification of a download. 82565c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * 82665c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * @throws Exception if timed out while waiting 82765c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen */ 82865c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen protected void waitForReceiverNotification() throws Exception { 82965c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen waitForReceiverNotifications(1); 83065c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen } 83165c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen 83265c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen /** 83365c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * Synchronously waits for our receiver to receive notification for a given number of 83465c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * downloads. 83565c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * 83665c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * @param targetNumber The number of notifications for unique downloads to wait for; pass in 83765c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * -1 to not wait for notification. 83865c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen * @throws Exception if timed out while waiting 83965c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen */ 84065c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen protected void waitForReceiverNotifications(int targetNumber) throws TimeoutException { 84165c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen int count = mReceiver.numDownloadsCompleted(); 84265c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen int currentWaitTime = 0; 84365c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen 84465c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen while (count < targetNumber) { 84565c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen Log.i(LOG_TAG, "Waiting for notification of downloads..."); 84665c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME, 84765c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for download notifications!" 84865c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen + " Received " + count + "notifications."); 84965c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen count = mReceiver.numDownloadsCompleted(); 85065c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen } 85165c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen } 85265c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen 85365c36e6133be04e008bc164b62d42884ff06a13aNeal Nguyen /** 85440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Synchronously waits for a file to increase in size (such as to monitor that a download is 85540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * progressing). 85640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 85740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param file The file whose size to track. 85840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @throws Exception if timed out while waiting for the file to grow in size. 85940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 86040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void waitForFileToGrow(File file) throws Exception { 86140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int currentWaitTime = 0; 86240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 86340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // File may not even exist yet, so wait until it does (or we timeout) 86440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen while (!file.exists()) { 86540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Log.i(LOG_TAG, "Waiting for file to exist..."); 86640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME, 86740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for file to be created."); 86840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 86940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 87040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // Get original file size... 87140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen long originalSize = file.length(); 87240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 87340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen while (file.length() <= originalSize) { 87440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Log.i(LOG_TAG, "Waiting for file to be written to..."); 87540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME, 87640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for file to be written to."); 87740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 87840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 87940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 88040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 88140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to remove all downloads that are registered with the DL Manager. 88240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 88340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Note: This gives us a clean slate b/c it includes downloads that are pending, running, 88440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * paused, or have completed. 88540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 88640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void removeAllCurrentDownloads() { 88740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Log.i(LOG_TAG, "Removing all current registered downloads..."); 88882e891b3259350a92b55969a6380ca1240ee0829Vasu Nori ArrayList<Long> ids = new ArrayList<Long>(); 88940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Cursor cursor = mDownloadManager.query(new Query()); 89040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen try { 89140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen if (cursor.moveToFirst()) { 89240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen do { 89340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int index = cursor.getColumnIndex(DownloadManager.COLUMN_ID); 89440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen long downloadId = cursor.getLong(index); 89582e891b3259350a92b55969a6380ca1240ee0829Vasu Nori ids.add(downloadId); 89640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } while (cursor.moveToNext()); 89740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 89840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } finally { 89940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen cursor.close(); 90040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 90182e891b3259350a92b55969a6380ca1240ee0829Vasu Nori // delete all ids 90282e891b3259350a92b55969a6380ca1240ee0829Vasu Nori for (long id : ids) { 90382e891b3259350a92b55969a6380ca1240ee0829Vasu Nori mDownloadManager.remove(id); 90482e891b3259350a92b55969a6380ca1240ee0829Vasu Nori } 90582e891b3259350a92b55969a6380ca1240ee0829Vasu Nori // make sure the database is empty 90682e891b3259350a92b55969a6380ca1240ee0829Vasu Nori cursor = mDownloadManager.query(new Query()); 90782e891b3259350a92b55969a6380ca1240ee0829Vasu Nori try { 90882e891b3259350a92b55969a6380ca1240ee0829Vasu Nori assertEquals(0, cursor.getCount()); 90982e891b3259350a92b55969a6380ca1240ee0829Vasu Nori } finally { 91082e891b3259350a92b55969a6380ca1240ee0829Vasu Nori cursor.close(); 91182e891b3259350a92b55969a6380ca1240ee0829Vasu Nori } 91240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 91340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 91440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 91540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to perform a standard enqueue of data to the mock server. 91682e891b3259350a92b55969a6380ca1240ee0829Vasu Nori * download is performed to the downloads cache dir (NOT systemcache dir) 91740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 91840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param body The body to return in the response from the server 91940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 92040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected long doStandardEnqueue(byte[] body) throws Exception { 92182e891b3259350a92b55969a6380ca1240ee0829Vasu Nori return enqueueDownloadRequest(body, DOWNLOAD_TO_DOWNLOAD_CACHE_DIR); 92282e891b3259350a92b55969a6380ca1240ee0829Vasu Nori } 92382e891b3259350a92b55969a6380ca1240ee0829Vasu Nori 92482e891b3259350a92b55969a6380ca1240ee0829Vasu Nori protected long enqueueDownloadRequest(byte[] body, int location) throws Exception { 92540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // Prepare the mock server with a standard response 926b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey mServer.enqueue(buildResponse(HTTP_OK, body)); 92782e891b3259350a92b55969a6380ca1240ee0829Vasu Nori return doEnqueue(location); 92840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 92940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 93040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 93140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to perform a standard enqueue of data to the mock server. 93240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 93340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param body The body to return in the response from the server, contained in the file 93440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 93540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected long doStandardEnqueue(File body) throws Exception { 93682e891b3259350a92b55969a6380ca1240ee0829Vasu Nori return enqueueDownloadRequest(body, DOWNLOAD_TO_DOWNLOAD_CACHE_DIR); 93782e891b3259350a92b55969a6380ca1240ee0829Vasu Nori } 93882e891b3259350a92b55969a6380ca1240ee0829Vasu Nori 93982e891b3259350a92b55969a6380ca1240ee0829Vasu Nori protected long enqueueDownloadRequest(File body, int location) throws Exception { 94040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen // Prepare the mock server with a standard response 941b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey mServer.enqueue(buildResponse(HTTP_OK, body)); 94282e891b3259350a92b55969a6380ca1240ee0829Vasu Nori return doEnqueue(location); 94340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 94440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 94540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 94640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to do the additional steps (setting title and Uri of default filename) when 94740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * doing a standard enqueue request to the server. 94840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 94940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected long doCommonStandardEnqueue() throws Exception { 95082e891b3259350a92b55969a6380ca1240ee0829Vasu Nori return doEnqueue(DOWNLOAD_TO_DOWNLOAD_CACHE_DIR); 95182e891b3259350a92b55969a6380ca1240ee0829Vasu Nori } 95282e891b3259350a92b55969a6380ca1240ee0829Vasu Nori 95382e891b3259350a92b55969a6380ca1240ee0829Vasu Nori private long doEnqueue(int location) throws Exception { 95440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Uri uri = getServerUri(DEFAULT_FILENAME); 95582e891b3259350a92b55969a6380ca1240ee0829Vasu Nori Request request = new Request(uri).setTitle(DEFAULT_FILENAME); 95682e891b3259350a92b55969a6380ca1240ee0829Vasu Nori if (location == DOWNLOAD_TO_SYSTEM_CACHE) { 95782e891b3259350a92b55969a6380ca1240ee0829Vasu Nori request.setDestinationToSystemCache(); 95882e891b3259350a92b55969a6380ca1240ee0829Vasu Nori } 95940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 96082e891b3259350a92b55969a6380ca1240ee0829Vasu Nori return mDownloadManager.enqueue(request); 96140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 96240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 96340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 96440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to verify an int value in a Cursor 96540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 96640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param cursor The cursor containing the query results 96740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param columnName The name of the column to query 96840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param expected The expected int value 96940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 97040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void verifyInt(Cursor cursor, String columnName, int expected) { 97140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int index = cursor.getColumnIndex(columnName); 97240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int actual = cursor.getInt(index); 97340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen assertEquals(expected, actual); 97440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 97540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 97640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 97740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Helper to verify a String value in a Cursor 97840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 97940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param cursor The cursor containing the query results 98040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param columnName The name of the column to query 98140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param expected The expected String value 98240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 98340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected void verifyString(Cursor cursor, String columnName, String expected) { 98440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int index = cursor.getColumnIndex(columnName); 98540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen String actual = cursor.getString(index); 98640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Log.i(LOG_TAG, ": " + actual); 98740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen assertEquals(expected, actual); 98840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 98940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 99040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen /** 99140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * Performs a query based on ID and returns a Cursor for the query. 99240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * 99340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @param id The id of the download in DL Manager; pass -1 to query all downloads 99440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen * @return A cursor for the query results 99540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen */ 99640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen protected Cursor getCursor(long id) throws Exception { 99740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Query query = new Query(); 99840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen if (id != -1) { 99940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen query.setFilterById(id); 100040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 100140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 100240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Cursor cursor = mDownloadManager.query(query); 100340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen int currentWaitTime = 0; 100440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 100540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen try { 100640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen while (!cursor.moveToFirst()) { 100740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen Thread.sleep(DEFAULT_WAIT_POLL_TIME); 100840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen currentWaitTime += DEFAULT_WAIT_POLL_TIME; 100940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen if (currentWaitTime > DEFAULT_MAX_WAIT_TIME) { 101040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen fail("timed out waiting for a non-null query result"); 101140ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 101240ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen cursor.requery(); 101340ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 101440ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } catch (Exception e) { 101540ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen cursor.close(); 101640ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen throw e; 101740ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 101840ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen return cursor; 101940ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen } 102040ef0f49ea9fa7c39eb0018fdb4df4b73a11a77dNeal Nguyen 102182e891b3259350a92b55969a6380ca1240ee0829Vasu Nori /** 102282e891b3259350a92b55969a6380ca1240ee0829Vasu Nori * Helper that does the actual basic download verification. 102382e891b3259350a92b55969a6380ca1240ee0829Vasu Nori */ 102482e891b3259350a92b55969a6380ca1240ee0829Vasu Nori protected long doBasicDownload(byte[] blobData, int location) throws Exception { 102582e891b3259350a92b55969a6380ca1240ee0829Vasu Nori long dlRequest = enqueueDownloadRequest(blobData, location); 102682e891b3259350a92b55969a6380ca1240ee0829Vasu Nori 102782e891b3259350a92b55969a6380ca1240ee0829Vasu Nori // wait for the download to complete 102882e891b3259350a92b55969a6380ca1240ee0829Vasu Nori waitForDownloadOrTimeout(dlRequest); 102982e891b3259350a92b55969a6380ca1240ee0829Vasu Nori 103082e891b3259350a92b55969a6380ca1240ee0829Vasu Nori assertEquals(1, mReceiver.numDownloadsCompleted()); 103182e891b3259350a92b55969a6380ca1240ee0829Vasu Nori return dlRequest; 103282e891b3259350a92b55969a6380ca1240ee0829Vasu Nori } 1033b14ad8cc8cb0ed774072b077694b21fd0a6f33beJeff Sharkey} 1034