/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.app;

import android.app.DownloadManager.Query;
import android.app.DownloadManager.Request;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.os.ParcelFileDescriptor.AutoCloseInputStream;
import android.os.SystemClock;
import android.provider.Settings;
import android.test.InstrumentationTestCase;
import android.util.Log;

import com.google.mockwebserver.MockResponse;
import com.google.mockwebserver.MockWebServer;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.TimeoutException;

import libcore.io.Streams;

/**
 * Base class for Instrumented tests for the Download Manager.
 */
public class DownloadManagerBaseTest extends InstrumentationTestCase {
    private static final String TAG = "DownloadManagerBaseTest";
    protected DownloadManager mDownloadManager = null;
    private MockWebServer mServer = null;
    protected String mFileType = "text/plain";
    protected Context mContext = null;
    protected MultipleDownloadsCompletedReceiver mReceiver = null;
    protected static final int DEFAULT_FILE_SIZE = 10 * 1024;  // 10kb
    protected static final int FILE_BLOCK_READ_SIZE = 1024 * 1024;

    protected static final String LOG_TAG = "android.net.DownloadManagerBaseTest";
    protected static final int HTTP_OK = 200;
    protected static final int HTTP_REDIRECT = 307;
    protected static final int HTTP_PARTIAL_CONTENT = 206;
    protected static final int HTTP_NOT_FOUND = 404;
    protected static final int HTTP_SERVICE_UNAVAILABLE = 503;
    protected String DEFAULT_FILENAME = "somefile.txt";

    protected static final int DEFAULT_MAX_WAIT_TIME = 2 * 60 * 1000;  // 2 minutes
    protected static final int DEFAULT_WAIT_POLL_TIME = 5 * 1000;  // 5 seconds

    protected static final int WAIT_FOR_DOWNLOAD_POLL_TIME = 1 * 1000;  // 1 second
    protected static final int MAX_WAIT_FOR_DOWNLOAD_TIME = 30 * 1000; // 30 seconds

    protected static final int DOWNLOAD_TO_SYSTEM_CACHE = 1;
    protected static final int DOWNLOAD_TO_DOWNLOAD_CACHE_DIR = 2;

    // Just a few popular file types used to return from a download
    protected enum DownloadFileType {
        PLAINTEXT,
        APK,
        GIF,
        GARBAGE,
        UNRECOGNIZED,
        ZIP
    }

    protected enum DataType {
        TEXT,
        BINARY
    }

    public static class LoggingRng extends Random {

        /**
         * Constructor
         *
         * Creates RNG with self-generated seed value.
         */
        public LoggingRng() {
            this(SystemClock.uptimeMillis());
        }

        /**
         * Constructor
         *
         * Creats RNG with given initial seed value

         * @param seed The initial seed value
         */
        public LoggingRng(long seed) {
            super(seed);
            Log.i(LOG_TAG, "Seeding RNG with value: " + seed);
        }
    }

    public static class MultipleDownloadsCompletedReceiver extends BroadcastReceiver {
        private volatile int mNumDownloadsCompleted = 0;
        private Set<Long> downloadIds = Collections.synchronizedSet(new HashSet<Long>());

        /**
         * {@inheritDoc}
         */
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equalsIgnoreCase(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
                synchronized(this) {
                    long id = intent.getExtras().getLong(DownloadManager.EXTRA_DOWNLOAD_ID);
                    Log.i(LOG_TAG, "Received Notification for download: " + id);
                    if (!downloadIds.contains(id)) {
                        ++mNumDownloadsCompleted;
                        Log.i(LOG_TAG, "MultipleDownloadsCompletedReceiver got intent: " +
                                intent.getAction() + " --> total count: " + mNumDownloadsCompleted);
                        downloadIds.add(id);

                        DownloadManager dm = (DownloadManager)context.getSystemService(
                                Context.DOWNLOAD_SERVICE);

                        Cursor cursor = dm.query(new Query().setFilterById(id));
                        try {
                            if (cursor.moveToFirst()) {
                                int status = cursor.getInt(cursor.getColumnIndex(
                                        DownloadManager.COLUMN_STATUS));
                                Log.i(LOG_TAG, "Download status is: " + status);
                            } else {
                                fail("No status found for completed download!");
                            }
                        } finally {
                            cursor.close();
                        }
                    } else {
                        Log.i(LOG_TAG, "Notification for id: " + id + " has already been made.");
                    }
                }
            }
        }

