/*
 * Copyright (C) 2016 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.telephony;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.telephony.mbms.DownloadStateCallback;
import android.telephony.mbms.FileInfo;
import android.telephony.mbms.DownloadRequest;
import android.telephony.mbms.InternalDownloadSessionCallback;
import android.telephony.mbms.InternalDownloadStateCallback;
import android.telephony.mbms.MbmsDownloadSessionCallback;
import android.telephony.mbms.MbmsDownloadReceiver;
import android.telephony.mbms.MbmsErrors;
import android.telephony.mbms.MbmsTempFileProvider;
import android.telephony.mbms.MbmsUtils;
import android.telephony.mbms.vendor.IMbmsDownloadService;
import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;

/**
 * This class provides functionality for file download over MBMS.
 * @hide
 */
public class MbmsDownloadSession implements AutoCloseable {
    private static final String LOG_TAG = MbmsDownloadSession.class.getSimpleName();

    /**
     * Service action which must be handled by the middleware implementing the MBMS file download
     * interface.
     * @hide
     */
    //@SystemApi
    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
    public static final String MBMS_DOWNLOAD_SERVICE_ACTION =
            "android.telephony.action.EmbmsDownload";

    /**
     * Integer extra that Android will attach to the intent supplied via
     * {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}
     * Indicates the result code of the download. One of
     * {@link #RESULT_SUCCESSFUL}, {@link #RESULT_EXPIRED}, {@link #RESULT_CANCELLED}, or
     * {@link #RESULT_IO_ERROR}.
     *
     * This extra may also be used by the middleware when it is sending intents to the app.
     */
    public static final String EXTRA_MBMS_DOWNLOAD_RESULT =
            "android.telephony.extra.MBMS_DOWNLOAD_RESULT";

    /**
     * {@link FileInfo} extra that Android will attach to the intent supplied via
     * {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}
     * Indicates the file for which the download result is for. Never null.
     *
     * This extra may also be used by the middleware when it is sending intents to the app.
     */
    public static final String EXTRA_MBMS_FILE_INFO = "android.telephony.extra.MBMS_FILE_INFO";

    /**
     * {@link Uri} extra that Android will attach to the intent supplied via
     * {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}
     * Indicates the location of the successfully downloaded file within the temp file root set
     * via {@link #setTempFileRootDirectory(File)}.
     * While you may use this file in-place, it is highly encouraged that you move
     * this file to a different location after receiving the download completion intent, as this
     * file resides within the temp file directory.
     *
     * Will always be set to a non-null value if
     * {@link #EXTRA_MBMS_DOWNLOAD_RESULT} is set to {@link #RESULT_SUCCESSFUL}.
     */
    public static final String EXTRA_MBMS_COMPLETED_FILE_URI =
            "android.telephony.extra.MBMS_COMPLETED_FILE_URI";

    /**
     * Extra containing the {@link DownloadRequest} for which the download result or file
     * descriptor request is for. Must not be null.
     */
    public static final String EXTRA_MBMS_DOWNLOAD_REQUEST =
            "android.telephony.extra.MBMS_DOWNLOAD_REQUEST";

    /**
     * The default directory name for all MBMS temp files. If you call
     * {@link #download(DownloadRequest)} without first calling
     * {@link #setTempFileRootDirectory(File)}, this directory will be created for you under the
     * path returned by {@link Context#getFilesDir()}.
     */
    public static final String DEFAULT_TOP_LEVEL_TEMP_DIRECTORY = "androidMbmsTempFileRoot";

    /**
     * Indicates that the download was successful.
     */
    public static final int RESULT_SUCCESSFUL = 1;

    /**
     * Indicates that the download was cancelled via {@link #cancelDownload(DownloadRequest)}.
     */
    public static final int RESULT_CANCELLED = 2;

    /**
     * Indicates that the download will not be completed due to the expiration of its download
     * window on the carrier's network.
     */
    public static final int RESULT_EXPIRED = 3;

    /**
     * Indicates that the download will not be completed due to an I/O error incurred while
     * writing to temp files. This commonly indicates that the device is out of storage space,
     * but may indicate other conditions as well (such as an SD card being removed).
     */
    public static final int RESULT_IO_ERROR = 4;
    // TODO - more results!

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({STATUS_UNKNOWN, STATUS_ACTIVELY_DOWNLOADING, STATUS_PENDING_DOWNLOAD,
            STATUS_PENDING_REPAIR, STATUS_PENDING_DOWNLOAD_WINDOW})
    public @interface DownloadStatus {}

