Merge changes from topics "embms-0728-adjustments", "embms-0721-adjustments", "fix-streaming-api", "mock-unhide-embms-streaming" into oc-mr1-dev
* changes: Embms adjustments for 7/28 Embms API adjustments for 7/21 Fix lint errors in the streaming API Mock-un-hide the MBMS streaming APIs
This commit is contained in:
@@ -18,19 +18,19 @@ package android.telephony;
|
|||||||
|
|
||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
import android.annotation.SdkConstant;
|
||||||
import android.content.ComponentName;
|
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.content.ServiceConnection;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.ResolveInfo;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.telephony.mbms.DownloadProgressListener;
|
||||||
import android.telephony.mbms.FileInfo;
|
import android.telephony.mbms.FileInfo;
|
||||||
import android.telephony.mbms.DownloadRequest;
|
import android.telephony.mbms.DownloadRequest;
|
||||||
import android.telephony.mbms.IDownloadProgressListener;
|
|
||||||
import android.telephony.mbms.IMbmsDownloadManagerCallback;
|
|
||||||
import android.telephony.mbms.MbmsDownloadManagerCallback;
|
import android.telephony.mbms.MbmsDownloadManagerCallback;
|
||||||
import android.telephony.mbms.MbmsDownloadReceiver;
|
import android.telephony.mbms.MbmsDownloadReceiver;
|
||||||
import android.telephony.mbms.MbmsException;
|
import android.telephony.mbms.MbmsException;
|
||||||
@@ -44,6 +44,7 @@ import java.io.IOException;
|
|||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||||
@@ -52,140 +53,30 @@ 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();
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
// TODO: systemapi
|
||||||
|
@SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
|
||||||
public static final String MBMS_DOWNLOAD_SERVICE_ACTION =
|
public static final String MBMS_DOWNLOAD_SERVICE_ACTION =
|
||||||
"android.telephony.action.EmbmsDownload";
|
"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
|
* Integer extra indicating the result code of the download. One of
|
||||||
* {@link #RESULT_SUCCESSFUL}, {@link #RESULT_EXPIRED}, or {@link #RESULT_CANCELLED}.
|
* {@link #RESULT_SUCCESSFUL}, {@link #RESULT_EXPIRED}, or {@link #RESULT_CANCELLED}.
|
||||||
* TODO: Not systemapi.
|
|
||||||
*/
|
*/
|
||||||
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: Not systemapi.
|
|
||||||
*/
|
*/
|
||||||
public static final String EXTRA_FILE_INFO = "android.telephony.mbms.extra.FILE_INFO";
|
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
|
* Extra containing a single {@link Uri} indicating the location of the successfully
|
||||||
* downloaded file. Set on the intent provided via
|
* downloaded file. Set on the intent provided via
|
||||||
* {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}.
|
* {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}.
|
||||||
* Will always be set to a non-null value if {@link #EXTRA_RESULT} is set to
|
* Will always be set to a non-null value if {@link #EXTRA_RESULT} is set to
|
||||||
* {@link #RESULT_SUCCESSFUL}.
|
* {@link #RESULT_SUCCESSFUL}.
|
||||||
* TODO: Not systemapi.
|
|
||||||
*/
|
*/
|
||||||
public static final String EXTRA_COMPLETED_FILE_URI =
|
public static final String EXTRA_COMPLETED_FILE_URI =
|
||||||
"android.telephony.mbms.extra.COMPLETED_FILE_URI";
|
"android.telephony.mbms.extra.COMPLETED_FILE_URI";
|
||||||
@@ -193,6 +84,7 @@ public class MbmsDownloadManager {
|
|||||||
public static final int RESULT_SUCCESSFUL = 1;
|
public static final int RESULT_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;
|
||||||
|
public static final int RESULT_IO_ERROR = 4;
|
||||||
// TODO - more results!
|
// TODO - more results!
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@@ -207,8 +99,16 @@ public class MbmsDownloadManager {
|
|||||||
public static final int STATUS_PENDING_REPAIR = 3;
|
public static final int STATUS_PENDING_REPAIR = 3;
|
||||||
public static final int STATUS_PENDING_DOWNLOAD_WINDOW = 4;
|
public static final int STATUS_PENDING_DOWNLOAD_WINDOW = 4;
|
||||||
|
|
||||||
|
private static AtomicBoolean sIsInitialized = new AtomicBoolean(false);
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private int mSubscriptionId = INVALID_SUBSCRIPTION_ID;
|
private int mSubscriptionId = INVALID_SUBSCRIPTION_ID;
|
||||||
|
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
|
||||||
|
@Override
|
||||||
|
public void binderDied() {
|
||||||
|
sendErrorToApp(MbmsException.ERROR_MIDDLEWARE_LOST, "Received death notification");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private AtomicReference<IMbmsDownloadService> mService = new AtomicReference<>(null);
|
private AtomicReference<IMbmsDownloadService> mService = new AtomicReference<>(null);
|
||||||
private final MbmsDownloadManagerCallback mCallback;
|
private final MbmsDownloadManagerCallback mCallback;
|
||||||
@@ -236,10 +136,21 @@ public class MbmsDownloadManager {
|
|||||||
*
|
*
|
||||||
* Note that this call will bind a remote service and that may take a bit. The instance of
|
* Note that this call will bind a remote service and that may take a bit. The instance of
|
||||||
* {@link MbmsDownloadManager} that is returned will not be ready for use until
|
* {@link MbmsDownloadManager} that is returned will not be ready for use until
|
||||||
* {@link IMbmsDownloadManagerCallback#middlewareReady()} is called on the provided callback.
|
* {@link MbmsDownloadManagerCallback#middlewareReady()} is called on the provided callback.
|
||||||
* If you attempt to use the manager before it is ready, a {@link MbmsException} will be thrown.
|
* If you attempt to use the manager before it is ready, a {@link MbmsException} will be thrown.
|
||||||
*
|
*
|
||||||
* This also may throw an {@link IllegalArgumentException} or a {@link MbmsException}.
|
* This also may throw an {@link IllegalArgumentException} or an {@link IllegalStateException}.
|
||||||
|
*
|
||||||
|
* You may only have one instance of {@link MbmsDownloadManager} per UID. If you call this
|
||||||
|
* method while there is an active instance of {@link MbmsDownloadManager} in your process
|
||||||
|
* (in other words, one that has not had {@link #dispose()} called on it), this method will
|
||||||
|
* throw an {@link MbmsException}. If you call this method in a different process
|
||||||
|
* running under the same UID, an error will be indicated via
|
||||||
|
* {@link MbmsDownloadManagerCallback#error(int, String)}.
|
||||||
|
*
|
||||||
|
* Note that initialization may fail asynchronously. If you wish to try again after you
|
||||||
|
* receive such an asynchronous error, you must call dispose() on the instance of
|
||||||
|
* {@link MbmsDownloadManager} that you received before calling this method again.
|
||||||
*
|
*
|
||||||
* @param context The instance of {@link Context} to use
|
* @param context The instance of {@link Context} to use
|
||||||
* @param listener A callback to get asynchronous error messages and file service updates.
|
* @param listener A callback to get asynchronous error messages and file service updates.
|
||||||
@@ -249,8 +160,16 @@ public class MbmsDownloadManager {
|
|||||||
public static MbmsDownloadManager create(Context context,
|
public static MbmsDownloadManager create(Context context,
|
||||||
MbmsDownloadManagerCallback listener, int subscriptionId)
|
MbmsDownloadManagerCallback listener, int subscriptionId)
|
||||||
throws MbmsException {
|
throws MbmsException {
|
||||||
|
if (!sIsInitialized.compareAndSet(false, true)) {
|
||||||
|
throw new MbmsException(MbmsException.InitializationErrors.ERROR_DUPLICATE_INITIALIZE);
|
||||||
|
}
|
||||||
MbmsDownloadManager mdm = new MbmsDownloadManager(context, listener, subscriptionId);
|
MbmsDownloadManager mdm = new MbmsDownloadManager(context, listener, subscriptionId);
|
||||||
|
try {
|
||||||
mdm.bindAndInitialize();
|
mdm.bindAndInitialize();
|
||||||
|
} catch (MbmsException e) {
|
||||||
|
sIsInitialized.set(false);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
return mdm;
|
return mdm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,16 +185,27 @@ public class MbmsDownloadManager {
|
|||||||
result = downloadService.initialize(mSubscriptionId, mCallback);
|
result = downloadService.initialize(mSubscriptionId, mCallback);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(LOG_TAG, "Service died before initialization");
|
Log.e(LOG_TAG, "Service died before initialization");
|
||||||
|
sIsInitialized.set(false);
|
||||||
return;
|
return;
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
Log.e(LOG_TAG, "Runtime exception during initialization");
|
Log.e(LOG_TAG, "Runtime exception during initialization");
|
||||||
mCallback.error(
|
sendErrorToApp(
|
||||||
MbmsException.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
|
MbmsException.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
|
||||||
e.toString());
|
e.toString());
|
||||||
|
sIsInitialized.set(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result != MbmsException.SUCCESS) {
|
if (result != MbmsException.SUCCESS) {
|
||||||
mCallback.error(result, "Error returned during initialization");
|
sendErrorToApp(result, "Error returned during initialization");
|
||||||
|
sIsInitialized.set(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
downloadService.asBinder().linkToDeath(mDeathRecipient, 0);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
sendErrorToApp(MbmsException.ERROR_MIDDLEWARE_LOST,
|
||||||
|
"Middleware lost during initialization");
|
||||||
|
sIsInitialized.set(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mService.set(downloadService);
|
mService.set(downloadService);
|
||||||
@@ -283,6 +213,7 @@ public class MbmsDownloadManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceDisconnected(ComponentName name) {
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
sIsInitialized.set(false);
|
||||||
mService.set(null);
|
mService.set(null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -292,7 +223,7 @@ public class MbmsDownloadManager {
|
|||||||
* An inspection API to retrieve the list of available
|
* An inspection API to retrieve the list of available
|
||||||
* {@link android.telephony.mbms.FileServiceInfo}s currently being advertised.
|
* {@link android.telephony.mbms.FileServiceInfo}s currently being advertised.
|
||||||
* The results are returned asynchronously via a call to
|
* The results are returned asynchronously via a call to
|
||||||
* {@link IMbmsDownloadManagerCallback#fileServicesUpdated(List)}
|
* {@link MbmsDownloadManagerCallback#fileServicesUpdated(List)}
|
||||||
*
|
*
|
||||||
* The serviceClasses argument lets the app filter on types of programming and is opaque data
|
* The serviceClasses argument lets the app filter on types of programming and is opaque data
|
||||||
* negotiated beforehand between the app and the carrier.
|
* negotiated beforehand between the app and the carrier.
|
||||||
@@ -306,7 +237,7 @@ public class MbmsDownloadManager {
|
|||||||
* {@link MbmsException.StreamingErrors#ERROR_UNABLE_TO_START_SERVICE}
|
* {@link MbmsException.StreamingErrors#ERROR_UNABLE_TO_START_SERVICE}
|
||||||
*
|
*
|
||||||
* @param classList A list of service classes which the app wishes to receive
|
* @param classList A list of service classes which the app wishes to receive
|
||||||
* {@link IMbmsDownloadManagerCallback#fileServicesUpdated(List)} callbacks
|
* {@link MbmsDownloadManagerCallback#fileServicesUpdated(List)} callbacks
|
||||||
* about. Subsequent calls to this method will replace this list of service
|
* about. Subsequent calls to this method will replace this list of service
|
||||||
* classes (i.e. the middleware will no longer send updates for services
|
* classes (i.e. the middleware will no longer send updates for services
|
||||||
* matching classes only in the old list).
|
* matching classes only in the old list).
|
||||||
@@ -336,14 +267,15 @@ public class MbmsDownloadManager {
|
|||||||
* local instance of {@link android.content.SharedPreferences} and by the middleware.
|
* local instance of {@link android.content.SharedPreferences} and by the middleware.
|
||||||
*
|
*
|
||||||
* If this method is not called at least once before calling
|
* If this method is not called at least once before calling
|
||||||
* {@link #download(DownloadRequest, IDownloadCallback)}, the framework
|
* {@link #download(DownloadRequest, DownloadProgressListener)}, the framework
|
||||||
* will default to a directory formed by the concatenation of the app's files directory and
|
* 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 android.telephony.mbms.MbmsTempFileProvider#DEFAULT_TOP_LEVEL_TEMP_DIRECTORY}.
|
||||||
*
|
*
|
||||||
* Before calling this method, the app must cancel all of its pending
|
* Before calling this method, the app must cancel all of its pending
|
||||||
* {@link DownloadRequest}s via {@link #cancelDownload(DownloadRequest)}. If this is not done,
|
* {@link DownloadRequest}s via {@link #cancelDownload(DownloadRequest)}. If this is not done,
|
||||||
* an {@link MbmsException} will be thrown with code
|
* 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
|
* The {@link File} supplied as a root temp file directory must already exist. If not, an
|
||||||
* {@link IllegalArgumentException} will be thrown.
|
* {@link IllegalArgumentException} will be thrown.
|
||||||
@@ -383,6 +315,26 @@ public class MbmsDownloadManager {
|
|||||||
prefs.edit().putString(MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_NAME, filePath).apply();
|
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.
|
* Requests a download of a file that is available via multicast.
|
||||||
*
|
*
|
||||||
@@ -404,7 +356,7 @@ public class MbmsDownloadManager {
|
|||||||
* @param progressListener Optional listener that will be provided progress updates
|
* @param progressListener Optional listener that will be provided progress updates
|
||||||
* if the app is running.
|
* if the app is running.
|
||||||
*/
|
*/
|
||||||
public void download(DownloadRequest request, IDownloadProgressListener progressListener)
|
public void download(DownloadRequest request, DownloadProgressListener progressListener)
|
||||||
throws MbmsException {
|
throws MbmsException {
|
||||||
IMbmsDownloadService downloadService = mService.get();
|
IMbmsDownloadService downloadService = mService.get();
|
||||||
if (downloadService == null) {
|
if (downloadService == null) {
|
||||||
@@ -434,7 +386,7 @@ public class MbmsDownloadManager {
|
|||||||
/**
|
/**
|
||||||
* Returns a list of pending {@link DownloadRequest}s that originated from this application.
|
* Returns a list of pending {@link DownloadRequest}s that originated from this application.
|
||||||
* A pending request is one that was issued via
|
* A pending request is one that was issued via
|
||||||
* {@link #download(DownloadRequest, IDownloadCallback)} but not cancelled through
|
* {@link #download(DownloadRequest, DownloadProgressListener)} but not cancelled through
|
||||||
* {@link #cancelDownload(DownloadRequest)}.
|
* {@link #cancelDownload(DownloadRequest)}.
|
||||||
* @return A list, possibly empty, of {@link DownloadRequest}s
|
* @return A list, possibly empty, of {@link DownloadRequest}s
|
||||||
*/
|
*/
|
||||||
@@ -550,43 +502,15 @@ public class MbmsDownloadManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
downloadService.dispose(mSubscriptionId);
|
downloadService.dispose(mSubscriptionId);
|
||||||
mService.set(null);
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Ignore
|
// Ignore
|
||||||
Log.i(LOG_TAG, "Remote exception while disposing of service");
|
Log.i(LOG_TAG, "Remote exception while disposing of service");
|
||||||
|
} finally {
|
||||||
|
mService.set(null);
|
||||||
|
sIsInitialized.set(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the {@link ComponentName} for the {@link android.content.BroadcastReceiver} that
|
|
||||||
* the various intents from the middleware should be targeted towards.
|
|
||||||
* @param uid The uid of the frontend app.
|
|
||||||
* @return The component name of the receiver that the middleware should send its intents to,
|
|
||||||
* or null if the app didn't declare it in the manifest.
|
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
* future systemapi
|
|
||||||
*/
|
|
||||||
public static ComponentName getAppReceiverFromUid(Context context, int uid) {
|
|
||||||
String[] packageNames = context.getPackageManager().getPackagesForUid(uid);
|
|
||||||
if (packageNames == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String packageName : packageNames) {
|
|
||||||
ComponentName candidate = new ComponentName(packageName,
|
|
||||||
MbmsDownloadReceiver.class.getCanonicalName());
|
|
||||||
Intent queryIntent = new Intent();
|
|
||||||
queryIntent.setComponent(candidate);
|
|
||||||
List<ResolveInfo> receivers =
|
|
||||||
context.getPackageManager().queryBroadcastReceivers(queryIntent, 0);
|
|
||||||
if (receivers != null && receivers.size() > 0) {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeDownloadRequestToken(DownloadRequest request) {
|
private void writeDownloadRequestToken(DownloadRequest request) {
|
||||||
File token = getDownloadRequestTokenPath(request);
|
File token = getDownloadRequestTokenPath(request);
|
||||||
if (!token.getParentFile().exists()) {
|
if (!token.getParentFile().exists()) {
|
||||||
@@ -651,4 +575,12 @@ public class MbmsDownloadManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendErrorToApp(int errorCode, String message) {
|
||||||
|
try {
|
||||||
|
mCallback.error(errorCode, message);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// Ignore, should not happen locally.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,17 @@
|
|||||||
|
|
||||||
package android.telephony;
|
package android.telephony;
|
||||||
|
|
||||||
|
import android.annotation.SdkConstant;
|
||||||
|
import android.annotation.SystemApi;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.Looper;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.telephony.mbms.InternalStreamingManagerCallback;
|
||||||
|
import android.telephony.mbms.InternalStreamingServiceCallback;
|
||||||
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.MbmsUtils;
|
||||||
@@ -31,6 +37,7 @@ import android.telephony.mbms.vendor.IMbmsStreamingService;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||||
@@ -41,21 +48,42 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
|||||||
*/
|
*/
|
||||||
public class MbmsStreamingManager {
|
public class MbmsStreamingManager {
|
||||||
private static final String LOG_TAG = "MbmsStreamingManager";
|
private static final String LOG_TAG = "MbmsStreamingManager";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service action which must be handled by the middleware implementing the MBMS streaming
|
||||||
|
* interface.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SystemApi
|
||||||
|
@SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
|
||||||
public static final String MBMS_STREAMING_SERVICE_ACTION =
|
public static final String MBMS_STREAMING_SERVICE_ACTION =
|
||||||
"android.telephony.action.EmbmsStreaming";
|
"android.telephony.action.EmbmsStreaming";
|
||||||
|
|
||||||
|
private static AtomicBoolean sIsInitialized = new AtomicBoolean(false);
|
||||||
|
|
||||||
private AtomicReference<IMbmsStreamingService> mService = new AtomicReference<>(null);
|
private AtomicReference<IMbmsStreamingService> mService = new AtomicReference<>(null);
|
||||||
private MbmsStreamingManagerCallback mCallbackToApp;
|
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
|
||||||
|
@Override
|
||||||
|
public void binderDied() {
|
||||||
|
sIsInitialized.set(false);
|
||||||
|
sendErrorToApp(MbmsException.ERROR_MIDDLEWARE_LOST, "Received death notification");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private InternalStreamingManagerCallback mInternalCallback;
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private int mSubscriptionId = INVALID_SUBSCRIPTION_ID;
|
private int mSubscriptionId = INVALID_SUBSCRIPTION_ID;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
private MbmsStreamingManager(Context context, MbmsStreamingManagerCallback callback,
|
private MbmsStreamingManager(Context context, MbmsStreamingManagerCallback callback,
|
||||||
int subscriptionId) {
|
int subscriptionId, Handler handler) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mCallbackToApp = callback;
|
|
||||||
mSubscriptionId = subscriptionId;
|
mSubscriptionId = subscriptionId;
|
||||||
|
if (handler == null) {
|
||||||
|
handler = new Handler(Looper.getMainLooper());
|
||||||
|
}
|
||||||
|
mInternalCallback = new InternalStreamingManagerCallback(callback, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,27 +93,62 @@ public class MbmsStreamingManager {
|
|||||||
* main thread. This may throw an {@link MbmsException}, indicating errors that may happen
|
* main thread. This may throw an {@link MbmsException}, indicating errors that may happen
|
||||||
* during the initialization or binding process.
|
* during the initialization or binding process.
|
||||||
*
|
*
|
||||||
|
*
|
||||||
|
* You may only have one instance of {@link MbmsStreamingManager} per UID. If you call this
|
||||||
|
* method while there is an active instance of {@link MbmsStreamingManager} in your process
|
||||||
|
* (in other words, one that has not had {@link #dispose()} called on it), this method will
|
||||||
|
* throw an {@link MbmsException}. If you call this method in a different process
|
||||||
|
* running under the same UID, an error will be indicated via
|
||||||
|
* {@link MbmsStreamingManagerCallback#onError(int, String)}.
|
||||||
|
*
|
||||||
|
* Note that initialization may fail asynchronously. If you wish to try again after you
|
||||||
|
* receive such an asynchronous error, you must call dispose() on the instance of
|
||||||
|
* {@link MbmsStreamingManager} that you received before calling this method again.
|
||||||
|
*
|
||||||
* @param context The {@link Context} to use.
|
* @param context The {@link Context} to use.
|
||||||
* @param callback A callback object on which you wish to receive results of asynchronous
|
* @param callback A callback object on which you wish to receive results of asynchronous
|
||||||
* operations.
|
* operations.
|
||||||
* @param subscriptionId The subscription ID to use.
|
* @param subscriptionId The subscription ID to use.
|
||||||
|
* @param handler The handler you wish to receive callbacks on. If null, callbacks will be
|
||||||
|
* processed on the main looper (in other words, the looper returned from
|
||||||
|
* {@link Looper#getMainLooper()}).
|
||||||
*/
|
*/
|
||||||
public static MbmsStreamingManager create(Context context,
|
public static MbmsStreamingManager create(Context context,
|
||||||
MbmsStreamingManagerCallback callback, int subscriptionId)
|
MbmsStreamingManagerCallback callback, int subscriptionId, Handler handler)
|
||||||
throws MbmsException {
|
throws MbmsException {
|
||||||
MbmsStreamingManager manager = new MbmsStreamingManager(context, callback, subscriptionId);
|
if (!sIsInitialized.compareAndSet(false, true)) {
|
||||||
|
throw new MbmsException(MbmsException.InitializationErrors.ERROR_DUPLICATE_INITIALIZE);
|
||||||
|
}
|
||||||
|
MbmsStreamingManager manager = new MbmsStreamingManager(context, callback,
|
||||||
|
subscriptionId, handler);
|
||||||
|
try {
|
||||||
manager.bindAndInitialize();
|
manager.bindAndInitialize();
|
||||||
|
} catch (MbmsException e) {
|
||||||
|
sIsInitialized.set(false);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new MbmsStreamingManager using the system default data subscription ID.
|
* Create a new MbmsStreamingManager using the system default data subscription ID.
|
||||||
* See {@link #create(Context, MbmsStreamingManagerCallback, int)}.
|
* See {@link #create(Context, MbmsStreamingManagerCallback, int, Handler)}.
|
||||||
|
*/
|
||||||
|
public static MbmsStreamingManager create(Context context,
|
||||||
|
MbmsStreamingManagerCallback callback, Handler handler)
|
||||||
|
throws MbmsException {
|
||||||
|
return create(context, callback, SubscriptionManager.getDefaultSubscriptionId(), handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new MbmsStreamingManager using the system default data subscription ID and
|
||||||
|
* default {@link Handler}.
|
||||||
|
* See {@link #create(Context, MbmsStreamingManagerCallback, int, Handler)}.
|
||||||
*/
|
*/
|
||||||
public static MbmsStreamingManager create(Context context,
|
public static MbmsStreamingManager create(Context context,
|
||||||
MbmsStreamingManagerCallback callback)
|
MbmsStreamingManagerCallback callback)
|
||||||
throws MbmsException {
|
throws MbmsException {
|
||||||
return create(context, callback, SubscriptionManager.getDefaultSubscriptionId());
|
return create(context, callback, SubscriptionManager.getDefaultSubscriptionId(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,17 +158,19 @@ public class MbmsStreamingManager {
|
|||||||
* May throw an {@link IllegalStateException}
|
* May throw an {@link IllegalStateException}
|
||||||
*/
|
*/
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
|
try {
|
||||||
IMbmsStreamingService streamingService = mService.get();
|
IMbmsStreamingService streamingService = mService.get();
|
||||||
if (streamingService == null) {
|
if (streamingService == null) {
|
||||||
// Ignore and return, assume already disposed.
|
// Ignore and return, assume already disposed.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
streamingService.dispose(mSubscriptionId);
|
streamingService.dispose(mSubscriptionId);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Ignore for now
|
// Ignore for now
|
||||||
}
|
} finally {
|
||||||
mService.set(null);
|
mService.set(null);
|
||||||
|
sIsInitialized.set(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,16 +204,17 @@ public class MbmsStreamingManager {
|
|||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(LOG_TAG, "Remote process died");
|
Log.w(LOG_TAG, "Remote process died");
|
||||||
mService.set(null);
|
mService.set(null);
|
||||||
|
sIsInitialized.set(false);
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts streaming a requested service, reporting status to the indicated listener.
|
* Starts streaming a requested service, reporting status to the indicated callback.
|
||||||
* Returns an object used to control that stream. The stream may not be ready for consumption
|
* Returns an object used to control that stream. The stream may not be ready for consumption
|
||||||
* immediately upon return from this method -- wait until the streaming state has been
|
* immediately upon return from this method -- wait until the streaming state has been
|
||||||
* reported via
|
* reported via
|
||||||
* {@link android.telephony.mbms.StreamingServiceCallback#streamStateUpdated(int, int)}
|
* {@link android.telephony.mbms.StreamingServiceCallback#onStreamStateUpdated(int, int)}
|
||||||
*
|
*
|
||||||
* May throw an
|
* May throw an
|
||||||
* {@link MbmsException} containing any of the error codes in
|
* {@link MbmsException} containing any of the error codes in
|
||||||
@@ -158,34 +224,44 @@ public class MbmsStreamingManager {
|
|||||||
*
|
*
|
||||||
* May also throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
|
* May also throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
|
||||||
*
|
*
|
||||||
* Asynchronous errors through the listener include any of the errors in
|
* Asynchronous errors through the callback include any of the errors in
|
||||||
* {@link android.telephony.mbms.MbmsException.GeneralErrors} or
|
* {@link android.telephony.mbms.MbmsException.GeneralErrors} or
|
||||||
* {@link android.telephony.mbms.MbmsException.StreamingErrors}.
|
* {@link android.telephony.mbms.MbmsException.StreamingErrors}.
|
||||||
*
|
*
|
||||||
* @param serviceInfo The information about the service to stream.
|
* @param serviceInfo The information about the service to stream.
|
||||||
* @param listener A listener that'll be called when something about the stream changes.
|
* @param callback A callback that'll be called when something about the stream changes.
|
||||||
|
* @param handler A handler that calls to {@code callback} should be called on. If null,
|
||||||
|
* defaults to the handler provided via
|
||||||
|
* {@link #create(Context, MbmsStreamingManagerCallback, int, Handler)}.
|
||||||
* @return An instance of {@link StreamingService} through which the stream can be controlled.
|
* @return An instance of {@link StreamingService} through which the stream can be controlled.
|
||||||
*/
|
*/
|
||||||
public StreamingService startStreaming(StreamingServiceInfo serviceInfo,
|
public StreamingService startStreaming(StreamingServiceInfo serviceInfo,
|
||||||
StreamingServiceCallback listener) throws MbmsException {
|
StreamingServiceCallback callback, Handler handler) throws MbmsException {
|
||||||
IMbmsStreamingService streamingService = mService.get();
|
IMbmsStreamingService streamingService = mService.get();
|
||||||
if (streamingService == null) {
|
if (streamingService == null) {
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
|
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InternalStreamingServiceCallback serviceCallback = new InternalStreamingServiceCallback(
|
||||||
|
callback, handler == null ? mInternalCallback.getHandler() : handler);
|
||||||
|
|
||||||
|
StreamingService serviceForApp = new StreamingService(
|
||||||
|
mSubscriptionId, streamingService, serviceInfo, serviceCallback);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int returnCode = streamingService.startStreaming(
|
int returnCode = streamingService.startStreaming(
|
||||||
mSubscriptionId, serviceInfo.getServiceId(), listener);
|
mSubscriptionId, serviceInfo.getServiceId(), serviceCallback);
|
||||||
if (returnCode != MbmsException.SUCCESS) {
|
if (returnCode != MbmsException.SUCCESS) {
|
||||||
throw new MbmsException(returnCode);
|
throw new MbmsException(returnCode);
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(LOG_TAG, "Remote process died");
|
Log.w(LOG_TAG, "Remote process died");
|
||||||
mService.set(null);
|
mService.set(null);
|
||||||
|
sIsInitialized.set(false);
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new StreamingService(mSubscriptionId, streamingService, serviceInfo, listener);
|
return serviceForApp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindAndInitialize() throws MbmsException {
|
private void bindAndInitialize() throws MbmsException {
|
||||||
@@ -197,19 +273,34 @@ public class MbmsStreamingManager {
|
|||||||
IMbmsStreamingService.Stub.asInterface(service);
|
IMbmsStreamingService.Stub.asInterface(service);
|
||||||
int result;
|
int result;
|
||||||
try {
|
try {
|
||||||
result = streamingService.initialize(mCallbackToApp, mSubscriptionId);
|
result = streamingService.initialize(mInternalCallback,
|
||||||
|
mSubscriptionId);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(LOG_TAG, "Service died before initialization");
|
Log.e(LOG_TAG, "Service died before initialization");
|
||||||
|
sendErrorToApp(
|
||||||
|
MbmsException.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
|
||||||
|
e.toString());
|
||||||
|
sIsInitialized.set(false);
|
||||||
return;
|
return;
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
Log.e(LOG_TAG, "Runtime exception during initialization");
|
Log.e(LOG_TAG, "Runtime exception during initialization");
|
||||||
mCallbackToApp.error(
|
sendErrorToApp(
|
||||||
MbmsException.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
|
MbmsException.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
|
||||||
e.toString());
|
e.toString());
|
||||||
|
sIsInitialized.set(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result != MbmsException.SUCCESS) {
|
if (result != MbmsException.SUCCESS) {
|
||||||
mCallbackToApp.error(result, "Error returned during initialization");
|
sendErrorToApp(result, "Error returned during initialization");
|
||||||
|
sIsInitialized.set(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
streamingService.asBinder().linkToDeath(mDeathRecipient, 0);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
sendErrorToApp(MbmsException.ERROR_MIDDLEWARE_LOST,
|
||||||
|
"Middleware lost during initialization");
|
||||||
|
sIsInitialized.set(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mService.set(streamingService);
|
mService.set(streamingService);
|
||||||
@@ -217,8 +308,17 @@ public class MbmsStreamingManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceDisconnected(ComponentName name) {
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
sIsInitialized.set(false);
|
||||||
mService.set(null);
|
mService.set(null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendErrorToApp(int errorCode, String message) {
|
||||||
|
try {
|
||||||
|
mInternalCallback.error(errorCode, message);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// Ignore, should not happen locally.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package android.telephony.mbms;
|
package android.telephony.mbms;
|
||||||
|
|
||||||
|
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.
|
||||||
* @hide
|
* @hide
|
||||||
@@ -38,8 +40,9 @@ public class DownloadProgressListener extends IDownloadProgressListener.Stub {
|
|||||||
* @param currentDecodedSize is the number of bytes that have been decoded.
|
* @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.
|
* @param fullDecodedSize is the total number of bytes that make up the final decoded content.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void progress(DownloadRequest request, FileInfo fileInfo,
|
public void progress(DownloadRequest request, FileInfo fileInfo,
|
||||||
int currentDownloadSize, int fullDownloadSize,
|
int currentDownloadSize, int fullDownloadSize,
|
||||||
int currentDecodedSize, int fullDecodedSize) {
|
int currentDecodedSize, int fullDecodedSize) throws RemoteException {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import android.util.Log;
|
|||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
@@ -77,12 +78,18 @@ public class DownloadRequest implements Parcelable {
|
|||||||
private String appIntent;
|
private String appIntent;
|
||||||
private int version = CURRENT_VERSION;
|
private int version = CURRENT_VERSION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the service from which the download request to be built will download from.
|
||||||
|
* @param serviceInfo
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public Builder setServiceInfo(FileServiceInfo serviceInfo) {
|
public Builder setServiceInfo(FileServiceInfo serviceInfo) {
|
||||||
fileServiceId = serviceInfo.getServiceId();
|
fileServiceId = serviceInfo.getServiceId();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Set the service ID for the download request. For use by the middleware only.
|
||||||
* @hide
|
* @hide
|
||||||
* TODO: systemapi
|
* TODO: systemapi
|
||||||
*/
|
*/
|
||||||
@@ -91,11 +98,23 @@ public class DownloadRequest implements Parcelable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the source URI for the download request to be built.
|
||||||
|
* @param source
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public Builder setSource(Uri source) {
|
public Builder setSource(Uri source) {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the destination URI for the download request to be built. The middleware should
|
||||||
|
* not set this directly.
|
||||||
|
* @param dest A URI obtained from {@link Uri#fromFile(File)}, denoting the requested
|
||||||
|
* final destination of the download.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public Builder setDest(Uri dest) {
|
public Builder setDest(Uri dest) {
|
||||||
if (dest.toString().length() > MAX_DESTINATION_URI_SIZE) {
|
if (dest.toString().length() > MAX_DESTINATION_URI_SIZE) {
|
||||||
throw new IllegalArgumentException("Destination uri must not exceed length " +
|
throw new IllegalArgumentException("Destination uri must not exceed length " +
|
||||||
@@ -105,11 +124,25 @@ public class DownloadRequest implements Parcelable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setSubscriptionId(int sub) {
|
/**
|
||||||
this.subscriptionId = sub;
|
* Set the subscription ID on which the file(s) should be downloaded.
|
||||||
|
* @param subscriptionId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Builder setSubscriptionId(int subscriptionId) {
|
||||||
|
this.subscriptionId = subscriptionId;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the {@link Intent} that should be sent when the download completes or fails. This
|
||||||
|
* should be an intent with a explicit {@link android.content.ComponentName} targeted to a
|
||||||
|
* {@link android.content.BroadcastReceiver} in the app's package.
|
||||||
|
*
|
||||||
|
* The middleware should not use this method.
|
||||||
|
* @param intent
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public Builder setAppIntent(Intent intent) {
|
public Builder setAppIntent(Intent intent) {
|
||||||
this.appIntent = intent.toUri(0);
|
this.appIntent = intent.toUri(0);
|
||||||
if (this.appIntent.length() > MAX_APP_INTENT_SIZE) {
|
if (this.appIntent.length() > MAX_APP_INTENT_SIZE) {
|
||||||
@@ -120,7 +153,12 @@ public class DownloadRequest implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For use by middleware only
|
* For use by the middleware to set the byte array of opaque data. The opaque data
|
||||||
|
* includes information about the download request that is used by the client app and the
|
||||||
|
* manager code, but is irrelevant to the middleware.
|
||||||
|
* @param data A byte array, the contents of which should have been originally obtained
|
||||||
|
* from {@link DownloadRequest#getOpaqueData()}.
|
||||||
|
* @return
|
||||||
* TODO: systemapi
|
* TODO: systemapi
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@@ -201,22 +239,40 @@ public class DownloadRequest implements Parcelable {
|
|||||||
out.writeInt(version);
|
out.writeInt(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The ID of the file service to download from.
|
||||||
|
*/
|
||||||
public String getFileServiceId() {
|
public String getFileServiceId() {
|
||||||
return fileServiceId;
|
return fileServiceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The source URI to download from
|
||||||
|
*/
|
||||||
public Uri getSourceUri() {
|
public Uri getSourceUri() {
|
||||||
return sourceUri;
|
return sourceUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For use by the client app only.
|
||||||
|
* @return The URI of the final destination of the download.
|
||||||
|
*/
|
||||||
public Uri getDestinationUri() {
|
public Uri getDestinationUri() {
|
||||||
return destinationUri;
|
return destinationUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The subscription ID on which to perform MBMS operations.
|
||||||
|
*/
|
||||||
public int getSubscriptionId() {
|
public int getSubscriptionId() {
|
||||||
return subscriptionId;
|
return subscriptionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For internal use -- returns the intent to send to the app after download completion or
|
||||||
|
* failure.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
public Intent getIntentForApp() {
|
public Intent getIntentForApp() {
|
||||||
try {
|
try {
|
||||||
return Intent.parseUri(serializedResultIntentForApp, 0);
|
return Intent.parseUri(serializedResultIntentForApp, 0);
|
||||||
@@ -226,6 +282,10 @@ public class DownloadRequest implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* For use by the middleware only. The byte array returned from this method should be
|
||||||
|
* persisted and sent back to the app upon download completion or failure by passing it into
|
||||||
|
* {@link Builder#setOpaqueData(byte[])}.
|
||||||
|
* @return A byte array of opaque data to persist.
|
||||||
* @hide
|
* @hide
|
||||||
* TODO: systemapi
|
* TODO: systemapi
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -38,16 +38,6 @@ public class FileInfo implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
private final String mimeType;
|
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 =
|
public static final Parcelable.Creator<FileInfo> CREATOR =
|
||||||
new Parcelable.Creator<FileInfo>() {
|
new Parcelable.Creator<FileInfo>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -61,29 +51,24 @@ public class FileInfo implements Parcelable {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public FileInfo(Uri uri, String mimeType, long size, byte[] md5Hash) {
|
/**
|
||||||
|
* @hide
|
||||||
|
* TODO: systemapi
|
||||||
|
*/
|
||||||
|
public FileInfo(Uri uri, String mimeType) {
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
this.mimeType = mimeType;
|
this.mimeType = mimeType;
|
||||||
this.size = size;
|
|
||||||
this.md5Hash = md5Hash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileInfo(Parcel in) {
|
private FileInfo(Parcel in) {
|
||||||
uri = in.readParcelable(null);
|
uri = in.readParcelable(null);
|
||||||
mimeType = in.readString();
|
mimeType = in.readString();
|
||||||
size = in.readLong();
|
|
||||||
int arraySize = in.readInt();
|
|
||||||
md5Hash = new byte[arraySize];
|
|
||||||
in.readByteArray(md5Hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
dest.writeParcelable(uri, flags);
|
dest.writeParcelable(uri, flags);
|
||||||
dest.writeString(mimeType);
|
dest.writeString(mimeType);
|
||||||
dest.writeLong(size);
|
|
||||||
dest.writeInt(md5Hash.length);
|
|
||||||
dest.writeByteArray(md5Hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -98,12 +83,4 @@ public class FileInfo implements Parcelable {
|
|||||||
public String getMimeType() {
|
public String getMimeType() {
|
||||||
return mimeType;
|
return mimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getMd5Hash() {
|
|
||||||
return md5Hash;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import java.util.Map;
|
|||||||
public class FileServiceInfo extends ServiceInfo implements Parcelable {
|
public class FileServiceInfo extends ServiceInfo implements Parcelable {
|
||||||
private final List<FileInfo> files;
|
private final List<FileInfo> files;
|
||||||
|
|
||||||
|
/** @hide TODO: systemapi */
|
||||||
public FileServiceInfo(Map<Locale, String> newNames, String newClassName,
|
public FileServiceInfo(Map<Locale, String> newNames, String newClassName,
|
||||||
List<Locale> newLocales, String newServiceId, Date start, Date end,
|
List<Locale> newLocales, String newServiceId, Date start, Date end,
|
||||||
List<FileInfo> newFiles) {
|
List<FileInfo> newFiles) {
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* 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.os.Handler;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.telephony.mbms.IMbmsStreamingManagerCallback;
|
||||||
|
import android.telephony.mbms.MbmsStreamingManagerCallback;
|
||||||
|
import android.telephony.mbms.StreamingServiceInfo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public class InternalStreamingManagerCallback extends IMbmsStreamingManagerCallback.Stub {
|
||||||
|
private final Handler mHandler;
|
||||||
|
private final MbmsStreamingManagerCallback mAppCallback;
|
||||||
|
|
||||||
|
public InternalStreamingManagerCallback(MbmsStreamingManagerCallback appCallback,
|
||||||
|
Handler handler) {
|
||||||
|
mAppCallback = appCallback;
|
||||||
|
mHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(int errorCode, String message) throws RemoteException {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mAppCallback.onError(errorCode, message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void streamingServicesUpdated(List<StreamingServiceInfo> services)
|
||||||
|
throws RemoteException {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mAppCallback.onStreamingServicesUpdated(services);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void middlewareReady() throws RemoteException {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mAppCallback.onMiddlewareReady();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public Handler getHandler() {
|
||||||
|
return mHandler;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* 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.os.Handler;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public class InternalStreamingServiceCallback extends IStreamingServiceCallback.Stub {
|
||||||
|
private final StreamingServiceCallback mAppCallback;
|
||||||
|
private final Handler mHandler;
|
||||||
|
|
||||||
|
public InternalStreamingServiceCallback(StreamingServiceCallback appCallback, Handler handler) {
|
||||||
|
mAppCallback = appCallback;
|
||||||
|
mHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(int errorCode, String message) throws RemoteException {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mAppCallback.onError(errorCode, message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void streamStateUpdated(int state, int reason) throws RemoteException {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mAppCallback.onStreamStateUpdated(state, reason);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mediaDescriptionUpdated() throws RemoteException {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mAppCallback.onMediaDescriptionUpdated();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void broadcastSignalStrengthUpdated(int signalStrength) throws RemoteException {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mAppCallback.onBroadcastSignalStrengthUpdated(signalStrength);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void streamMethodUpdated(int methodType) throws RemoteException {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mAppCallback.onStreamMethodUpdated(methodType);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
package android.telephony.mbms;
|
package android.telephony.mbms;
|
||||||
|
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.telephony.MbmsDownloadManager;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,12 +27,8 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class MbmsDownloadManagerCallback extends IMbmsDownloadManagerCallback.Stub {
|
public class MbmsDownloadManagerCallback extends IMbmsDownloadManagerCallback.Stub {
|
||||||
|
|
||||||
public final static int ERROR_CARRIER_NOT_SUPPORTED = 1;
|
@Override
|
||||||
public final static int ERROR_UNABLE_TO_INITIALIZE = 2;
|
public void error(int errorCode, String message) throws RemoteException {
|
||||||
public final static int ERROR_UNABLE_TO_ALLOCATE_MEMORY = 3;
|
|
||||||
|
|
||||||
|
|
||||||
public void error(int errorCode, String message) {
|
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +44,8 @@ public class MbmsDownloadManagerCallback extends IMbmsDownloadManagerCallback.St
|
|||||||
* @param services a List of FileServiceInfos
|
* @param services a List of FileServiceInfos
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void fileServicesUpdated(List<FileServiceInfo> services) {
|
@Override
|
||||||
|
public void fileServicesUpdated(List<FileServiceInfo> services) throws RemoteException {
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ public class MbmsDownloadManagerCallback extends IMbmsDownloadManagerCallback.St
|
|||||||
* or {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}
|
* or {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void middlewareReady() {
|
public void middlewareReady() throws RemoteException {
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import android.content.pm.PackageManager;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.telephony.MbmsDownloadManager;
|
import android.telephony.MbmsDownloadManager;
|
||||||
|
import android.telephony.mbms.vendor.VendorIntents;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.File;
|
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
|
* Indicates that the intent sent had an invalid action. This will be the result if
|
||||||
* {@link Intent#getAction()} returns anything other than
|
* {@link Intent#getAction()} returns anything other than
|
||||||
* {@link MbmsDownloadManager#ACTION_DOWNLOAD_RESULT_INTERNAL},
|
* {@link VendorIntents#ACTION_DOWNLOAD_RESULT_INTERNAL},
|
||||||
* {@link MbmsDownloadManager#ACTION_FILE_DESCRIPTOR_REQUEST}, or
|
* {@link VendorIntents#ACTION_FILE_DESCRIPTOR_REQUEST}, or
|
||||||
* {@link MbmsDownloadManager#ACTION_CLEANUP}.
|
* {@link VendorIntents#ACTION_CLEANUP}.
|
||||||
* This is a fatal result code and no result extras should be expected.
|
* This is a fatal result code and no result extras should be expected.
|
||||||
*/
|
*/
|
||||||
public static final int RESULT_INVALID_ACTION = 1;
|
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;
|
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.
|
* does not match what the app has stored.
|
||||||
* This is a fatal result code and no result extras should be expected.
|
* 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);
|
setResultCode(RESULT_MALFORMED_INTENT);
|
||||||
return;
|
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())) {
|
MbmsTempFileProvider.getEmbmsTempFileDir(context).getPath())) {
|
||||||
setResultCode(RESULT_BAD_TEMP_FILE_ROOT);
|
setResultCode(RESULT_BAD_TEMP_FILE_ROOT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MbmsDownloadManager.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
|
if (VendorIntents.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
|
||||||
moveDownloadedFile(context, intent);
|
moveDownloadedFile(context, intent);
|
||||||
cleanupPostMove(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);
|
generateTempFiles(context, intent);
|
||||||
} else if (MbmsDownloadManager.ACTION_CLEANUP.equals(intent.getAction())) {
|
} else if (VendorIntents.ACTION_CLEANUP.equals(intent.getAction())) {
|
||||||
cleanupTempFiles(context, intent);
|
cleanupTempFiles(context, intent);
|
||||||
} else {
|
} else {
|
||||||
setResultCode(RESULT_INVALID_ACTION);
|
setResultCode(RESULT_INVALID_ACTION);
|
||||||
@@ -123,16 +124,16 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean verifyIntentContents(Context context, Intent intent) {
|
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)) {
|
if (!intent.hasExtra(MbmsDownloadManager.EXTRA_RESULT)) {
|
||||||
Log.w(LOG_TAG, "Download result did not include a result code. Ignoring.");
|
Log.w(LOG_TAG, "Download result did not include a result code. Ignoring.");
|
||||||
return false;
|
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.");
|
Log.w(LOG_TAG, "Download result did not include the associated request. Ignoring.");
|
||||||
return false;
|
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.");
|
Log.w(LOG_TAG, "Download result did not include the temp file root. Ignoring.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -141,12 +142,12 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
"Ignoring.");
|
"Ignoring.");
|
||||||
return false;
|
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 " +
|
Log.w(LOG_TAG, "Download result did not include the path to the final " +
|
||||||
"temp file. Ignoring.");
|
"temp file. Ignoring.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
DownloadRequest request = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_REQUEST);
|
DownloadRequest request = intent.getParcelableExtra(VendorIntents.EXTRA_REQUEST);
|
||||||
String expectedTokenFileName = request.getHash() + DOWNLOAD_TOKEN_SUFFIX;
|
String expectedTokenFileName = request.getHash() + DOWNLOAD_TOKEN_SUFFIX;
|
||||||
File expectedTokenFile = new File(
|
File expectedTokenFile = new File(
|
||||||
MbmsUtils.getEmbmsTempFileDirForService(context, request.getFileServiceId()),
|
MbmsUtils.getEmbmsTempFileDirForService(context, request.getFileServiceId()),
|
||||||
@@ -156,27 +157,27 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
"Expected " + expectedTokenFile);
|
"Expected " + expectedTokenFile);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (MbmsDownloadManager.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
|
} else if (VendorIntents.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
|
||||||
if (!intent.hasExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO)) {
|
if (!intent.hasExtra(VendorIntents.EXTRA_SERVICE_INFO)) {
|
||||||
Log.w(LOG_TAG, "Temp file request did not include the associated service info." +
|
Log.w(LOG_TAG, "Temp file request did not include the associated service info." +
|
||||||
" Ignoring.");
|
" Ignoring.");
|
||||||
return false;
|
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.");
|
Log.w(LOG_TAG, "Download result did not include the temp file root. Ignoring.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (MbmsDownloadManager.ACTION_CLEANUP.equals(intent.getAction())) {
|
} else if (VendorIntents.ACTION_CLEANUP.equals(intent.getAction())) {
|
||||||
if (!intent.hasExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO)) {
|
if (!intent.hasExtra(VendorIntents.EXTRA_SERVICE_INFO)) {
|
||||||
Log.w(LOG_TAG, "Cleanup request did not include the associated service info." +
|
Log.w(LOG_TAG, "Cleanup request did not include the associated service info." +
|
||||||
" Ignoring.");
|
" Ignoring.");
|
||||||
return false;
|
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.");
|
Log.w(LOG_TAG, "Cleanup request did not include the temp file root. Ignoring.");
|
||||||
return false;
|
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. " +
|
Log.w(LOG_TAG, "Cleanup request did not include the list of temp files in use. " +
|
||||||
"Ignoring.");
|
"Ignoring.");
|
||||||
return false;
|
return false;
|
||||||
@@ -186,7 +187,7 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void moveDownloadedFile(Context context, Intent intent) {
|
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();
|
Intent intentForApp = request.getIntentForApp();
|
||||||
|
|
||||||
int result = intent.getIntExtra(MbmsDownloadManager.EXTRA_RESULT,
|
int result = intent.getIntExtra(MbmsDownloadManager.EXTRA_RESULT,
|
||||||
@@ -200,7 +201,7 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Uri destinationUri = request.getDestinationUri();
|
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)) {
|
if (!verifyTempFilePath(context, request.getFileServiceId(), finalTempFile)) {
|
||||||
Log.w(LOG_TAG, "Download result specified an invalid temp file " + finalTempFile);
|
Log.w(LOG_TAG, "Download result specified an invalid temp file " + finalTempFile);
|
||||||
setResultCode(RESULT_DOWNLOAD_FINALIZATION_ERROR);
|
setResultCode(RESULT_DOWNLOAD_FINALIZATION_ERROR);
|
||||||
@@ -225,13 +226,13 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void cleanupPostMove(Context context, Intent intent) {
|
private void cleanupPostMove(Context context, Intent intent) {
|
||||||
DownloadRequest request = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_REQUEST);
|
DownloadRequest request = intent.getParcelableExtra(VendorIntents.EXTRA_REQUEST);
|
||||||
if (request == null) {
|
if (request == null) {
|
||||||
Log.w(LOG_TAG, "Intent does not include a DownloadRequest. Ignoring.");
|
Log.w(LOG_TAG, "Intent does not include a DownloadRequest. Ignoring.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Uri> tempFiles = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_TEMP_LIST);
|
List<Uri> tempFiles = intent.getParcelableExtra(VendorIntents.EXTRA_TEMP_LIST);
|
||||||
if (tempFiles == null) {
|
if (tempFiles == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -246,15 +247,15 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
|
|
||||||
private void generateTempFiles(Context context, Intent intent) {
|
private void generateTempFiles(Context context, Intent intent) {
|
||||||
FileServiceInfo serviceInfo =
|
FileServiceInfo serviceInfo =
|
||||||
intent.getParcelableExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO);
|
intent.getParcelableExtra(VendorIntents.EXTRA_SERVICE_INFO);
|
||||||
if (serviceInfo == null) {
|
if (serviceInfo == null) {
|
||||||
Log.w(LOG_TAG, "Temp file request did not include the associated service info. " +
|
Log.w(LOG_TAG, "Temp file request did not include the associated service info. " +
|
||||||
"Ignoring.");
|
"Ignoring.");
|
||||||
setResultCode(RESULT_MALFORMED_INTENT);
|
setResultCode(RESULT_MALFORMED_INTENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int fdCount = intent.getIntExtra(MbmsDownloadManager.EXTRA_FD_COUNT, 0);
|
int fdCount = intent.getIntExtra(VendorIntents.EXTRA_FD_COUNT, 0);
|
||||||
List<Uri> pausedList = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_PAUSED_LIST);
|
List<Uri> pausedList = intent.getParcelableExtra(VendorIntents.EXTRA_PAUSED_LIST);
|
||||||
|
|
||||||
if (fdCount == 0 && (pausedList == null || pausedList.size() == 0)) {
|
if (fdCount == 0 && (pausedList == null || pausedList.size() == 0)) {
|
||||||
Log.i(LOG_TAG, "No temp files actually requested. Ending.");
|
Log.i(LOG_TAG, "No temp files actually requested. Ending.");
|
||||||
@@ -269,8 +270,8 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
generateUrisForPausedFiles(context, serviceInfo, pausedList);
|
generateUrisForPausedFiles(context, serviceInfo, pausedList);
|
||||||
|
|
||||||
Bundle result = new Bundle();
|
Bundle result = new Bundle();
|
||||||
result.putParcelableArrayList(MbmsDownloadManager.EXTRA_FREE_URI_LIST, freshTempFiles);
|
result.putParcelableArrayList(VendorIntents.EXTRA_FREE_URI_LIST, freshTempFiles);
|
||||||
result.putParcelableArrayList(MbmsDownloadManager.EXTRA_PAUSED_URI_LIST, pausedFiles);
|
result.putParcelableArrayList(VendorIntents.EXTRA_PAUSED_URI_LIST, pausedFiles);
|
||||||
setResultCode(RESULT_OK);
|
setResultCode(RESULT_OK);
|
||||||
setResultExtras(result);
|
setResultExtras(result);
|
||||||
}
|
}
|
||||||
@@ -353,11 +354,11 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
|
|
||||||
private void cleanupTempFiles(Context context, Intent intent) {
|
private void cleanupTempFiles(Context context, Intent intent) {
|
||||||
FileServiceInfo serviceInfo =
|
FileServiceInfo serviceInfo =
|
||||||
intent.getParcelableExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO);
|
intent.getParcelableExtra(VendorIntents.EXTRA_SERVICE_INFO);
|
||||||
File tempFileDir = MbmsUtils.getEmbmsTempFileDirForService(context,
|
File tempFileDir = MbmsUtils.getEmbmsTempFileDirForService(context,
|
||||||
serviceInfo.getServiceId());
|
serviceInfo.getServiceId());
|
||||||
final List<Uri> filesInUse =
|
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() {
|
File[] filesToDelete = tempFileDir.listFiles(new FileFilter() {
|
||||||
@Override
|
@Override
|
||||||
public boolean accept(File file) {
|
public boolean accept(File file) {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class MbmsException extends Exception {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the app attempted to perform an operation on an instance of
|
* Indicates that the app attempted to perform an operation on an instance of
|
||||||
* {@link android.telephony.MbmsDownloadManager} or
|
* TODO: link android.telephony.MbmsDownloadManager or
|
||||||
* {@link android.telephony.MbmsStreamingManager} without being bound to the middleware.
|
* {@link android.telephony.MbmsStreamingManager} without being bound to the middleware.
|
||||||
*/
|
*/
|
||||||
public static final int ERROR_MIDDLEWARE_NOT_BOUND = 2;
|
public static final int ERROR_MIDDLEWARE_NOT_BOUND = 2;
|
||||||
@@ -44,10 +44,11 @@ public class MbmsException extends Exception {
|
|||||||
* middleware. They are applicable to both streaming and file-download use-cases.
|
* middleware. They are applicable to both streaming and file-download use-cases.
|
||||||
*/
|
*/
|
||||||
public static class InitializationErrors {
|
public static class InitializationErrors {
|
||||||
|
private InitializationErrors() {}
|
||||||
/**
|
/**
|
||||||
* Indicates that the app tried to create more than one instance each of
|
* Indicates that the app tried to create more than one instance each of
|
||||||
* {@link android.telephony.MbmsStreamingManager} or
|
* {@link android.telephony.MbmsStreamingManager} or
|
||||||
* {@link android.telephony.MbmsDownloadManager}.
|
* TODO: link android.telephony.MbmsDownloadManager
|
||||||
*/
|
*/
|
||||||
public static final int ERROR_DUPLICATE_INITIALIZE = 101;
|
public static final int ERROR_DUPLICATE_INITIALIZE = 101;
|
||||||
/** Indicates that the app is not authorized to access media via MBMS.*/
|
/** Indicates that the app is not authorized to access media via MBMS.*/
|
||||||
@@ -61,10 +62,11 @@ public class MbmsException extends Exception {
|
|||||||
* streaming and file-download.
|
* streaming and file-download.
|
||||||
*/
|
*/
|
||||||
public static class GeneralErrors {
|
public static class GeneralErrors {
|
||||||
|
private GeneralErrors() {}
|
||||||
/**
|
/**
|
||||||
* Indicates that the app attempted to perform an operation before receiving notification
|
* Indicates that the app attempted to perform an operation before receiving notification
|
||||||
* that the middleware is ready via {@link MbmsStreamingManagerCallback#middlewareReady()}
|
* that the middleware is ready via {@link MbmsStreamingManagerCallback#onMiddlewareReady()}
|
||||||
* or {@link MbmsDownloadManagerCallback#middlewareReady()}.
|
* or TODO: link MbmsDownloadManagerCallback#middlewareReady
|
||||||
*/
|
*/
|
||||||
public static final int ERROR_MIDDLEWARE_NOT_YET_READY = 201;
|
public static final int ERROR_MIDDLEWARE_NOT_YET_READY = 201;
|
||||||
/**
|
/**
|
||||||
@@ -97,6 +99,7 @@ public class MbmsException extends Exception {
|
|||||||
* Indicates the errors that are applicable only to the streaming use-case
|
* Indicates the errors that are applicable only to the streaming use-case
|
||||||
*/
|
*/
|
||||||
public static class StreamingErrors {
|
public static class StreamingErrors {
|
||||||
|
private StreamingErrors() {}
|
||||||
/** Indicates that the middleware cannot start a stream due to too many ongoing streams */
|
/** Indicates that the middleware cannot start a stream due to too many ongoing streams */
|
||||||
public static final int ERROR_CONCURRENT_SERVICE_LIMIT_REACHED = 301;
|
public static final int ERROR_CONCURRENT_SERVICE_LIMIT_REACHED = 301;
|
||||||
|
|
||||||
@@ -105,7 +108,8 @@ public class MbmsException extends Exception {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the app called
|
* Indicates that the app called
|
||||||
* {@link android.telephony.MbmsStreamingManager#startStreaming(StreamingServiceInfo, StreamingServiceCallback)}
|
* {@link android.telephony.MbmsStreamingManager#startStreaming(
|
||||||
|
* StreamingServiceInfo, StreamingServiceCallback, android.os.Handler)}
|
||||||
* more than once for the same {@link StreamingServiceInfo}.
|
* more than once for the same {@link StreamingServiceInfo}.
|
||||||
*/
|
*/
|
||||||
public static final int ERROR_DUPLICATE_START_STREAM = 303;
|
public static final int ERROR_DUPLICATE_START_STREAM = 303;
|
||||||
@@ -113,6 +117,8 @@ public class MbmsException extends Exception {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates the errors that are applicable only to the file-download use-case
|
* Indicates the errors that are applicable only to the file-download use-case
|
||||||
|
* TODO: unhide
|
||||||
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static class DownloadErrors {
|
public static class DownloadErrors {
|
||||||
/**
|
/**
|
||||||
@@ -127,9 +133,7 @@ public class MbmsException extends Exception {
|
|||||||
|
|
||||||
private final int mErrorCode;
|
private final int mErrorCode;
|
||||||
|
|
||||||
/** @hide
|
/** @hide */
|
||||||
* TODO: future systemapi
|
|
||||||
*/
|
|
||||||
public MbmsException(int errorCode) {
|
public MbmsException(int errorCode) {
|
||||||
super();
|
super();
|
||||||
mErrorCode = errorCode;
|
mErrorCode = errorCode;
|
||||||
|
|||||||
@@ -16,20 +16,26 @@
|
|||||||
|
|
||||||
package android.telephony.mbms;
|
package android.telephony.mbms;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.telephony.MbmsStreamingManager;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Parcelable class with Cell-Broadcast service information.
|
* A callback class that is used to receive information from the middleware on MBMS streaming
|
||||||
|
* services. An instance of this object should be passed into
|
||||||
|
* {@link android.telephony.MbmsStreamingManager#create(Context, MbmsStreamingManagerCallback)}.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class MbmsStreamingManagerCallback extends IMbmsStreamingManagerCallback.Stub {
|
public class MbmsStreamingManagerCallback {
|
||||||
|
/**
|
||||||
public final static int ERROR_CARRIER_NOT_SUPPORTED = 1;
|
* Called by the middleware when it has detected an error condition. The possible error codes
|
||||||
public final static int ERROR_UNABLE_TO_INITIALIZE = 2;
|
* are listed in {@link MbmsException}.
|
||||||
public final static int ERROR_UNABLE_TO_ALLOCATE_MEMORY = 3;
|
* @param errorCode The error code.
|
||||||
|
* @param message A human-readable message generated by the middleware for debugging purposes.
|
||||||
|
*/
|
||||||
public void error(int errorCode, String message) {
|
public void onError(int errorCode, String message) {
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +51,7 @@ public class MbmsStreamingManagerCallback extends IMbmsStreamingManagerCallback.
|
|||||||
* @param services a List of StreamingServiceInfos
|
* @param services a List of StreamingServiceInfos
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void streamingServicesUpdated(List<StreamingServiceInfo> services) {
|
public void onStreamingServicesUpdated(List<StreamingServiceInfo> services) {
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,8 +63,7 @@ public class MbmsStreamingManagerCallback extends IMbmsStreamingManagerCallback.
|
|||||||
* being thrown with error code {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
|
* being thrown with error code {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
|
||||||
* or {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}
|
* or {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}
|
||||||
*/
|
*/
|
||||||
@Override
|
public void onMiddlewareReady() {
|
||||||
public void middlewareReady() {
|
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,43 +30,22 @@ import java.util.Objects;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Parcelable class with Cell-Broadcast service information.
|
* Describes a cell-broadcast service. This class should not be instantiated directly -- use
|
||||||
|
* {@link StreamingServiceInfo} or FileServiceInfo TODO: add link once that's unhidden
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class ServiceInfo implements Parcelable {
|
public class ServiceInfo {
|
||||||
// arbitrary limit on the number of locale -> name pairs we support
|
// arbitrary limit on the number of locale -> name pairs we support
|
||||||
final static int MAP_LIMIT = 1000;
|
final static int MAP_LIMIT = 1000;
|
||||||
/**
|
|
||||||
* User displayable names listed by language. Unmodifiable.
|
|
||||||
*/
|
|
||||||
final Map<Locale, String> names;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The class name for this service - used to catagorize and filter
|
|
||||||
*/
|
|
||||||
final String className;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The languages available for this service content
|
|
||||||
*/
|
|
||||||
final List<Locale> locales;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The carrier's identifier for the service.
|
|
||||||
*/
|
|
||||||
final String serviceId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The start time indicating when this service will be available.
|
|
||||||
*/
|
|
||||||
final Date sessionStartTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The end time indicating when this sesion stops being available.
|
|
||||||
*/
|
|
||||||
final Date sessionEndTime;
|
|
||||||
|
|
||||||
|
private final Map<Locale, String> names;
|
||||||
|
private final String className;
|
||||||
|
private final List<Locale> locales;
|
||||||
|
private final String serviceId;
|
||||||
|
private final Date sessionStartTime;
|
||||||
|
private final Date sessionEndTime;
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
public ServiceInfo(Map<Locale, String> newNames, String newClassName, List<Locale> newLocales,
|
public ServiceInfo(Map<Locale, String> newNames, String newClassName, List<Locale> newLocales,
|
||||||
String newServiceId, Date start, Date end) {
|
String newServiceId, Date start, Date end) {
|
||||||
if (newNames == null || newNames.isEmpty() || TextUtils.isEmpty(newClassName)
|
if (newNames == null || newNames.isEmpty() || TextUtils.isEmpty(newClassName)
|
||||||
@@ -89,20 +68,8 @@ public class ServiceInfo implements Parcelable {
|
|||||||
sessionEndTime = (Date)end.clone();
|
sessionEndTime = (Date)end.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Parcelable.Creator<FileServiceInfo> CREATOR =
|
/** @hide */
|
||||||
new Parcelable.Creator<FileServiceInfo>() {
|
protected ServiceInfo(Parcel in) {
|
||||||
@Override
|
|
||||||
public FileServiceInfo createFromParcel(Parcel source) {
|
|
||||||
return new FileServiceInfo(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FileServiceInfo[] newArray(int size) {
|
|
||||||
return new FileServiceInfo[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ServiceInfo(Parcel in) {
|
|
||||||
int mapCount = in.readInt();
|
int mapCount = in.readInt();
|
||||||
if (mapCount > MAP_LIMIT || mapCount < 0) {
|
if (mapCount > MAP_LIMIT || mapCount < 0) {
|
||||||
throw new RuntimeException("bad map length" + mapCount);
|
throw new RuntimeException("bad map length" + mapCount);
|
||||||
@@ -128,7 +95,7 @@ public class ServiceInfo implements Parcelable {
|
|||||||
sessionEndTime = (java.util.Date) in.readSerializable();
|
sessionEndTime = (java.util.Date) in.readSerializable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/** @hide */
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
Set<Locale> keySet = names.keySet();
|
Set<Locale> keySet = names.keySet();
|
||||||
dest.writeInt(keySet.size());
|
dest.writeInt(keySet.size());
|
||||||
@@ -147,31 +114,44 @@ public class ServiceInfo implements Parcelable {
|
|||||||
dest.writeSerializable(sessionEndTime);
|
dest.writeSerializable(sessionEndTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public int describeContents() {
|
* User displayable names listed by language. Do not modify the map returned from this method.
|
||||||
return 0;
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Locale, String> getNames() {
|
public Map<Locale, String> getNames() {
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class name for this service - used to categorize and filter
|
||||||
|
*/
|
||||||
public String getClassName() {
|
public String getClassName() {
|
||||||
return className;
|
return className;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The languages available for this service content
|
||||||
|
*/
|
||||||
public List<Locale> getLocales() {
|
public List<Locale> getLocales() {
|
||||||
return locales;
|
return locales;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The carrier's identifier for the service.
|
||||||
|
*/
|
||||||
public String getServiceId() {
|
public String getServiceId() {
|
||||||
return serviceId;
|
return serviceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The start time indicating when this service will be available.
|
||||||
|
*/
|
||||||
public Date getSessionStartTime() {
|
public Date getSessionStartTime() {
|
||||||
return sessionStartTime;
|
return sessionStartTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The end time indicating when this session stops being available.
|
||||||
|
*/
|
||||||
public Date getSessionEndTime() {
|
public Date getSessionEndTime() {
|
||||||
return sessionEndTime;
|
return sessionEndTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,13 +26,17 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Class used to represent a single MBMS stream. After a stream has been started with
|
||||||
|
* {@link android.telephony.MbmsStreamingManager#startStreaming(StreamingServiceInfo,
|
||||||
|
* StreamingServiceCallback, android.os.Handler)},
|
||||||
|
* this class is used to hold information about the stream and control it.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class StreamingService {
|
public class StreamingService {
|
||||||
private static final String LOG_TAG = "MbmsStreamingService";
|
private static final String LOG_TAG = "MbmsStreamingService";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The state of a stream, reported via {@link StreamingServiceCallback#streamStateUpdated}
|
* The state of a stream, reported via {@link StreamingServiceCallback#onStreamStateUpdated}
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@@ -44,7 +48,7 @@ public class StreamingService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The reason for a stream state change, reported via
|
* The reason for a stream state change, reported via
|
||||||
* {@link StreamingServiceCallback#streamStateUpdated}
|
* {@link StreamingServiceCallback#onStreamStateUpdated}
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@@ -60,7 +64,8 @@ public class StreamingService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* State changed due to a call to {@link #stopStreaming()} or
|
* State changed due to a call to {@link #stopStreaming()} or
|
||||||
* {@link android.telephony.MbmsStreamingManager#startStreaming(StreamingServiceInfo, StreamingServiceCallback)}
|
* {@link android.telephony.MbmsStreamingManager#startStreaming(StreamingServiceInfo,
|
||||||
|
* StreamingServiceCallback, android.os.Handler)}
|
||||||
*/
|
*/
|
||||||
public static final int REASON_BY_USER_REQUEST = 1;
|
public static final int REASON_BY_USER_REQUEST = 1;
|
||||||
|
|
||||||
@@ -87,27 +92,28 @@ public class StreamingService {
|
|||||||
/**
|
/**
|
||||||
* State changed due to the device leaving the where this stream is being broadcast.
|
* State changed due to the device leaving the where this stream is being broadcast.
|
||||||
*/
|
*/
|
||||||
public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 5;
|
public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 6;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method of transmission currently used for a stream,
|
* The method of transmission currently used for a stream,
|
||||||
* reported via {@link StreamingServiceCallback#streamMethodUpdated}
|
* reported via {@link StreamingServiceCallback#onStreamMethodUpdated}
|
||||||
*/
|
*/
|
||||||
public final static int BROADCAST_METHOD = 1;
|
public final static int BROADCAST_METHOD = 1;
|
||||||
public final static int UNICAST_METHOD = 2;
|
public final static int UNICAST_METHOD = 2;
|
||||||
|
|
||||||
private final int mSubscriptionId;
|
private final int mSubscriptionId;
|
||||||
private final StreamingServiceInfo mServiceInfo;
|
private final StreamingServiceInfo mServiceInfo;
|
||||||
private final IStreamingServiceCallback mCallback;
|
private final InternalStreamingServiceCallback mCallback;
|
||||||
|
|
||||||
private IMbmsStreamingService mService;
|
private IMbmsStreamingService mService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public StreamingService(int subscriptionId,
|
public StreamingService(int subscriptionId,
|
||||||
IMbmsStreamingService service,
|
IMbmsStreamingService service,
|
||||||
StreamingServiceInfo streamingServiceInfo,
|
StreamingServiceInfo streamingServiceInfo,
|
||||||
IStreamingServiceCallback callback) {
|
InternalStreamingServiceCallback callback) {
|
||||||
mSubscriptionId = subscriptionId;
|
mSubscriptionId = subscriptionId;
|
||||||
mService = service;
|
mService = service;
|
||||||
mServiceInfo = streamingServiceInfo;
|
mServiceInfo = streamingServiceInfo;
|
||||||
|
|||||||
@@ -17,10 +17,11 @@
|
|||||||
package android.telephony.mbms;
|
package android.telephony.mbms;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Callback class for use when the application is actively streaming content.
|
* A callback class for use when the application is actively streaming content. The middleware
|
||||||
|
* will provide updates on the status of the stream via this callback.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class StreamingServiceCallback extends IStreamingServiceCallback.Stub {
|
public class StreamingServiceCallback {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates broadcast signal strength is not available for this service.
|
* Indicates broadcast signal strength is not available for this service.
|
||||||
@@ -31,8 +32,13 @@ public class StreamingServiceCallback extends IStreamingServiceCallback.Stub {
|
|||||||
*/
|
*/
|
||||||
public static final int SIGNAL_STRENGTH_UNAVAILABLE = -1;
|
public static final int SIGNAL_STRENGTH_UNAVAILABLE = -1;
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void error(int errorCode, String message) {
|
* Called by the middleware when it has detected an error condition in this stream. The
|
||||||
|
* possible error codes are listed in {@link MbmsException}.
|
||||||
|
* @param errorCode The error code.
|
||||||
|
* @param message A human-readable message generated by the middleware for debugging purposes.
|
||||||
|
*/
|
||||||
|
public void onError(int errorCode, String message) {
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,8 +48,7 @@ public class StreamingServiceCallback extends IStreamingServiceCallback.Stub {
|
|||||||
* See {@link StreamingService#STATE_STOPPED}, {@link StreamingService#STATE_STARTED}
|
* See {@link StreamingService#STATE_STOPPED}, {@link StreamingService#STATE_STARTED}
|
||||||
* and {@link StreamingService#STATE_STALLED}.
|
* and {@link StreamingService#STATE_STALLED}.
|
||||||
*/
|
*/
|
||||||
@Override
|
public void onStreamStateUpdated(@StreamingService.StreamingState int state,
|
||||||
public void streamStateUpdated(@StreamingService.StreamingState int state,
|
|
||||||
@StreamingService.StreamingStateChangeReason int reason) {
|
@StreamingService.StreamingStateChangeReason int reason) {
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
}
|
}
|
||||||
@@ -58,8 +63,7 @@ public class StreamingServiceCallback extends IStreamingServiceCallback.Stub {
|
|||||||
* This may be called when a looping stream hits the end or
|
* This may be called when a looping stream hits the end or
|
||||||
* when parameters have changed to account for time drift.
|
* when parameters have changed to account for time drift.
|
||||||
*/
|
*/
|
||||||
@Override
|
public void onMediaDescriptionUpdated() {
|
||||||
public void mediaDescriptionUpdated() {
|
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,8 +77,7 @@ public class StreamingServiceCallback extends IStreamingServiceCallback.Stub {
|
|||||||
* {@link #SIGNAL_STRENGTH_UNAVAILABLE} if broadcast is not available
|
* {@link #SIGNAL_STRENGTH_UNAVAILABLE} if broadcast is not available
|
||||||
* for this service due to timing, geography or popularity.
|
* for this service due to timing, geography or popularity.
|
||||||
*/
|
*/
|
||||||
@Override
|
public void onBroadcastSignalStrengthUpdated(int signalStrength) {
|
||||||
public void broadcastSignalStrengthUpdated(int signalStrength) {
|
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,8 +97,7 @@ public class StreamingServiceCallback extends IStreamingServiceCallback.Stub {
|
|||||||
* See {@link StreamingService#BROADCAST_METHOD} and
|
* See {@link StreamingService#BROADCAST_METHOD} and
|
||||||
* {@link StreamingService#UNICAST_METHOD}
|
* {@link StreamingService#UNICAST_METHOD}
|
||||||
*/
|
*/
|
||||||
@Override
|
public void onStreamMethodUpdated(int methodType) {
|
||||||
public void streamMethodUpdated(int methodType) {
|
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package android.telephony.mbms;
|
package android.telephony.mbms;
|
||||||
|
|
||||||
|
import android.annotation.SystemApi;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
@@ -25,15 +26,25 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Parcelable class Cell-Broadcast media stream information.
|
* Describes a single MBMS streaming service.
|
||||||
* This may not have any more info than ServiceInfo, but kept for completeness.
|
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class StreamingServiceInfo extends ServiceInfo implements Parcelable {
|
public final class StreamingServiceInfo extends ServiceInfo implements Parcelable {
|
||||||
|
|
||||||
public StreamingServiceInfo(Map<Locale, String> newNames, String newClassName,
|
/**
|
||||||
List<Locale> newLocales, String newServiceId, Date start, Date end) {
|
* @param names User displayable names listed by language.
|
||||||
super(newNames, newClassName, newLocales, newServiceId, start, end);
|
* @param className The class name for this service - used by frontend apps to categorize and
|
||||||
|
* filter.
|
||||||
|
* @param locales The languages available for this service content.
|
||||||
|
* @param serviceId The carrier's identifier for the service.
|
||||||
|
* @param start The start time indicating when this service will be available.
|
||||||
|
* @param end The end time indicating when this session stops being available.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SystemApi
|
||||||
|
public StreamingServiceInfo(Map<Locale, String> names, String className,
|
||||||
|
List<Locale> locales, String serviceId, Date start, Date end) {
|
||||||
|
super(names, className, locales, serviceId, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Parcelable.Creator<StreamingServiceInfo> CREATOR =
|
public static final Parcelable.Creator<StreamingServiceInfo> CREATOR =
|
||||||
@@ -49,7 +60,7 @@ public class StreamingServiceInfo extends ServiceInfo implements Parcelable {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
StreamingServiceInfo(Parcel in) {
|
private StreamingServiceInfo(Parcel in) {
|
||||||
super(in);
|
super(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,10 +18,13 @@ package android.telephony.mbms.vendor;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.telephony.mbms.DownloadProgressListener;
|
||||||
import android.telephony.mbms.DownloadRequest;
|
import android.telephony.mbms.DownloadRequest;
|
||||||
import android.telephony.mbms.FileInfo;
|
import android.telephony.mbms.FileInfo;
|
||||||
|
import android.telephony.mbms.FileServiceInfo;
|
||||||
import android.telephony.mbms.IDownloadProgressListener;
|
import android.telephony.mbms.IDownloadProgressListener;
|
||||||
import android.telephony.mbms.IMbmsDownloadManagerCallback;
|
import android.telephony.mbms.IMbmsDownloadManagerCallback;
|
||||||
|
import android.telephony.mbms.MbmsDownloadManagerCallback;
|
||||||
import android.telephony.mbms.MbmsException;
|
import android.telephony.mbms.MbmsException;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -44,15 +47,39 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
* or {@link MbmsException#SUCCESS}. Non-successful error codes will be passed to the app via
|
* or {@link MbmsException#SUCCESS}. Non-successful error codes will be passed to the app via
|
||||||
* {@link IMbmsDownloadManagerCallback#error(int, String)}.
|
* {@link IMbmsDownloadManagerCallback#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.
|
* @param subscriptionId The subscription ID to use.
|
||||||
*/
|
*/
|
||||||
@Override
|
public int initialize(int subscriptionId, MbmsDownloadManagerCallback callback)
|
||||||
public int initialize(int subscriptionId,
|
throws RemoteException {
|
||||||
IMbmsDownloadManagerCallback listener) throws RemoteException {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actual AIDL implementation -- hides the callback AIDL from the API.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
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 {
|
||||||
|
callback.error(errorCode, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fileServicesUpdated(List<FileServiceInfo> services) throws RemoteException {
|
||||||
|
callback.fileServicesUpdated(services);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void middlewareReady() throws RemoteException {
|
||||||
|
callback.middlewareReady();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers serviceClasses of interest with the appName/subId key.
|
* Registers serviceClasses of interest with the appName/subId key.
|
||||||
* Starts async fetching data on streaming services of matching classes to be reported
|
* Starts async fetching data on streaming services of matching classes to be reported
|
||||||
@@ -107,19 +134,36 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
* @param downloadRequest An object describing the set of files to be downloaded.
|
* @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
|
* @param listener A listener through which the middleware can provide progress updates to
|
||||||
* the app while both are still running.
|
* 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
|
@Override
|
||||||
public int download(DownloadRequest downloadRequest, IDownloadProgressListener listener)
|
public final int download(DownloadRequest downloadRequest, IDownloadProgressListener listener)
|
||||||
throws RemoteException {
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of pending {@link DownloadRequest}s that originated from the calling
|
* Returns a list of pending {@link DownloadRequest}s that originated from the calling
|
||||||
* application, identified by its uid. A pending request is one that was issued via
|
* application, identified by its uid. A pending request is one that was issued via
|
||||||
* {@link #download(DownloadRequest, IDownloadCallback)} but not cancelled through
|
* {@link #download(DownloadRequest, IDownloadProgressListener)} but not cancelled through
|
||||||
* {@link #cancelDownload(DownloadRequest)}.
|
* {@link #cancelDownload(DownloadRequest)}.
|
||||||
* The middleware must return a non-null result synchronously or throw an exception
|
* The middleware must return a non-null result synchronously or throw an exception
|
||||||
* inheriting from {@link RuntimeException}.
|
* inheriting from {@link RuntimeException}.
|
||||||
|
|||||||
@@ -17,23 +17,29 @@
|
|||||||
package android.telephony.mbms.vendor;
|
package android.telephony.mbms.vendor;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.annotation.SystemApi;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Binder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.telephony.mbms.IMbmsStreamingManagerCallback;
|
import android.telephony.mbms.IMbmsStreamingManagerCallback;
|
||||||
import android.telephony.mbms.IStreamingServiceCallback;
|
import android.telephony.mbms.IStreamingServiceCallback;
|
||||||
import android.telephony.mbms.MbmsException;
|
import android.telephony.mbms.MbmsException;
|
||||||
|
import android.telephony.mbms.MbmsStreamingManagerCallback;
|
||||||
|
import android.telephony.mbms.StreamingService;
|
||||||
|
import android.telephony.mbms.StreamingServiceCallback;
|
||||||
|
import android.telephony.mbms.StreamingServiceInfo;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
* TODO: future systemapi
|
|
||||||
*/
|
*/
|
||||||
|
//@SystemApi
|
||||||
public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
||||||
/**
|
/**
|
||||||
* Initialize streaming service for this app and subId, registering the listener.
|
* Initialize streaming service for this app and subId, registering the listener.
|
||||||
*
|
*
|
||||||
* May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}, which
|
* May throw an {@link IllegalArgumentException} or a {@link SecurityException}, which
|
||||||
* will be intercepted and passed to the app as
|
* will be intercepted and passed to the app as
|
||||||
* {@link android.telephony.mbms.MbmsException.InitializationErrors#ERROR_UNABLE_TO_INITIALIZE}
|
* {@link android.telephony.mbms.MbmsException.InitializationErrors#ERROR_UNABLE_TO_INITIALIZE}
|
||||||
*
|
*
|
||||||
@@ -41,15 +47,60 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
|||||||
* or {@link MbmsException#SUCCESS}. Non-successful error codes will be passed to the app via
|
* or {@link MbmsException#SUCCESS}. Non-successful error codes will be passed to the app via
|
||||||
* {@link IMbmsStreamingManagerCallback#error(int, String)}.
|
* {@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.
|
* @param subscriptionId The subscription ID to use.
|
||||||
*/
|
*/
|
||||||
@Override
|
public int initialize(MbmsStreamingManagerCallback callback, int subscriptionId)
|
||||||
public int initialize(IMbmsStreamingManagerCallback listener, int subscriptionId)
|
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actual AIDL implementation that hides the callback AIDL from the middleware.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final int initialize(final IMbmsStreamingManagerCallback callback,
|
||||||
|
final int subscriptionId) throws RemoteException {
|
||||||
|
final int uid = Binder.getCallingUid();
|
||||||
|
callback.asBinder().linkToDeath(new DeathRecipient() {
|
||||||
|
@Override
|
||||||
|
public void binderDied() {
|
||||||
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
return initialize(new MbmsStreamingManagerCallback() {
|
||||||
|
@Override
|
||||||
|
public void onError(int errorCode, String message) {
|
||||||
|
try {
|
||||||
|
callback.error(errorCode, message);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStreamingServicesUpdated(List<StreamingServiceInfo> services) {
|
||||||
|
try {
|
||||||
|
callback.streamingServicesUpdated(services);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMiddlewareReady() {
|
||||||
|
try {
|
||||||
|
callback.middlewareReady();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, subscriptionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers serviceClasses of interest with the appName/subId key.
|
* Registers serviceClasses of interest with the appName/subId key.
|
||||||
* Starts async fetching data on streaming services of matching classes to be reported
|
* Starts async fetching data on streaming services of matching classes to be reported
|
||||||
@@ -82,13 +133,77 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
|||||||
*
|
*
|
||||||
* @param subscriptionId The subscription id to use.
|
* @param subscriptionId The subscription id to use.
|
||||||
* @param serviceId The ID of the streaming service that the app has requested.
|
* @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}
|
* @return Any error in {@link android.telephony.mbms.MbmsException.GeneralErrors}
|
||||||
*/
|
*/
|
||||||
|
public int startStreaming(int subscriptionId, String serviceId,
|
||||||
|
StreamingServiceCallback callback) throws RemoteException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actual AIDL implementation of startStreaming that hides the callback AIDL from the
|
||||||
|
* middleware.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int startStreaming(int subscriptionId, String serviceId,
|
public int startStreaming(int subscriptionId, String serviceId,
|
||||||
IStreamingServiceCallback listener) throws RemoteException {
|
IStreamingServiceCallback callback) throws RemoteException {
|
||||||
return 0;
|
final int uid = Binder.getCallingUid();
|
||||||
|
callback.asBinder().linkToDeath(new DeathRecipient() {
|
||||||
|
@Override
|
||||||
|
public void binderDied() {
|
||||||
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
return startStreaming(subscriptionId, serviceId, new StreamingServiceCallback() {
|
||||||
|
@Override
|
||||||
|
public void onError(int errorCode, String message) {
|
||||||
|
try {
|
||||||
|
callback.error(errorCode, message);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStreamStateUpdated(@StreamingService.StreamingState int state,
|
||||||
|
@StreamingService.StreamingStateChangeReason int reason) {
|
||||||
|
try {
|
||||||
|
callback.streamStateUpdated(state, reason);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMediaDescriptionUpdated() {
|
||||||
|
try {
|
||||||
|
callback.mediaDescriptionUpdated();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBroadcastSignalStrengthUpdated(int signalStrength) {
|
||||||
|
try {
|
||||||
|
callback.broadcastSignalStrengthUpdated(signalStrength);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStreamMethodUpdated(int methodType) {
|
||||||
|
try {
|
||||||
|
callback.streamMethodUpdated(methodType);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -153,4 +268,12 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public void dispose(int subscriptionId) throws RemoteException {
|
public void dispose(int subscriptionId) throws RemoteException {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the app identified by the given UID and subscription ID has died.
|
||||||
|
* @param uid the UID of the app, as returned by {@link Binder#getCallingUid()}.
|
||||||
|
* @param subscriptionId The subscription ID the app is using.
|
||||||
|
*/
|
||||||
|
public void onAppCallbackDied(int uid, int subscriptionId) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
166
telephony/java/android/telephony/mbms/vendor/VendorIntents.java
vendored
Normal file
166
telephony/java/android/telephony/mbms/vendor/VendorIntents.java
vendored
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user