/*
 * 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.
 */
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);
            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.
        }
    }
}