        /**
         * Gets the number of times the {@link #onReceive} callback has been called for the
         * {@link DownloadManager.ACTION_DOWNLOAD_COMPLETED} action, indicating the number of
         * downloads completed thus far.
         *
         * @return the number of downloads completed so far.
         */
        public int numDownloadsCompleted() {
            return mNumDownloadsCompleted;
        }

        /**
         * Gets the list of download IDs.
         * @return A Set<Long> with the ids of the completed downloads.
         */
        public Set<Long> getDownloadIds() {
            synchronized(this) {
                Set<Long> returnIds = new HashSet<Long>(downloadIds);
                return returnIds;
            }
        }

    }

    public static class WiFiChangedReceiver extends BroadcastReceiver {
        private Context mContext = null;

        /**
         * Constructor
         *
         * Sets the current state of WiFi.
         *
         * @param context The current app {@link Context}.
         */
        public WiFiChangedReceiver(Context context) {
            mContext = context;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equalsIgnoreCase(ConnectivityManager.CONNECTIVITY_ACTION)) {
                Log.i(LOG_TAG, "ConnectivityManager state change: " + intent.getAction());
                synchronized (this) {
                    this.notify();
                }
            }
        }

        /**
         * Gets the current state of WiFi.
         *
         * @return Returns true if WiFi is on, false otherwise.
         */
        public boolean getWiFiIsOn() {
            ConnectivityManager connManager = (ConnectivityManager)mContext.getSystemService(
                    Context.CONNECTIVITY_SERVICE);
            NetworkInfo info = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
            Log.i(LOG_TAG, "WiFi Connection state is currently: " + info.isConnected());
            return info.isConnected();
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setUp() throws Exception {
        mContext = getInstrumentation().getContext();
        mDownloadManager = (DownloadManager)mContext.getSystemService(Context.DOWNLOAD_SERVICE);
        mServer = new MockWebServer();
        mServer.play();
        mReceiver = registerNewMultipleDownloadsReceiver();
        // Note: callers overriding this should call mServer.play() with the desired port #
    }

    /**
     * Helper to build a response from the MockWebServer with no body.
     *
     * @param status The HTTP status code to return for this response
     * @return Returns the mock web server response that was queued (which can be modified)
     */
    protected MockResponse buildResponse(int status) {
        MockResponse response = new MockResponse().setResponseCode(status);
        response.setHeader("Content-type", mFileType);
        return response;
    }

    /**
     * Helper to build a response from the MockWebServer.
     *
     * @param status The HTTP status code to return for this response
     * @param body The body to return in this response
     * @return Returns the mock web server response that was queued (which can be modified)
     */
    protected MockResponse buildResponse(int status, byte[] body) {
        return buildResponse(status).setBody(body);
    }

    /**
     * Helper to build a response from the MockWebServer.
     *
     * @param status The HTTP status code to return for this response
     * @param bodyFile The body to return in this response
     * @return Returns the mock web server response that was queued (which can be modified)
     */
    protected MockResponse buildResponse(int status, File bodyFile)
            throws FileNotFoundException, IOException {
        final byte[] body = Streams.readFully(new FileInputStream(bodyFile));
        return buildResponse(status).setBody(body);
    }

    protected void enqueueResponse(MockResponse resp) {
        mServer.enqueue(resp);
    }

    /**
     * Helper to generate a random blob of bytes.
     *
     * @param size The size of the data to generate
     * @param type The type of data to generate: currently, one of {@link DataType#TEXT} or
     *         {@link DataType#BINARY}.
     * @return The random data that is generated.
     */
    protected byte[] generateData(int size, DataType type) {
        return generateData(size, type, null);
    }

    /**
     * Helper to generate a random blob of bytes using a given RNG.
     *
     * @param size The size of the data to generate
     * @param type The type of data to generate: currently, one of {@link DataType#TEXT} or
     *         {@link DataType#BINARY}.
     * @param rng (optional) The RNG to use; pass null to use
     * @return The random data that is generated.
     */
    protected byte[] generateData(int size, DataType type, Random rng) {
        int min = Byte.MIN_VALUE;
        int max = Byte.MAX_VALUE;

        // Only use chars in the HTTP ASCII printable character range for Text
        if (type == DataType.TEXT) {
            min = 32;
            max = 126;
        }
        byte[] result = new byte[size];
        Log.i(LOG_TAG, "Generating data of size: " + size);

        if (rng == null) {
            rng = new LoggingRng();
        }

        for (int i = 0; i < size; ++i) {
            result[i] = (byte) (min + rng.nextInt(max - min + 1));
        }
        return result;
    }

    /**
     * Helper to verify the size of a file.
     *
     * @param pfd The input file to compare the size of
     * @param size The expected size of the file
     */
    protected void verifyFileSize(ParcelFileDescriptor pfd, long size) {
        assertEquals(pfd.getStatSize(), size);
    }

    /**
     * Helper to verify the contents of a downloaded file versus a byte[].
     *
     * @param actual The file of whose contents to verify
     * @param expected The data we expect to find in the aforementioned file
     * @throws IOException if there was a problem reading from the file
     */
    protected void verifyFileContents(ParcelFileDescriptor actual, byte[] expected)
            throws IOException {
        AutoCloseInputStream input = new ParcelFileDescriptor.AutoCloseInputStream(actual);
        long fileSize = actual.getStatSize();

        assertTrue(fileSize <= Integer.MAX_VALUE);
        assertEquals(expected.length, fileSize);

        byte[] actualData = new byte[expected.length];
        assertEquals(input.read(actualData), fileSize);
        compareByteArrays(actualData, expected);
    }

    /**
     * Helper to compare 2 byte arrays.
     *
     * @param actual The array whose data we want to verify
     * @param expected The array of data we expect to see
     */
    protected void compareByteArrays(byte[] actual, byte[] expected) {
        assertEquals(actual.length, expected.length);
        int length = actual.length;
        for (int i = 0; i < length; ++i) {
            // assert has a bit of overhead, so only do the assert when the values are not the same
            if (actual[i] != expected[i]) {
                fail("Byte arrays are not equal.");
            }
        }
    }

    /**
     * Verifies the contents of a downloaded file versus the contents of a File.
     *
     * @param pfd The file whose data we want to verify
     * @param file The file containing the data we expect to see in the aforementioned file
     * @throws IOException If there was a problem reading either of the two files
     */
    protected void verifyFileContents(ParcelFileDescriptor pfd, File file) throws IOException {
        byte[] actual = new byte[FILE_BLOCK_READ_SIZE];
        byte[] expected = new byte[FILE_BLOCK_READ_SIZE];

        AutoCloseInputStream input = new ParcelFileDescriptor.AutoCloseInputStream(pfd);

        assertEquals(file.length(), pfd.getStatSize());

        DataInputStream inFile = new DataInputStream(new FileInputStream(file));
        int actualRead = 0;
        int expectedRead = 0;

        while (((actualRead = input.read(actual)) != -1) &&
                ((expectedRead = inFile.read(expected)) != -1)) {
            assertEquals(actualRead, expectedRead);
            compareByteArrays(actual, expected);
        }
    }

    /**
     * Sets the MIME type of file that will be served from the mock server
     *
     * @param type The MIME type to return from the server
     */
    protected void setServerMimeType(DownloadFileType type) {
        mFileType = getMimeMapping(type);
    }

    /**
     * Gets the MIME content string for a given type
     *
     * @param type The MIME type to return
     * @return the String representation of that MIME content type
     */
    protected String getMimeMapping(DownloadFileType type) {
        switch (type) {
            case APK:
                return "application/vnd.android.package-archive";
            case GIF:
                return "image/gif";
            case ZIP:
                return "application/x-zip-compressed";
            case GARBAGE:
                return "zip\\pidy/doo/da";
            case UNRECOGNIZED:
                return "application/new.undefined.type.of.app";
        }
        return "text/plain";
    }

    /**
     * Gets the Uri that should be used to access the mock server
     *
     * @param filename The name of the file to try to retrieve from the mock server
     * @return the Uri to use for access the file on the mock server
     */
    protected Uri getServerUri(String filename) throws Exception {
        URL url = mServer.getUrl("/" + filename);
        return Uri.parse(url.toString());
    }

   /**
    * Gets the Uri that should be used to access the mock server
    *
    * @param filename The name of the file to try to retrieve from the mock server
    * @return the Uri to use for access the file on the mock server
    */
    protected void logDBColumnData(Cursor cursor, String column) {
        int index = cursor.getColumnIndex(column);
        Log.i(LOG_TAG, "columnName: " + column);
        Log.i(LOG_TAG, "columnValue: " + cursor.getString(index));
    }

    /**
     * Helper to create and register a new MultipleDownloadCompletedReciever
     *
     * This is used to track many simultaneous downloads by keeping count of all the downloads
     * that have completed.
     *
     * @return A new receiver that records and can be queried on how many downloads have completed.
     */
    protected MultipleDownloadsCompletedReceiver registerNewMultipleDownloadsReceiver() {
        MultipleDownloadsCompletedReceiver receiver = new MultipleDownloadsCompletedReceiver();
        mContext.registerReceiver(receiver, new IntentFilter(
                DownloadManager.ACTION_DOWNLOAD_COMPLETE));
        return receiver;
    }

    /**
     * Helper to verify a standard single-file download from the mock server, and clean up after
     * verification
     *
     * Note that this also calls the Download manager's remove, which cleans up the file from cache.
     *
     * @param requestId The id of the download to remove
     * @param fileData The data to verify the file contains
     */
    protected void verifyAndCleanupSingleFileDownload(long requestId, byte[] fileData)
            throws Exception {
        int fileSize = fileData.length;
        ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(requestId);
        Cursor cursor = mDownloadManager.query(new Query().setFilterById(requestId));

        try {
            assertEquals(1, cursor.getCount());
            assertTrue(cursor.moveToFirst());

            verifyFileSize(pfd, fileSize);
            verifyFileContents(pfd, fileData);
        } finally {
            pfd.close();
            cursor.close();
            mDownloadManager.remove(requestId);
        }
    }

    /**
     * Enables or disables WiFi.
     *
     * Note: Needs the following permissions:
     *  android.permission.ACCESS_WIFI_STATE
     *  android.permission.CHANGE_WIFI_STATE
     * @param enable true if it should be enabled, false if it should be disabled
     */
    protected void setWiFiStateOn(boolean enable) throws Exception {
        Log.i(LOG_TAG, "Setting WiFi State to: " + enable);
        WifiManager manager = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);

        manager.setWifiEnabled(enable);

        String timeoutMessage = "Timed out waiting for Wifi to be "
            + (enable ? "enabled!" : "disabled!");

        WiFiChangedReceiver receiver = new WiFiChangedReceiver(mContext);
        mContext.registerReceiver(receiver, new IntentFilter(
                ConnectivityManager.CONNECTIVITY_ACTION));

        synchronized (receiver) {
            long timeoutTime = SystemClock.elapsedRealtime() + DEFAULT_MAX_WAIT_TIME;
            boolean timedOut = false;

            while (receiver.getWiFiIsOn() != enable && !timedOut) {
                try {
                    receiver.wait(DEFAULT_WAIT_POLL_TIME);

                    if (SystemClock.elapsedRealtime() > timeoutTime) {
                        timedOut = true;
                    }
                }
                catch (InterruptedException e) {
                    // ignore InterruptedExceptions
                }
            }
            if (timedOut) {
                fail(timeoutMessage);
            }
        }
        assertEquals(enable, receiver.getWiFiIsOn());
    }

    /**
     * Helper to enables or disables airplane mode. If successful, it also broadcasts an intent
     * indicating that the mode has changed.
     *
     * Note: Needs the following permission:
     *  android.permission.WRITE_SETTINGS
     * @param enable true if airplane mode should be ON, false if it should be OFF
     */
    protected void setAirplaneModeOn(boolean enable) throws Exception {
        int state = enable ? 1 : 0;

        // Change the system setting
        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON,
                state);

        String timeoutMessage = "Timed out waiting for airplane mode to be " +
                (enable ? "enabled!" : "disabled!");

        // wait for airplane mode to change state
        int currentWaitTime = 0;
        while (Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.AIRPLANE_MODE_ON, -1) != state) {
            timeoutWait(currentWaitTime, DEFAULT_WAIT_POLL_TIME, DEFAULT_MAX_WAIT_TIME,
                    timeoutMessage);
        }

        // Post the intent
        Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        intent.putExtra("state", true);
        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
    }

    /**
     * Helper to create a large file of random data on the SD card.
     *
     * @param filename (optional) The name of the file to create on the SD card; pass in null to
     *          use a default temp filename.
     * @param type The type of file to create
     * @param subdirectory If not null, the subdirectory under the SD card where the file should go
     * @return The File that was created
     * @throws IOException if there was an error while creating the file.
     */
    protected File createFileOnSD(String filename, long fileSize, DataType type,
            String subdirectory) throws IOException {

        // Build up the file path and name
        String sdPath = Environment.getExternalStorageDirectory().getPath();
        StringBuilder fullPath = new StringBuilder(sdPath);
        if (subdirectory != null) {
            fullPath.append(File.separatorChar).append(subdirectory);
        }

        File file = null;
        if (filename == null) {
            file = File.createTempFile("DMTEST_", null, new File(fullPath.toString()));
        }
        else {
            fullPath.append(File.separatorChar).append(filename);
            file = new File(fullPath.toString());
            file.createNewFile();
        }

        // Fill the file with random data
        DataOutputStream output = new DataOutputStream(new FileOutputStream(file));
        final int CHUNK_SIZE = 1000000;  // copy random data in 1000000-char chunks
        long remaining = fileSize;
        int nextChunkSize = CHUNK_SIZE;
        byte[] randomData = null;
        Random rng = new LoggingRng();
        byte[] chunkSizeData = generateData(nextChunkSize, type, rng);

        try {
            while (remaining > 0) {
                if (remaining < CHUNK_SIZE) {
                    nextChunkSize = (int)remaining;
                    remaining = 0;
                    randomData = generateData(nextChunkSize, type, rng);
                }
                else {
                    remaining -= CHUNK_SIZE;
                    randomData = chunkSizeData;
                }
                output.write(randomData);
                Log.i(TAG, "while creating " + fileSize + " file, " +
                        "remaining bytes to be written: " + remaining);
            }
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error writing to file " + file.getAbsolutePath());
            file.delete();
            throw e;
        } finally {
            output.close();
        }
        return file;
    }

    /**
     * Helper to wait for a particular download to finish, or else a timeout to occur
     *
     * Does not wait for a receiver notification of the download.
     *
     * @param id The download id to query on (wait for)
     */
    protected void waitForDownloadOrTimeout_skipNotification(long id) throws TimeoutException,
            InterruptedException {
        waitForDownloadOrTimeout(id, WAIT_FOR_DOWNLOAD_POLL_TIME, MAX_WAIT_FOR_DOWNLOAD_TIME);
    }

    /**
     * Helper to wait for a particular download to finish, or else a timeout to occur
     *
     * Also guarantees a notification has been posted for the download.
     *
     * @param id The download id to query on (wait for)
     */
    protected void waitForDownloadOrTimeout(long id) throws TimeoutException,
            InterruptedException {
        waitForDownloadOrTimeout_skipNotification(id);
        waitForReceiverNotifications(1);
    }

    /**
     * Helper to wait for a particular download to finish, or else a timeout to occur
     *
     * Also guarantees a notification has been posted for the download.
     *
     * @param id The download id to query on (wait for)
     * @param poll The amount of time to wait
     * @param timeoutMillis The max time (in ms) to wait for the download(s) to complete
     */
    protected void waitForDownloadOrTimeout(long id, long poll, long timeoutMillis)
            throws TimeoutException, InterruptedException {
        doWaitForDownloadsOrTimeout(new Query().setFilterById(id), poll, timeoutMillis);
        waitForReceiverNotifications(1);
    }

    /**
     * Helper to wait for all downloads to finish, or else a specified timeout to occur
     *
     * Makes no guaranee that notifications have been posted for all downloads.
     *
     * @param poll The amount of time to wait
     * @param timeoutMillis The max time (in ms) to wait for the download(s) to complete
     */
    protected void waitForDownloadsOrTimeout(long poll, long timeoutMillis) throws TimeoutException,
            InterruptedException {
        doWaitForDownloadsOrTimeout(new Query(), poll, timeoutMillis);
    }

    /**
     * Helper to wait for all downloads to finish, or else a timeout to occur, but does not throw
     *
     * Also guarantees a notification has been posted for the download.
     *
     * @param id The id of the download to query against
     * @param poll The amount of time to wait
     * @param timeoutMillis The max time (in ms) to wait for the download(s) to complete
     * @return true if download completed successfully (didn't timeout), false otherwise
     */
    protected boolean waitForDownloadOrTimeoutNoThrow(long id, long poll, long timeoutMillis) {
        try {
            doWaitForDownloadsOrTimeout(new Query().setFilterById(id), poll, timeoutMillis);
            waitForReceiverNotifications(1);
        } catch (TimeoutException e) {
            return false;
        }
        return true;
    }

    /**
     * Helper function to synchronously wait, or timeout if the maximum threshold has been exceeded.
     *
     * @param currentTotalWaitTime The total time waited so far
     * @param poll The amount of time to wait
     * @param maxTimeoutMillis The total wait time threshold; if we've waited more than this long,
     *          we timeout and fail
     * @param timedOutMessage The message to display in the failure message if we timeout
     * @return The new total amount of time we've waited so far
     * @throws TimeoutException if timed out waiting for SD card to mount
     */
    protected int timeoutWait(int currentTotalWaitTime, long poll, long maxTimeoutMillis,
            String timedOutMessage) throws TimeoutException {
        long now = SystemClock.elapsedRealtime();
        long end = now + poll;

        // if we get InterruptedException's, ignore them and just keep sleeping
        while (now < end) {
            try {
                Thread.sleep(end - now);
            } catch (InterruptedException e) {
                // ignore interrupted exceptions
            }
            now = SystemClock.elapsedRealtime();
        }

        currentTotalWaitTime += poll;
        if (currentTotalWaitTime > maxTimeoutMillis) {
            throw new TimeoutException(timedOutMessage);
        }
        return currentTotalWaitTime;
    }

    /**
     * Helper to wait for all downloads to finish, or else a timeout to occur
     *
     * @param query The query to pass to the download manager
     * @param poll The poll time to wait between checks
     * @param timeoutMillis The max amount of time (in ms) to wait for the download(s) to complete
     */
    protected void doWaitForDownloadsOrTimeout(Query query, long poll, long timeoutMillis)
            throws TimeoutException {
        int currentWaitTime = 0;
        while (true) {
            query.setFilterByStatus(DownloadManager.STATUS_PENDING | DownloadManager.STATUS_PAUSED
                    | DownloadManager.STATUS_RUNNING);
            Cursor cursor = mDownloadManager.query(query);

            try {
                if (cursor.getCount() == 0) {
                    Log.i(LOG_TAG, "All downloads should be done...");
                    break;
                }
                currentWaitTime = timeoutWait(currentWaitTime, poll, timeoutMillis,
                        "Timed out waiting for all downloads to finish");
            } finally {
                cursor.close();
            }
        }
    }

    /**
     * Synchronously waits for external store to be mounted (eg: SD Card).
     *
     * @throws InterruptedException if interrupted
     * @throws Exception if timed out waiting for SD card to mount
     */
    protected void waitForExternalStoreMount() throws Exception {
        String extStorageState = Environment.getExternalStorageState();
        int currentWaitTime = 0;
        while (!extStorageState.equals(Environment.MEDIA_MOUNTED)) {
            Log.i(LOG_TAG, "Waiting for SD card...");
            currentWaitTime = timeoutWait(currentWaitTime, DEFAULT_WAIT_POLL_TIME,
                    DEFAULT_MAX_WAIT_TIME, "Timed out waiting for SD Card to be ready!");
            extStorageState = Environment.getExternalStorageState();
        }
    }

    /**
     * Synchronously waits for a download to start.
     *
     * @param dlRequest the download request id used by Download Manager to track the download.
     * @throws Exception if timed out while waiting for SD card to mount
     */
    protected void waitForDownloadToStart(long dlRequest) throws Exception {
        Cursor cursor = getCursor(dlRequest);
        try {
            int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
            int value = cursor.getInt(columnIndex);
            int currentWaitTime = 0;

            while (value != DownloadManager.STATUS_RUNNING &&
                    (value != DownloadManager.STATUS_FAILED) &&
                    (value != DownloadManager.STATUS_SUCCESSFUL)) {
                Log.i(LOG_TAG, "Waiting for download to start...");
                currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME,
                        MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for download to start!");
                cursor.requery();
                assertTrue(cursor.moveToFirst());
                columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
                value = cursor.getInt(columnIndex);
            }
            assertFalse("Download failed immediately after start",
                    value == DownloadManager.STATUS_FAILED);
        } finally {
            cursor.close();
        }
    }

    /**
     * Convenience function to wait for just 1 notification of a download.
     *
     * @throws Exception if timed out while waiting
     */
    protected void waitForReceiverNotification() throws Exception {
        waitForReceiverNotifications(1);
    }

    /**
     * Synchronously waits for our receiver to receive notification for a given number of
     * downloads.
     *
     * @param targetNumber The number of notifications for unique downloads to wait for; pass in
     *         -1 to not wait for notification.
     * @throws Exception if timed out while waiting
     */
    protected void waitForReceiverNotifications(int targetNumber) throws TimeoutException {
        int count = mReceiver.numDownloadsCompleted();
        int currentWaitTime = 0;

        while (count < targetNumber) {
            Log.i(LOG_TAG, "Waiting for notification of downloads...");
            currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME,
                    MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for download notifications!"
                    + " Received " + count + "notifications.");
            count = mReceiver.numDownloadsCompleted();
        }
    }

    /**
     * Synchronously waits for a file to increase in size (such as to monitor that a download is
     * progressing).
     *
     * @param file The file whose size to track.
     * @throws Exception if timed out while waiting for the file to grow in size.
     */
    protected void waitForFileToGrow(File file) throws Exception {
        int currentWaitTime = 0;

        // File may not even exist yet, so wait until it does (or we timeout)
        while (!file.exists()) {
            Log.i(LOG_TAG, "Waiting for file to exist...");
            currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME,
                    MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for file to be created.");
        }

        // Get original file size...
        long originalSize = file.length();

        while (file.length() <= originalSize) {
            Log.i(LOG_TAG, "Waiting for file to be written to...");
            currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME,
                    MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for file to be written to.");
        }
    }

    /**
     * Helper to remove all downloads that are registered with the DL Manager.
     *
     * Note: This gives us a clean slate b/c it includes downloads that are pending, running,
     * paused, or have completed.
     */
    protected void removeAllCurrentDownloads() {
        Log.i(LOG_TAG, "Removing all current registered downloads...");
        ArrayList<Long> ids = new ArrayList<Long>();
        Cursor cursor = mDownloadManager.query(new Query());
        try {
            if (cursor.moveToFirst()) {
                do {
                    int index = cursor.getColumnIndex(DownloadManager.COLUMN_ID);
                    long downloadId = cursor.getLong(index);
                    ids.add(downloadId);
                } while (cursor.moveToNext());
            }
        } finally {
            cursor.close();
        }
        // delete all ids
        for (long id : ids) {
            mDownloadManager.remove(id);
        }
        // make sure the database is empty
        cursor = mDownloadManager.query(new Query());
        try {
            assertEquals(0, cursor.getCount());
        } finally {
            cursor.close();
        }
    }

    /**
     * Helper to perform a standard enqueue of data to the mock server.
     * download is performed to the downloads cache dir (NOT systemcache dir)
     *
     * @param body The body to return in the response from the server
     */
    protected long doStandardEnqueue(byte[] body) throws Exception {
        return enqueueDownloadRequest(body, DOWNLOAD_TO_DOWNLOAD_CACHE_DIR);
    }

    protected long enqueueDownloadRequest(byte[] body, int location) throws Exception {
        // Prepare the mock server with a standard response
        mServer.enqueue(buildResponse(HTTP_OK, body));
        return doEnqueue(location);
    }

    /**
     * Helper to perform a standard enqueue of data to the mock server.
     *
     * @param body The body to return in the response from the server, contained in the file
     */
    protected long doStandardEnqueue(File body) throws Exception {
        return enqueueDownloadRequest(body, DOWNLOAD_TO_DOWNLOAD_CACHE_DIR);
    }

    protected long enqueueDownloadRequest(File body, int location) throws Exception {
        // Prepare the mock server with a standard response
        mServer.enqueue(buildResponse(HTTP_OK, body));
        return doEnqueue(location);
    }

    /**
     * Helper to do the additional steps (setting title and Uri of default filename) when
     * doing a standard enqueue request to the server.
     */
    protected long doCommonStandardEnqueue() throws Exception {
        return doEnqueue(DOWNLOAD_TO_DOWNLOAD_CACHE_DIR);
    }

    private long doEnqueue(int location) throws Exception {
        Uri uri = getServerUri(DEFAULT_FILENAME);
        Request request = new Request(uri).setTitle(DEFAULT_FILENAME);
        if (location == DOWNLOAD_TO_SYSTEM_CACHE) {
            request.setDestinationToSystemCache();
        }

        return mDownloadManager.enqueue(request);
    }

    /**
     * Helper to verify an int value in a Cursor
     *
     * @param cursor The cursor containing the query results
     * @param columnName The name of the column to query
     * @param expected The expected int value
     */
    protected void verifyInt(Cursor cursor, String columnName, int expected) {
        int index = cursor.getColumnIndex(columnName);
        int actual = cursor.getInt(index);
        assertEquals(String.format("Expected = %d : Actual = %d", expected, actual), expected, actual);
    }

    /**
     * Helper to verify a String value in a Cursor
     *
     * @param cursor The cursor containing the query results
     * @param columnName The name of the column to query
     * @param expected The expected String value
     */
    protected void verifyString(Cursor cursor, String columnName, String expected) {
        int index = cursor.getColumnIndex(columnName);
        String actual = cursor.getString(index);
        Log.i(LOG_TAG, ": " + actual);
        assertEquals(expected, actual);
    }

    /**
     * Performs a query based on ID and returns a Cursor for the query.
     *
     * @param id The id of the download in DL Manager; pass -1 to query all downloads
     * @return A cursor for the query results
     */
    protected Cursor getCursor(long id) throws Exception {
        Query query = new Query();
        if (id != -1) {
            query.setFilterById(id);
        }

        Cursor cursor = mDownloadManager.query(query);
        int currentWaitTime = 0;

        try {
            while (!cursor.moveToFirst()) {
                Thread.sleep(DEFAULT_WAIT_POLL_TIME);
                currentWaitTime += DEFAULT_WAIT_POLL_TIME;
                if (currentWaitTime > DEFAULT_MAX_WAIT_TIME) {
                    fail("timed out waiting for a non-null query result");
                }
                cursor.requery();
            }
        } catch (Exception e) {
            cursor.close();
            throw e;
        }
        return cursor;
    }

    /**
     * Helper that does the actual basic download verification.
     */
    protected long doBasicDownload(byte[] blobData, int location) throws Exception {
        long dlRequest = enqueueDownloadRequest(blobData, location);

        // wait for the download to complete
        waitForDownloadOrTimeout(dlRequest);

        assertEquals(1, mReceiver.numDownloadsCompleted());
        return dlRequest;
    }
}
