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