import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-/** @hide */
+/**
+ * This class provides functionality for file download over MBMS.
+ * @hide
+ */
public class MbmsDownloadManager {
private static final String LOG_TAG = MbmsDownloadManager.class.getSimpleName();
- /** @hide */
- // TODO: systemapi
+ /**
+ * Service action which must be handled by the middleware implementing the MBMS file download
+ * interface.
+ * @hide
+ */
+ @SystemApi
@SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
public static final String MBMS_DOWNLOAD_SERVICE_ACTION =
"android.telephony.action.EmbmsDownload";
/**
- * Integer extra indicating the result code of the download. One of
- * {@link #RESULT_SUCCESSFUL}, {@link #RESULT_EXPIRED}, or {@link #RESULT_CANCELLED}.
+ * Integer extra that Android will attach to the intent supplied via
+ * {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}
+ * Indicates the result code of the download. One of
+ * {@link #RESULT_SUCCESSFUL}, {@link #RESULT_EXPIRED}, {@link #RESULT_CANCELLED}, or
+ * {@link #RESULT_IO_ERROR}.
+ *
+ * This extra may also be used by the middleware when it is sending intents to the app.
*/
public static final String EXTRA_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.
+ * {@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_FILE_INFO = "android.telephony.mbms.extra.FILE_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 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. 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";
+ /**
+ * The default directory name for all MBMS temp files. If you call
+ * {@link #download(DownloadRequest, DownloadProgressListener)} without first calling
+ * {@link #setTempFileRootDirectory(File)}, this directory will be created for you under the
+ * path returned by {@link Context#getFilesDir()}.
+ */
+ public static final String DEFAULT_TOP_LEVEL_TEMP_DIRECTORY = "androidMbmsTempFileRoot";
+
+ /**
+ * Indicates that the download was successful.
+ */
public static final int RESULT_SUCCESSFUL = 1;
+
+ /**
+ * Indicates that the download was cancelled via {@link #cancelDownload(DownloadRequest)}.
+ */
public static final int RESULT_CANCELLED = 2;
+
+ /**
+ * Indicates that the download will not be completed due to the expiration of its download
+ * window on the carrier's network.
+ */
public static final int RESULT_EXPIRED = 3;
+
+ /**
+ * Indicates that the download will not be completed due to an I/O error incurred while
+ * writing to temp files. This commonly indicates that the device is out of storage space,
+ * but may indicate other conditions as well (such as an SD card being removed).
+ */
public static final int RESULT_IO_ERROR = 4;
// TODO - more results!
STATUS_PENDING_REPAIR, STATUS_PENDING_DOWNLOAD_WINDOW})
public @interface DownloadStatus {}
+ /**
+ * Indicates that the middleware has no information on the file.
+ */
public static final int STATUS_UNKNOWN = 0;
+
+ /**
+ * Indicates that the file is actively downloading.
+ */
public static final int STATUS_ACTIVELY_DOWNLOADING = 1;
+
+ /**
+ * TODO: I don't know...
+ */
public static final int STATUS_PENDING_DOWNLOAD = 2;
+
+ /**
+ * Indicates that the file is being repaired after the download being interrupted.
+ */
public static final int STATUS_PENDING_REPAIR = 3;
+
+ /**
+ * Indicates that the file is waiting to download because its download window has not yet
+ * started.
+ */
public static final int STATUS_PENDING_DOWNLOAD_WINDOW = 4;
private static AtomicBoolean sIsInitialized = new AtomicBoolean(false);
* If this method is not called at least once before calling
* {@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}.
+ * {@link MbmsDownloadManager#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,
*
* 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 MbmsTempFileProvider#DEFAULT_TOP_LEVEL_TEMP_DIRECTORY} and store that as the temp
+ * {@link MbmsDownloadManager#DEFAULT_TOP_LEVEL_TEMP_DIRECTORY} and store that as the temp
* file root directory.
*
* Asynchronous errors through the listener include any of the errors
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(),
- MbmsTempFileProvider.DEFAULT_TOP_LEVEL_TEMP_DIRECTORY);
+ DEFAULT_TOP_LEVEL_TEMP_DIRECTORY);
tempRootDirectory.mkdirs();
setTempFileRootDirectory(tempRootDirectory);
}
import android.os.RemoteException;
/**
- * A optional listener class used by download clients to track progress.
+ * A optional listener class used by download clients to track progress. Apps should extend this
+ * class and pass an instance into
+ * {@link android.telephony.MbmsDownloadManager#download(DownloadRequest, DownloadProgressListener)}
* @hide
*/
public class DownloadProgressListener extends IDownloadProgressListener.Stub {
package android.telephony.mbms;
+import android.annotation.SystemApi;
import android.content.Intent;
import android.net.Uri;
import android.os.Parcel;
import java.util.Objects;
/**
- * A Parcelable class describing a pending Cell-Broadcast download request
+ * Describes a request to download files over cell-broadcast. Instances of this class should be
+ * created by the app when requesting a download, and instances of this class will be passed back
+ * to the app when the middleware updates the status of the download.
* @hide
*/
public class DownloadRequest implements Parcelable {
/**
* Set the service ID for the download request. For use by the middleware only.
* @hide
- * TODO: systemapi
*/
+ //@SystemApi
public Builder setServiceId(String serviceId) {
fileServiceId = serviceId;
return this;
* @param data A byte array, the contents of which should have been originally obtained
* from {@link DownloadRequest#getOpaqueData()}.
* @return
- * TODO: systemapi
* @hide
*/
+ //@SystemApi
public Builder setOpaqueData(byte[] data) {
try {
ObjectInputStream stream = new ObjectInputStream(new ByteArrayInputStream(data));
* {@link Builder#setOpaqueData(byte[])}.
* @return A byte array of opaque data to persist.
* @hide
- * TODO: systemapi
*/
+ //@SystemApi
public byte[] getOpaqueData() {
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
package android.telephony.mbms;
+import android.annotation.SystemApi;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
/**
- * A Parcelable class Cell-Broadcast downloadable file information.
+ * Describes a single file that is available over MBMS.
* @hide
*/
public class FileInfo implements Parcelable {
- /**
- * The URI into the carriers infrastructure which points to this file.
- * This is used internally but is also one of the few pieces of data about the content that is
- * exposed and may be needed for disambiguation by the application.
- */
private final Uri uri;
- /**
- * The mime type of the content.
- */
private final String mimeType;
public static final Parcelable.Creator<FileInfo> CREATOR =
/**
* @hide
- * TODO: systemapi
*/
+ //@SystemApi
public FileInfo(Uri uri, String mimeType) {
this.uri = uri;
this.mimeType = mimeType;
return 0;
}
+ /**
+ * @return The URI in the carrier's infrastructure which points to this file. Apps should
+ * negotiate the contents of this URI separately with the carrier.
+ */
public Uri getUri() {
return uri;
}
+ /**
+ * @return The MIME type of the file.
+ */
public String getMimeType() {
return mimeType;
}
package android.telephony.mbms;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Map;
/**
- * A Parcelable class Cell-Broadcast downloadable file information.
+ * Describes a file service available from the carrier from which files can be downloaded via
+ * cell-broadcast.
* @hide
*/
public class FileServiceInfo extends ServiceInfo implements Parcelable {
private final List<FileInfo> files;
- /** @hide TODO: systemapi */
+ /** @hide */
+ @SystemApi
public FileServiceInfo(Map<Locale, String> newNames, String newClassName,
List<Locale> newLocales, String newServiceId, Date start, Date end,
List<FileInfo> newFiles) {
return 0;
}
+ /**
+ * @return A list of files available from this service. Note that this list may not be
+ * exhaustive -- the middleware may not have information on all files that are available.
+ * Consult the carrier for an authoritative and exhaustive list.
+ */
public List<FileInfo> getFiles() {
return files;
}
-
}
import java.util.List;
/**
- * A Parcelable class with Cell-Broadcast service information.
+ * A callback class that apps should use to receive information on file downloads over
+ * cell-broadcast.
* @hide
*/
public class MbmsDownloadManagerCallback extends IMbmsDownloadManagerCallback.Stub {
+ /**
+ * Indicates that the middleware has encountered an asynchronous error.
+ * @param errorCode Any error code listed in {@link MbmsException}
+ * @param message A message, intended for debugging purposes, describing the error in further
+ * detail.
+ * @throws RemoteException
+ */
@Override
public void error(int errorCode, String message) throws RemoteException {
// default implementation empty
/**
* Called to indicate published File Services have changed.
*
- * This will only be called after the application has requested
- * a list of file services and specified a service class list
- * of interest AND the results of a subsequent getFileServices
- * call with the same service class list would return different
- * results.
- *
- * @param services a List of FileServiceInfos
+ * This will only be called after the application has requested a list of file services and
+ * specified a service class list of interest via
+ * {@link MbmsDownloadManager#getFileServices(List)}. If there are subsequent calls to
+ * {@link MbmsDownloadManager#getFileServices(List)}, this method may not be called again if
+ * the list of service classes would remain the same.
*
+ * @param services The most recently updated list of available file services.
*/
@Override
public void fileServicesUpdated(List<FileServiceInfo> services) throws RemoteException {
package android.telephony.mbms;
+import android.annotation.SystemApi;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.MbmsDownloadManager;
-import android.telephony.mbms.vendor.VendorIntents;
+import android.telephony.mbms.vendor.VendorUtils;
import android.util.Log;
import java.io.File;
import java.util.UUID;
/**
+ * The {@link BroadcastReceiver} responsible for handling intents sent from the middleware. Apps
+ * that wish to download using MBMS APIs should declare this class in their AndroidManifest.xml as
+ * follows:
+<pre>{@code
+<receiver
+ android:name="android.telephony.mbms.MbmsDownloadReceiver"
+ android:permission="android.permission.SEND_EMBMS_INTENTS"
+ android:enabled="true"
+ android:exported="true">
+</receiver>}</pre>
* @hide
*/
public class MbmsDownloadReceiver extends BroadcastReceiver {
+ /** @hide */
public static final String DOWNLOAD_TOKEN_SUFFIX = ".download_token";
+ /** @hide */
public static final String MBMS_FILE_PROVIDER_META_DATA_KEY = "mbms-file-provider-authority";
/**
- * TODO: @SystemApi all these result codes
* Indicates that the requested operation completed without error.
+ * @hide
*/
+ //@SystemApi
public static final int RESULT_OK = 0;
/**
* Indicates that the intent sent had an invalid action. This will be the result if
* {@link Intent#getAction()} returns anything other than
- * {@link VendorIntents#ACTION_DOWNLOAD_RESULT_INTERNAL},
- * {@link VendorIntents#ACTION_FILE_DESCRIPTOR_REQUEST}, or
- * {@link VendorIntents#ACTION_CLEANUP}.
+ * {@link VendorUtils#ACTION_DOWNLOAD_RESULT_INTERNAL},
+ * {@link VendorUtils#ACTION_FILE_DESCRIPTOR_REQUEST}, or
+ * {@link VendorUtils#ACTION_CLEANUP}.
* This is a fatal result code and no result extras should be expected.
+ * @hide
*/
+ //@SystemApi
public static final int RESULT_INVALID_ACTION = 1;
/**
* Indicates that the intent was missing some required extras.
* This is a fatal result code and no result extras should be expected.
+ * @hide
*/
+ //@SystemApi
public static final int RESULT_MALFORMED_INTENT = 2;
/**
- * Indicates that the supplied value for {@link VendorIntents#EXTRA_TEMP_FILE_ROOT}
+ * Indicates that the supplied value for {@link VendorUtils#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.
+ * @hide
*/
+ //@SystemApi
public static final int RESULT_BAD_TEMP_FILE_ROOT = 3;
/**
* Indicates that the manager was unable to move the completed download to its final location.
* This is a fatal result code and no result extras should be expected.
+ * @hide
*/
+ //@SystemApi
public static final int RESULT_DOWNLOAD_FINALIZATION_ERROR = 4;
/**
* descriptors.
* This is a non-fatal result code -- some file descriptors may still be generated, but there
* is no guarantee that they will be the same number as requested.
+ * @hide
*/
+ //@SystemApi
public static final int RESULT_TEMP_FILE_GENERATION_ERROR = 5;
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;
-
private String mFileProviderAuthorityCache = null;
private String mMiddlewarePackageNameCache = null;
+ /** @hide */
@Override
public void onReceive(Context context, Intent intent) {
if (!verifyIntentContents(context, intent)) {
setResultCode(RESULT_MALFORMED_INTENT);
return;
}
- if (!Objects.equals(intent.getStringExtra(VendorIntents.EXTRA_TEMP_FILE_ROOT),
+ if (!Objects.equals(intent.getStringExtra(VendorUtils.EXTRA_TEMP_FILE_ROOT),
MbmsTempFileProvider.getEmbmsTempFileDir(context).getPath())) {
setResultCode(RESULT_BAD_TEMP_FILE_ROOT);
return;
}
- if (VendorIntents.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
+ if (VendorUtils.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
moveDownloadedFile(context, intent);
cleanupPostMove(context, intent);
- } else if (VendorIntents.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
+ } else if (VendorUtils.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
generateTempFiles(context, intent);
- } else if (VendorIntents.ACTION_CLEANUP.equals(intent.getAction())) {
+ } else if (VendorUtils.ACTION_CLEANUP.equals(intent.getAction())) {
cleanupTempFiles(context, intent);
} else {
setResultCode(RESULT_INVALID_ACTION);
}
private boolean verifyIntentContents(Context context, Intent intent) {
- if (VendorIntents.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
+ if (VendorUtils.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(VendorIntents.EXTRA_REQUEST)) {
+ if (!intent.hasExtra(VendorUtils.EXTRA_REQUEST)) {
Log.w(LOG_TAG, "Download result did not include the associated request. Ignoring.");
return false;
}
- if (!intent.hasExtra(VendorIntents.EXTRA_TEMP_FILE_ROOT)) {
+ if (!intent.hasExtra(VendorUtils.EXTRA_TEMP_FILE_ROOT)) {
Log.w(LOG_TAG, "Download result did not include the temp file root. Ignoring.");
return false;
}
"Ignoring.");
return false;
}
- if (!intent.hasExtra(VendorIntents.EXTRA_FINAL_URI)) {
+ if (!intent.hasExtra(VendorUtils.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(VendorIntents.EXTRA_REQUEST);
+ DownloadRequest request = intent.getParcelableExtra(VendorUtils.EXTRA_REQUEST);
String expectedTokenFileName = request.getHash() + DOWNLOAD_TOKEN_SUFFIX;
File expectedTokenFile = new File(
MbmsUtils.getEmbmsTempFileDirForService(context, request.getFileServiceId()),
"Expected " + expectedTokenFile);
return false;
}
- } else if (VendorIntents.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
- if (!intent.hasExtra(VendorIntents.EXTRA_SERVICE_INFO)) {
+ } else if (VendorUtils.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
+ if (!intent.hasExtra(VendorUtils.EXTRA_SERVICE_INFO)) {
Log.w(LOG_TAG, "Temp file request did not include the associated service info." +
" Ignoring.");
return false;
}
- if (!intent.hasExtra(VendorIntents.EXTRA_TEMP_FILE_ROOT)) {
+ if (!intent.hasExtra(VendorUtils.EXTRA_TEMP_FILE_ROOT)) {
Log.w(LOG_TAG, "Download result did not include the temp file root. Ignoring.");
return false;
}
- } else if (VendorIntents.ACTION_CLEANUP.equals(intent.getAction())) {
- if (!intent.hasExtra(VendorIntents.EXTRA_SERVICE_INFO)) {
+ } else if (VendorUtils.ACTION_CLEANUP.equals(intent.getAction())) {
+ if (!intent.hasExtra(VendorUtils.EXTRA_SERVICE_INFO)) {
Log.w(LOG_TAG, "Cleanup request did not include the associated service info." +
" Ignoring.");
return false;
}
- if (!intent.hasExtra(VendorIntents.EXTRA_TEMP_FILE_ROOT)) {
+ if (!intent.hasExtra(VendorUtils.EXTRA_TEMP_FILE_ROOT)) {
Log.w(LOG_TAG, "Cleanup request did not include the temp file root. Ignoring.");
return false;
}
- if (!intent.hasExtra(VendorIntents.EXTRA_TEMP_FILES_IN_USE)) {
+ if (!intent.hasExtra(VendorUtils.EXTRA_TEMP_FILES_IN_USE)) {
Log.w(LOG_TAG, "Cleanup request did not include the list of temp files in use. " +
"Ignoring.");
return false;
}
private void moveDownloadedFile(Context context, Intent intent) {
- DownloadRequest request = intent.getParcelableExtra(VendorIntents.EXTRA_REQUEST);
+ DownloadRequest request = intent.getParcelableExtra(VendorUtils.EXTRA_REQUEST);
Intent intentForApp = request.getIntentForApp();
int result = intent.getIntExtra(MbmsDownloadManager.EXTRA_RESULT,
}
Uri destinationUri = request.getDestinationUri();
- Uri finalTempFile = intent.getParcelableExtra(VendorIntents.EXTRA_FINAL_URI);
+ Uri finalTempFile = intent.getParcelableExtra(VendorUtils.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);
}
private void cleanupPostMove(Context context, Intent intent) {
- DownloadRequest request = intent.getParcelableExtra(VendorIntents.EXTRA_REQUEST);
+ DownloadRequest request = intent.getParcelableExtra(VendorUtils.EXTRA_REQUEST);
if (request == null) {
Log.w(LOG_TAG, "Intent does not include a DownloadRequest. Ignoring.");
return;
}
- List<Uri> tempFiles = intent.getParcelableExtra(VendorIntents.EXTRA_TEMP_LIST);
+ List<Uri> tempFiles = intent.getParcelableExtra(VendorUtils.EXTRA_TEMP_LIST);
if (tempFiles == null) {
return;
}
private void generateTempFiles(Context context, Intent intent) {
FileServiceInfo serviceInfo =
- intent.getParcelableExtra(VendorIntents.EXTRA_SERVICE_INFO);
+ intent.getParcelableExtra(VendorUtils.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(VendorIntents.EXTRA_FD_COUNT, 0);
- List<Uri> pausedList = intent.getParcelableExtra(VendorIntents.EXTRA_PAUSED_LIST);
+ int fdCount = intent.getIntExtra(VendorUtils.EXTRA_FD_COUNT, 0);
+ List<Uri> pausedList = intent.getParcelableExtra(VendorUtils.EXTRA_PAUSED_LIST);
if (fdCount == 0 && (pausedList == null || pausedList.size() == 0)) {
Log.i(LOG_TAG, "No temp files actually requested. Ending.");
generateUrisForPausedFiles(context, serviceInfo, pausedList);
Bundle result = new Bundle();
- result.putParcelableArrayList(VendorIntents.EXTRA_FREE_URI_LIST, freshTempFiles);
- result.putParcelableArrayList(VendorIntents.EXTRA_PAUSED_URI_LIST, pausedFiles);
+ result.putParcelableArrayList(VendorUtils.EXTRA_FREE_URI_LIST, freshTempFiles);
+ result.putParcelableArrayList(VendorUtils.EXTRA_PAUSED_URI_LIST, pausedFiles);
setResultCode(RESULT_OK);
setResultExtras(result);
}
private void cleanupTempFiles(Context context, Intent intent) {
FileServiceInfo serviceInfo =
- intent.getParcelableExtra(VendorIntents.EXTRA_SERVICE_INFO);
+ intent.getParcelableExtra(VendorUtils.EXTRA_SERVICE_INFO);
File tempFileDir = MbmsUtils.getEmbmsTempFileDirForService(context,
serviceInfo.getServiceId());
final List<Uri> filesInUse =
- intent.getParcelableArrayListExtra(VendorIntents.EXTRA_TEMP_FILES_IN_USE);
+ intent.getParcelableArrayListExtra(VendorUtils.EXTRA_TEMP_FILES_IN_USE);
File[] filesToDelete = tempFileDir.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
/**
* Indicates that the app attempted to perform an operation on an instance of
- * TODO: link android.telephony.MbmsDownloadManager or
+ * TODO link android.telephony.MbmsDownloadManager or
* {@link android.telephony.MbmsStreamingManager} without being bound to the middleware.
*/
public static final int ERROR_MIDDLEWARE_NOT_BOUND = 2;
/**
* Indicates that the app tried to create more than one instance each of
* {@link android.telephony.MbmsStreamingManager} or
- * TODO: link android.telephony.MbmsDownloadManager
+ * TODO link android.telephony.MbmsDownloadManager
*/
public static final int ERROR_DUPLICATE_INITIALIZE = 101;
/** Indicates that the app is not authorized to access media via MBMS.*/
/**
* Indicates the errors that are applicable only to the file-download use-case
- * TODO: unhide
* @hide
*/
public static class DownloadErrors {
+ private DownloadErrors() { }
/**
* Indicates that the app is not allowed to change the temp file root at this time due to
* outstanding download requests.
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.net.Uri;
-import android.os.Bundle;
import android.os.ParcelFileDescriptor;
+import android.telephony.MbmsDownloadManager;
import java.io.File;
import java.io.FileNotFoundException;
* @hide
*/
public class MbmsTempFileProvider extends ContentProvider {
- public static final String DEFAULT_TOP_LEVEL_TEMP_DIRECTORY = "androidMbmsTempFileRoot";
public static final String TEMP_FILE_ROOT_PREF_FILE_NAME = "MbmsTempFileRootPrefs";
public static final String TEMP_FILE_ROOT_PREF_NAME = "mbms_temp_file_root";
if (storedTempFileRoot != null) {
return new File(storedTempFileRoot).getCanonicalFile();
} else {
- return new File(context.getFilesDir(), DEFAULT_TOP_LEVEL_TEMP_DIRECTORY)
- .getCanonicalFile();
+ return new File(context.getFilesDir(),
+ MbmsDownloadManager.DEFAULT_TOP_LEVEL_TEMP_DIRECTORY).getCanonicalFile();
}
} catch (IOException e) {
throw new RuntimeException("Unable to canonicalize temp file root path " + e);
/**
* Describes a cell-broadcast service. This class should not be instantiated directly -- use
- * {@link StreamingServiceInfo} or FileServiceInfo TODO: add link once that's unhidden
+ * {@link StreamingServiceInfo} or TODO link FileServiceInfo
* @hide
*/
public class ServiceInfo {
package android.telephony.mbms;
+import android.annotation.SystemApi;
import android.content.ContentResolver;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.mbms.vendor.VendorUtils;
-/** @hide */
+/**
+ * Wrapper for a pair of {@link Uri}s that describe a temp file used by the middleware to
+ * download files via cell-broadcast.
+ * @hide
+ */
+//@SystemApi
public class UriPathPair implements Parcelable {
private final Uri mFilePathUri;
private final Uri mContentUri;
}
/** @hide */
- protected UriPathPair(Parcel in) {
+ private UriPathPair(Parcel in) {
mFilePathUri = in.readParcelable(Uri.class.getClassLoader());
mContentUri = in.readParcelable(Uri.class.getClassLoader());
}
}
};
- /** future systemapi */
+ /**
+ * Returns the file-path {@link Uri}. This has scheme {@code file} and points to the actual
+ * location on disk where the temp file resides. Use this when sending {@link Uri}s back to the
+ * app in the intents in {@link VendorUtils}.
+ * @return A {@code file} {@link Uri}.
+ */
public Uri getFilePathUri() {
return mFilePathUri;
}
- /** future systemapi */
+ /**
+ * Returns the content {@link Uri} that may be used with
+ * {@link ContentResolver#openFileDescriptor(Uri, String)} to obtain a
+ * {@link android.os.ParcelFileDescriptor} to a temp file to write to. This {@link Uri} will
+ * expire if the middleware process dies.
+ * @return A {@code content} {@link Uri}
+ */
public Uri getContentUri() {
return mContentUri;
}
package android.telephony.mbms.vendor;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.content.Intent;
import android.os.RemoteException;
import android.telephony.mbms.DownloadProgressListener;
import android.telephony.mbms.DownloadRequest;
import java.util.List;
/**
- * Base class for MbmsDownloadService. The middleware should extend this base class rather than
- * the aidl stub for compatibility
+ * Base class for MbmsDownloadService. The middleware should return an instance of this object from
+ * its {@link android.app.Service#onBind(Intent)} method.
* @hide
- * TODO: future systemapi
*/
+//@SystemApi
public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
/**
* Initialize the download service for this app and subId, registering the listener.
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.content.Intent;
import android.net.Uri;
import android.os.Binder;
import android.os.RemoteException;
import java.util.List;
/**
+ * Base class for MBMS streaming services. The middleware should return an instance of this
+ * object from its {@link android.app.Service#onBind(Intent)} method.
* @hide
*/
//@SystemApi
package android.telephony.mbms.vendor;
+import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import java.util.List;
/**
+ * Contains constants and utility methods for MBMS Download middleware apps to communicate with
+ * frontend apps.
* @hide
- * TODO: future systemapi
*/
-public class VendorIntents {
+//@SystemApi
+public class VendorUtils {
/**
* The MBMS middleware should send this when a download of single file has completed or
/**
* 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.
+ * @param packageName The package name of the 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;
- }
+ public static ComponentName getAppReceiverFromPackageName(Context context, String packageName) {
+ 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;
}