Embms API adjustments for 7/21
* Enforce that only one instance of each manager can be active. * Add a death receipient for both managers to notify the app of binder death * Add documentation informing the app that it may not call create() multiple times * Fix a collision in streaming state reason codes * Add documentation in DownloadRequest to indicate which methods should be called by the middleware. Bug: 30981736 Test: testapps Change-Id: Ie15283b5c34fee736e8023dbd4f889c2ca95299e
This commit is contained in:
@@ -30,7 +30,6 @@ import android.os.RemoteException;
|
|||||||
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.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 +43,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;
|
||||||
@@ -207,8 +207,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 +244,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 +268,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);
|
||||||
mdm.bindAndInitialize();
|
try {
|
||||||
|
mdm.bindAndInitialize();
|
||||||
|
} catch (MbmsException e) {
|
||||||
|
sIsInitialized.set(false);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
return mdm;
|
return mdm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,16 +293,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 +321,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 +331,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 +345,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,7 +375,7 @@ 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, IDownloadProgressListener)}, 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}.
|
||||||
*
|
*
|
||||||
@@ -434,7 +473,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, IDownloadProgressListener)} 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,10 +589,12 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,4 +692,12 @@ public class MbmsDownloadManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendErrorToApp(int errorCode, String message) {
|
||||||
|
try {
|
||||||
|
mCallback.error(errorCode, message);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// Ignore, should not happen locally.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,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;
|
||||||
@@ -58,7 +59,17 @@ public class MbmsStreamingManager {
|
|||||||
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 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 InternalStreamingManagerCallback mInternalCallback;
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
@@ -82,6 +93,18 @@ 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.
|
||||||
@@ -93,9 +116,17 @@ public class MbmsStreamingManager {
|
|||||||
public static MbmsStreamingManager create(Context context,
|
public static MbmsStreamingManager create(Context context,
|
||||||
MbmsStreamingManagerCallback callback, int subscriptionId, Handler handler)
|
MbmsStreamingManagerCallback callback, int subscriptionId, Handler handler)
|
||||||
throws MbmsException {
|
throws MbmsException {
|
||||||
|
if (!sIsInitialized.compareAndSet(false, true)) {
|
||||||
|
throw new MbmsException(MbmsException.InitializationErrors.ERROR_DUPLICATE_INITIALIZE);
|
||||||
|
}
|
||||||
MbmsStreamingManager manager = new MbmsStreamingManager(context, callback,
|
MbmsStreamingManager manager = new MbmsStreamingManager(context, callback,
|
||||||
subscriptionId, handler);
|
subscriptionId, handler);
|
||||||
manager.bindAndInitialize();
|
try {
|
||||||
|
manager.bindAndInitialize();
|
||||||
|
} catch (MbmsException e) {
|
||||||
|
sIsInitialized.set(false);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,17 +158,19 @@ public class MbmsStreamingManager {
|
|||||||
* May throw an {@link IllegalStateException}
|
* May throw an {@link IllegalStateException}
|
||||||
*/
|
*/
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
IMbmsStreamingService streamingService = mService.get();
|
|
||||||
if (streamingService == null) {
|
|
||||||
// Ignore and return, assume already disposed.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
|
IMbmsStreamingService streamingService = mService.get();
|
||||||
|
if (streamingService == null) {
|
||||||
|
// Ignore and return, assume already disposed.
|
||||||
|
return;
|
||||||
|
}
|
||||||
streamingService.dispose(mSubscriptionId);
|
streamingService.dispose(mSubscriptionId);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Ignore for now
|
// Ignore for now
|
||||||
|
} finally {
|
||||||
|
mService.set(null);
|
||||||
|
sIsInitialized.set(false);
|
||||||
}
|
}
|
||||||
mService.set(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,6 +204,7 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,6 +257,7 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,26 +277,30 @@ public class MbmsStreamingManager {
|
|||||||
mSubscriptionId);
|
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");
|
||||||
try {
|
sendErrorToApp(
|
||||||
mInternalCallback.error(
|
MbmsException.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
|
||||||
MbmsException.InitializationErrors
|
e.toString());
|
||||||
.ERROR_UNABLE_TO_INITIALIZE,
|
sIsInitialized.set(false);
|
||||||
e.toString());
|
|
||||||
} catch (RemoteException e1) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result != MbmsException.SUCCESS) {
|
if (result != MbmsException.SUCCESS) {
|
||||||
try {
|
sendErrorToApp(result, "Error returned during initialization");
|
||||||
mInternalCallback.error(
|
sIsInitialized.set(false);
|
||||||
result, "Error returned during initialization");
|
return;
|
||||||
} catch (RemoteException e) {
|
}
|
||||||
// ignore
|
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);
|
||||||
@@ -269,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.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package android.telephony.mbms;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.telephony.MbmsStreamingManager;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ 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,
|
||||||
|
|||||||
@@ -20,8 +20,10 @@ import android.annotation.NonNull;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
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,13 +46,37 @@ 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.
|
||||||
*/
|
*/
|
||||||
|
public int initialize(int subscriptionId, MbmsDownloadManagerCallback callback)
|
||||||
|
throws RemoteException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actual AIDL implementation -- hides the callback AIDL from the API.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int initialize(int subscriptionId,
|
public int initialize(int subscriptionId,
|
||||||
IMbmsDownloadManagerCallback listener) throws RemoteException {
|
IMbmsDownloadManagerCallback callback) throws RemoteException {
|
||||||
return 0;
|
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();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,7 +145,7 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
/**
|
/**
|
||||||
* 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}.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ 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}
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user