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

Commit 6e1e2090 authored by Android Build Merger (Role)'s avatar Android Build Merger (Role) Committed by Android (Google) Code Review
Browse files

Merge "Merge "Embms download setup" am: da5b77fa am: a807ee8f am:...

Merge "Merge "Embms download setup" am: da5b77fa am: a807ee8f am: b6a16546" into oc-dr1-dev-plus-aosp
parents e6d4e7dd 7d576f60
Loading
Loading
Loading
Loading
+52 −9
Original line number Original line Diff line number Diff line
@@ -16,19 +16,24 @@


package android.telephony;
package android.telephony;


import android.content.ComponentName;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.Uri;
import android.net.Uri;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.RemoteException;
import android.telephony.mbms.IDownloadCallback;
import android.telephony.mbms.IDownloadCallback;
import android.telephony.mbms.DownloadRequest;
import android.telephony.mbms.DownloadRequest;
import android.telephony.mbms.DownloadStatus;
import android.telephony.mbms.DownloadStatus;
import android.telephony.mbms.IMbmsDownloadManagerCallback;
import android.telephony.mbms.IMbmsDownloadManagerCallback;
import android.telephony.mbms.MbmsException;
import android.telephony.mbms.MbmsException;
import android.telephony.mbms.MbmsUtils;
import android.telephony.mbms.vendor.IMbmsDownloadService;
import android.telephony.mbms.vendor.IMbmsDownloadService;
import android.util.Log;
import android.util.Log;


import java.util.List;
import java.util.List;
import java.util.concurrent.CountDownLatch;


import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;


