Merge "Embms adjustments for 7/28"

This commit is contained in:
Hall Liu
2017-08-23 20:18:15 +00:00
committed by Gerrit Code Review
7 changed files with 277 additions and 233 deletions

View File

@@ -18,18 +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.MbmsDownloadManagerCallback;
import android.telephony.mbms.MbmsDownloadReceiver;
import android.telephony.mbms.MbmsException;
@@ -52,147 +53,38 @@ 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";
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_CANCELLED = 2;
public static final int RESULT_EXPIRED = 3;
public static final int RESULT_IO_ERROR = 4;
// TODO - more results!
/** @hide */
@@ -375,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, IDownloadProgressListener)}, 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.
@@ -422,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.
*
@@ -443,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) {
@@ -473,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, IDownloadProgressListener)} but not cancelled through
* {@link #download(DownloadRequest, DownloadProgressListener)} but not cancelled through
* {@link #cancelDownload(DownloadRequest)}.
* @return A list, possibly empty, of {@link DownloadRequest}s
*/
@@ -598,36 +511,6 @@ public class MbmsDownloadManager {
}
}
/**
* 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()) {

View File

@@ -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 {
}
}

View File

@@ -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
@@ -65,29 +55,20 @@ public class FileInfo implements Parcelable {
* @hide
* TODO: systemapi
*/
public FileInfo(Uri uri, String mimeType, long size, byte[] md5Hash) {
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
@@ -102,12 +83,4 @@ public class FileInfo implements Parcelable {
public String getMimeType() {
return mimeType;
}
public long getSize() {
return size;
}
public byte[] getMd5Hash() {
return md5Hash;
}
}

View File

@@ -25,6 +25,7 @@ import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.MbmsDownloadManager;
import android.telephony.mbms.vendor.VendorIntents;
import android.util.Log;
import java.io.File;
@@ -56,9 +57,9 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
/**
* Indicates that the intent sent had an invalid action. This will be the result if
* {@link Intent#getAction()} returns anything other than
* {@link MbmsDownloadManager#ACTION_DOWNLOAD_RESULT_INTERNAL},
* {@link MbmsDownloadManager#ACTION_FILE_DESCRIPTOR_REQUEST}, or
* {@link MbmsDownloadManager#ACTION_CLEANUP}.
* {@link VendorIntents#ACTION_DOWNLOAD_RESULT_INTERNAL},
* {@link VendorIntents#ACTION_FILE_DESCRIPTOR_REQUEST}, or
* {@link VendorIntents#ACTION_CLEANUP}.
* This is a fatal result code and no result extras should be expected.
*/
public static final int RESULT_INVALID_ACTION = 1;
@@ -70,7 +71,7 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
public static final int RESULT_MALFORMED_INTENT = 2;
/**
* Indicates that the supplied value for {@link MbmsDownloadManager#EXTRA_TEMP_FILE_ROOT}
* Indicates that the supplied value for {@link VendorIntents#EXTRA_TEMP_FILE_ROOT}
* does not match what the app has stored.
* This is a fatal result code and no result extras should be expected.
*/
@@ -104,18 +105,18 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
setResultCode(RESULT_MALFORMED_INTENT);
return;
}
if (!Objects.equals(intent.getStringExtra(MbmsDownloadManager.EXTRA_TEMP_FILE_ROOT),
if (!Objects.equals(intent.getStringExtra(VendorIntents.EXTRA_TEMP_FILE_ROOT),
MbmsTempFileProvider.getEmbmsTempFileDir(context).getPath())) {
setResultCode(RESULT_BAD_TEMP_FILE_ROOT);
return;
}
if (MbmsDownloadManager.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
if (VendorIntents.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
moveDownloadedFile(context, intent);
cleanupPostMove(context, intent);
} else if (MbmsDownloadManager.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
} else if (VendorIntents.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
generateTempFiles(context, intent);
} else if (MbmsDownloadManager.ACTION_CLEANUP.equals(intent.getAction())) {
} else if (VendorIntents.ACTION_CLEANUP.equals(intent.getAction())) {
cleanupTempFiles(context, intent);
} else {
setResultCode(RESULT_INVALID_ACTION);
@@ -123,16 +124,16 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
}
private boolean verifyIntentContents(Context context, Intent intent) {
if (MbmsDownloadManager.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
if (VendorIntents.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)) {
if (!intent.hasExtra(VendorIntents.EXTRA_REQUEST)) {
Log.w(LOG_TAG, "Download result did not include the associated request. Ignoring.");
return false;
}
if (!intent.hasExtra(MbmsDownloadManager.EXTRA_TEMP_FILE_ROOT)) {
if (!intent.hasExtra(VendorIntents.EXTRA_TEMP_FILE_ROOT)) {
Log.w(LOG_TAG, "Download result did not include the temp file root. Ignoring.");
return false;
}
@@ -141,12 +142,12 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
"Ignoring.");
return false;
}
if (!intent.hasExtra(MbmsDownloadManager.EXTRA_FINAL_URI)) {
if (!intent.hasExtra(VendorIntents.EXTRA_FINAL_URI)) {
Log.w(LOG_TAG, "Download result did not include the path to the final " +
"temp file. Ignoring.");
return false;
}
DownloadRequest request = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_REQUEST);
DownloadRequest request = intent.getParcelableExtra(VendorIntents.EXTRA_REQUEST);
String expectedTokenFileName = request.getHash() + DOWNLOAD_TOKEN_SUFFIX;
File expectedTokenFile = new File(
MbmsUtils.getEmbmsTempFileDirForService(context, request.getFileServiceId()),
@@ -156,27 +157,27 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
"Expected " + expectedTokenFile);
return false;
}
} else if (MbmsDownloadManager.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
if (!intent.hasExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO)) {
} else if (VendorIntents.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
if (!intent.hasExtra(VendorIntents.EXTRA_SERVICE_INFO)) {
Log.w(LOG_TAG, "Temp file request did not include the associated service info." +
" Ignoring.");
return false;
}
if (!intent.hasExtra(MbmsDownloadManager.EXTRA_TEMP_FILE_ROOT)) {
if (!intent.hasExtra(VendorIntents.EXTRA_TEMP_FILE_ROOT)) {
Log.w(LOG_TAG, "Download result did not include the temp file root. Ignoring.");
return false;
}
} else if (MbmsDownloadManager.ACTION_CLEANUP.equals(intent.getAction())) {
if (!intent.hasExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO)) {
} else if (VendorIntents.ACTION_CLEANUP.equals(intent.getAction())) {
if (!intent.hasExtra(VendorIntents.EXTRA_SERVICE_INFO)) {
Log.w(LOG_TAG, "Cleanup request did not include the associated service info." +
" Ignoring.");
return false;
}
if (!intent.hasExtra(MbmsDownloadManager.EXTRA_TEMP_FILE_ROOT)) {
if (!intent.hasExtra(VendorIntents.EXTRA_TEMP_FILE_ROOT)) {
Log.w(LOG_TAG, "Cleanup request did not include the temp file root. Ignoring.");
return false;
}
if (!intent.hasExtra(MbmsDownloadManager.EXTRA_TEMP_FILES_IN_USE)) {
if (!intent.hasExtra(VendorIntents.EXTRA_TEMP_FILES_IN_USE)) {
Log.w(LOG_TAG, "Cleanup request did not include the list of temp files in use. " +
"Ignoring.");
return false;
@@ -186,7 +187,7 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
}
private void moveDownloadedFile(Context context, Intent intent) {
DownloadRequest request = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_REQUEST);
DownloadRequest request = intent.getParcelableExtra(VendorIntents.EXTRA_REQUEST);
Intent intentForApp = request.getIntentForApp();
int result = intent.getIntExtra(MbmsDownloadManager.EXTRA_RESULT,
@@ -200,7 +201,7 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
}
Uri destinationUri = request.getDestinationUri();
Uri finalTempFile = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_FINAL_URI);
Uri finalTempFile = intent.getParcelableExtra(VendorIntents.EXTRA_FINAL_URI);
if (!verifyTempFilePath(context, request.getFileServiceId(), finalTempFile)) {
Log.w(LOG_TAG, "Download result specified an invalid temp file " + finalTempFile);
setResultCode(RESULT_DOWNLOAD_FINALIZATION_ERROR);
@@ -225,13 +226,13 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
}
private void cleanupPostMove(Context context, Intent intent) {
DownloadRequest request = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_REQUEST);
DownloadRequest request = intent.getParcelableExtra(VendorIntents.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);
List<Uri> tempFiles = intent.getParcelableExtra(VendorIntents.EXTRA_TEMP_LIST);
if (tempFiles == null) {
return;
}
@@ -246,15 +247,15 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
private void generateTempFiles(Context context, Intent intent) {
FileServiceInfo serviceInfo =
intent.getParcelableExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO);
intent.getParcelableExtra(VendorIntents.EXTRA_SERVICE_INFO);
if (serviceInfo == null) {
Log.w(LOG_TAG, "Temp file request did not include the associated service info. " +
"Ignoring.");
setResultCode(RESULT_MALFORMED_INTENT);
return;
}
int fdCount = intent.getIntExtra(MbmsDownloadManager.EXTRA_FD_COUNT, 0);
List<Uri> pausedList = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_PAUSED_LIST);
int fdCount = intent.getIntExtra(VendorIntents.EXTRA_FD_COUNT, 0);
List<Uri> pausedList = intent.getParcelableExtra(VendorIntents.EXTRA_PAUSED_LIST);
if (fdCount == 0 && (pausedList == null || pausedList.size() == 0)) {
Log.i(LOG_TAG, "No temp files actually requested. Ending.");
@@ -269,8 +270,8 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
generateUrisForPausedFiles(context, serviceInfo, pausedList);
Bundle result = new Bundle();
result.putParcelableArrayList(MbmsDownloadManager.EXTRA_FREE_URI_LIST, freshTempFiles);
result.putParcelableArrayList(MbmsDownloadManager.EXTRA_PAUSED_URI_LIST, pausedFiles);
result.putParcelableArrayList(VendorIntents.EXTRA_FREE_URI_LIST, freshTempFiles);
result.putParcelableArrayList(VendorIntents.EXTRA_PAUSED_URI_LIST, pausedFiles);
setResultCode(RESULT_OK);
setResultExtras(result);
}
@@ -353,11 +354,11 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
private void cleanupTempFiles(Context context, Intent intent) {
FileServiceInfo serviceInfo =
intent.getParcelableExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO);
intent.getParcelableExtra(VendorIntents.EXTRA_SERVICE_INFO);
File tempFileDir = MbmsUtils.getEmbmsTempFileDirForService(context,
serviceInfo.getServiceId());
final List<Uri> filesInUse =
intent.getParcelableArrayListExtra(MbmsDownloadManager.EXTRA_TEMP_FILES_IN_USE);
intent.getParcelableArrayListExtra(VendorIntents.EXTRA_TEMP_FILES_IN_USE);
File[] filesToDelete = tempFileDir.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {

View File

@@ -18,6 +18,7 @@ package android.telephony.mbms.vendor;
import android.annotation.NonNull;
import android.os.RemoteException;
import android.telephony.mbms.DownloadProgressListener;
import android.telephony.mbms.DownloadRequest;
import android.telephony.mbms.FileInfo;
import android.telephony.mbms.FileServiceInfo;
@@ -59,8 +60,8 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
* @hide
*/
@Override
public int initialize(int subscriptionId,
IMbmsDownloadManagerCallback callback) throws RemoteException {
public final int initialize(int subscriptionId,
final IMbmsDownloadManagerCallback callback) throws RemoteException {
return initialize(subscriptionId, new MbmsDownloadManagerCallback() {
@Override
public void error(int errorCode, String message) throws RemoteException {
@@ -133,12 +134,29 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
* @param downloadRequest An object describing the set of files to be downloaded.
* @param listener A listener through which the middleware can provide progress updates to
* the app while both are still running.
* @return TODO: enumerate possible return values
* @return Any error from {@link android.telephony.mbms.MbmsException.GeneralErrors}
* or {@link MbmsException#SUCCESS}
*/
public int download(DownloadRequest downloadRequest, DownloadProgressListener listener) {
return 0;
}
/**
* Actual AIDL implementation -- hides the callback AIDL from the API.
* @hide
*/
@Override
public int download(DownloadRequest downloadRequest, IDownloadProgressListener listener)
public final int download(DownloadRequest downloadRequest, IDownloadProgressListener listener)
throws RemoteException {
return 0;
return download(downloadRequest, new DownloadProgressListener() {
@Override
public void progress(DownloadRequest request, FileInfo fileInfo, int
currentDownloadSize, int fullDownloadSize, int currentDecodedSize, int
fullDecodedSize) throws RemoteException {
listener.progress(request, fileInfo, currentDownloadSize, fullDownloadSize,
currentDecodedSize, fullDecodedSize);
}
});
}

View File

@@ -47,10 +47,10 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
* or {@link MbmsException#SUCCESS}. Non-successful error codes will be passed to the app via
* {@link IMbmsStreamingManagerCallback#error(int, String)}.
*
* @param listener The callback to use to communicate with the app.
* @param callback The callback to use to communicate with the app.
* @param subscriptionId The subscription ID to use.
*/
public int initialize(MbmsStreamingManagerCallback listener, int subscriptionId)
public int initialize(MbmsStreamingManagerCallback callback, int subscriptionId)
throws RemoteException {
return 0;
}
@@ -60,10 +60,10 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
* @hide
*/
@Override
public final int initialize(IMbmsStreamingManagerCallback listener, final int subscriptionId)
throws RemoteException {
public final int initialize(final IMbmsStreamingManagerCallback callback,
final int subscriptionId) throws RemoteException {
final int uid = Binder.getCallingUid();
listener.asBinder().linkToDeath(new DeathRecipient() {
callback.asBinder().linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
onAppCallbackDied(uid, subscriptionId);
@@ -74,7 +74,7 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
@Override
public void onError(int errorCode, String message) {
try {
listener.error(errorCode, message);
callback.error(errorCode, message);
} catch (RemoteException e) {
onAppCallbackDied(uid, subscriptionId);
}
@@ -83,7 +83,7 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
@Override
public void onStreamingServicesUpdated(List<StreamingServiceInfo> services) {
try {
listener.streamingServicesUpdated(services);
callback.streamingServicesUpdated(services);
} catch (RemoteException e) {
onAppCallbackDied(uid, subscriptionId);
}
@@ -92,7 +92,7 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
@Override
public void onMiddlewareReady() {
try {
listener.middlewareReady();
callback.middlewareReady();
} catch (RemoteException e) {
onAppCallbackDied(uid, subscriptionId);
}
@@ -133,11 +133,11 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
*
* @param subscriptionId The subscription id to use.
* @param serviceId The ID of the streaming service that the app has requested.
* @param listener The listener object on which the app wishes to receive updates.
* @param callback The callback object on which the app wishes to receive updates.
* @return Any error in {@link android.telephony.mbms.MbmsException.GeneralErrors}
*/
public int startStreaming(int subscriptionId, String serviceId,
StreamingServiceCallback listener) throws RemoteException {
StreamingServiceCallback callback) throws RemoteException {
return 0;
}
@@ -148,9 +148,9 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
*/
@Override
public int startStreaming(int subscriptionId, String serviceId,
IStreamingServiceCallback listener) throws RemoteException {
IStreamingServiceCallback callback) throws RemoteException {
final int uid = Binder.getCallingUid();
listener.asBinder().linkToDeath(new DeathRecipient() {
callback.asBinder().linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
onAppCallbackDied(uid, subscriptionId);
@@ -161,7 +161,7 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
@Override
public void onError(int errorCode, String message) {
try {
listener.error(errorCode, message);
callback.error(errorCode, message);
} catch (RemoteException e) {
onAppCallbackDied(uid, subscriptionId);
}
@@ -171,7 +171,7 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
public void onStreamStateUpdated(@StreamingService.StreamingState int state,
@StreamingService.StreamingStateChangeReason int reason) {
try {
listener.streamStateUpdated(state, reason);
callback.streamStateUpdated(state, reason);
} catch (RemoteException e) {
onAppCallbackDied(uid, subscriptionId);
}
@@ -180,7 +180,7 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
@Override
public void onMediaDescriptionUpdated() {
try {
listener.mediaDescriptionUpdated();
callback.mediaDescriptionUpdated();
} catch (RemoteException e) {
onAppCallbackDied(uid, subscriptionId);
}
@@ -189,7 +189,7 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
@Override
public void onBroadcastSignalStrengthUpdated(int signalStrength) {
try {
listener.broadcastSignalStrengthUpdated(signalStrength);
callback.broadcastSignalStrengthUpdated(signalStrength);
} catch (RemoteException e) {
onAppCallbackDied(uid, subscriptionId);
}
@@ -198,7 +198,7 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
@Override
public void onStreamMethodUpdated(int methodType) {
try {
listener.streamMethodUpdated(methodType);
callback.streamMethodUpdated(methodType);
} catch (RemoteException e) {
onAppCallbackDied(uid, subscriptionId);
}

View File

@@ -0,0 +1,166 @@
/*
* 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.vendor;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.telephony.mbms.DownloadRequest;
import android.telephony.mbms.MbmsDownloadReceiver;
import java.io.File;
import java.util.List;
/**
* @hide
* TODO: future systemapi
*/
public class VendorIntents {
/**
* The MBMS middleware should send this when a download of single file has completed or
* failed. Mandatory extras are
* {@link android.telephony.MbmsDownloadManager#EXTRA_RESULT}
* {@link android.telephony.MbmsDownloadManager#EXTRA_FILE_INFO}
* {@link #EXTRA_REQUEST}
* {@link #EXTRA_TEMP_LIST}
* {@link #EXTRA_FINAL_URI}
*/
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)
*/
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}
*/
public static final String ACTION_CLEANUP =
"android.telephony.mbms.action.CLEANUP";
/**
* 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 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 the {@link DownloadRequest} for which the download result or file
* descriptor request is for. Must not be null.
*/
public static final String EXTRA_REQUEST = "android.telephony.mbms.extra.REQUEST";
/**
* 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 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";
/**
* 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.
*/
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;
}
}