Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aee278d6 authored by Hall Liu's avatar Hall Liu Committed by Android (Google) Code Review
Browse files

Merge changes from topics "embms-0728-adjustments", "embms-0721-adjustments",...

Merge changes from topics "embms-0728-adjustments", "embms-0721-adjustments", "fix-streaming-api", "mock-unhide-embms-streaming" into oc-mr1-dev

* changes:
  Embms adjustments for 7/28
  Embms API adjustments for 7/21
  Fix lint errors in the streaming API
  Mock-un-hide the MBMS streaming APIs
parents 7e036126 25bdb2c8
Loading
Loading
Loading
Loading
+92 −160
Original line number Diff line number Diff line
@@ -18,19 +18,19 @@ package android.telephony;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.IBinder;
import android.os.RemoteException;
import android.telephony.mbms.DownloadProgressListener;
import android.telephony.mbms.FileInfo;
import android.telephony.mbms.DownloadRequest;
import android.telephony.mbms.IDownloadProgressListener;
import android.telephony.mbms.IMbmsDownloadManagerCallback;
import android.telephony.mbms.MbmsDownloadManagerCallback;
import android.telephony.mbms.MbmsDownloadReceiver;
import android.telephony.mbms.MbmsException;
@@ -44,6 +44,7 @@ import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -52,140 +53,30 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
public class MbmsDownloadManager {
    private static final String LOG_TAG = MbmsDownloadManager.class.getSimpleName();

    /** @hide */
    // TODO: systemapi
    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
    public static final String MBMS_DOWNLOAD_SERVICE_ACTION =
            "android.telephony.action.EmbmsDownload";
    /**
     * The MBMS middleware should send this when a download of single file has completed or
     * failed. Mandatory extras are
     * {@link #EXTRA_RESULT}
     * {@link #EXTRA_FILE_INFO}
     * {@link #EXTRA_REQUEST}
     * {@link #EXTRA_TEMP_LIST}
     * {@link #EXTRA_FINAL_URI}
     *
     * TODO: future systemapi
     */
    public static final String ACTION_DOWNLOAD_RESULT_INTERNAL =
            "android.telephony.mbms.action.DOWNLOAD_RESULT_INTERNAL";

    /**
     * The MBMS middleware should send this when it wishes to request {@code content://} URIs to
     * serve as temp files for downloads or when it wishes to resume paused downloads. Mandatory
     * extras are
     * {@link #EXTRA_REQUEST}
     *
     * Optional extras are
     * {@link #EXTRA_FD_COUNT} (0 if not present)
     * {@link #EXTRA_PAUSED_LIST} (empty if not present)
     *
     * TODO: future systemapi
     */
    public static final String ACTION_FILE_DESCRIPTOR_REQUEST =
            "android.telephony.mbms.action.FILE_DESCRIPTOR_REQUEST";

    /**
     * The MBMS middleware should send this when it wishes to clean up temp  files in the app's
     * filesystem. Mandatory extras are:
     * {@link #EXTRA_TEMP_FILES_IN_USE}
     *
     * TODO: future systemapi
     */
    public static final String ACTION_CLEANUP =
            "android.telephony.mbms.action.CLEANUP";

    /**
     * Integer extra indicating the result code of the download. One of
     * {@link #RESULT_SUCCESSFUL}, {@link #RESULT_EXPIRED}, or {@link #RESULT_CANCELLED}.
     * TODO: Not systemapi.
     */
    public static final String EXTRA_RESULT = "android.telephony.mbms.extra.RESULT";

    /**
     * Extra containing the {@link android.telephony.mbms.FileInfo} for which the download result
     * is for. Must not be null.
     * TODO: Not systemapi.
     */
    public static final String EXTRA_FILE_INFO = "android.telephony.mbms.extra.FILE_INFO";

    /**
     * Extra containing the {@link DownloadRequest} for which the download result or file
     * descriptor request is for. Must not be null.
     * TODO: future systemapi (here and and all extras) except the three for the app intent
     */
    public static final String EXTRA_REQUEST = "android.telephony.mbms.extra.REQUEST";

    /**
     * Extra containing a {@link List} of {@link Uri}s that were used as temp files for this
     * completed file. These {@link Uri}s should have scheme {@code file://}, and the temp
     * files will be deleted upon receipt of the intent.
     * May be null.
     */
    public static final String EXTRA_TEMP_LIST = "android.telephony.mbms.extra.TEMP_LIST";