    /**
     * Indicates that the middleware has no information on the file.
     */
    public static final int STATUS_UNKNOWN = 0;

    /**
     * Indicates that the file is actively downloading.
     */
    public static final int STATUS_ACTIVELY_DOWNLOADING = 1;

    /**
     * TODO: I don't know...
     */
    public static final int STATUS_PENDING_DOWNLOAD = 2;

    /**
     * Indicates that the file is being repaired after the download being interrupted.
     */
    public static final int STATUS_PENDING_REPAIR = 3;

    /**
     * Indicates that the file is waiting to download because its download window has not yet
     * started.
     */
    public static final int STATUS_PENDING_DOWNLOAD_WINDOW = 4;

    private static AtomicBoolean sIsInitialized = new AtomicBoolean(false);

    private final Context mContext;
    private int mSubscriptionId = INVALID_SUBSCRIPTION_ID;
    private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, "Received death notification");
        }
    };

    private AtomicReference<IMbmsDownloadService> mService = new AtomicReference<>(null);
    private final InternalDownloadSessionCallback mInternalCallback;
    private final Map<DownloadStateCallback, InternalDownloadStateCallback>
            mInternalDownloadCallbacks = new HashMap<>();

    private MbmsDownloadSession(Context context, MbmsDownloadSessionCallback callback,
            int subscriptionId, Handler handler) {
        mContext = context;
        mSubscriptionId = subscriptionId;
        if (handler == null) {
            handler = new Handler(Looper.getMainLooper());
        }
        mInternalCallback = new InternalDownloadSessionCallback(callback, handler);
    }

    /**
     * Create a new {@link MbmsDownloadSession} using the system default data subscription ID.
     * See {@link #create(Context, MbmsDownloadSessionCallback, int, Handler)}
     */
    public static MbmsDownloadSession create(@NonNull Context context,
            @NonNull MbmsDownloadSessionCallback callback, @NonNull Handler handler) {
        return create(context, callback, SubscriptionManager.getDefaultSubscriptionId(), handler);
    }

    /**
     * Create a new MbmsDownloadManager using the given subscription ID.
     *
     * Note that this call will bind a remote service and that may take a bit. The instance of
     * {@link MbmsDownloadSession} that is returned will not be ready for use until
     * {@link MbmsDownloadSessionCallback#onMiddlewareReady()} is called on the provided callback.
     * If you attempt to use the instance before it is ready, an {@link IllegalStateException}
     * will be thrown or an error will be delivered through
     * {@link MbmsDownloadSessionCallback#onError(int, String)}.
     *
     * This also may throw an {@link IllegalArgumentException}.
     *
     * You may only have one instance of {@link MbmsDownloadSession} per UID. If you call this
     * method while there is an active instance of {@link MbmsDownloadSession} in your process
     * (in other words, one that has not had {@link #close()} called on it), this method will
     * throw an {@link IllegalStateException}. If you call this method in a different process
     * running under the same UID, an error will be indicated via
     * {@link MbmsDownloadSessionCallback#onError(int, String)}.
     *
     * Note that initialization may fail asynchronously. If you wish to try again after you
     * receive such an asynchronous error, you must call {@link #close()} on the instance of
     * {@link MbmsDownloadSession} that you received before calling this method again.
     *
     * @param context The instance of {@link Context} to use
     * @param callback A callback to get asynchronous error messages and file service updates.
     * @param subscriptionId The data subscription ID to use
     * @param handler The {@link Handler} on which callbacks should be enqueued.
     * @return A new instance of {@link MbmsDownloadSession}, or null if an error occurred during
     * setup.
     */
    public static @Nullable MbmsDownloadSession create(@NonNull Context context,
            final @NonNull MbmsDownloadSessionCallback callback,
            int subscriptionId, @NonNull Handler handler) {
        if (!sIsInitialized.compareAndSet(false, true)) {
            throw new IllegalStateException("Cannot have two active instances");
        }
        MbmsDownloadSession session =
                new MbmsDownloadSession(context, callback, subscriptionId, handler);
        final int result = session.bindAndInitialize();
        if (result != MbmsErrors.SUCCESS) {
            sIsInitialized.set(false);
            handler.post(new Runnable() {
                @Override
                public void run() {
                    callback.onError(result, null);
                }
            });
            return null;
        }
        return session;
    }

    private int bindAndInitialize() {
        return MbmsUtils.startBinding(mContext, MBMS_DOWNLOAD_SERVICE_ACTION,
                new ServiceConnection() {
                    @Override
                    public void onServiceConnected(ComponentName name, IBinder service) {
                        IMbmsDownloadService downloadService =
                                IMbmsDownloadService.Stub.asInterface(service);
                        int result;
                        try {
                            result = downloadService.initialize(mSubscriptionId, mInternalCallback);
                        } catch (RemoteException e) {
                            Log.e(LOG_TAG, "Service died before initialization");
                            sIsInitialized.set(false);
                            return;
                        } catch (RuntimeException e) {
                            Log.e(LOG_TAG, "Runtime exception during initialization");
                            sendErrorToApp(
                                    MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
                                    e.toString());
                            sIsInitialized.set(false);
                            return;
                        }
                        if (result != MbmsErrors.SUCCESS) {
                            sendErrorToApp(result, "Error returned during initialization");
                            sIsInitialized.set(false);
                            return;
                        }
                        try {
                            downloadService.asBinder().linkToDeath(mDeathRecipient, 0);
                        } catch (RemoteException e) {
                            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST,
                                    "Middleware lost during initialization");
                            sIsInitialized.set(false);
                            return;
                        }
                        mService.set(downloadService);
                    }

                    @Override
                    public void onServiceDisconnected(ComponentName name) {
                        sIsInitialized.set(false);
                        mService.set(null);
                    }
                });
    }

    /**
     * An inspection API to retrieve the list of available
     * {@link android.telephony.mbms.FileServiceInfo}s currently being advertised.
     * The results are returned asynchronously via a call to
     * {@link MbmsDownloadSessionCallback#onFileServicesUpdated(List)}
     *
     * Asynchronous error codes via the {@link MbmsDownloadSessionCallback#onError(int, String)}
     * callback may include any of the errors that are not specific to the streaming use-case.
     *
     * May throw an {@link IllegalStateException} or {@link IllegalArgumentException}.
     *
     * @param classList A list of service classes which the app wishes to receive
     *                  {@link MbmsDownloadSessionCallback#onFileServicesUpdated(List)} callbacks
     *                  about. Subsequent calls to this method will replace this list of service
     *                  classes (i.e. the middleware will no longer send updates for services
     *                  matching classes only in the old list).
     *                  Values in this list should be negotiated with the wireless carrier prior
     *                  to using this API.
     */
    public void requestUpdateFileServices(@NonNull List<String> classList) {
        IMbmsDownloadService downloadService = mService.get();
        if (downloadService == null) {
            throw new IllegalStateException("Middleware not yet bound");
        }
        try {
            int returnCode = downloadService.requestUpdateFileServices(mSubscriptionId, classList);
            if (returnCode != MbmsErrors.SUCCESS) {
                sendErrorToApp(returnCode, null);
            }
        } catch (RemoteException e) {
            Log.w(LOG_TAG, "Remote process died");
            mService.set(null);
            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
        }
    }

    /**
     * Sets the temp file root for downloads.
     * All temp files created for the middleware to write to will be contained in the specified
     * directory. Applications that wish to specify a location only need to call this method once
     * as long their data is persisted in storage -- the argument will be stored both in a
     * local instance of {@link android.content.SharedPreferences} and by the middleware.
     *
     * If this method is not called at least once before calling
     * {@link #download(DownloadRequest)}, the framework
     * will default to a directory formed by the concatenation of the app's files directory and
     * {@link MbmsDownloadSession#DEFAULT_TOP_LEVEL_TEMP_DIRECTORY}.
     *
     * Before calling this method, the app must cancel all of its pending
     * {@link DownloadRequest}s via {@link #cancelDownload(DownloadRequest)}. If this is not done,
     * you will receive an asynchronous error with code
     * {@link MbmsErrors.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT} unless the
     * provided directory is the same as what has been previously configured.
     *
     * The {@link File} supplied as a root temp file directory must already exist. If not, an
     * {@link IllegalArgumentException} will be thrown. In addition, as an additional sanity
     * check, an {@link IllegalArgumentException} will be thrown if you attempt to set the temp
     * file root directory to one of your data roots (the value of {@link Context#getDataDir()},
     * {@link Context#getFilesDir()}, or {@link Context#getCacheDir()}).
     * @param tempFileRootDirectory A directory to place temp files in.
     */
    public void setTempFileRootDirectory(@NonNull File tempFileRootDirectory) {
        IMbmsDownloadService downloadService = mService.get();
        if (downloadService == null) {
            throw new IllegalStateException("Middleware not yet bound");
        }
        try {
            validateTempFileRootSanity(tempFileRootDirectory);
        } catch (IOException e) {
            throw new IllegalStateException("Got IOException checking directory sanity");
        }
        String filePath;
        try {
            filePath = tempFileRootDirectory.getCanonicalPath();
        } catch (IOException e) {
            throw new IllegalArgumentException("Unable to canonicalize the provided path: " + e);
        }

        try {
            int result = downloadService.setTempFileRootDirectory(mSubscriptionId, filePath);
            if (result != MbmsErrors.SUCCESS) {
                sendErrorToApp(result, null);
            }
        } catch (RemoteException e) {
            mService.set(null);
            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
            return;
        }

        SharedPreferences prefs = mContext.getSharedPreferences(
                MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_FILE_NAME, 0);
        prefs.edit().putString(MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_NAME, filePath).apply();
    }

    private void validateTempFileRootSanity(File tempFileRootDirectory) throws IOException {
        if (!tempFileRootDirectory.exists()) {
            throw new IllegalArgumentException("Provided directory does not exist");
        }
        if (!tempFileRootDirectory.isDirectory()) {
            throw new IllegalArgumentException("Provided File is not a directory");
        }
        String canonicalTempFilePath = tempFileRootDirectory.getCanonicalPath();
        if (mContext.getDataDir().getCanonicalPath().equals(canonicalTempFilePath)) {
            throw new IllegalArgumentException("Temp file root cannot be your data dir");
        }
        if (mContext.getCacheDir().getCanonicalPath().equals(canonicalTempFilePath)) {
            throw new IllegalArgumentException("Temp file root cannot be your cache dir");
        }
        if (mContext.getFilesDir().getCanonicalPath().equals(canonicalTempFilePath)) {
            throw new IllegalArgumentException("Temp file root cannot be your files dir");
        }
    }
    /**
     * Retrieves the currently configured temp file root directory. Returns the file that was
     * configured via {@link #setTempFileRootDirectory(File)} or the default directory
     * {@link #download(DownloadRequest)} was called without ever
     * setting the temp file root. If neither method has been called since the last time the app's
     * shared preferences were reset, returns {@code null}.
     *
     * @return A {@link File} pointing to the configured temp file directory, or null if not yet
     *         configured.
     */
    public @Nullable File getTempFileRootDirectory() {
        SharedPreferences prefs = mContext.getSharedPreferences(
                MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_FILE_NAME, 0);
        String path = prefs.getString(MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_NAME, null);
        if (path != null) {
            return new File(path);
        }
        return null;
    }

    /**
     * Requests the download of a file or set of files that the carrier has indicated to be
     * available.
     *
     * May throw an {@link IllegalArgumentException}
     *
     * If {@link #setTempFileRootDirectory(File)} has not called after the app has been installed,
     * this method will create a directory at the default location defined at
     * {@link MbmsDownloadSession#DEFAULT_TOP_LEVEL_TEMP_DIRECTORY} and store that as the temp
     * file root directory.
     *
     * Asynchronous errors through the callback may include any error not specific to the
     * streaming use-case.
     * @param request The request that specifies what should be downloaded.
     */
    public void download(@NonNull DownloadRequest request) {
        IMbmsDownloadService downloadService = mService.get();
        if (downloadService == null) {
            throw new IllegalStateException("Middleware not yet bound");
        }

        // Check to see whether the app's set a temp root dir yet, and set it if not.
        SharedPreferences prefs = mContext.getSharedPreferences(
                MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_FILE_NAME, 0);
        if (prefs.getString(MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_NAME, null) == null) {
            File tempRootDirectory = new File(mContext.getFilesDir(),
                    DEFAULT_TOP_LEVEL_TEMP_DIRECTORY);
            tempRootDirectory.mkdirs();
            setTempFileRootDirectory(tempRootDirectory);
        }

        writeDownloadRequestToken(request);
        try {
            downloadService.download(request);
        } catch (RemoteException e) {
            mService.set(null);
            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
        }
    }

    /**
     * Returns a list of pending {@link DownloadRequest}s that originated from this application.
     * A pending request is one that was issued via
     * {@link #download(DownloadRequest)} but not cancelled through
     * {@link #cancelDownload(DownloadRequest)}.
     * @return A list, possibly empty, of {@link DownloadRequest}s
     */
    public @NonNull List<DownloadRequest> listPendingDownloads() {
        IMbmsDownloadService downloadService = mService.get();
        if (downloadService == null) {
            throw new IllegalStateException("Middleware not yet bound");
        }

        try {
            return downloadService.listPendingDownloads(mSubscriptionId);
        } catch (RemoteException e) {
            mService.set(null);
            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
            return Collections.emptyList();
        }
    }

    /**
     * Registers a callback for a {@link DownloadRequest} previously requested via
     * {@link #download(DownloadRequest)}. This callback will only be called as long as both this
     * app and the middleware are both running -- if either one stops, no further calls on the
     * provided {@link DownloadStateCallback} will be enqueued.
     *
     * If the middleware is not aware of the specified download request,
     * this method will throw an {@link IllegalArgumentException}.
     *
     * @param request The {@link DownloadRequest} that you want updates on.
     * @param callback The callback that should be called when the middleware has information to
     *                 share on the download.
     * @param handler The {@link Handler} on which calls to {@code callback} should be enqueued on.
     */
    public void registerStateCallback(@NonNull DownloadRequest request,
            @NonNull DownloadStateCallback callback, @NonNull Handler handler) {
        IMbmsDownloadService downloadService = mService.get();
        if (downloadService == null) {
            throw new IllegalStateException("Middleware not yet bound");
        }

        InternalDownloadStateCallback internalCallback =
                new InternalDownloadStateCallback(callback, handler);

        try {
            int result = downloadService.registerStateCallback(request, internalCallback,
                    callback.getCallbackFilterFlags());
            if (result != MbmsErrors.SUCCESS) {
                if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
                    throw new IllegalArgumentException("Unknown download request.");
                }
                sendErrorToApp(result, null);
                return;
            }
        } catch (RemoteException e) {
            mService.set(null);
            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
            return;
        }
        mInternalDownloadCallbacks.put(callback, internalCallback);
    }

    /**
     * Un-register a callback previously registered via
     * {@link #registerStateCallback(DownloadRequest, DownloadStateCallback, Handler)}. After
     * this method is called, no further callbacks will be enqueued on the {@link Handler}
     * provided upon registration, even if this method throws an exception.
     *
     * If the middleware is not aware of the specified download request,
     * this method will throw an {@link IllegalArgumentException}.
     *
     * @param request The {@link DownloadRequest} provided during registration
     * @param callback The callback provided during registration.
     */
    public void unregisterStateCallback(@NonNull DownloadRequest request,
            @NonNull DownloadStateCallback callback) {
        try {
            IMbmsDownloadService downloadService = mService.get();
            if (downloadService == null) {
                throw new IllegalStateException("Middleware not yet bound");
            }

            InternalDownloadStateCallback internalCallback =
                    mInternalDownloadCallbacks.get(callback);

            try {
                int result = downloadService.unregisterStateCallback(request, internalCallback);
                if (result != MbmsErrors.SUCCESS) {
                    if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
                        throw new IllegalArgumentException("Unknown download request.");
                    }
                    sendErrorToApp(result, null);
                }
            } catch (RemoteException e) {
                mService.set(null);
                sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
            }
        } finally {
            InternalDownloadStateCallback internalCallback =
                    mInternalDownloadCallbacks.remove(callback);
            if (internalCallback != null) {
                internalCallback.stop();
            }
        }
    }

    /**
     * Attempts to cancel the specified {@link DownloadRequest}.
     *
     * If the middleware is not aware of the specified download request,
     * this method will throw an {@link IllegalArgumentException}.
     *
     * @param downloadRequest The download request that you wish to cancel.
     */
    public void cancelDownload(@NonNull DownloadRequest downloadRequest) {
        IMbmsDownloadService downloadService = mService.get();
        if (downloadService == null) {
            throw new IllegalStateException("Middleware not yet bound");
        }

        try {
            int result = downloadService.cancelDownload(downloadRequest);
            if (result != MbmsErrors.SUCCESS) {
                if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
                    throw new IllegalArgumentException("Unknown download request.");
                }
                sendErrorToApp(result, null);
                return;
            }
        } catch (RemoteException e) {
            mService.set(null);
            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
            return;
        }
        deleteDownloadRequestToken(downloadRequest);
    }

    /**
     * Gets information about the status of a file pending download.
     *
     * If there was a problem communicating with the middleware or if it has no records of the
     * file indicated by {@code fileInfo} being associated with {@code downloadRequest},
     * {@link #STATUS_UNKNOWN} will be returned.
     *
     * @param downloadRequest The download request to query.
     * @param fileInfo The particular file within the request to get information on.
     * @return The status of the download.
     */
    @DownloadStatus
    public int getDownloadStatus(DownloadRequest downloadRequest, FileInfo fileInfo) {
        IMbmsDownloadService downloadService = mService.get();
        if (downloadService == null) {
            throw new IllegalStateException("Middleware not yet bound");
        }

        try {
            return downloadService.getDownloadStatus(downloadRequest, fileInfo);
        } catch (RemoteException e) {
            mService.set(null);
            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
            return STATUS_UNKNOWN;
        }
    }

    /**
     * Resets the middleware's knowledge of previously-downloaded files in this download request.
     *
     * Normally, the middleware keeps track of the hashes of downloaded files and won't re-download
     * files whose server-reported hash matches one of the already-downloaded files. This means
     * that if the file is accidentally deleted by the user or by the app, the middleware will
     * not try to download it again.
     * This method will reset the middleware's cache of hashes for the provided
     * {@link DownloadRequest}, so that previously downloaded content will be downloaded again
     * when available.
     * This will not interrupt in-progress downloads.
     *
     * This is distinct from cancelling and re-issuing the download request -- if you cancel and
     * re-issue, the middleware will not clear its cache of download state information.
     *
     * If the middleware is not aware of the specified download request, an
     * {@link IllegalArgumentException} will be thrown.
     *
     * @param downloadRequest The request to re-download files for.
     */
    public void resetDownloadKnowledge(DownloadRequest downloadRequest) {
        IMbmsDownloadService downloadService = mService.get();
        if (downloadService == null) {
            throw new IllegalStateException("Middleware not yet bound");
        }

        try {
            int result = downloadService.resetDownloadKnowledge(downloadRequest);
            if (result != MbmsErrors.SUCCESS) {
                if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
                    throw new IllegalArgumentException("Unknown download request.");
                }
                sendErrorToApp(result, null);
            }
        } catch (RemoteException e) {
            mService.set(null);
            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
        }
    }

    /**
     * Terminates this instance.
     *
     * After this method returns,
     * no further callbacks originating from the middleware will be enqueued on the provided
     * instance of {@link MbmsDownloadSessionCallback}, but callbacks that have already been
     * enqueued will still be delivered.
     *
     * It is safe to call {@link #create(Context, MbmsDownloadSessionCallback, int, Handler)} to
     * obtain another instance of {@link MbmsDownloadSession} immediately after this method
     * returns.
     *
     * May throw an {@link IllegalStateException}
     */
    @Override
    public void close() {
        try {
            IMbmsDownloadService downloadService = mService.get();
            if (downloadService == null) {
                Log.i(LOG_TAG, "Service already dead");
                return;
            }
            downloadService.dispose(mSubscriptionId);
        } catch (RemoteException e) {
            // Ignore
            Log.i(LOG_TAG, "Remote exception while disposing of service");
        } finally {
            mService.set(null);
            sIsInitialized.set(false);
            mInternalCallback.stop();
        }
    }

    private void writeDownloadRequestToken(DownloadRequest request) {
        File token = getDownloadRequestTokenPath(request);
        if (!token.getParentFile().exists()) {
            token.getParentFile().mkdirs();
        }
        if (token.exists()) {
            Log.w(LOG_TAG, "Download token " + token.getName() + " already exists");
            return;
        }
        try {
            if (!token.createNewFile()) {
                throw new RuntimeException("Failed to create download token for request "
                        + request);
            }
        } catch (IOException e) {
            throw new RuntimeException("Failed to create download token for request " + request
                    + " due to IOException " + e);
        }
    }

    private void deleteDownloadRequestToken(DownloadRequest request) {
        File token = getDownloadRequestTokenPath(request);
        if (!token.isFile()) {
            Log.w(LOG_TAG, "Attempting to delete non-existent download token at " + token);
            return;
        }
        if (!token.delete()) {
            Log.w(LOG_TAG, "Couldn't delete download token at " + token);
        }
    }

    private File getDownloadRequestTokenPath(DownloadRequest request) {
        File tempFileLocation = MbmsUtils.getEmbmsTempFileDirForService(mContext,
                request.getFileServiceId());
        String downloadTokenFileName = request.getHash()
                + MbmsDownloadReceiver.DOWNLOAD_TOKEN_SUFFIX;
        return new File(tempFileLocation, downloadTokenFileName);
    }

    private void sendErrorToApp(int errorCode, String message) {
        try {
            mInternalCallback.onError(errorCode, message);
        } catch (RemoteException e) {
            // Ignore, should not happen locally.
        }
    }
}