@@ -36,6 +41,8 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
public class MbmsDownloadManager {
public class MbmsDownloadManager {
    private static final String LOG_TAG = MbmsDownloadManager.class.getSimpleName();
    private static final String LOG_TAG = MbmsDownloadManager.class.getSimpleName();


    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
     * The MBMS middleware should send this when a download of single file has completed or
     * failed. Mandatory extras are
     * failed. Mandatory extras are
@@ -76,15 +83,15 @@ public class MbmsDownloadManager {
            "android.telephony.mbms.action.CLEANUP";
            "android.telephony.mbms.action.CLEANUP";


    /**
    /**
     * Integer extra indicating the result code of the download.
     * Integer extra indicating the result code of the download. One of
     * TODO: put in link to error list
     * {@link #RESULT_SUCCESSFUL}, {@link #RESULT_EXPIRED}, or {@link #RESULT_CANCELLED}.
     * TODO: future systemapi (here and and all extras)
     */
     */
    public static final String EXTRA_RESULT = "android.telephony.mbms.extra.RESULT";
    public static final String EXTRA_RESULT = "android.telephony.mbms.extra.RESULT";


    /**
    /**
     * Extra containing the {@link android.telephony.mbms.FileInfo} for which the download result
     * Extra containing the {@link android.telephony.mbms.FileInfo} for which the download result
     * is for. Must not be null.
     * is for. Must not be null.
     * TODO: future systemapi (here and and all extras) except the two for the app intent
     */
     */
    public static final String EXTRA_INFO = "android.telephony.mbms.extra.INFO";
    public static final String EXTRA_INFO = "android.telephony.mbms.extra.INFO";


@@ -143,11 +150,23 @@ public class MbmsDownloadManager {
    public static final String EXTRA_TEMP_FILES_IN_USE =
    public static final String EXTRA_TEMP_FILES_IN_USE =
            "android.telephony.mbms.extra.TEMP_FILES_IN_USE";
            "android.telephony.mbms.extra.TEMP_FILES_IN_USE";


    /**
     * 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}.
     */
    public static final String EXTRA_COMPLETED_FILE_URI =
            "android.telephony.mbms.extra.COMPLETED_FILE_URI";

    public static final int RESULT_SUCCESSFUL = 1;
    public static final int RESULT_SUCCESSFUL = 1;
    public static final int RESULT_CANCELLED  = 2;
    public static final int RESULT_CANCELLED  = 2;
    public static final int RESULT_EXPIRED    = 3;
    public static final int RESULT_EXPIRED    = 3;
    // TODO - more results!
    // TODO - more results!


    private static final long BIND_TIMEOUT_MS = 3000;

    private final Context mContext;
    private final Context mContext;
    private int mSubId = INVALID_SUBSCRIPTION_ID;
    private int mSubId = INVALID_SUBSCRIPTION_ID;


@@ -199,12 +218,31 @@ public class MbmsDownloadManager {
    }
    }


    private void bindAndInitialize() throws MbmsException {
    private void bindAndInitialize() throws MbmsException {
        // TODO: bind
        // TODO: fold binding for download and streaming into a common utils class.
        try {
        final CountDownLatch latch = new CountDownLatch(1);
            mService.initialize(mDownloadAppName, mSubId, mCallback);
        ServiceConnection bindListener = new ServiceConnection() {
        } catch (RemoteException e) {
            @Override
            throw new MbmsException(0); // TODO: proper error code
            public void onServiceConnected(ComponentName name, IBinder service) {
                mService = IMbmsDownloadService.Stub.asInterface(service);
                latch.countDown();
            }
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                mService = null;
            }
        };

        Intent bindIntent = new Intent();
        bindIntent.setComponent(MbmsUtils.toComponentName(
                MbmsUtils.getMiddlewareServiceInfo(mContext, MBMS_DOWNLOAD_SERVICE_ACTION)));

        // Kick off the binding, and synchronously wait until binding is complete
        mContext.bindService(bindIntent, bindListener, Context.BIND_AUTO_CREATE);

        MbmsUtils.waitOnLatchWithTimeout(latch, BIND_TIMEOUT_MS);

        // TODO: initialize
    }
    }


    /**
    /**
@@ -245,6 +283,11 @@ public class MbmsDownloadManager {
     */
     */
    public DownloadRequest download(DownloadRequest request, IDownloadCallback listener) {
    public DownloadRequest download(DownloadRequest request, IDownloadCallback listener) {
        request.setAppName(mDownloadAppName);
        request.setAppName(mDownloadAppName);
        try {
            mService.download(request, listener);
        } catch (RemoteException e) {
            mService = null;
        }
        return request;
        return request;
    }
    }


+12 −34
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.RemoteException;
import android.telephony.mbms.MbmsException;
import android.telephony.mbms.MbmsException;
import android.telephony.mbms.MbmsStreamingManagerCallback;
import android.telephony.mbms.MbmsStreamingManagerCallback;
import android.telephony.mbms.MbmsUtils;
import android.telephony.mbms.StreamingService;
import android.telephony.mbms.StreamingService;
import android.telephony.mbms.StreamingServiceCallback;
import android.telephony.mbms.StreamingServiceCallback;
import android.telephony.mbms.StreamingServiceInfo;
import android.telephony.mbms.StreamingServiceInfo;
@@ -62,7 +63,9 @@ public class MbmsStreamingManager {
                Log.i(LOG_TAG, String.format("Connected to service %s", name));
                Log.i(LOG_TAG, String.format("Connected to service %s", name));
                synchronized (MbmsStreamingManager.this) {
                synchronized (MbmsStreamingManager.this) {
                    mService = IMbmsStreamingService.Stub.asInterface(service);
                    mService = IMbmsStreamingService.Stub.asInterface(service);
                    mServiceListeners.forEach(ServiceListener::onServiceConnected);
                    for (ServiceListener l : mServiceListeners) {
                        l.onServiceConnected();
                    }
                }
                }
            }
            }
        }
        }
@@ -72,10 +75,13 @@ public class MbmsStreamingManager {
            Log.i(LOG_TAG, String.format("Disconnected from service %s", name));
            Log.i(LOG_TAG, String.format("Disconnected from service %s", name));
            synchronized (MbmsStreamingManager.this) {
            synchronized (MbmsStreamingManager.this) {
                mService = null;
                mService = null;
                mServiceListeners.forEach(ServiceListener::onServiceDisconnected);
                for (ServiceListener l : mServiceListeners) {
                    l.onServiceDisconnected();
                }
            }
            }
        }
        }
    };
    };

    private List<ServiceListener> mServiceListeners = new LinkedList<>();
    private List<ServiceListener> mServiceListeners = new LinkedList<>();


    private MbmsStreamingManagerCallback mCallbackToApp;
    private MbmsStreamingManagerCallback mCallbackToApp;