    /**
     * Extra containing a single {@link Uri} indicating the path to the temp file in which the
     * decoded downloaded file resides. Must not be null.
     */
    public static final String EXTRA_FINAL_URI = "android.telephony.mbms.extra.FINAL_URI";

    /**
     * Extra containing an integer indicating the number of temp files requested.
     */
    public static final String EXTRA_FD_COUNT = "android.telephony.mbms.extra.FD_COUNT";

    /**
     * Extra containing a list of {@link Uri}s that the middleware is requesting access to via
     * {@link #ACTION_FILE_DESCRIPTOR_REQUEST} in order to resume downloading. These {@link Uri}s
     * should have scheme {@code file://}.
     */
    public static final String EXTRA_PAUSED_LIST = "android.telephony.mbms.extra.PAUSED_LIST";

    /**
     * Extra containing a list of {@link android.telephony.mbms.UriPathPair}s, used in the
     * response to {@link #ACTION_FILE_DESCRIPTOR_REQUEST}. These are temp files that are meant
     * to be used for new file downloads.
     */
    public static final String EXTRA_FREE_URI_LIST = "android.telephony.mbms.extra.FREE_URI_LIST";

    /**
     * Extra containing a list of {@link android.telephony.mbms.UriPathPair}s, used in the
     * response to {@link #ACTION_FILE_DESCRIPTOR_REQUEST}. These
     * {@link android.telephony.mbms.UriPathPair}s contain {@code content://} URIs that provide
     * access to previously paused downloads.
     */
    public static final String EXTRA_PAUSED_URI_LIST =
            "android.telephony.mbms.extra.PAUSED_URI_LIST";

    /**
     * Extra containing a string that points to the middleware's knowledge of where the temp file
     * root for the app is. The path should be a canonical path as returned by
     * {@link File#getCanonicalPath()}
     */
    public static final String EXTRA_TEMP_FILE_ROOT =
            "android.telephony.mbms.extra.TEMP_FILE_ROOT";

    /**
     * Extra containing a list of {@link Uri}s indicating temp files which the middleware is
     * still using.
     */
    public static final String EXTRA_TEMP_FILES_IN_USE =
            "android.telephony.mbms.extra.TEMP_FILES_IN_USE";

    /**
     * Extra containing an instance of {@link android.telephony.mbms.ServiceInfo}, used by
     * file-descriptor requests and cleanup requests to specify which service they want to
     * request temp files or clean up temp files for, respectively.
     */
    public static final String EXTRA_SERVICE_INFO =
            "android.telephony.mbms.extra.SERVICE_INFO";

    /**
     * Extra containing a single {@link Uri} indicating the location of the successfully
     * downloaded file. Set on the intent provided via
     * {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}.
     * Will always be set to a non-null value if {@link #EXTRA_RESULT} is set to
     * {@link #RESULT_SUCCESSFUL}.
     * TODO: Not systemapi.
     */
    public static final String EXTRA_COMPLETED_FILE_URI =
            "android.telephony.mbms.extra.COMPLETED_FILE_URI";
@@ -193,6 +84,7 @@ public class MbmsDownloadManager {
    public static final int RESULT_SUCCESSFUL = 1;
    public static final int RESULT_CANCELLED = 2;
    public static final int RESULT_EXPIRED = 3;
    public static final int RESULT_IO_ERROR = 4;
    // TODO - more results!

    /** @hide */
@@ -207,8 +99,16 @@ public class MbmsDownloadManager {
    public static final int STATUS_PENDING_REPAIR = 3;
    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(MbmsException.ERROR_MIDDLEWARE_LOST, "Received death notification");
        }
    };

