/*
 * 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 static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.TestApi;
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.RemoteException;
import android.telephony.mbms.DownloadProgressListener;
import android.telephony.mbms.DownloadRequest;
import android.telephony.mbms.DownloadStatusListener;
import android.telephony.mbms.FileInfo;
import android.telephony.mbms.InternalDownloadProgressListener;
import android.telephony.mbms.InternalDownloadSessionCallback;
import android.telephony.mbms.InternalDownloadStatusListener;
import android.telephony.mbms.MbmsDownloadReceiver;
import android.telephony.mbms.MbmsDownloadSessionCallback;
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.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 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";

    /**
     * Metadata key that specifies the component name of the service to bind to for file-download.
     * @hide
     */
    @TestApi
    public static final String MBMS_DOWNLOAD_SERVICE_OVERRIDE_METADATA =
            "mbms-download-service-override";

    /**
     * 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},
     * {@link #RESULT_IO_ERROR}, {@link #RESULT_DOWNLOAD_FAILURE}, {@link #RESULT_OUT_OF_STORAGE},
     * {@link #RESULT_SERVICE_ID_NOT_DEFINED}, or {@link #RESULT_FILE_ROOT_UNREACHABLE}.
     *
     * 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 directory that the
     * app provided via the builder.
     *
     * 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";


    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(value = {RESULT_SUCCESSFUL, RESULT_CANCELLED, RESULT_EXPIRED, RESULT_IO_ERROR,
            RESULT_SERVICE_ID_NOT_DEFINED, RESULT_DOWNLOAD_FAILURE, RESULT_OUT_OF_STORAGE,
            RESULT_FILE_ROOT_UNREACHABLE}, prefix = { "RESULT_" })
    public @interface DownloadResultCode{}

    /**
     * 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 is likely a transient error and another {@link DownloadRequest} should be sent to try
     * the download again.
     */
    public static final int RESULT_IO_ERROR = 4;

    /**
     * Indicates that the Service ID specified in the {@link DownloadRequest} is incorrect due to
     * the Id being incorrect, stale, expired, or similar.
     */
    public static final int RESULT_SERVICE_ID_NOT_DEFINED = 5;

    /**
     * Indicates that there was an error while processing downloaded files, such as a file repair or
     * file decoding error and is not due to a file I/O error.
     *
     * This is likely a transient error and another {@link DownloadRequest} should be sent to try
     * the download again.
     */
    public static final int RESULT_DOWNLOAD_FAILURE = 6;

    /**
     * Indicates that the file system is full and the {@link DownloadRequest} can not complete.
     * Either space must be made on the current file system or the temp file root location must be
     * changed to a location that is not full to download the temp files.
     */
    public static final int RESULT_OUT_OF_STORAGE = 7;

    /**
     * Indicates that the file root that was set is currently unreachable. This can happen if the
     * temp files are set to be stored on external storage and the SD card was removed, for example.
     * The temp file root should be changed before sending another DownloadRequest.
     */
    public static final int RESULT_FILE_ROOT_UNREACHABLE = 8;

    /** @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 being downloaded.
     */
    public static final int STATUS_ACTIVELY_DOWNLOADING = 1;

    /**
     * Indicates that the file is awaiting the next download or repair operations. When a more
     * precise status is known, the status will change to either {@link #STATUS_PENDING_REPAIR} or
     * {@link #STATUS_PENDING_DOWNLOAD_WINDOW}.
     */
    public static final int STATUS_PENDING_DOWNLOAD = 2;

    /**
     * Indicates that the file is awaiting file repair after the download has ended.
     */
    public static final int STATUS_PENDING_REPAIR = 3;

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

    private static final String DESTINATION_SANITY_CHECK_FILE_NAME = "destinationSanityCheckFile";

    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 ServiceConnection mServiceConnection;
    private final InternalDownloadSessionCallback mInternalCallback;
    private final Map<DownloadStatusListener, InternalDownloadStatusListener>
            mInternalDownloadStatusListeners = new HashMap<>();
    private final Map<DownloadProgressListener, InternalDownloadProgressListener>
            mInternalDownloadProgressListeners = new HashMap<>();

    private MbmsDownloadSession(Context context, Executor executor, int subscriptionId,
            MbmsDownloadSessionCallback callback) {
        mContext = context;
        mSubscriptionId = subscriptionId;
        mInternalCallback = new InternalDownloadSessionCallback(callback, executor);
    }

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

    /**
     * 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 executor The executor on which you wish to execute callbacks.
     * @param subscriptionId The data subscription ID to use
     * @param callback A callback to get asynchronous error messages and file service updates.
     * @return A new instance of {@link MbmsDownloadSession}, or null if an error occurred during
     * setup.
     */
    public static @Nullable MbmsDownloadSession create(@NonNull Context context,
            @NonNull Executor executor, int subscriptionId,
            final @NonNull MbmsDownloadSessionCallback callback) {
        if (!sIsInitialized.compareAndSet(false, true)) {
            throw new IllegalStateException("Cannot have two active instances");
        }
        MbmsDownloadSession session =
                new MbmsDownloadSession(context, executor, subscriptionId, callback);
        final int result = session.bindAndInitialize();
        if (result != MbmsErrors.SUCCESS) {
            sIsInitialized.set(false);
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    callback.onError(result, null);
                }
            });
            return null;
        }
        return session;
    }

    private int bindAndInitialize() {
        mServiceConnection = 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.UNKNOWN) {
                    // Unbind and throw an obvious error
                    close();
                    throw new IllegalStateException("Middleware must not return an"
                            + " unknown error code");
                }
                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) {
                Log.w(LOG_TAG, "bindAndInitialize: Remote service disconnected");
                sIsInitialized.set(false);
                mService.set(null);
            }

            @Override
            public void onNullBinding(ComponentName name) {
                Log.w(LOG_TAG, "bindAndInitialize: Remote service returned null");
                sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST,
                        "Middleware service binding returned null");
                sIsInitialized.set(false);
                mService.set(null);
                mContext.unbindService(this);
            }
        };
        return MbmsUtils.startBinding(mContext, MBMS_DOWNLOAD_SERVICE_ACTION, mServiceConnection);
    }

    /**
     * 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.UNKNOWN) {
                // Unbind and throw an obvious error
                close();
                throw new IllegalStateException("Middleware must not return an unknown error code");
            }
            if (returnCode != MbmsErrors.SUCCESS) {
                sendErrorToApp(returnCode, null);
            }
        } catch (RemoteException e) {
            Log.w(LOG_TAG, "Remote process died");
            mService.set(null);
            sIsInitialized.set(false);
            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.UNKNOWN) {
                // Unbind and throw an obvious error
                close();
                throw new IllegalStateException("Middleware must not return an unknown error code");
            }
            if (result != MbmsErrors.SUCCESS) {
                sendErrorToApp(result, null);
                return;
            }
        } catch (RemoteException e) {
            mService.set(null);
            sIsInitialized.set(false);
            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.
     *
     * If the {@link DownloadRequest} has a destination that is not on the same filesystem as the
     * temp file directory provided via {@link #getTempFileRootDirectory()}, an
     * {@link IllegalArgumentException} will be thrown.
     *
     * Asynchronous errors through the callback may include any error not specific to the
     * streaming use-case.
     *
     * If no error is delivered via the callback after calling this method, that means that the
     * middleware has successfully started the download or scheduled the download, if the download
     * is at a future time.
     * @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);
        }

        checkDownloadRequestDestination(request);

        try {
            int result = downloadService.download(request);
            if (result == MbmsErrors.SUCCESS) {
                writeDownloadRequestToken(request);
            } else {
                if (result == MbmsErrors.UNKNOWN) {
                    // Unbind and throw an obvious error
                    close();
                    throw new IllegalStateException("Middleware must not return an unknown"
                            + " error code");
                }
                sendErrorToApp(result, null);
            }
        } catch (RemoteException e) {
            mService.set(null);
            sIsInitialized.set(false);
            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);
            sIsInitialized.set(false);
            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
            return Collections.emptyList();
        }
    }

    /**
     * Registers a download status listener 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 DownloadStatusListener} will be enqueued.
     *
     * If the middleware is not aware of the specified download request,
     * this method will throw an {@link IllegalArgumentException}.
     *
     * If the operation encountered an error, the error code will be delivered via
     * {@link MbmsDownloadSessionCallback#onError}.
     *
     * Repeated calls to this method for the same {@link DownloadRequest} will replace the
     * previously registered listener.
     *
     * @param request The {@link DownloadRequest} that you want updates on.
     * @param executor The {@link Executor} on which calls to {@code listener } should be executed.
     * @param listener The listener that should be called when the middleware has information to
     *                 share on the status download.
     */
    public void addStatusListener(@NonNull DownloadRequest request,
            @NonNull Executor executor, @NonNull DownloadStatusListener listener) {
        IMbmsDownloadService downloadService = mService.get();
        if (downloadService == null) {
            throw new IllegalStateException("Middleware not yet bound");
        }

        InternalDownloadStatusListener internalListener =
                new InternalDownloadStatusListener(listener, executor);

        try {
            int result = downloadService.addStatusListener(request, internalListener);
            if (result == MbmsErrors.UNKNOWN) {
                // Unbind and throw an obvious error
                close();
                throw new IllegalStateException("Middleware must not return an unknown error code");
            }
            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);
            sIsInitialized.set(false);
            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
            return;
        }
        mInternalDownloadStatusListeners.put(listener, internalListener);
    }

    /**
     * Un-register a listener previously registered via
     * {@link #addStatusListener(DownloadRequest, Executor, DownloadStatusListener)}. After
     * this method is called, no further calls will be enqueued on the {@link Executor}
     * 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}.
     *
     * If the operation encountered an error, the error code will be delivered via
     * {@link MbmsDownloadSessionCallback#onError}.
     *
     * @param request The {@link DownloadRequest} provided during registration
     * @param listener The listener provided during registration.
     */
    public void removeStatusListener(@NonNull DownloadRequest request,
            @NonNull DownloadStatusListener listener) {
        try {
            IMbmsDownloadService downloadService = mService.get();
            if (downloadService == null) {
                throw new IllegalStateException("Middleware not yet bound");
            }

            InternalDownloadStatusListener internalListener =
                    mInternalDownloadStatusListeners.get(listener);
            if (internalListener == null) {
                throw new IllegalArgumentException("Provided listener was never registered");
            }

            try {
                int result = downloadService.removeStatusListener(request, internalListener);
                if (result == MbmsErrors.UNKNOWN) {
                    // Unbind and throw an obvious error
                    close();
                    throw new IllegalStateException("Middleware must not return an"
                            + " unknown error code");
                }
                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);
                sIsInitialized.set(false);
                sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
                return;
            }
        } finally {
            InternalDownloadStatusListener internalCallback =
                    mInternalDownloadStatusListeners.remove(listener);
            if (internalCallback != null) {
                internalCallback.stop();
            }
        }
    }

    /**
     * Registers a progress listener for a {@link DownloadRequest} previously requested via
     * {@link #download(DownloadRequest)}. This listener 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 DownloadProgressListener} will be enqueued.
     *
     * If the middleware is not aware of the specified download request,
     * this method will throw an {@link IllegalArgumentException}.
     *
     * If the operation encountered an error, the error code will be delivered via
     * {@link MbmsDownloadSessionCallback#onError}.
     *
     * Repeated calls to this method for the same {@link DownloadRequest} will replace the
     * previously registered listener.
     *
     * @param request The {@link DownloadRequest} that you want updates on.
     * @param executor The {@link Executor} on which calls to {@code listener} should be executed.
     * @param listener The listener that should be called when the middleware has information to
     *                 share on the progress of the download.
     */
    public void addProgressListener(@NonNull DownloadRequest request,
            @NonNull Executor executor, @NonNull DownloadProgressListener listener) {
        IMbmsDownloadService downloadService = mService.get();
        if (downloadService == null) {
            throw new IllegalStateException("Middleware not yet bound");
        }

        InternalDownloadProgressListener internalListener =
                new InternalDownloadProgressListener(listener, executor);

        try {
            int result = downloadService.addProgressListener(request, internalListener);
            if (result == MbmsErrors.UNKNOWN) {
                // Unbind and throw an obvious error
                close();
                throw new IllegalStateException("Middleware must not return an unknown error code");
            }
            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);
            sIsInitialized.set(false);
            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
            return;
        }
        mInternalDownloadProgressListeners.put(listener, internalListener);
    }

    /**
     * Un-register a listener previously registered via
     * {@link #addProgressListener(DownloadRequest, Executor, DownloadProgressListener)}. 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}.
     *
     * If the operation encountered an error, the error code will be delivered via
     * {@link MbmsDownloadSessionCallback#onError}.
     *
     * @param request The {@link DownloadRequest} provided during registration
     * @param listener The listener provided during registration.
     */
    public void removeProgressListener(@NonNull DownloadRequest request,
            @NonNull DownloadProgressListener listener) {
        try {
            IMbmsDownloadService downloadService = mService.get();
            if (downloadService == null) {
                throw new IllegalStateException("Middleware not yet bound");
            }

            InternalDownloadProgressListener internalListener =
                    mInternalDownloadProgressListeners.get(listener);
            if (internalListener == null) {
                throw new IllegalArgumentException("Provided listener was never registered");
            }

            try {
                int result = downloadService.removeProgressListener(request, internalListener);
                if (result == MbmsErrors.UNKNOWN) {
                    // Unbind and throw an obvious error
                    close();
                    throw new IllegalStateException("Middleware must not"
                            + " return an unknown error code");
                }
                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);
                sIsInitialized.set(false);
                sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
                return;
            }
        } finally {
            InternalDownloadProgressListener internalCallback =
                    mInternalDownloadProgressListeners.remove(listener);
            if (internalCallback != null) {
                internalCallback.stop();
            }
        }
    }

    /**
     * Attempts to cancel the specified {@link DownloadRequest}.
     *
     * If the operation encountered an error, the error code will be delivered via
     * {@link MbmsDownloadSessionCallback#onError}.
     *
     * @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.UNKNOWN) {
                // Unbind and throw an obvious error
                close();
                throw new IllegalStateException("Middleware must not return an unknown error code");
            }
            if (result != MbmsErrors.SUCCESS) {
                sendErrorToApp(result, null);
            } else {
                deleteDownloadRequestToken(downloadRequest);
            }
        } catch (RemoteException e) {
            mService.set(null);
            sIsInitialized.set(false);
            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
        }
    }

    /**
     * Requests information about the state of a file pending download.
     *
     * The state will be delivered as a callback via
     * {@link DownloadStatusListener#onStatusUpdated(DownloadRequest, FileInfo, int)}. If no such
     * callback has been registered via
     * {@link #addProgressListener(DownloadRequest, Executor, DownloadProgressListener)}, this
     * method will be a no-op.
     *
     * If the middleware has no record of the
     * file indicated by {@code fileInfo} being associated with {@code downloadRequest},
     * an {@link IllegalArgumentException} will be thrown.
     *
     * @param downloadRequest The download request to query.
     * @param fileInfo The particular file within the request to get information on.
     */
    public void requestDownloadState(DownloadRequest downloadRequest, FileInfo fileInfo) {
        IMbmsDownloadService downloadService = mService.get();
        if (downloadService == null) {
            throw new IllegalStateException("Middleware not yet bound");
        }

        try {
            int result = downloadService.requestDownloadState(downloadRequest, fileInfo);
            if (result == MbmsErrors.UNKNOWN) {
                // Unbind and throw an obvious error
                close();
                throw new IllegalStateException("Middleware must not return an unknown error code");
            }
            if (result != MbmsErrors.SUCCESS) {
                if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
                    throw new IllegalArgumentException("Unknown download request.");
                }
                if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_FILE_INFO) {
                    throw new IllegalArgumentException("Unknown file.");
                }
                sendErrorToApp(result, null);
            }
        } catch (RemoteException e) {
            mService.set(null);
            sIsInitialized.set(false);
            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
        }
    }

    /**
     * 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.UNKNOWN) {
                // Unbind and throw an obvious error
                close();
                throw new IllegalStateException("Middleware must not return an unknown error code");
            }
            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);
            sIsInitialized.set(false);
            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, Executor, int, MbmsDownloadSessionCallback)} 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 || mServiceConnection == null) {
                Log.i(LOG_TAG, "Service already dead");
                return;
            }
            downloadService.dispose(mSubscriptionId);
            mContext.unbindService(mServiceConnection);
        } catch (RemoteException e) {
            // Ignore
            Log.i(LOG_TAG, "Remote exception while disposing of service");
        } finally {
            mService.set(null);
            sIsInitialized.set(false);
            mServiceConnection = null;
            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 + ". Token location is " + token.getPath());
            }
        } catch (IOException e) {
            throw new RuntimeException("Failed to create download token for request " + request
                    + " due to IOException " + e + ". Attempted to write to " + token.getPath());
        }
    }

    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 void checkDownloadRequestDestination(DownloadRequest request) {
        File downloadRequestDestination = new File(request.getDestinationUri().getPath());
        if (!downloadRequestDestination.isDirectory()) {
            throw new IllegalArgumentException("The destination path must be a directory");
        }
        // Check if the request destination is okay to use by attempting to rename an empty
        // file to there.
        File testFile = new File(MbmsTempFileProvider.getEmbmsTempFileDir(mContext),
                DESTINATION_SANITY_CHECK_FILE_NAME);
        File testFileDestination = new File(downloadRequestDestination,
                DESTINATION_SANITY_CHECK_FILE_NAME);

        try {
            if (!testFile.exists()) {
                testFile.createNewFile();
            }
            if (!testFile.renameTo(testFileDestination)) {
                throw new IllegalArgumentException("Destination provided in the download request " +
                        "is invalid -- files in the temp file directory cannot be directly moved " +
                        "there.");
            }
        } catch (IOException e) {
            throw new IllegalStateException("Got IOException while testing out the destination: "
                    + e);
        } finally {
            testFile.delete();
            testFileDestination.delete();
        }
    }

    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) {
        mInternalCallback.onError(errorCode, message);
    }
}