@@ -218,22 +224,6 @@ public class MbmsStreamingManager {
    }
    }


    private void bindAndInitialize() throws MbmsException {
    private void bindAndInitialize() throws MbmsException {
        // Query for the proper service
        PackageManager packageManager = mContext.getPackageManager();
        Intent queryIntent = new Intent();
        queryIntent.setAction(MBMS_STREAMING_SERVICE_ACTION);
        List<ResolveInfo> streamingServices = packageManager.queryIntentServices(queryIntent,
                PackageManager.MATCH_SYSTEM_ONLY);

        if (streamingServices == null || streamingServices.size() == 0) {
            throw new MbmsException(
                    MbmsException.ERROR_NO_SERVICE_INSTALLED);
        }
        if (streamingServices.size() > 1) {
            throw new MbmsException(
                    MbmsException.ERROR_MULTIPLE_SERVICES_INSTALLED);
        }

        // Kick off the binding, and synchronously wait until binding is complete
        // Kick off the binding, and synchronously wait until binding is complete
        final CountDownLatch latch = new CountDownLatch(1);
        final CountDownLatch latch = new CountDownLatch(1);
        ServiceListener bindListener = new ServiceListener() {
        ServiceListener bindListener = new ServiceListener() {
@@ -252,11 +242,12 @@ public class MbmsStreamingManager {
        }
        }


        Intent bindIntent = new Intent();
        Intent bindIntent = new Intent();
        bindIntent.setComponent(streamingServices.get(0).getComponentInfo().getComponentName());
        bindIntent.setComponent(MbmsUtils.toComponentName(
                MbmsUtils.getMiddlewareServiceInfo(mContext, MBMS_STREAMING_SERVICE_ACTION)));


        mContext.bindService(bindIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
        mContext.bindService(bindIntent, mServiceConnection, Context.BIND_AUTO_CREATE);


        waitOnLatchWithTimeout(latch, BIND_TIMEOUT_MS);
        MbmsUtils.waitOnLatchWithTimeout(latch, BIND_TIMEOUT_MS);


       // Remove the listener and call the initialization method through the interface.
       // Remove the listener and call the initialization method through the interface.
        synchronized (this) {
        synchronized (this) {
@@ -279,17 +270,4 @@ public class MbmsStreamingManager {
        }
        }
    }
    }


    private static void waitOnLatchWithTimeout(CountDownLatch l, long timeoutMs) {
        long endTime = System.currentTimeMillis() + timeoutMs;
        while (System.currentTimeMillis() < endTime) {
            try {
                l.await(timeoutMs, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                // keep waiting
            }
            if (l.getCount() <= 0) {
                return;
            }
        }
    }
}
}
+365 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2017 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.mbms;

import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.MbmsDownloadManager;
import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;

/**
 * @hide
 */
public class MbmsDownloadReceiver extends BroadcastReceiver {
    private static final String LOG_TAG = "MbmsDownloadReceiver";
    private static final String TEMP_FILE_SUFFIX = ".embms.temp";
    private static final int MAX_TEMP_FILE_RETRIES = 5;

    public static final String MBMS_FILE_PROVIDER_META_DATA_KEY = "mbms-file-provider-authority";

    private String mFileProviderAuthorityCache = null;
    private String mMiddlewarePackageNameCache = null;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (!verifyIntentContents(intent)) {
            setResultCode(1 /* TODO: define error constants */);
            return;
        }

        if (MbmsDownloadManager.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
            moveDownloadedFile(context, intent);
            cleanupPostMove(context, intent);
        } else if (MbmsDownloadManager.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
            generateTempFiles(context, intent);
        }
        // TODO: Add handling for ACTION_CLEANUP
    }

    private boolean verifyIntentContents(Intent intent) {
        if (MbmsDownloadManager.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
            if (!intent.hasExtra(MbmsDownloadManager.EXTRA_RESULT)) {
                Log.w(LOG_TAG, "Download result did not include a result code. Ignoring.");
                return false;
            }
            if (!intent.hasExtra(MbmsDownloadManager.EXTRA_REQUEST)) {
                Log.w(LOG_TAG, "Download result did not include the associated request. Ignoring.");
                return false;
            }
            if (!intent.hasExtra(MbmsDownloadManager.EXTRA_INFO)) {
                Log.w(LOG_TAG, "Download result did not include the associated file info. " +
                        "Ignoring.");
                return false;
            }
            if (!intent.hasExtra(MbmsDownloadManager.EXTRA_FINAL_URI)) {
                Log.w(LOG_TAG, "Download result did not include the path to the final " +
                        "temp file. Ignoring.");
                return false;
            }
            return true;
        } else if (MbmsDownloadManager.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
            if (!intent.hasExtra(MbmsDownloadManager.EXTRA_REQUEST)) {
                Log.w(LOG_TAG, "Temp file request not include the associated request. Ignoring.");
                return false;
            }
            return true;
        }

        Log.w(LOG_TAG, "Received intent with unknown action: " + intent.getAction());
        return false;
    }

    private void moveDownloadedFile(Context context, Intent intent) {
        DownloadRequest request = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_REQUEST);
        // TODO: check request against token
        Intent intentForApp = request.getIntentForApp();

        int result = intent.getIntExtra(MbmsDownloadManager.EXTRA_RESULT,
                MbmsDownloadManager.RESULT_CANCELLED);
        intentForApp.putExtra(MbmsDownloadManager.EXTRA_RESULT, result);

        if (result != MbmsDownloadManager.RESULT_SUCCESSFUL) {
            Log.i(LOG_TAG, "Download request indicated a failed download. Aborting.");
            context.sendBroadcast(intentForApp);
            return;
        }

        Uri destinationUri = request.getDestinationUri();
        Uri finalTempFile = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_FINAL_URI);
        if (!verifyTempFilePath(context, request, finalTempFile)) {
            Log.w(LOG_TAG, "Download result specified an invalid temp file " + finalTempFile);
            setResultCode(1);
            return;
        }

        String relativePath = calculateDestinationFileRelativePath(request,
                (FileInfo) intent.getParcelableExtra(MbmsDownloadManager.EXTRA_INFO));

        if (!moveTempFile(finalTempFile, destinationUri, relativePath)) {
            Log.w(LOG_TAG, "Failed to move temp file to final destination");
            setResultCode(1);
        }

        context.sendBroadcast(intentForApp);
        setResultCode(0);
    }

    private void cleanupPostMove(Context context, Intent intent) {
        // TODO: account for in-use temp files
        DownloadRequest request = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_REQUEST);
        if (request == null) {
            Log.w(LOG_TAG, "Intent does not include a DownloadRequest. Ignoring.");
            return;
        }

        List<Uri> tempFiles = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_TEMP_LIST);
        if (tempFiles == null) {
            return;
        }

        for (Uri tempFileUri : tempFiles) {
            if (verifyTempFilePath(context, request, tempFileUri)) {
                File tempFile = new File(tempFileUri.getSchemeSpecificPart());
                tempFile.delete();
            }
        }
    }

    private void generateTempFiles(Context context, Intent intent) {
        // TODO: update pursuant to final decision on temp file locations
        DownloadRequest request = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_REQUEST);
        if (request == null) {
            Log.w(LOG_TAG, "Temp file request did not include the associated request. Ignoring.");
            setResultCode(1 /* TODO: define error constants */);
            return;
        }
        int fdCount = intent.getIntExtra(MbmsDownloadManager.EXTRA_FD_COUNT, 0);
        List<Uri> pausedList = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_PAUSED_LIST);

        if (fdCount == 0 && (pausedList == null || pausedList.size() == 0)) {
            Log.i(LOG_TAG, "No temp files actually requested. Ending.");
            setResultCode(0);
            setResultExtras(Bundle.EMPTY);
            return;
        }

        ArrayList<UriPathPair> freshTempFiles = generateFreshTempFiles(context, request, fdCount);
        ArrayList<UriPathPair> pausedFiles =
                generateUrisForPausedFiles(context, request, pausedList);

        Bundle result = new Bundle();
        result.putParcelableArrayList(MbmsDownloadManager.EXTRA_FREE_URI_LIST, freshTempFiles);
        result.putParcelableArrayList(MbmsDownloadManager.EXTRA_PAUSED_URI_LIST, pausedFiles);
        setResultExtras(result);
    }

    private ArrayList<UriPathPair> generateFreshTempFiles(Context context, DownloadRequest request,
            int freshFdCount) {
        File tempFileDir = getEmbmsTempFileDirForRequest(context, request);
        if (!tempFileDir.exists()) {
            tempFileDir.mkdirs();
        }

        // Name the files with the template "N-UUID", where N is the request ID and UUID is a
        // random uuid.
        ArrayList<UriPathPair> result = new ArrayList<>(freshFdCount);
        for (int i = 0; i < freshFdCount; i++) {
            File tempFile = generateSingleTempFile(tempFileDir);
            if (tempFile == null) {
                setResultCode(2 /* TODO: define error constants */);
                Log.w(LOG_TAG, "Failed to generate a temp file. Moving on.");
                continue;
            }
            Uri fileUri = Uri.fromParts(ContentResolver.SCHEME_FILE, tempFile.getPath(), null);
            Uri contentUri = MbmsTempFileProvider.getUriForFile(
                    context, getFileProviderAuthorityCached(context), tempFile);
            context.grantUriPermission(getMiddlewarePackageCached(context), contentUri,
                    Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            result.add(new UriPathPair(fileUri, contentUri));
        }

        return result;
    }

    private static File generateSingleTempFile(File tempFileDir) {
        int numTries = 0;
        while (numTries < MAX_TEMP_FILE_RETRIES) {
            numTries++;
            String fileName =  UUID.randomUUID() + TEMP_FILE_SUFFIX;
            File tempFile = new File(tempFileDir, fileName);
            try {
                if (tempFile.createNewFile()) {
                    return tempFile.getCanonicalFile();
                }
            } catch (IOException e) {
                continue;
            }
        }
        return null;
    }


    private ArrayList<UriPathPair> generateUrisForPausedFiles(Context context,
            DownloadRequest request, List<Uri> pausedFiles) {
        if (pausedFiles == null) {
            return new ArrayList<>(0);
        }
        ArrayList<UriPathPair> result = new ArrayList<>(pausedFiles.size());

        for (Uri fileUri : pausedFiles) {
            if (!verifyTempFilePath(context, request, fileUri)) {
                Log.w(LOG_TAG, "Supplied file " + fileUri + " is not a valid temp file to resume");
                setResultCode(2 /* TODO: define error codes */);
                continue;
            }
            File tempFile = new File(fileUri.getSchemeSpecificPart());
            if (!tempFile.exists()) {
                Log.w(LOG_TAG, "Supplied file " + fileUri + " does not exist.");
                setResultCode(2 /* TODO: define error codes */);
                continue;
            }
            Uri contentUri = MbmsTempFileProvider.getUriForFile(
                    context, getFileProviderAuthorityCached(context), tempFile);
            context.grantUriPermission(getMiddlewarePackageCached(context), contentUri,
                    Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

            result.add(new UriPathPair(fileUri, contentUri));
        }
        return result;
    }

    private static String calculateDestinationFileRelativePath(DownloadRequest request,
            FileInfo info) {
        // TODO: determine whether this is actually the path determination scheme we want to use
        List<String> filePathComponents = info.uri.getPathSegments();
        List<String> requestPathComponents = request.getSourceUri().getPathSegments();
        Iterator<String> filePathIter = filePathComponents.iterator();
        Iterator<String> requestPathIter = requestPathComponents.iterator();

        LinkedList<String> relativePathComponents = new LinkedList<>();
        while (filePathIter.hasNext()) {
            String currFilePathComponent = filePathIter.next();
            if (requestPathIter.hasNext()) {
                String requestFilePathComponent = requestPathIter.next();
                if (requestFilePathComponent.equals(currFilePathComponent)) {
                    continue;
                }
            }
            relativePathComponents.add(currFilePathComponent);
        }
        return String.join("/", relativePathComponents);
    }

    private static boolean moveTempFile(Uri fromPath, Uri toPath, String relativePath) {
        if (!ContentResolver.SCHEME_FILE.equals(fromPath.getScheme())) {
            Log.w(LOG_TAG, "Moving source uri " + fromPath+ " does not have a file scheme");
            return false;
        }
        if (!ContentResolver.SCHEME_FILE.equals(toPath.getScheme())) {
            Log.w(LOG_TAG, "Moving destination uri " + toPath + " does not have a file scheme");
            return false;
        }

        File fromFile = new File(fromPath.getSchemeSpecificPart());
        File toFile = new File(toPath.getSchemeSpecificPart(), relativePath);
        toFile.getParentFile().mkdirs();

        // TODO: This may not work if the two files are on different filesystems. Should we
        // enforce that the temp file storage and the permanent storage are both in the same fs?
        return fromFile.renameTo(toFile);
    }

    private static boolean verifyTempFilePath(Context context, DownloadRequest request,
            Uri filePath) {
        // TODO: modify pursuant to final decision on temp file path scheme
        if (!ContentResolver.SCHEME_FILE.equals(filePath.getScheme())) {
            Log.w(LOG_TAG, "Uri " + filePath + " does not have a file scheme");
            return false;
        }

        String path = filePath.getSchemeSpecificPart();
        File tempFile = new File(path);
        if (!tempFile.exists()) {
            Log.w(LOG_TAG, "File at " + path + " does not exist.");
            return false;
        }

        if (!MbmsUtils.isContainedIn(getEmbmsTempFileDirForRequest(context, request), tempFile)) {
            return false;
        }

        return true;
    }

    /**
     * Returns a File linked to the directory used to store temp files for this request
     */
    private static File getEmbmsTempFileDirForRequest(Context context, DownloadRequest request) {
        File embmsTempFileDir = MbmsTempFileProvider.getEmbmsTempFileDir(
                context, getFileProviderAuthority(context));

        // TODO: better naming scheme for temp file dirs
        String tempFileDirName = String.valueOf(request.getFileServiceInfo().getServiceId());
        return new File(embmsTempFileDir, tempFileDirName);
    }

    private String getFileProviderAuthorityCached(Context context) {
        if (mFileProviderAuthorityCache != null) {
            return mFileProviderAuthorityCache;
        }

        mFileProviderAuthorityCache = getFileProviderAuthority(context);
        return mFileProviderAuthorityCache;
    }

    private static String getFileProviderAuthority(Context context) {
        ApplicationInfo appInfo;
        try {
            appInfo = context.getPackageManager()
                    .getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException("Package manager couldn't find " + context.getPackageName());
        }
        String authority = appInfo.metaData.getString(MBMS_FILE_PROVIDER_META_DATA_KEY);
        if (authority == null) {
            throw new RuntimeException("Must declare the file provider authority as meta data");
        }
        return authority;
    }

    private String getMiddlewarePackageCached(Context context) {
        if (mMiddlewarePackageNameCache == null) {
            mMiddlewarePackageNameCache = MbmsUtils.getMiddlewareServiceInfo(context,
                    MbmsDownloadManager.MBMS_DOWNLOAD_SERVICE_ACTION).packageName;
        }
        return mMiddlewarePackageNameCache;
    }
}
+193 −0

File added.

Preview size limit exceeded, changes collapsed.

+86 −0

File added.

Preview size limit exceeded, changes collapsed.