    private AtomicReference<IMbmsDownloadService> mService = new AtomicReference<>(null);
    private final MbmsDownloadManagerCallback mCallback;
@@ -236,10 +136,21 @@ public class MbmsDownloadManager {
     *
     * Note that this call will bind a remote service and that may take a bit. The instance of
     * {@link MbmsDownloadManager} that is returned will not be ready for use until
     * {@link IMbmsDownloadManagerCallback#middlewareReady()} is called on the provided callback.
     * {@link MbmsDownloadManagerCallback#middlewareReady()} is called on the provided callback.
     * If you attempt to use the manager before it is ready, a {@link MbmsException} will be thrown.
     *
     * This also may throw an {@link IllegalArgumentException} or a {@link MbmsException}.
     * This also may throw an {@link IllegalArgumentException} or an {@link IllegalStateException}.
     *
     * You may only have one instance of {@link MbmsDownloadManager} per UID. If you call this
     * method while there is an active instance of {@link MbmsDownloadManager} in your process
     * (in other words, one that has not had {@link #dispose()} called on it), this method will
     * throw an {@link MbmsException}. If you call this method in a different process
     * running under the same UID, an error will be indicated via
     * {@link MbmsDownloadManagerCallback#error(int, String)}.
     *
     * Note that initialization may fail asynchronously. If you wish to try again after you
     * receive such an asynchronous error, you must call dispose() on the instance of
     * {@link MbmsDownloadManager} that you received before calling this method again.
     *
     * @param context The instance of {@link Context} to use
     * @param listener A callback to get asynchronous error messages and file service updates.
@@ -249,8 +160,16 @@ public class MbmsDownloadManager {
    public static MbmsDownloadManager create(Context context,
            MbmsDownloadManagerCallback listener, int subscriptionId)
            throws MbmsException {
        if (!sIsInitialized.compareAndSet(false, true)) {
            throw new MbmsException(MbmsException.InitializationErrors.ERROR_DUPLICATE_INITIALIZE);
        }
        MbmsDownloadManager mdm = new MbmsDownloadManager(context, listener, subscriptionId);
        try {
            mdm.bindAndInitialize();
        } catch (MbmsException e) {
            sIsInitialized.set(false);
            throw e;
        }
        return mdm;
    }

@@ -266,16 +185,27 @@ public class MbmsDownloadManager {
                            result = downloadService.initialize(mSubscriptionId, mCallback);
                        } 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");
                            mCallback.error(
                            sendErrorToApp(
                                    MbmsException.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
                                    e.toString());
                            sIsInitialized.set(false);
                            return;
                        }
                        if (result != MbmsException.SUCCESS) {
                            mCallback.error(result, "Error returned during initialization");
                            sendErrorToApp(result, "Error returned during initialization");
                            sIsInitialized.set(false);
                            return;
                        }
                        try {
                            downloadService.asBinder().linkToDeath(mDeathRecipient, 0);
                        } catch (RemoteException e) {
                            sendErrorToApp(MbmsException.ERROR_MIDDLEWARE_LOST,
                                    "Middleware lost during initialization");
                            sIsInitialized.set(false);
                            return;
                        }
                        mService.set(downloadService);
@@ -283,6 +213,7 @@ public class MbmsDownloadManager {

                    @Override
                    public void onServiceDisconnected(ComponentName name) {
                        sIsInitialized.set(false);
                        mService.set(null);
                    }
                });
@@ -292,7 +223,7 @@ public class MbmsDownloadManager {
     * 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 IMbmsDownloadManagerCallback#fileServicesUpdated(List)}
     * {@link MbmsDownloadManagerCallback#fileServicesUpdated(List)}
     *
     * The serviceClasses argument lets the app filter on types of programming and is opaque data
     * negotiated beforehand between the app and the carrier.
@@ -306,7 +237,7 @@ public class MbmsDownloadManager {
     * {@link MbmsException.StreamingErrors#ERROR_UNABLE_TO_START_SERVICE}
     *
     * @param classList A list of service classes which the app wishes to receive
     *                  {@link IMbmsDownloadManagerCallback#fileServicesUpdated(List)} callbacks
     *                  {@link MbmsDownloadManagerCallback#fileServicesUpdated(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).
@@ -336,14 +267,15 @@ public class MbmsDownloadManager {
     * 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, IDownloadCallback)}, the framework
     * {@link #download(DownloadRequest, DownloadProgressListener)}, the framework
     * will default to a directory formed by the concatenation of the app's files directory and
     * {@link android.telephony.mbms.MbmsTempFileProvider#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,
     * an {@link MbmsException} will be thrown with code
     * {@link MbmsException.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT}
     * {@link MbmsException.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.
@@ -383,6 +315,26 @@ public class MbmsDownloadManager {
        prefs.edit().putString(MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_NAME, filePath).apply();
    }

    /**
     * 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, DownloadProgressListener)} 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 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 a download of a file that is available via multicast.
     *
@@ -404,7 +356,7 @@ public class MbmsDownloadManager {
     * @param progressListener Optional listener that will be provided progress updates
     *                         if the app is running.
     */
    public void download(DownloadRequest request, IDownloadProgressListener progressListener)
    public void download(DownloadRequest request, DownloadProgressListener progressListener)
            throws MbmsException {
        IMbmsDownloadService downloadService = mService.get();
        if (downloadService == null) {
@@ -434,7 +386,7 @@ public class MbmsDownloadManager {
    /**
     * 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, IDownloadCallback)} but not cancelled through
     * {@link #download(DownloadRequest, DownloadProgressListener)} but not cancelled through
     * {@link #cancelDownload(DownloadRequest)}.
     * @return A list, possibly empty, of {@link DownloadRequest}s
     */
@@ -550,43 +502,15 @@ public class MbmsDownloadManager {
                return;
            }
            downloadService.dispose(mSubscriptionId);
            mService.set(null);
        } catch (RemoteException e) {
            // Ignore
            Log.i(LOG_TAG, "Remote exception while disposing of service");
        } finally {
            mService.set(null);
            sIsInitialized.set(false);
        }
    }

    /**
     * Retrieves the {@link ComponentName} for the {@link android.content.BroadcastReceiver} that
     * the various intents from the middleware should be targeted towards.
     * @param uid The uid of the frontend app.
     * @return The component name of the receiver that the middleware should send its intents to,
     * or null if the app didn't declare it in the manifest.
     *
     * @hide
     * future systemapi
     */
    public static ComponentName getAppReceiverFromUid(Context context, int uid) {
        String[] packageNames = context.getPackageManager().getPackagesForUid(uid);
        if (packageNames == null) {
            return null;
        }

        for (String packageName : packageNames) {
            ComponentName candidate = new ComponentName(packageName,
                    MbmsDownloadReceiver.class.getCanonicalName());
            Intent queryIntent = new Intent();
            queryIntent.setComponent(candidate);
            List<ResolveInfo> receivers =
                    context.getPackageManager().queryBroadcastReceivers(queryIntent, 0);
            if (receivers != null && receivers.size() > 0) {
                return candidate;
            }
        }
        return null;
    }

    private void writeDownloadRequestToken(DownloadRequest request) {
        File token = getDownloadRequestTokenPath(request);
        if (!token.getParentFile().exists()) {
@@ -651,4 +575,12 @@ public class MbmsDownloadManager {
            }
        }
    }

    private void sendErrorToApp(int errorCode, String message) {
        try {
            mCallback.error(errorCode, message);
        } catch (RemoteException e) {
            // Ignore, should not happen locally.
        }
    }
}
+124 −24

File changed.

Preview size limit exceeded, changes collapsed.

+4 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.telephony.mbms;

import android.os.RemoteException;

/**
 * A optional listener class used by download clients to track progress.
 * @hide
@@ -38,8 +40,9 @@ public class DownloadProgressListener extends IDownloadProgressListener.Stub {
     * @param currentDecodedSize is the number of bytes that have been decoded.
     * @param fullDecodedSize is the total number of bytes that make up the final decoded content.
     */
    @Override
    public void progress(DownloadRequest request, FileInfo fileInfo,
            int currentDownloadSize, int fullDownloadSize,
            int currentDecodedSize, int fullDecodedSize) {
            int currentDecodedSize, int fullDecodedSize) throws RemoteException {
    }
}
+63 −3
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.util.Log;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
@@ -77,12 +78,18 @@ public class DownloadRequest implements Parcelable {
        private String appIntent;
        private int version = CURRENT_VERSION;

        /**
         * Sets the service from which the download request to be built will download from.
         * @param serviceInfo
         * @return
         */
        public Builder setServiceInfo(FileServiceInfo serviceInfo) {
            fileServiceId = serviceInfo.getServiceId();
            return this;
        }

        /**
         * Set the service ID for the download request. For use by the middleware only.
         * @hide
         * TODO: systemapi
         */
@@ -91,11 +98,23 @@ public class DownloadRequest implements Parcelable {
            return this;
        }

        /**
         * Sets the source URI for the download request to be built.
         * @param source
         * @return
         */
        public Builder setSource(Uri source) {
            this.source = source;
            return this;
        }

        /**
         * Sets the destination URI for the download request to be built. The middleware should
         * not set this directly.
         * @param dest A URI obtained from {@link Uri#fromFile(File)}, denoting the requested
         *             final destination of the download.
         * @return
         */
        public Builder setDest(Uri dest) {
            if (dest.toString().length() > MAX_DESTINATION_URI_SIZE) {
                throw new IllegalArgumentException("Destination uri must not exceed length " +
@@ -105,11 +124,25 @@ public class DownloadRequest implements Parcelable {
            return this;
        }

        public Builder setSubscriptionId(int sub) {
            this.subscriptionId = sub;
        /**
         * Set the subscription ID on which the file(s) should be downloaded.
         * @param subscriptionId
         * @return
         */
        public Builder setSubscriptionId(int subscriptionId) {
            this.subscriptionId = subscriptionId;
            return this;
        }

        /**
         * Set the {@link Intent} that should be sent when the download completes or fails. This
         * should be an intent with a explicit {@link android.content.ComponentName} targeted to a
         * {@link android.content.BroadcastReceiver} in the app's package.
         *
         * The middleware should not use this method.
         * @param intent
         * @return
         */
        public Builder setAppIntent(Intent intent) {
            this.appIntent = intent.toUri(0);
            if (this.appIntent.length() > MAX_APP_INTENT_SIZE) {
@@ -120,7 +153,12 @@ public class DownloadRequest implements Parcelable {
        }

        /**
         * For use by middleware only
         * For use by the middleware to set the byte array of opaque data. The opaque data
         * includes information about the download request that is used by the client app and the
         * manager code, but is irrelevant to the middleware.
         * @param data A byte array, the contents of which should have been originally obtained
         *             from {@link DownloadRequest#getOpaqueData()}.
         * @return
         * TODO: systemapi
         * @hide
         */
@@ -201,22 +239,40 @@ public class DownloadRequest implements Parcelable {
        out.writeInt(version);
    }

    /**
     * @return The ID of the file service to download from.
     */
    public String getFileServiceId() {
        return fileServiceId;
    }

    /**
     * @return The source URI to download from
     */
    public Uri getSourceUri() {
        return sourceUri;
    }

    /**
     * For use by the client app only.
     * @return The URI of the final destination of the download.
     */
    public Uri getDestinationUri() {
        return destinationUri;
    }

    /**
     * @return The subscription ID on which to perform MBMS operations.
     */
    public int getSubscriptionId() {
        return subscriptionId;
    }

    /**
     * For internal use -- returns the intent to send to the app after download completion or
     * failure.
     * @hide
     */
    public Intent getIntentForApp() {
        try {
            return Intent.parseUri(serializedResultIntentForApp, 0);
@@ -226,6 +282,10 @@ public class DownloadRequest implements Parcelable {
    }

    /**
     * For use by the middleware only. The byte array returned from this method should be
     * persisted and sent back to the app upon download completion or failure by passing it into
     * {@link Builder#setOpaqueData(byte[])}.
     * @return A byte array of opaque data to persist.
     * @hide
     * TODO: systemapi
     */
+5 −28
Original line number Diff line number Diff line
@@ -38,16 +38,6 @@ public class FileInfo implements Parcelable {
     */
    private final String mimeType;

    /**
     * The size of the file in bytes.
     */
    private final long size;

    /**
     * The MD5 hash of the file.
     */
    private final byte md5Hash[];

    public static final Parcelable.Creator<FileInfo> CREATOR =
            new Parcelable.Creator<FileInfo>() {
        @Override
@@ -61,29 +51,24 @@ public class FileInfo implements Parcelable {
        }
    };

    public FileInfo(Uri uri, String mimeType, long size, byte[] md5Hash) {
    /**
     * @hide
     * TODO: systemapi
     */
    public FileInfo(Uri uri, String mimeType) {
        this.uri = uri;
        this.mimeType = mimeType;
        this.size = size;
        this.md5Hash = md5Hash;
    }

    private FileInfo(Parcel in) {
        uri = in.readParcelable(null);
        mimeType = in.readString();
        size = in.readLong();
        int arraySize = in.readInt();
        md5Hash = new byte[arraySize];
        in.readByteArray(md5Hash);
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeParcelable(uri, flags);
        dest.writeString(mimeType);
        dest.writeLong(size);
        dest.writeInt(md5Hash.length);
        dest.writeByteArray(md5Hash);
    }

    @Override
@@ -98,12 +83,4 @@ public class FileInfo implements Parcelable {
    public String getMimeType() {
        return mimeType;
    }

    public long getSize() {
        return size;
    }

    public byte[] getMd5Hash() {
        return md5Hash;
    }
}
Loading