Merge changes from topic "embms-cherry-pick-3" into oc-mr1-dev
* changes: API council suggested edits, part 3 Apply suggested edits to the file-download API Make changes to MBMS Streaming APIs per recommendations
This commit is contained in:
@@ -502,8 +502,8 @@ LOCAL_SRC_FILES += \
|
|||||||
telecomm/java/com/android/internal/telecom/IInCallService.aidl \
|
telecomm/java/com/android/internal/telecom/IInCallService.aidl \
|
||||||
telecomm/java/com/android/internal/telecom/ITelecomService.aidl \
|
telecomm/java/com/android/internal/telecom/ITelecomService.aidl \
|
||||||
telecomm/java/com/android/internal/telecom/RemoteServiceCallback.aidl \
|
telecomm/java/com/android/internal/telecom/RemoteServiceCallback.aidl \
|
||||||
telephony/java/android/telephony/mbms/IMbmsDownloadManagerCallback.aidl \
|
telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl \
|
||||||
telephony/java/android/telephony/mbms/IMbmsStreamingManagerCallback.aidl \
|
telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl \
|
||||||
telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl \
|
telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl \
|
||||||
telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl \
|
telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl \
|
||||||
telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl \
|
telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl \
|
||||||
|
|||||||
@@ -34,11 +34,11 @@ import android.os.RemoteException;
|
|||||||
import android.telephony.mbms.DownloadStateCallback;
|
import android.telephony.mbms.DownloadStateCallback;
|
||||||
import android.telephony.mbms.FileInfo;
|
import android.telephony.mbms.FileInfo;
|
||||||
import android.telephony.mbms.DownloadRequest;
|
import android.telephony.mbms.DownloadRequest;
|
||||||
import android.telephony.mbms.InternalDownloadManagerCallback;
|
import android.telephony.mbms.InternalDownloadSessionCallback;
|
||||||
import android.telephony.mbms.InternalDownloadStateCallback;
|
import android.telephony.mbms.InternalDownloadStateCallback;
|
||||||
import android.telephony.mbms.MbmsDownloadManagerCallback;
|
import android.telephony.mbms.MbmsDownloadSessionCallback;
|
||||||
import android.telephony.mbms.MbmsDownloadReceiver;
|
import android.telephony.mbms.MbmsDownloadReceiver;
|
||||||
import android.telephony.mbms.MbmsException;
|
import android.telephony.mbms.MbmsErrors;
|
||||||
import android.telephony.mbms.MbmsTempFileProvider;
|
import android.telephony.mbms.MbmsTempFileProvider;
|
||||||
import android.telephony.mbms.MbmsUtils;
|
import android.telephony.mbms.MbmsUtils;
|
||||||
import android.telephony.mbms.vendor.IMbmsDownloadService;
|
import android.telephony.mbms.vendor.IMbmsDownloadService;
|
||||||
@@ -48,7 +48,10 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
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.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
@@ -58,8 +61,8 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
|||||||
* This class provides functionality for file download over MBMS.
|
* This class provides functionality for file download over MBMS.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class MbmsDownloadManager {
|
public class MbmsDownloadSession implements AutoCloseable {
|
||||||
private static final String LOG_TAG = MbmsDownloadManager.class.getSimpleName();
|
private static final String LOG_TAG = MbmsDownloadSession.class.getSimpleName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service action which must be handled by the middleware implementing the MBMS file download
|
* Service action which must be handled by the middleware implementing the MBMS file download
|
||||||
@@ -95,16 +98,28 @@ public class MbmsDownloadManager {
|
|||||||
/**
|
/**
|
||||||
* {@link Uri} extra that Android will attach to the intent supplied via
|
* {@link Uri} extra that Android will attach to the intent supplied via
|
||||||
* {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}
|
* {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}
|
||||||
* Indicates the location of the successfully
|
* Indicates the location of the successfully downloaded file within the temp file root set
|
||||||
* downloaded file. Will always be set to a non-null value if
|
* via {@link #setTempFileRootDirectory(File)}.
|
||||||
|
* While you may use this file in-place, it is highly encouraged that you move
|
||||||
|
* this file to a different location after receiving the download completion intent, as this
|
||||||
|
* file resides within the temp file directory.
|
||||||
|
*
|
||||||
|
* Will always be set to a non-null value if
|
||||||
* {@link #EXTRA_MBMS_DOWNLOAD_RESULT} is set to {@link #RESULT_SUCCESSFUL}.
|
* {@link #EXTRA_MBMS_DOWNLOAD_RESULT} is set to {@link #RESULT_SUCCESSFUL}.
|
||||||
*/
|
*/
|
||||||
public static final String EXTRA_MBMS_COMPLETED_FILE_URI =
|
public static final String EXTRA_MBMS_COMPLETED_FILE_URI =
|
||||||
"android.telephony.extra.MBMS_COMPLETED_FILE_URI";
|
"android.telephony.extra.MBMS_COMPLETED_FILE_URI";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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_MBMS_DOWNLOAD_REQUEST =
|
||||||
|
"android.telephony.extra.MBMS_DOWNLOAD_REQUEST";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default directory name for all MBMS temp files. If you call
|
* The default directory name for all MBMS temp files. If you call
|
||||||
* {@link #download(DownloadRequest, DownloadStateCallback, Handler)} without first calling
|
* {@link #download(DownloadRequest)} without first calling
|
||||||
* {@link #setTempFileRootDirectory(File)}, this directory will be created for you under the
|
* {@link #setTempFileRootDirectory(File)}, this directory will be created for you under the
|
||||||
* path returned by {@link Context#getFilesDir()}.
|
* path returned by {@link Context#getFilesDir()}.
|
||||||
*/
|
*/
|
||||||
@@ -173,98 +188,88 @@ public class MbmsDownloadManager {
|
|||||||
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
|
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
|
||||||
@Override
|
@Override
|
||||||
public void binderDied() {
|
public void binderDied() {
|
||||||
sendErrorToApp(MbmsException.ERROR_MIDDLEWARE_LOST, "Received death notification");
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, "Received death notification");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private AtomicReference<IMbmsDownloadService> mService = new AtomicReference<>(null);
|
private AtomicReference<IMbmsDownloadService> mService = new AtomicReference<>(null);
|
||||||
private final InternalDownloadManagerCallback mInternalCallback;
|
private final InternalDownloadSessionCallback mInternalCallback;
|
||||||
|
private final Map<DownloadStateCallback, InternalDownloadStateCallback>
|
||||||
|
mInternalDownloadCallbacks = new HashMap<>();
|
||||||
|
|
||||||
private MbmsDownloadManager(Context context, MbmsDownloadManagerCallback callback,
|
private MbmsDownloadSession(Context context, MbmsDownloadSessionCallback callback,
|
||||||
int subscriptionId, Handler handler) {
|
int subscriptionId, Handler handler) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mSubscriptionId = subscriptionId;
|
mSubscriptionId = subscriptionId;
|
||||||
if (handler == null) {
|
if (handler == null) {
|
||||||
handler = new Handler(Looper.myLooper());
|
handler = new Handler(Looper.getMainLooper());
|
||||||
}
|
}
|
||||||
mInternalCallback = new InternalDownloadManagerCallback(callback, handler);
|
mInternalCallback = new InternalDownloadSessionCallback(callback, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new MbmsDownloadManager using the system default data subscription ID and default
|
* Create a new {@link MbmsDownloadSession} using the system default data subscription ID.
|
||||||
* {@link Handler}
|
* See {@link #create(Context, MbmsDownloadSessionCallback, int, Handler)}
|
||||||
* See {@link #create(Context, MbmsDownloadManagerCallback, int, Handler)}
|
|
||||||
*/
|
*/
|
||||||
public static MbmsDownloadManager create(Context context,
|
public static MbmsDownloadSession create(@NonNull Context context,
|
||||||
MbmsDownloadManagerCallback callback)
|
@NonNull MbmsDownloadSessionCallback callback, @NonNull Handler handler) {
|
||||||
throws MbmsException {
|
|
||||||
return create(context, callback, SubscriptionManager.getDefaultSubscriptionId(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new MbmsDownloadManager using the system default data subscription ID.
|
|
||||||
* See {@link #create(Context, MbmsDownloadManagerCallback, int, Handler)}
|
|
||||||
*/
|
|
||||||
public static MbmsDownloadManager create(Context context,
|
|
||||||
MbmsDownloadManagerCallback callback, Handler handler)
|
|
||||||
throws MbmsException {
|
|
||||||
return create(context, callback, SubscriptionManager.getDefaultSubscriptionId(), handler);
|
return create(context, callback, SubscriptionManager.getDefaultSubscriptionId(), handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new MbmsDownloadManager using the default {@link Handler}
|
|
||||||
* See {@link #create(Context, MbmsDownloadManagerCallback, int, Handler)}
|
|
||||||
*/
|
|
||||||
public static MbmsDownloadManager create(Context context,
|
|
||||||
MbmsDownloadManagerCallback callback, int subscriptionId)
|
|
||||||
throws MbmsException {
|
|
||||||
return create(context, callback, subscriptionId, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new MbmsDownloadManager using the given subscription ID.
|
* Create a new MbmsDownloadManager using the given subscription ID.
|
||||||
*
|
*
|
||||||
* 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 MbmsDownloadSession} that is returned will not be ready for use until
|
||||||
* {@link MbmsDownloadManagerCallback#onMiddlewareReady()} is called on the provided callback.
|
* {@link MbmsDownloadSessionCallback#onMiddlewareReady()} 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 instance before it is ready, an {@link IllegalStateException}
|
||||||
|
* will be thrown or an error will be delivered through
|
||||||
|
* {@link MbmsDownloadSessionCallback#onError(int, String)}.
|
||||||
*
|
*
|
||||||
* This also may throw an {@link IllegalArgumentException} or an {@link IllegalStateException}.
|
* This also may throw an {@link IllegalArgumentException}.
|
||||||
*
|
*
|
||||||
* You may only have one instance of {@link MbmsDownloadManager} per UID. If you call this
|
* You may only have one instance of {@link MbmsDownloadSession} per UID. If you call this
|
||||||
* method while there is an active instance of {@link MbmsDownloadManager} in your process
|
* method while there is an active instance of {@link MbmsDownloadSession} in your process
|
||||||
* (in other words, one that has not had {@link #dispose()} called on it), this method will
|
* (in other words, one that has not had {@link #close()} called on it), this method will
|
||||||
* throw an {@link MbmsException}. If you call this method in a different process
|
* throw an {@link IllegalStateException}. If you call this method in a different process
|
||||||
* running under the same UID, an error will be indicated via
|
* running under the same UID, an error will be indicated via
|
||||||
* {@link MbmsDownloadManagerCallback#onError(int, String)}.
|
* {@link MbmsDownloadSessionCallback#onError(int, String)}.
|
||||||
*
|
*
|
||||||
* Note that initialization may fail asynchronously. If you wish to try again after you
|
* 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
|
* receive such an asynchronous error, you must call {@link #close()} on the instance of
|
||||||
* {@link MbmsDownloadManager} that you received before calling this method again.
|
* {@link MbmsDownloadSession} 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 callback A callback to get asynchronous error messages and file service updates.
|
||||||
* @param subscriptionId The data subscription ID to use
|
* @param subscriptionId The data subscription ID to use
|
||||||
|
* @param handler The {@link Handler} on which callbacks should be enqueued.
|
||||||
|
* @return A new instance of {@link MbmsDownloadSession}, or null if an error occurred during
|
||||||
|
* setup.
|
||||||
*/
|
*/
|
||||||
public static MbmsDownloadManager create(Context context,
|
public static @Nullable MbmsDownloadSession create(@NonNull Context context,
|
||||||
MbmsDownloadManagerCallback listener, int subscriptionId, Handler handler)
|
final @NonNull MbmsDownloadSessionCallback callback,
|
||||||
throws MbmsException {
|
int subscriptionId, @NonNull Handler handler) {
|
||||||
if (!sIsInitialized.compareAndSet(false, true)) {
|
if (!sIsInitialized.compareAndSet(false, true)) {
|
||||||
throw new MbmsException(MbmsException.InitializationErrors.ERROR_DUPLICATE_INITIALIZE);
|
throw new IllegalStateException("Cannot have two active instances");
|
||||||
}
|
}
|
||||||
MbmsDownloadManager mdm =
|
MbmsDownloadSession session =
|
||||||
new MbmsDownloadManager(context, listener, subscriptionId, handler);
|
new MbmsDownloadSession(context, callback, subscriptionId, handler);
|
||||||
try {
|
final int result = session.bindAndInitialize();
|
||||||
mdm.bindAndInitialize();
|
if (result != MbmsErrors.SUCCESS) {
|
||||||
} catch (MbmsException e) {
|
|
||||||
sIsInitialized.set(false);
|
sIsInitialized.set(false);
|
||||||
throw e;
|
handler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
callback.onError(result, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return mdm;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindAndInitialize() throws MbmsException {
|
private int bindAndInitialize() {
|
||||||
MbmsUtils.startBinding(mContext, MBMS_DOWNLOAD_SERVICE_ACTION,
|
return MbmsUtils.startBinding(mContext, MBMS_DOWNLOAD_SERVICE_ACTION,
|
||||||
new ServiceConnection() {
|
new ServiceConnection() {
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
@@ -280,12 +285,12 @@ public class MbmsDownloadManager {
|
|||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
Log.e(LOG_TAG, "Runtime exception during initialization");
|
Log.e(LOG_TAG, "Runtime exception during initialization");
|
||||||
sendErrorToApp(
|
sendErrorToApp(
|
||||||
MbmsException.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
|
MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
|
||||||
e.toString());
|
e.toString());
|
||||||
sIsInitialized.set(false);
|
sIsInitialized.set(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result != MbmsException.SUCCESS) {
|
if (result != MbmsErrors.SUCCESS) {
|
||||||
sendErrorToApp(result, "Error returned during initialization");
|
sendErrorToApp(result, "Error returned during initialization");
|
||||||
sIsInitialized.set(false);
|
sIsInitialized.set(false);
|
||||||
return;
|
return;
|
||||||
@@ -293,7 +298,7 @@ public class MbmsDownloadManager {
|
|||||||
try {
|
try {
|
||||||
downloadService.asBinder().linkToDeath(mDeathRecipient, 0);
|
downloadService.asBinder().linkToDeath(mDeathRecipient, 0);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
sendErrorToApp(MbmsException.ERROR_MIDDLEWARE_LOST,
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST,
|
||||||
"Middleware lost during initialization");
|
"Middleware lost during initialization");
|
||||||
sIsInitialized.set(false);
|
sIsInitialized.set(false);
|
||||||
return;
|
return;
|
||||||
@@ -313,39 +318,35 @@ 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 MbmsDownloadManagerCallback#onFileServicesUpdated(List)}
|
* {@link MbmsDownloadSessionCallback#onFileServicesUpdated(List)}
|
||||||
*
|
*
|
||||||
* The serviceClasses argument lets the app filter on types of programming and is opaque data
|
* Asynchronous error codes via the {@link MbmsDownloadSessionCallback#onError(int, String)}
|
||||||
* negotiated beforehand between the app and the carrier.
|
* callback may include any of the errors that are not specific to the streaming use-case.
|
||||||
*
|
*
|
||||||
* This may throw an {@link MbmsException} containing one of the following errors:
|
* May throw an {@link IllegalStateException} or {@link IllegalArgumentException}.
|
||||||
* {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
|
|
||||||
* {@link MbmsException#ERROR_MIDDLEWARE_LOST}
|
|
||||||
*
|
|
||||||
* Asynchronous error codes via the {@link MbmsDownloadManagerCallback#onError(int, String)}
|
|
||||||
* callback can include any of the errors except:
|
|
||||||
* {@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 MbmsDownloadManagerCallback#onFileServicesUpdated(List)} callbacks
|
* {@link MbmsDownloadSessionCallback#onFileServicesUpdated(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).
|
||||||
|
* Values in this list should be negotiated with the wireless carrier prior
|
||||||
|
* to using this API.
|
||||||
*/
|
*/
|
||||||
public void getFileServices(List<String> classList) throws MbmsException {
|
public void requestUpdateFileServices(@NonNull List<String> classList) {
|
||||||
IMbmsDownloadService downloadService = mService.get();
|
IMbmsDownloadService downloadService = mService.get();
|
||||||
if (downloadService == null) {
|
if (downloadService == null) {
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
|
throw new IllegalStateException("Middleware not yet bound");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
int returnCode = downloadService.getFileServices(mSubscriptionId, classList);
|
int returnCode = downloadService.requestUpdateFileServices(mSubscriptionId, classList);
|
||||||
if (returnCode != MbmsException.SUCCESS) {
|
if (returnCode != MbmsErrors.SUCCESS) {
|
||||||
throw new MbmsException(returnCode);
|
sendErrorToApp(returnCode, null);
|
||||||
}
|
}
|
||||||
} 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);
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,31 +358,32 @@ 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, DownloadStateCallback, Handler)}, the framework
|
* {@link #download(DownloadRequest)}, 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 MbmsDownloadManager#DEFAULT_TOP_LEVEL_TEMP_DIRECTORY}.
|
* {@link MbmsDownloadSession#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
|
* you will receive an asynchronous error with code
|
||||||
* {@link MbmsException.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT} unless the
|
* {@link MbmsErrors.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT} unless the
|
||||||
* provided directory is the same as what has been previously configured.
|
* 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. In addition, as an additional sanity
|
||||||
|
* check, an {@link IllegalArgumentException} will be thrown if you attempt to set the temp
|
||||||
|
* file root directory to one of your data roots (the value of {@link Context#getDataDir()},
|
||||||
|
* {@link Context#getFilesDir()}, or {@link Context#getCacheDir()}).
|
||||||
* @param tempFileRootDirectory A directory to place temp files in.
|
* @param tempFileRootDirectory A directory to place temp files in.
|
||||||
*/
|
*/
|
||||||
public void setTempFileRootDirectory(@NonNull File tempFileRootDirectory)
|
public void setTempFileRootDirectory(@NonNull File tempFileRootDirectory) {
|
||||||
throws MbmsException {
|
|
||||||
IMbmsDownloadService downloadService = mService.get();
|
IMbmsDownloadService downloadService = mService.get();
|
||||||
if (downloadService == null) {
|
if (downloadService == null) {
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
|
throw new IllegalStateException("Middleware not yet bound");
|
||||||
}
|
}
|
||||||
if (!tempFileRootDirectory.exists()) {
|
try {
|
||||||
throw new IllegalArgumentException("Provided directory does not exist");
|
validateTempFileRootSanity(tempFileRootDirectory);
|
||||||
}
|
} catch (IOException e) {
|
||||||
if (!tempFileRootDirectory.isDirectory()) {
|
throw new IllegalStateException("Got IOException checking directory sanity");
|
||||||
throw new IllegalArgumentException("Provided File is not a directory");
|
|
||||||
}
|
}
|
||||||
String filePath;
|
String filePath;
|
||||||
try {
|
try {
|
||||||
@@ -392,12 +394,13 @@ public class MbmsDownloadManager {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
int result = downloadService.setTempFileRootDirectory(mSubscriptionId, filePath);
|
int result = downloadService.setTempFileRootDirectory(mSubscriptionId, filePath);
|
||||||
if (result != MbmsException.SUCCESS) {
|
if (result != MbmsErrors.SUCCESS) {
|
||||||
throw new MbmsException(result);
|
sendErrorToApp(result, null);
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
mService.set(null);
|
mService.set(null);
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPreferences prefs = mContext.getSharedPreferences(
|
SharedPreferences prefs = mContext.getSharedPreferences(
|
||||||
@@ -405,10 +408,28 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateTempFileRootSanity(File tempFileRootDirectory) throws IOException {
|
||||||
|
if (!tempFileRootDirectory.exists()) {
|
||||||
|
throw new IllegalArgumentException("Provided directory does not exist");
|
||||||
|
}
|
||||||
|
if (!tempFileRootDirectory.isDirectory()) {
|
||||||
|
throw new IllegalArgumentException("Provided File is not a directory");
|
||||||
|
}
|
||||||
|
String canonicalTempFilePath = tempFileRootDirectory.getCanonicalPath();
|
||||||
|
if (mContext.getDataDir().getCanonicalPath().equals(canonicalTempFilePath)) {
|
||||||
|
throw new IllegalArgumentException("Temp file root cannot be your data dir");
|
||||||
|
}
|
||||||
|
if (mContext.getCacheDir().getCanonicalPath().equals(canonicalTempFilePath)) {
|
||||||
|
throw new IllegalArgumentException("Temp file root cannot be your cache dir");
|
||||||
|
}
|
||||||
|
if (mContext.getFilesDir().getCanonicalPath().equals(canonicalTempFilePath)) {
|
||||||
|
throw new IllegalArgumentException("Temp file root cannot be your files dir");
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Retrieves the currently configured temp file root directory. Returns the file that was
|
* Retrieves the currently configured temp file root directory. Returns the file that was
|
||||||
* configured via {@link #setTempFileRootDirectory(File)} or the default directory
|
* configured via {@link #setTempFileRootDirectory(File)} or the default directory
|
||||||
* {@link #download(DownloadRequest, DownloadStateCallback, Handler)} was called without ever
|
* {@link #download(DownloadRequest)} was called without ever
|
||||||
* setting the temp file root. If neither method has been called since the last time the app's
|
* setting the temp file root. If neither method has been called since the last time the app's
|
||||||
* shared preferences were reset, returns {@code null}.
|
* shared preferences were reset, returns {@code null}.
|
||||||
*
|
*
|
||||||
@@ -426,31 +447,24 @@ public class MbmsDownloadManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests a download of a file that is available via multicast.
|
* Requests the download of a file or set of files that the carrier has indicated to be
|
||||||
|
* available.
|
||||||
*
|
*
|
||||||
* May throw an {@link IllegalArgumentException}
|
* May throw an {@link IllegalArgumentException}
|
||||||
*
|
*
|
||||||
* If {@link #setTempFileRootDirectory(File)} has not called after the app has been installed,
|
* If {@link #setTempFileRootDirectory(File)} has not called after the app has been installed,
|
||||||
* this method will create a directory at the default location defined at
|
* this method will create a directory at the default location defined at
|
||||||
* {@link MbmsDownloadManager#DEFAULT_TOP_LEVEL_TEMP_DIRECTORY} and store that as the temp
|
* {@link MbmsDownloadSession#DEFAULT_TOP_LEVEL_TEMP_DIRECTORY} and store that as the temp
|
||||||
* file root directory.
|
* file root directory.
|
||||||
*
|
*
|
||||||
* Asynchronous errors through the listener include any of the errors
|
* Asynchronous errors through the callback may include any error not specific to the
|
||||||
*
|
* streaming use-case.
|
||||||
* @param request The request that specifies what should be downloaded
|
* @param request The request that specifies what should be downloaded.
|
||||||
* @param stateCallback Optional listener that will be provided progress updates
|
|
||||||
* if the app is running. If {@code null}, no callbacks will be
|
|
||||||
* provided.
|
|
||||||
* @param handler A handler that calls to {@code stateCallback} should be called on. If
|
|
||||||
* null, defaults to the handler provided via
|
|
||||||
* {@link #create(Context, MbmsDownloadManagerCallback, int, Handler)}
|
|
||||||
*/
|
*/
|
||||||
public void download(DownloadRequest request, @Nullable DownloadStateCallback stateCallback,
|
public void download(@NonNull DownloadRequest request) {
|
||||||
Handler handler)
|
|
||||||
throws MbmsException {
|
|
||||||
IMbmsDownloadService downloadService = mService.get();
|
IMbmsDownloadService downloadService = mService.get();
|
||||||
if (downloadService == null) {
|
if (downloadService == null) {
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
|
throw new IllegalStateException("Middleware not yet bound");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see whether the app's set a temp root dir yet, and set it if not.
|
// Check to see whether the app's set a temp root dir yet, and set it if not.
|
||||||
@@ -462,67 +476,151 @@ public class MbmsDownloadManager {
|
|||||||
tempRootDirectory.mkdirs();
|
tempRootDirectory.mkdirs();
|
||||||
setTempFileRootDirectory(tempRootDirectory);
|
setTempFileRootDirectory(tempRootDirectory);
|
||||||
}
|
}
|
||||||
InternalDownloadStateCallback internalCallback = null;
|
|
||||||
if (stateCallback != null) {
|
|
||||||
internalCallback = new InternalDownloadStateCallback(stateCallback,
|
|
||||||
handler == null ? mInternalCallback.getHandler() : handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkValidDownloadDestination(request);
|
|
||||||
writeDownloadRequestToken(request);
|
writeDownloadRequestToken(request);
|
||||||
try {
|
try {
|
||||||
downloadService.download(request, internalCallback);
|
downloadService.download(request);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
mService.set(null);
|
mService.set(null);
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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, DownloadStateCallback, Handler)} but not cancelled through
|
* {@link #download(DownloadRequest)} 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
|
||||||
*/
|
*/
|
||||||
public @NonNull List<DownloadRequest> listPendingDownloads() throws MbmsException {
|
public @NonNull List<DownloadRequest> listPendingDownloads() {
|
||||||
IMbmsDownloadService downloadService = mService.get();
|
IMbmsDownloadService downloadService = mService.get();
|
||||||
if (downloadService == null) {
|
if (downloadService == null) {
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
|
throw new IllegalStateException("Middleware not yet bound");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return downloadService.listPendingDownloads(mSubscriptionId);
|
return downloadService.listPendingDownloads(mSubscriptionId);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
mService.set(null);
|
mService.set(null);
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a callback for a {@link DownloadRequest} previously requested via
|
||||||
|
* {@link #download(DownloadRequest)}. This callback will only be called as long as both this
|
||||||
|
* app and the middleware are both running -- if either one stops, no further calls on the
|
||||||
|
* provided {@link DownloadStateCallback} will be enqueued.
|
||||||
|
*
|
||||||
|
* If the middleware is not aware of the specified download request,
|
||||||
|
* this method will throw an {@link IllegalArgumentException}.
|
||||||
|
*
|
||||||
|
* @param request The {@link DownloadRequest} that you want updates on.
|
||||||
|
* @param callback The callback that should be called when the middleware has information to
|
||||||
|
* share on the download.
|
||||||
|
* @param handler The {@link Handler} on which calls to {@code callback} should be enqueued on.
|
||||||
|
*/
|
||||||
|
public void registerStateCallback(@NonNull DownloadRequest request,
|
||||||
|
@NonNull DownloadStateCallback callback,
|
||||||
|
@NonNull Handler handler) {
|
||||||
|
IMbmsDownloadService downloadService = mService.get();
|
||||||
|
if (downloadService == null) {
|
||||||
|
throw new IllegalStateException("Middleware not yet bound");
|
||||||
|
}
|
||||||
|
|
||||||
|
InternalDownloadStateCallback internalCallback =
|
||||||
|
new InternalDownloadStateCallback(callback, handler);
|
||||||
|
|
||||||
|
try {
|
||||||
|
int result = downloadService.registerStateCallback(request, internalCallback);
|
||||||
|
if (result != MbmsErrors.SUCCESS) {
|
||||||
|
if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
|
||||||
|
throw new IllegalArgumentException("Unknown download request.");
|
||||||
|
}
|
||||||
|
sendErrorToApp(result, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
mService.set(null);
|
||||||
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mInternalDownloadCallbacks.put(callback, internalCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Un-register a callback previously registered via
|
||||||
|
* {@link #registerStateCallback(DownloadRequest, DownloadStateCallback, Handler)}. After
|
||||||
|
* this method is called, no further callbacks will be enqueued on the {@link Handler}
|
||||||
|
* provided upon registration, even if this method throws an exception.
|
||||||
|
*
|
||||||
|
* If the middleware is not aware of the specified download request,
|
||||||
|
* this method will throw an {@link IllegalArgumentException}.
|
||||||
|
*
|
||||||
|
* @param request The {@link DownloadRequest} provided during registration
|
||||||
|
* @param callback The callback provided during registration.
|
||||||
|
*/
|
||||||
|
public void unregisterStateCallback(@NonNull DownloadRequest request,
|
||||||
|
@NonNull DownloadStateCallback callback) {
|
||||||
|
try {
|
||||||
|
IMbmsDownloadService downloadService = mService.get();
|
||||||
|
if (downloadService == null) {
|
||||||
|
throw new IllegalStateException("Middleware not yet bound");
|
||||||
|
}
|
||||||
|
|
||||||
|
InternalDownloadStateCallback internalCallback =
|
||||||
|
mInternalDownloadCallbacks.get(callback);
|
||||||
|
|
||||||
|
try {
|
||||||
|
int result = downloadService.unregisterStateCallback(request, internalCallback);
|
||||||
|
if (result != MbmsErrors.SUCCESS) {
|
||||||
|
if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
|
||||||
|
throw new IllegalArgumentException("Unknown download request.");
|
||||||
|
}
|
||||||
|
sendErrorToApp(result, null);
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
mService.set(null);
|
||||||
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
InternalDownloadStateCallback internalCallback =
|
||||||
|
mInternalDownloadCallbacks.remove(callback);
|
||||||
|
if (internalCallback != null) {
|
||||||
|
internalCallback.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to cancel the specified {@link DownloadRequest}.
|
* Attempts to cancel the specified {@link DownloadRequest}.
|
||||||
*
|
*
|
||||||
* If the middleware is not aware of the specified download request, an MbmsException will be
|
* If the middleware is not aware of the specified download request,
|
||||||
* thrown with error code {@link MbmsException.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST}.
|
* this method will throw an {@link IllegalArgumentException}.
|
||||||
*
|
*
|
||||||
* If this method returns without throwing an exception, you may assume that cancellation
|
|
||||||
* was successful.
|
|
||||||
* @param downloadRequest The download request that you wish to cancel.
|
* @param downloadRequest The download request that you wish to cancel.
|
||||||
*/
|
*/
|
||||||
public void cancelDownload(DownloadRequest downloadRequest) throws MbmsException {
|
public void cancelDownload(@NonNull DownloadRequest downloadRequest) {
|
||||||
IMbmsDownloadService downloadService = mService.get();
|
IMbmsDownloadService downloadService = mService.get();
|
||||||
if (downloadService == null) {
|
if (downloadService == null) {
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
|
throw new IllegalStateException("Middleware not yet bound");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int result = downloadService.cancelDownload(downloadRequest);
|
int result = downloadService.cancelDownload(downloadRequest);
|
||||||
if (result != MbmsException.SUCCESS) {
|
if (result != MbmsErrors.SUCCESS) {
|
||||||
throw new MbmsException(result);
|
if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
|
||||||
|
throw new IllegalArgumentException("Unknown download request.");
|
||||||
|
}
|
||||||
|
sendErrorToApp(result, null);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
mService.set(null);
|
mService.set(null);
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
deleteDownloadRequestToken(downloadRequest);
|
deleteDownloadRequestToken(downloadRequest);
|
||||||
}
|
}
|
||||||
@@ -530,7 +628,7 @@ public class MbmsDownloadManager {
|
|||||||
/**
|
/**
|
||||||
* Gets information about the status of a file pending download.
|
* Gets information about the status of a file pending download.
|
||||||
*
|
*
|
||||||
* If the middleware has not yet been properly initialized or if it has no records of the
|
* If there was a problem communicating with the middleware or if it has no records of the
|
||||||
* file indicated by {@code fileInfo} being associated with {@code downloadRequest},
|
* file indicated by {@code fileInfo} being associated with {@code downloadRequest},
|
||||||
* {@link #STATUS_UNKNOWN} will be returned.
|
* {@link #STATUS_UNKNOWN} will be returned.
|
||||||
*
|
*
|
||||||
@@ -539,18 +637,18 @@ public class MbmsDownloadManager {
|
|||||||
* @return The status of the download.
|
* @return The status of the download.
|
||||||
*/
|
*/
|
||||||
@DownloadStatus
|
@DownloadStatus
|
||||||
public int getDownloadStatus(DownloadRequest downloadRequest, FileInfo fileInfo)
|
public int getDownloadStatus(DownloadRequest downloadRequest, FileInfo fileInfo) {
|
||||||
throws MbmsException {
|
|
||||||
IMbmsDownloadService downloadService = mService.get();
|
IMbmsDownloadService downloadService = mService.get();
|
||||||
if (downloadService == null) {
|
if (downloadService == null) {
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
|
throw new IllegalStateException("Middleware not yet bound");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return downloadService.getDownloadStatus(downloadRequest, fileInfo);
|
return downloadService.getDownloadStatus(downloadRequest, fileInfo);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
mService.set(null);
|
mService.set(null);
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||||
|
return STATUS_UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,30 +664,50 @@ public class MbmsDownloadManager {
|
|||||||
* when available.
|
* when available.
|
||||||
* This will not interrupt in-progress downloads.
|
* This will not interrupt in-progress downloads.
|
||||||
*
|
*
|
||||||
* If the middleware is not aware of the specified download request, an MbmsException will be
|
* This is distinct from cancelling and re-issuing the download request -- if you cancel and
|
||||||
* thrown with error code {@link MbmsException.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST}.
|
* re-issue, the middleware will not clear its cache of download state information.
|
||||||
|
*
|
||||||
|
* If the middleware is not aware of the specified download request, an
|
||||||
|
* {@link IllegalArgumentException} will be thrown.
|
||||||
*
|
*
|
||||||
* May throw a {@link MbmsException} with error code
|
|
||||||
* @param downloadRequest The request to re-download files for.
|
* @param downloadRequest The request to re-download files for.
|
||||||
*/
|
*/
|
||||||
public void resetDownloadKnowledge(DownloadRequest downloadRequest) throws MbmsException {
|
public void resetDownloadKnowledge(DownloadRequest downloadRequest) {
|
||||||
IMbmsDownloadService downloadService = mService.get();
|
IMbmsDownloadService downloadService = mService.get();
|
||||||
if (downloadService == null) {
|
if (downloadService == null) {
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
|
throw new IllegalStateException("Middleware not yet bound");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int result = downloadService.resetDownloadKnowledge(downloadRequest);
|
int result = downloadService.resetDownloadKnowledge(downloadRequest);
|
||||||
if (result != MbmsException.SUCCESS) {
|
if (result != MbmsErrors.SUCCESS) {
|
||||||
throw new MbmsException(result);
|
if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
|
||||||
|
throw new IllegalArgumentException("Unknown download request.");
|
||||||
|
}
|
||||||
|
sendErrorToApp(result, null);
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
mService.set(null);
|
mService.set(null);
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispose() {
|
/**
|
||||||
|
* Terminates this instance.
|
||||||
|
*
|
||||||
|
* After this method returns,
|
||||||
|
* no further callbacks originating from the middleware will be enqueued on the provided
|
||||||
|
* instance of {@link MbmsDownloadSessionCallback}, but callbacks that have already been
|
||||||
|
* enqueued will still be delivered.
|
||||||
|
*
|
||||||
|
* It is safe to call {@link #create(Context, MbmsDownloadSessionCallback, int, Handler)} to
|
||||||
|
* obtain another instance of {@link MbmsDownloadSession} immediately after this method
|
||||||
|
* returns.
|
||||||
|
*
|
||||||
|
* May throw an {@link IllegalStateException}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
try {
|
try {
|
||||||
IMbmsDownloadService downloadService = mService.get();
|
IMbmsDownloadService downloadService = mService.get();
|
||||||
if (downloadService == null) {
|
if (downloadService == null) {
|
||||||
@@ -603,6 +721,7 @@ public class MbmsDownloadManager {
|
|||||||
} finally {
|
} finally {
|
||||||
mService.set(null);
|
mService.set(null);
|
||||||
sIsInitialized.set(false);
|
sIsInitialized.set(false);
|
||||||
|
mInternalCallback.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -645,35 +764,9 @@ public class MbmsDownloadManager {
|
|||||||
return new File(tempFileLocation, downloadTokenFileName);
|
return new File(tempFileLocation, downloadTokenFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies the following:
|
|
||||||
* If a request is multi-part,
|
|
||||||
* 1. Destination Uri must exist and be a directory
|
|
||||||
* 2. Directory specified must contain no files.
|
|
||||||
* Otherwise
|
|
||||||
* 1. The file specified by the destination Uri must not exist.
|
|
||||||
*/
|
|
||||||
private void checkValidDownloadDestination(DownloadRequest request) {
|
|
||||||
File toFile = new File(request.getDestinationUri().getSchemeSpecificPart());
|
|
||||||
if (request.isMultipartDownload()) {
|
|
||||||
if (!toFile.isDirectory()) {
|
|
||||||
throw new IllegalArgumentException("Multipart download must specify valid " +
|
|
||||||
"destination directory.");
|
|
||||||
}
|
|
||||||
if (toFile.listFiles().length > 0) {
|
|
||||||
throw new IllegalArgumentException("Destination directory must be clear of all " +
|
|
||||||
"files.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (toFile.exists()) {
|
|
||||||
throw new IllegalArgumentException("Destination file must not exist.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendErrorToApp(int errorCode, String message) {
|
private void sendErrorToApp(int errorCode, String message) {
|
||||||
try {
|
try {
|
||||||
mInternalCallback.error(errorCode, message);
|
mInternalCallback.onError(errorCode, message);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Ignore, should not happen locally.
|
// Ignore, should not happen locally.
|
||||||
}
|
}
|
||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package android.telephony;
|
package android.telephony;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.annotation.SdkConstant;
|
import android.annotation.SdkConstant;
|
||||||
import android.annotation.SystemApi;
|
import android.annotation.SystemApi;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
@@ -25,18 +27,20 @@ import android.os.Handler;
|
|||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.telephony.mbms.InternalStreamingManagerCallback;
|
import android.telephony.mbms.InternalStreamingSessionCallback;
|
||||||
import android.telephony.mbms.InternalStreamingServiceCallback;
|
import android.telephony.mbms.InternalStreamingServiceCallback;
|
||||||
import android.telephony.mbms.MbmsException;
|
import android.telephony.mbms.MbmsErrors;
|
||||||
import android.telephony.mbms.MbmsStreamingManagerCallback;
|
import android.telephony.mbms.MbmsStreamingSessionCallback;
|
||||||
import android.telephony.mbms.MbmsUtils;
|
import android.telephony.mbms.MbmsUtils;
|
||||||
import android.telephony.mbms.StreamingService;
|
import android.telephony.mbms.StreamingService;
|
||||||
import android.telephony.mbms.StreamingServiceCallback;
|
import android.telephony.mbms.StreamingServiceCallback;
|
||||||
import android.telephony.mbms.StreamingServiceInfo;
|
import android.telephony.mbms.StreamingServiceInfo;
|
||||||
import android.telephony.mbms.vendor.IMbmsStreamingService;
|
import android.telephony.mbms.vendor.IMbmsStreamingService;
|
||||||
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
@@ -46,8 +50,8 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
|||||||
* This class provides functionality for streaming media over MBMS.
|
* This class provides functionality for streaming media over MBMS.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class MbmsStreamingManager {
|
public class MbmsStreamingSession implements AutoCloseable {
|
||||||
private static final String LOG_TAG = "MbmsStreamingManager";
|
private static final String LOG_TAG = "MbmsStreamingSession";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service action which must be handled by the middleware implementing the MBMS streaming
|
* Service action which must be handled by the middleware implementing the MBMS streaming
|
||||||
@@ -66,98 +70,98 @@ public class MbmsStreamingManager {
|
|||||||
@Override
|
@Override
|
||||||
public void binderDied() {
|
public void binderDied() {
|
||||||
sIsInitialized.set(false);
|
sIsInitialized.set(false);
|
||||||
sendErrorToApp(MbmsException.ERROR_MIDDLEWARE_LOST, "Received death notification");
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, "Received death notification");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private InternalStreamingManagerCallback mInternalCallback;
|
private InternalStreamingSessionCallback mInternalCallback;
|
||||||
|
private Set<StreamingService> mKnownActiveStreamingServices = new ArraySet<>();
|
||||||
|
|
||||||
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 MbmsStreamingSession(Context context, MbmsStreamingSessionCallback callback,
|
||||||
int subscriptionId, Handler handler) {
|
int subscriptionId, Handler handler) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mSubscriptionId = subscriptionId;
|
mSubscriptionId = subscriptionId;
|
||||||
if (handler == null) {
|
if (handler == null) {
|
||||||
handler = new Handler(Looper.getMainLooper());
|
handler = new Handler(Looper.getMainLooper());
|
||||||
}
|
}
|
||||||
mInternalCallback = new InternalStreamingManagerCallback(callback, handler);
|
mInternalCallback = new InternalStreamingSessionCallback(callback, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new MbmsStreamingManager using the given subscription ID.
|
* Create a new {@link MbmsStreamingSession} using the given subscription ID.
|
||||||
*
|
*
|
||||||
* Note that this call will bind a remote service. You may not call this method on your app's
|
* Note that this call will bind a remote service. You may not call this method on your app's
|
||||||
* main thread. This may throw an {@link MbmsException}, indicating errors that may happen
|
* main thread.
|
||||||
* during the initialization or binding process.
|
|
||||||
*
|
*
|
||||||
*
|
* You may only have one instance of {@link MbmsStreamingSession} per UID. If you call this
|
||||||
* You may only have one instance of {@link MbmsStreamingManager} per UID. If you call this
|
* method while there is an active instance of {@link MbmsStreamingSession} in your process
|
||||||
* method while there is an active instance of {@link MbmsStreamingManager} in your process
|
* (in other words, one that has not had {@link #close()} called on it), this method will
|
||||||
* (in other words, one that has not had {@link #dispose()} called on it), this method will
|
* throw an {@link IllegalStateException}. If you call this method in a different process
|
||||||
* throw an {@link MbmsException}. If you call this method in a different process
|
|
||||||
* running under the same UID, an error will be indicated via
|
* running under the same UID, an error will be indicated via
|
||||||
* {@link MbmsStreamingManagerCallback#onError(int, String)}.
|
* {@link MbmsStreamingSessionCallback#onError(int, String)}.
|
||||||
*
|
*
|
||||||
* Note that initialization may fail asynchronously. If you wish to try again after you
|
* 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
|
* receive such an asynchronous error, you must call {@link #close()} on the instance of
|
||||||
* {@link MbmsStreamingManager} that you received before calling this method again.
|
* {@link MbmsStreamingSession} 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
|
* @param handler The handler you wish to receive callbacks on.
|
||||||
* processed on the main looper (in other words, the looper returned from
|
* @return An instance of {@link MbmsStreamingSession}, or null if an error occurred.
|
||||||
* {@link Looper#getMainLooper()}).
|
|
||||||
*/
|
*/
|
||||||
public static MbmsStreamingManager create(Context context,
|
public static @Nullable MbmsStreamingSession create(@NonNull Context context,
|
||||||
MbmsStreamingManagerCallback callback, int subscriptionId, Handler handler)
|
final @NonNull MbmsStreamingSessionCallback callback, int subscriptionId,
|
||||||
throws MbmsException {
|
@NonNull Handler handler) {
|
||||||
if (!sIsInitialized.compareAndSet(false, true)) {
|
if (!sIsInitialized.compareAndSet(false, true)) {
|
||||||
throw new MbmsException(MbmsException.InitializationErrors.ERROR_DUPLICATE_INITIALIZE);
|
throw new IllegalStateException("Cannot create two instances of MbmsStreamingSession");
|
||||||
}
|
}
|
||||||
MbmsStreamingManager manager = new MbmsStreamingManager(context, callback,
|
MbmsStreamingSession session = new MbmsStreamingSession(context, callback,
|
||||||
subscriptionId, handler);
|
subscriptionId, handler);
|
||||||
try {
|
|
||||||
manager.bindAndInitialize();
|
final int result = session.bindAndInitialize();
|
||||||
} catch (MbmsException e) {
|
if (result != MbmsErrors.SUCCESS) {
|
||||||
sIsInitialized.set(false);
|
sIsInitialized.set(false);
|
||||||
throw e;
|
handler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
callback.onError(result, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return manager;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new MbmsStreamingManager using the system default data subscription ID.
|
* Create a new {@link MbmsStreamingSession} using the system default data subscription ID.
|
||||||
* See {@link #create(Context, MbmsStreamingManagerCallback, int, Handler)}.
|
* See {@link #create(Context, MbmsStreamingSessionCallback, int, Handler)}.
|
||||||
*/
|
*/
|
||||||
public static MbmsStreamingManager create(Context context,
|
public static MbmsStreamingSession create(@NonNull Context context,
|
||||||
MbmsStreamingManagerCallback callback, Handler handler)
|
@NonNull MbmsStreamingSessionCallback callback, @NonNull Handler handler) {
|
||||||
throws MbmsException {
|
|
||||||
return create(context, callback, SubscriptionManager.getDefaultSubscriptionId(), handler);
|
return create(context, callback, SubscriptionManager.getDefaultSubscriptionId(), handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new MbmsStreamingManager using the system default data subscription ID and
|
* Terminates this instance. Also terminates
|
||||||
* default {@link Handler}.
|
* any streaming services spawned from this instance as if
|
||||||
* See {@link #create(Context, MbmsStreamingManagerCallback, int, Handler)}.
|
* {@link StreamingService#stopStreaming()} had been called on them. After this method returns,
|
||||||
*/
|
* no further callbacks originating from the middleware will be enqueued on the provided
|
||||||
public static MbmsStreamingManager create(Context context,
|
* instance of {@link MbmsStreamingSessionCallback}, but callbacks that have already been
|
||||||
MbmsStreamingManagerCallback callback)
|
* enqueued will still be delivered.
|
||||||
throws MbmsException {
|
*
|
||||||
return create(context, callback, SubscriptionManager.getDefaultSubscriptionId(), null);
|
* It is safe to call {@link #create(Context, MbmsStreamingSessionCallback, int, Handler)} to
|
||||||
}
|
* obtain another instance of {@link MbmsStreamingSession} immediately after this method
|
||||||
|
* returns.
|
||||||
/**
|
|
||||||
* Terminates this instance, ending calls to the registered listener. Also terminates
|
|
||||||
* any streaming services spawned from this instance.
|
|
||||||
*
|
*
|
||||||
* May throw an {@link IllegalStateException}
|
* May throw an {@link IllegalStateException}
|
||||||
*/
|
*/
|
||||||
public void dispose() {
|
public void close() {
|
||||||
try {
|
try {
|
||||||
IMbmsStreamingService streamingService = mService.get();
|
IMbmsStreamingService streamingService = mService.get();
|
||||||
if (streamingService == null) {
|
if (streamingService == null) {
|
||||||
@@ -165,47 +169,49 @@ public class MbmsStreamingManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
streamingService.dispose(mSubscriptionId);
|
streamingService.dispose(mSubscriptionId);
|
||||||
|
for (StreamingService s : mKnownActiveStreamingServices) {
|
||||||
|
s.getCallback().stop();
|
||||||
|
}
|
||||||
|
mKnownActiveStreamingServices.clear();
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Ignore for now
|
// Ignore for now
|
||||||
} finally {
|
} finally {
|
||||||
mService.set(null);
|
mService.set(null);
|
||||||
sIsInitialized.set(false);
|
sIsInitialized.set(false);
|
||||||
|
mInternalCallback.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An inspection API to retrieve the list of streaming media currently be advertised.
|
* An inspection API to retrieve the list of streaming media currently be advertised.
|
||||||
* The results are returned asynchronously through the previously registered callback.
|
* The results are returned asynchronously via
|
||||||
* serviceClasses lets the app filter on types of programming and is opaque data between
|
* {@link MbmsStreamingSessionCallback#onStreamingServicesUpdated(List)} on the callback
|
||||||
* the app and the carrier.
|
* provided upon creation.
|
||||||
*
|
*
|
||||||
* Multiple calls replace the list of serviceClasses of interest.
|
* Multiple calls replace the list of service classes of interest.
|
||||||
*
|
*
|
||||||
* This may throw an {@link MbmsException} containing any error in
|
* May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}.
|
||||||
* {@link android.telephony.mbms.MbmsException.GeneralErrors},
|
|
||||||
* {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}, or
|
|
||||||
* {@link MbmsException#ERROR_MIDDLEWARE_LOST}.
|
|
||||||
*
|
*
|
||||||
* May also throw an unchecked {@link IllegalArgumentException} or an
|
* @param serviceClassList A list of streaming service classes that the app would like updates
|
||||||
* {@link IllegalStateException}
|
* on. The exact names of these classes should be negotiated with the
|
||||||
*
|
* wireless carrier separately.
|
||||||
* @param classList A list of streaming service classes that the app would like updates on.
|
|
||||||
*/
|
*/
|
||||||
public void getStreamingServices(List<String> classList) throws MbmsException {
|
public void requestUpdateStreamingServices(List<String> serviceClassList) {
|
||||||
IMbmsStreamingService streamingService = mService.get();
|
IMbmsStreamingService streamingService = mService.get();
|
||||||
if (streamingService == null) {
|
if (streamingService == null) {
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
|
throw new IllegalStateException("Middleware not yet bound");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
int returnCode = streamingService.getStreamingServices(mSubscriptionId, classList);
|
int returnCode = streamingService.requestUpdateStreamingServices(
|
||||||
if (returnCode != MbmsException.SUCCESS) {
|
mSubscriptionId, serviceClassList);
|
||||||
throw new MbmsException(returnCode);
|
if (returnCode != MbmsErrors.SUCCESS) {
|
||||||
|
sendErrorToApp(returnCode, null);
|
||||||
}
|
}
|
||||||
} 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);
|
sIsInitialized.set(false);
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,56 +222,57 @@ public class MbmsStreamingManager {
|
|||||||
* reported via
|
* reported via
|
||||||
* {@link android.telephony.mbms.StreamingServiceCallback#onStreamStateUpdated(int, int)}
|
* {@link android.telephony.mbms.StreamingServiceCallback#onStreamStateUpdated(int, int)}
|
||||||
*
|
*
|
||||||
* May throw an
|
* May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
|
||||||
* {@link MbmsException} containing any of the error codes in
|
|
||||||
* {@link android.telephony.mbms.MbmsException.GeneralErrors},
|
|
||||||
* {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}, or
|
|
||||||
* {@link MbmsException#ERROR_MIDDLEWARE_LOST}.
|
|
||||||
*
|
|
||||||
* May also throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
|
|
||||||
*
|
*
|
||||||
* Asynchronous errors through the callback 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 MbmsErrors.GeneralErrors} or
|
||||||
* {@link android.telephony.mbms.MbmsException.StreamingErrors}.
|
* {@link MbmsErrors.StreamingErrors}.
|
||||||
*
|
*
|
||||||
* @param serviceInfo The information about the service to stream.
|
* @param serviceInfo The information about the service to stream.
|
||||||
* @param callback A callback 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,
|
* @param handler A handler that calls to {@code callback} should be called on.
|
||||||
* 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.
|
||||||
|
* May be {@code null} if an error occurred.
|
||||||
*/
|
*/
|
||||||
public StreamingService startStreaming(StreamingServiceInfo serviceInfo,
|
public @Nullable StreamingService startStreaming(StreamingServiceInfo serviceInfo,
|
||||||
StreamingServiceCallback callback, Handler handler) throws MbmsException {
|
StreamingServiceCallback callback, @NonNull Handler handler) {
|
||||||
IMbmsStreamingService streamingService = mService.get();
|
IMbmsStreamingService streamingService = mService.get();
|
||||||
if (streamingService == null) {
|
if (streamingService == null) {
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
|
throw new IllegalStateException("Middleware not yet bound");
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalStreamingServiceCallback serviceCallback = new InternalStreamingServiceCallback(
|
InternalStreamingServiceCallback serviceCallback = new InternalStreamingServiceCallback(
|
||||||
callback, handler == null ? mInternalCallback.getHandler() : handler);
|
callback, handler);
|
||||||
|
|
||||||
StreamingService serviceForApp = new StreamingService(
|
StreamingService serviceForApp = new StreamingService(
|
||||||
mSubscriptionId, streamingService, serviceInfo, serviceCallback);
|
mSubscriptionId, streamingService, this, serviceInfo, serviceCallback);
|
||||||
|
mKnownActiveStreamingServices.add(serviceForApp);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int returnCode = streamingService.startStreaming(
|
int returnCode = streamingService.startStreaming(
|
||||||
mSubscriptionId, serviceInfo.getServiceId(), serviceCallback);
|
mSubscriptionId, serviceInfo.getServiceId(), serviceCallback);
|
||||||
if (returnCode != MbmsException.SUCCESS) {
|
if (returnCode != MbmsErrors.SUCCESS) {
|
||||||
throw new MbmsException(returnCode);
|
sendErrorToApp(returnCode, null);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
} 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);
|
sIsInitialized.set(false);
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return serviceForApp;
|
return serviceForApp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindAndInitialize() throws MbmsException {
|
/** @hide */
|
||||||
MbmsUtils.startBinding(mContext, MBMS_STREAMING_SERVICE_ACTION,
|
public void onStreamingServiceStopped(StreamingService service) {
|
||||||
|
mKnownActiveStreamingServices.remove(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int bindAndInitialize() {
|
||||||
|
return MbmsUtils.startBinding(mContext, MBMS_STREAMING_SERVICE_ACTION,
|
||||||
new ServiceConnection() {
|
new ServiceConnection() {
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
@@ -278,19 +285,19 @@ public class MbmsStreamingManager {
|
|||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(LOG_TAG, "Service died before initialization");
|
Log.e(LOG_TAG, "Service died before initialization");
|
||||||
sendErrorToApp(
|
sendErrorToApp(
|
||||||
MbmsException.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
|
MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
|
||||||
e.toString());
|
e.toString());
|
||||||
sIsInitialized.set(false);
|
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");
|
||||||
sendErrorToApp(
|
sendErrorToApp(
|
||||||
MbmsException.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
|
MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
|
||||||
e.toString());
|
e.toString());
|
||||||
sIsInitialized.set(false);
|
sIsInitialized.set(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result != MbmsException.SUCCESS) {
|
if (result != MbmsErrors.SUCCESS) {
|
||||||
sendErrorToApp(result, "Error returned during initialization");
|
sendErrorToApp(result, "Error returned during initialization");
|
||||||
sIsInitialized.set(false);
|
sIsInitialized.set(false);
|
||||||
return;
|
return;
|
||||||
@@ -298,7 +305,7 @@ public class MbmsStreamingManager {
|
|||||||
try {
|
try {
|
||||||
streamingService.asBinder().linkToDeath(mDeathRecipient, 0);
|
streamingService.asBinder().linkToDeath(mDeathRecipient, 0);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
sendErrorToApp(MbmsException.ERROR_MIDDLEWARE_LOST,
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST,
|
||||||
"Middleware lost during initialization");
|
"Middleware lost during initialization");
|
||||||
sIsInitialized.set(false);
|
sIsInitialized.set(false);
|
||||||
return;
|
return;
|
||||||
@@ -316,7 +323,7 @@ public class MbmsStreamingManager {
|
|||||||
|
|
||||||
private void sendErrorToApp(int errorCode, String message) {
|
private void sendErrorToApp(int errorCode, String message) {
|
||||||
try {
|
try {
|
||||||
mInternalCallback.error(errorCode, message);
|
mInternalCallback.onError(errorCode, message);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Ignore, should not happen locally.
|
// Ignore, should not happen locally.
|
||||||
}
|
}
|
||||||
@@ -56,12 +56,10 @@ public final class DownloadRequest implements Parcelable {
|
|||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
private static class OpaqueDataContainer implements Serializable {
|
private static class OpaqueDataContainer implements Serializable {
|
||||||
private final String destinationUri;
|
|
||||||
private final String appIntent;
|
private final String appIntent;
|
||||||
private final int version;
|
private final int version;
|
||||||
|
|
||||||
public OpaqueDataContainer(String destinationUri, String appIntent, int version) {
|
public OpaqueDataContainer(String appIntent, int version) {
|
||||||
this.destinationUri = destinationUri;
|
|
||||||
this.appIntent = appIntent;
|
this.appIntent = appIntent;
|
||||||
this.version = version;
|
this.version = version;
|
||||||
}
|
}
|
||||||
@@ -70,7 +68,6 @@ public final class DownloadRequest implements Parcelable {
|
|||||||
public static class Builder {
|
public static class Builder {
|
||||||
private String fileServiceId;
|
private String fileServiceId;
|
||||||
private Uri source;
|
private Uri source;
|
||||||
private Uri dest;
|
|
||||||
private int subscriptionId;
|
private int subscriptionId;
|
||||||
private String appIntent;
|
private String appIntent;
|
||||||
private int version = CURRENT_VERSION;
|
private int version = CURRENT_VERSION;
|
||||||
@@ -104,21 +101,6 @@ public final class DownloadRequest implements Parcelable {
|
|||||||
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.
|
|
||||||
*/
|
|
||||||
public Builder setDest(Uri dest) {
|
|
||||||
if (dest.toString().length() > MAX_DESTINATION_URI_SIZE) {
|
|
||||||
throw new IllegalArgumentException("Destination uri must not exceed length " +
|
|
||||||
MAX_DESTINATION_URI_SIZE);
|
|
||||||
}
|
|
||||||
this.dest = dest;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the subscription ID on which the file(s) should be downloaded.
|
* Set the subscription ID on which the file(s) should be downloaded.
|
||||||
* @param subscriptionId
|
* @param subscriptionId
|
||||||
@@ -160,7 +142,6 @@ public final class DownloadRequest implements Parcelable {
|
|||||||
OpaqueDataContainer dataContainer = (OpaqueDataContainer) stream.readObject();
|
OpaqueDataContainer dataContainer = (OpaqueDataContainer) stream.readObject();
|
||||||
version = dataContainer.version;
|
version = dataContainer.version;
|
||||||
appIntent = dataContainer.appIntent;
|
appIntent = dataContainer.appIntent;
|
||||||
dest = Uri.parse(dataContainer.destinationUri);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// Really should never happen
|
// Really should never happen
|
||||||
Log.e(LOG_TAG, "Got IOException trying to parse opaque data");
|
Log.e(LOG_TAG, "Got IOException trying to parse opaque data");
|
||||||
@@ -173,24 +154,21 @@ public final class DownloadRequest implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DownloadRequest build() {
|
public DownloadRequest build() {
|
||||||
return new DownloadRequest(fileServiceId, source, dest,
|
return new DownloadRequest(fileServiceId, source, subscriptionId, appIntent, version);
|
||||||
subscriptionId, appIntent, version);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String fileServiceId;
|
private final String fileServiceId;
|
||||||
private final Uri sourceUri;
|
private final Uri sourceUri;
|
||||||
private final Uri destinationUri;
|
|
||||||
private final int subscriptionId;
|
private final int subscriptionId;
|
||||||
private final String serializedResultIntentForApp;
|
private final String serializedResultIntentForApp;
|
||||||
private final int version;
|
private final int version;
|
||||||
|
|
||||||
private DownloadRequest(String fileServiceId,
|
private DownloadRequest(String fileServiceId,
|
||||||
Uri source, Uri dest,
|
Uri source, int sub,
|
||||||
int sub, String appIntent, int version) {
|
String appIntent, int version) {
|
||||||
this.fileServiceId = fileServiceId;
|
this.fileServiceId = fileServiceId;
|
||||||
sourceUri = source;
|
sourceUri = source;
|
||||||
destinationUri = dest;
|
|
||||||
subscriptionId = sub;
|
subscriptionId = sub;
|
||||||
serializedResultIntentForApp = appIntent;
|
serializedResultIntentForApp = appIntent;
|
||||||
this.version = version;
|
this.version = version;
|
||||||
@@ -203,7 +181,6 @@ public final class DownloadRequest implements Parcelable {
|
|||||||
private DownloadRequest(DownloadRequest dr) {
|
private DownloadRequest(DownloadRequest dr) {
|
||||||
fileServiceId = dr.fileServiceId;
|
fileServiceId = dr.fileServiceId;
|
||||||
sourceUri = dr.sourceUri;
|
sourceUri = dr.sourceUri;
|
||||||
destinationUri = dr.destinationUri;
|
|
||||||
subscriptionId = dr.subscriptionId;
|
subscriptionId = dr.subscriptionId;
|
||||||
serializedResultIntentForApp = dr.serializedResultIntentForApp;
|
serializedResultIntentForApp = dr.serializedResultIntentForApp;
|
||||||
version = dr.version;
|
version = dr.version;
|
||||||
@@ -212,7 +189,6 @@ public final class DownloadRequest implements Parcelable {
|
|||||||
private DownloadRequest(Parcel in) {
|
private DownloadRequest(Parcel in) {
|
||||||
fileServiceId = in.readString();
|
fileServiceId = in.readString();
|
||||||
sourceUri = in.readParcelable(getClass().getClassLoader());
|
sourceUri = in.readParcelable(getClass().getClassLoader());
|
||||||
destinationUri = in.readParcelable(getClass().getClassLoader());
|
|
||||||
subscriptionId = in.readInt();
|
subscriptionId = in.readInt();
|
||||||
serializedResultIntentForApp = in.readString();
|
serializedResultIntentForApp = in.readString();
|
||||||
version = in.readInt();
|
version = in.readInt();
|
||||||
@@ -225,7 +201,6 @@ public final class DownloadRequest implements Parcelable {
|
|||||||
public void writeToParcel(Parcel out, int flags) {
|
public void writeToParcel(Parcel out, int flags) {
|
||||||
out.writeString(fileServiceId);
|
out.writeString(fileServiceId);
|
||||||
out.writeParcelable(sourceUri, flags);
|
out.writeParcelable(sourceUri, flags);
|
||||||
out.writeParcelable(destinationUri, flags);
|
|
||||||
out.writeInt(subscriptionId);
|
out.writeInt(subscriptionId);
|
||||||
out.writeString(serializedResultIntentForApp);
|
out.writeString(serializedResultIntentForApp);
|
||||||
out.writeInt(version);
|
out.writeInt(version);
|
||||||
@@ -245,14 +220,6 @@ public final class DownloadRequest implements Parcelable {
|
|||||||
return sourceUri;
|
return sourceUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* For use by the client app only.
|
|
||||||
* @return The URI of the final destination of the download.
|
|
||||||
*/
|
|
||||||
public Uri getDestinationUri() {
|
|
||||||
return destinationUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The subscription ID on which to perform MBMS operations.
|
* @return The subscription ID on which to perform MBMS operations.
|
||||||
*/
|
*/
|
||||||
@@ -286,7 +253,7 @@ public final class DownloadRequest implements Parcelable {
|
|||||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
ObjectOutputStream stream = new ObjectOutputStream(byteArrayOutputStream);
|
ObjectOutputStream stream = new ObjectOutputStream(byteArrayOutputStream);
|
||||||
OpaqueDataContainer container = new OpaqueDataContainer(
|
OpaqueDataContainer container = new OpaqueDataContainer(
|
||||||
destinationUri.toString(), serializedResultIntentForApp, version);
|
serializedResultIntentForApp, version);
|
||||||
stream.writeObject(container);
|
stream.writeObject(container);
|
||||||
stream.flush();
|
stream.flush();
|
||||||
return byteArrayOutputStream.toByteArray();
|
return byteArrayOutputStream.toByteArray();
|
||||||
@@ -352,7 +319,6 @@ public final class DownloadRequest implements Parcelable {
|
|||||||
if (version >= 1) {
|
if (version >= 1) {
|
||||||
// Hash the source URI, destination URI, and the app intent
|
// Hash the source URI, destination URI, and the app intent
|
||||||
digest.update(sourceUri.toString().getBytes(StandardCharsets.UTF_8));
|
digest.update(sourceUri.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
digest.update(destinationUri.toString().getBytes(StandardCharsets.UTF_8));
|
|
||||||
digest.update(serializedResultIntentForApp.getBytes(StandardCharsets.UTF_8));
|
digest.update(serializedResultIntentForApp.getBytes(StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
// Add updates for future versions here
|
// Add updates for future versions here
|
||||||
@@ -373,13 +339,12 @@ public final class DownloadRequest implements Parcelable {
|
|||||||
version == request.version &&
|
version == request.version &&
|
||||||
Objects.equals(fileServiceId, request.fileServiceId) &&
|
Objects.equals(fileServiceId, request.fileServiceId) &&
|
||||||
Objects.equals(sourceUri, request.sourceUri) &&
|
Objects.equals(sourceUri, request.sourceUri) &&
|
||||||
Objects.equals(destinationUri, request.destinationUri) &&
|
|
||||||
Objects.equals(serializedResultIntentForApp, request.serializedResultIntentForApp);
|
Objects.equals(serializedResultIntentForApp, request.serializedResultIntentForApp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(fileServiceId, sourceUri, destinationUri,
|
return Objects.hash(fileServiceId, sourceUri,
|
||||||
subscriptionId, serializedResultIntentForApp, version);
|
subscriptionId, serializedResultIntentForApp, version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,12 @@
|
|||||||
|
|
||||||
package android.telephony.mbms;
|
package android.telephony.mbms;
|
||||||
|
|
||||||
import android.os.Handler;
|
import android.telephony.MbmsDownloadSession;
|
||||||
import android.telephony.MbmsDownloadManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A optional listener class used by download clients to track progress. Apps should extend this
|
* A optional listener class used by download clients to track progress. Apps should extend this
|
||||||
* class and pass an instance into
|
* class and pass an instance into
|
||||||
* {@link android.telephony.MbmsDownloadManager#download(
|
* {@link MbmsDownloadSession#download(DownloadRequest)}
|
||||||
* DownloadRequest, DownloadStateCallback, Handler)}
|
|
||||||
*
|
*
|
||||||
* This is optionally specified when requesting a download and will only be called while the app
|
* This is optionally specified when requesting a download and will only be called while the app
|
||||||
* is running.
|
* is running.
|
||||||
@@ -59,7 +57,7 @@ public class DownloadStateCallback {
|
|||||||
* may not have been able to get a list of them in advance.
|
* may not have been able to get a list of them in advance.
|
||||||
* @param state The current state of the download.
|
* @param state The current state of the download.
|
||||||
*/
|
*/
|
||||||
public void onStateChanged(DownloadRequest request, FileInfo fileInfo,
|
public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
|
||||||
@MbmsDownloadManager.DownloadStatus int state) {
|
@MbmsDownloadSession.DownloadStatus int state) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public final class FileServiceInfo extends ServiceInfo implements Parcelable {
|
|||||||
FileServiceInfo(Parcel in) {
|
FileServiceInfo(Parcel in) {
|
||||||
super(in);
|
super(in);
|
||||||
files = new ArrayList<FileInfo>();
|
files = new ArrayList<FileInfo>();
|
||||||
in.readList(files, null);
|
in.readList(files, FileInfo.class.getClassLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -29,8 +29,9 @@ interface IDownloadStateCallback
|
|||||||
* Gives progress callbacks for a given DownloadRequest. Includes a FileInfo
|
* Gives progress callbacks for a given DownloadRequest. Includes a FileInfo
|
||||||
* as the list of files may not have been known at request-time.
|
* as the list of files may not have been known at request-time.
|
||||||
*/
|
*/
|
||||||
void progress(in DownloadRequest request, in FileInfo fileInfo, int currentDownloadSize,
|
void onProgressUpdated(in DownloadRequest request, in FileInfo fileInfo,
|
||||||
int fullDownloadSize, int currentDecodedSize, int fullDecodedSize);
|
int currentDownloadSize, int fullDownloadSize,
|
||||||
|
int currentDecodedSize, int fullDecodedSize);
|
||||||
|
|
||||||
void state(in DownloadRequest request, in FileInfo fileInfo, int state);
|
void onStateUpdated(in DownloadRequest request, in FileInfo fileInfo, int state);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ import java.util.List;
|
|||||||
* The interface the clients top-level file download listener will satisfy.
|
* The interface the clients top-level file download listener will satisfy.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
oneway interface IMbmsDownloadManagerCallback
|
oneway interface IMbmsDownloadSessionCallback
|
||||||
{
|
{
|
||||||
void error(int errorCode, String message);
|
void onError(int errorCode, String message);
|
||||||
|
|
||||||
void fileServicesUpdated(in List<FileServiceInfo> services);
|
void onFileServicesUpdated(in List<FileServiceInfo> services);
|
||||||
|
|
||||||
void middlewareReady();
|
void onMiddlewareReady();
|
||||||
}
|
}
|
||||||
@@ -24,11 +24,11 @@ import java.util.List;
|
|||||||
* The interface the clients top-level streaming listener will satisfy.
|
* The interface the clients top-level streaming listener will satisfy.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
oneway interface IMbmsStreamingManagerCallback
|
oneway interface IMbmsStreamingSessionCallback
|
||||||
{
|
{
|
||||||
void error(int errorCode, String message);
|
void onError(int errorCode, String message);
|
||||||
|
|
||||||
void streamingServicesUpdated(in List<StreamingServiceInfo> services);
|
void onStreamingServicesUpdated(in List<StreamingServiceInfo> services);
|
||||||
|
|
||||||
void middlewareReady();
|
void onMiddlewareReady();
|
||||||
}
|
}
|
||||||
@@ -20,9 +20,9 @@ package android.telephony.mbms;
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
oneway interface IStreamingServiceCallback {
|
oneway interface IStreamingServiceCallback {
|
||||||
void error(int errorCode, String message);
|
void onError(int errorCode, String message);
|
||||||
void streamStateUpdated(int state, int reason);
|
void onStreamStateUpdated(int state, int reason);
|
||||||
void mediaDescriptionUpdated();
|
void onMediaDescriptionUpdated();
|
||||||
void broadcastSignalStrengthUpdated(int signalStrength);
|
void onBroadcastSignalStrengthUpdated(int signalStrength);
|
||||||
void streamMethodUpdated(int methodType);
|
void onStreamMethodUpdated(int methodType);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,19 +22,24 @@ import android.os.RemoteException;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public class InternalDownloadManagerCallback extends IMbmsDownloadManagerCallback.Stub {
|
public class InternalDownloadSessionCallback extends IMbmsDownloadSessionCallback.Stub {
|
||||||
|
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
private final MbmsDownloadManagerCallback mAppCallback;
|
private final MbmsDownloadSessionCallback mAppCallback;
|
||||||
|
private volatile boolean mIsStopped = false;
|
||||||
|
|
||||||
public InternalDownloadManagerCallback(MbmsDownloadManagerCallback appCallback,
|
public InternalDownloadSessionCallback(MbmsDownloadSessionCallback appCallback,
|
||||||
Handler handler) {
|
Handler handler) {
|
||||||
mAppCallback = appCallback;
|
mAppCallback = appCallback;
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(final int errorCode, final String message) throws RemoteException {
|
public void onError(final int errorCode, final String message) throws RemoteException {
|
||||||
|
if (mIsStopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -44,7 +49,11 @@ public class InternalDownloadManagerCallback extends IMbmsDownloadManagerCallbac
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fileServicesUpdated(final List<FileServiceInfo> services) throws RemoteException {
|
public void onFileServicesUpdated(final List<FileServiceInfo> services) throws RemoteException {
|
||||||
|
if (mIsStopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -54,7 +63,11 @@ public class InternalDownloadManagerCallback extends IMbmsDownloadManagerCallbac
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void middlewareReady() throws RemoteException {
|
public void onMiddlewareReady() throws RemoteException {
|
||||||
|
if (mIsStopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -66,4 +79,8 @@ public class InternalDownloadManagerCallback extends IMbmsDownloadManagerCallbac
|
|||||||
public Handler getHandler() {
|
public Handler getHandler() {
|
||||||
return mHandler;
|
return mHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
mIsStopped = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -25,6 +25,7 @@ import android.os.RemoteException;
|
|||||||
public class InternalDownloadStateCallback extends IDownloadStateCallback.Stub {
|
public class InternalDownloadStateCallback extends IDownloadStateCallback.Stub {
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
private final DownloadStateCallback mAppCallback;
|
private final DownloadStateCallback mAppCallback;
|
||||||
|
private volatile boolean mIsStopped = false;
|
||||||
|
|
||||||
public InternalDownloadStateCallback(DownloadStateCallback appCallback, Handler handler) {
|
public InternalDownloadStateCallback(DownloadStateCallback appCallback, Handler handler) {
|
||||||
mAppCallback = appCallback;
|
mAppCallback = appCallback;
|
||||||
@@ -32,9 +33,13 @@ public class InternalDownloadStateCallback extends IDownloadStateCallback.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void progress(final DownloadRequest request, final FileInfo fileInfo,
|
public void onProgressUpdated(final DownloadRequest request, final FileInfo fileInfo,
|
||||||
final int currentDownloadSize, final int fullDownloadSize, final int currentDecodedSize,
|
final int currentDownloadSize, final int fullDownloadSize, final int currentDecodedSize,
|
||||||
final int fullDecodedSize) throws RemoteException {
|
final int fullDecodedSize) throws RemoteException {
|
||||||
|
if (mIsStopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -45,13 +50,21 @@ public class InternalDownloadStateCallback extends IDownloadStateCallback.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void state(final DownloadRequest request, final FileInfo fileInfo, final int state)
|
public void onStateUpdated(final DownloadRequest request, final FileInfo fileInfo,
|
||||||
throws RemoteException {
|
final int state) throws RemoteException {
|
||||||
|
if (mIsStopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mAppCallback.onStateChanged(request, fileInfo, state);
|
mAppCallback.onStateUpdated(request, fileInfo, state);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
mIsStopped = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.os.RemoteException;
|
|||||||
public class InternalStreamingServiceCallback extends IStreamingServiceCallback.Stub {
|
public class InternalStreamingServiceCallback extends IStreamingServiceCallback.Stub {
|
||||||
private final StreamingServiceCallback mAppCallback;
|
private final StreamingServiceCallback mAppCallback;
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
|
private volatile boolean mIsStopped = false;
|
||||||
|
|
||||||
public InternalStreamingServiceCallback(StreamingServiceCallback appCallback, Handler handler) {
|
public InternalStreamingServiceCallback(StreamingServiceCallback appCallback, Handler handler) {
|
||||||
mAppCallback = appCallback;
|
mAppCallback = appCallback;
|
||||||
@@ -30,7 +31,11 @@ public class InternalStreamingServiceCallback extends IStreamingServiceCallback.
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(int errorCode, String message) throws RemoteException {
|
public void onError(final int errorCode, final String message) throws RemoteException {
|
||||||
|
if (mIsStopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -40,7 +45,11 @@ public class InternalStreamingServiceCallback extends IStreamingServiceCallback.
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void streamStateUpdated(int state, int reason) throws RemoteException {
|
public void onStreamStateUpdated(final int state, final int reason) throws RemoteException {
|
||||||
|
if (mIsStopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -50,7 +59,11 @@ public class InternalStreamingServiceCallback extends IStreamingServiceCallback.
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mediaDescriptionUpdated() throws RemoteException {
|
public void onMediaDescriptionUpdated() throws RemoteException {
|
||||||
|
if (mIsStopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -60,7 +73,11 @@ public class InternalStreamingServiceCallback extends IStreamingServiceCallback.
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void broadcastSignalStrengthUpdated(int signalStrength) throws RemoteException {
|
public void onBroadcastSignalStrengthUpdated(final int signalStrength) throws RemoteException {
|
||||||
|
if (mIsStopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -70,7 +87,11 @@ public class InternalStreamingServiceCallback extends IStreamingServiceCallback.
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void streamMethodUpdated(int methodType) throws RemoteException {
|
public void onStreamMethodUpdated(final int methodType) throws RemoteException {
|
||||||
|
if (mIsStopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -78,4 +99,8 @@ public class InternalStreamingServiceCallback extends IStreamingServiceCallback.
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
mIsStopped = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,25 +18,27 @@ package android.telephony.mbms;
|
|||||||
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.telephony.mbms.IMbmsStreamingManagerCallback;
|
|
||||||
import android.telephony.mbms.MbmsStreamingManagerCallback;
|
|
||||||
import android.telephony.mbms.StreamingServiceInfo;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public class InternalStreamingManagerCallback extends IMbmsStreamingManagerCallback.Stub {
|
public class InternalStreamingSessionCallback extends IMbmsStreamingSessionCallback.Stub {
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
private final MbmsStreamingManagerCallback mAppCallback;
|
private final MbmsStreamingSessionCallback mAppCallback;
|
||||||
|
private volatile boolean mIsStopped = false;
|
||||||
|
|
||||||
public InternalStreamingManagerCallback(MbmsStreamingManagerCallback appCallback,
|
public InternalStreamingSessionCallback(MbmsStreamingSessionCallback appCallback,
|
||||||
Handler handler) {
|
Handler handler) {
|
||||||
mAppCallback = appCallback;
|
mAppCallback = appCallback;
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(int errorCode, String message) throws RemoteException {
|
public void onError(final int errorCode, final String message) throws RemoteException {
|
||||||
|
if (mIsStopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -46,8 +48,12 @@ public class InternalStreamingManagerCallback extends IMbmsStreamingManagerCallb
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void streamingServicesUpdated(List<StreamingServiceInfo> services)
|
public void onStreamingServicesUpdated(final List<StreamingServiceInfo> services)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
|
if (mIsStopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -57,7 +63,11 @@ public class InternalStreamingManagerCallback extends IMbmsStreamingManagerCallb
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void middlewareReady() throws RemoteException {
|
public void onMiddlewareReady() throws RemoteException {
|
||||||
|
if (mIsStopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -69,4 +79,8 @@ public class InternalStreamingManagerCallback extends IMbmsStreamingManagerCallb
|
|||||||
public Handler getHandler() {
|
public Handler getHandler() {
|
||||||
return mHandler;
|
return mHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
mIsStopped = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ import android.content.pm.ApplicationInfo;
|
|||||||
import android.content.pm.PackageManager;
|
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.MbmsDownloadSession;
|
||||||
import android.telephony.mbms.vendor.VendorUtils;
|
import android.telephony.mbms.vendor.VendorUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@@ -36,8 +36,10 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.nio.file.FileSystems;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -115,8 +117,19 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
//@SystemApi
|
//@SystemApi
|
||||||
public static final int RESULT_TEMP_FILE_GENERATION_ERROR = 5;
|
public static final int RESULT_TEMP_FILE_GENERATION_ERROR = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the manager was unable to notify the app of the completed download.
|
||||||
|
* This is a fatal result code and no result extras should be expected.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SystemApi
|
||||||
|
public static final int RESULT_APP_NOTIFICATION_ERROR = 6;
|
||||||
|
|
||||||
|
|
||||||
private static final String LOG_TAG = "MbmsDownloadReceiver";
|
private static final String LOG_TAG = "MbmsDownloadReceiver";
|
||||||
private static final String TEMP_FILE_SUFFIX = ".embms.temp";
|
private static final String TEMP_FILE_SUFFIX = ".embms.temp";
|
||||||
|
private static final String TEMP_FILE_STAGING_LOCATION = "staged_completed_files";
|
||||||
|
|
||||||
private static final int MAX_TEMP_FILE_RETRIES = 5;
|
private static final int MAX_TEMP_FILE_RETRIES = 5;
|
||||||
|
|
||||||
private String mFileProviderAuthorityCache = null;
|
private String mFileProviderAuthorityCache = null;
|
||||||
@@ -149,11 +162,11 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
|
|
||||||
private boolean verifyIntentContents(Context context, Intent intent) {
|
private boolean verifyIntentContents(Context context, Intent intent) {
|
||||||
if (VendorUtils.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
|
if (VendorUtils.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
|
||||||
if (!intent.hasExtra(MbmsDownloadManager.EXTRA_MBMS_DOWNLOAD_RESULT)) {
|
if (!intent.hasExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_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(VendorUtils.EXTRA_REQUEST)) {
|
if (!intent.hasExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_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;
|
||||||
}
|
}
|
||||||
@@ -161,7 +174,7 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
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;
|
||||||
}
|
}
|
||||||
if (!intent.hasExtra(MbmsDownloadManager.EXTRA_MBMS_FILE_INFO)) {
|
if (!intent.hasExtra(MbmsDownloadSession.EXTRA_MBMS_FILE_INFO)) {
|
||||||
Log.w(LOG_TAG, "Download result did not include the associated file info. " +
|
Log.w(LOG_TAG, "Download result did not include the associated file info. " +
|
||||||
"Ignoring.");
|
"Ignoring.");
|
||||||
return false;
|
return false;
|
||||||
@@ -171,7 +184,8 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
"temp file. Ignoring.");
|
"temp file. Ignoring.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
DownloadRequest request = intent.getParcelableExtra(VendorUtils.EXTRA_REQUEST);
|
DownloadRequest request = intent.getParcelableExtra(
|
||||||
|
MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_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()),
|
||||||
@@ -211,20 +225,25 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void moveDownloadedFile(Context context, Intent intent) {
|
private void moveDownloadedFile(Context context, Intent intent) {
|
||||||
DownloadRequest request = intent.getParcelableExtra(VendorUtils.EXTRA_REQUEST);
|
DownloadRequest request = intent.getParcelableExtra(
|
||||||
|
MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST);
|
||||||
Intent intentForApp = request.getIntentForApp();
|
Intent intentForApp = request.getIntentForApp();
|
||||||
|
if (intentForApp == null) {
|
||||||
|
Log.i(LOG_TAG, "Malformed app notification intent");
|
||||||
|
setResultCode(RESULT_APP_NOTIFICATION_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int result = intent.getIntExtra(MbmsDownloadManager.EXTRA_MBMS_DOWNLOAD_RESULT,
|
int result = intent.getIntExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT,
|
||||||
MbmsDownloadManager.RESULT_CANCELLED);
|
MbmsDownloadSession.RESULT_CANCELLED);
|
||||||
intentForApp.putExtra(MbmsDownloadManager.EXTRA_MBMS_DOWNLOAD_RESULT, result);
|
intentForApp.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT, result);
|
||||||
|
|
||||||
if (result != MbmsDownloadManager.RESULT_SUCCESSFUL) {
|
if (result != MbmsDownloadSession.RESULT_SUCCESSFUL) {
|
||||||
Log.i(LOG_TAG, "Download request indicated a failed download. Aborting.");
|
Log.i(LOG_TAG, "Download request indicated a failed download. Aborting.");
|
||||||
context.sendBroadcast(intentForApp);
|
context.sendBroadcast(intentForApp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Uri destinationUri = request.getDestinationUri();
|
|
||||||
Uri finalTempFile = intent.getParcelableExtra(VendorUtils.EXTRA_FINAL_URI);
|
Uri finalTempFile = intent.getParcelableExtra(VendorUtils.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);
|
||||||
@@ -233,24 +252,31 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FileInfo completedFileInfo =
|
FileInfo completedFileInfo =
|
||||||
(FileInfo) intent.getParcelableExtra(MbmsDownloadManager.EXTRA_MBMS_FILE_INFO);
|
(FileInfo) intent.getParcelableExtra(MbmsDownloadSession.EXTRA_MBMS_FILE_INFO);
|
||||||
String relativePath = calculateDestinationFileRelativePath(request, completedFileInfo);
|
Path stagingDirectory = FileSystems.getDefault().getPath(
|
||||||
|
MbmsTempFileProvider.getEmbmsTempFileDir(context).getPath(),
|
||||||
|
TEMP_FILE_STAGING_LOCATION);
|
||||||
|
|
||||||
Uri finalFileLocation = moveTempFile(finalTempFile, destinationUri, relativePath);
|
Uri stagedFileLocation;
|
||||||
if (finalFileLocation == null) {
|
try {
|
||||||
|
stagedFileLocation = stageTempFile(finalTempFile, stagingDirectory);
|
||||||
|
} catch (IOException e) {
|
||||||
Log.w(LOG_TAG, "Failed to move temp file to final destination");
|
Log.w(LOG_TAG, "Failed to move temp file to final destination");
|
||||||
setResultCode(RESULT_DOWNLOAD_FINALIZATION_ERROR);
|
setResultCode(RESULT_DOWNLOAD_FINALIZATION_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
intentForApp.putExtra(MbmsDownloadManager.EXTRA_MBMS_COMPLETED_FILE_URI, finalFileLocation);
|
intentForApp.putExtra(MbmsDownloadSession.EXTRA_MBMS_COMPLETED_FILE_URI,
|
||||||
intentForApp.putExtra(MbmsDownloadManager.EXTRA_MBMS_FILE_INFO, completedFileInfo);
|
stagedFileLocation);
|
||||||
|
intentForApp.putExtra(MbmsDownloadSession.EXTRA_MBMS_FILE_INFO, completedFileInfo);
|
||||||
|
intentForApp.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST, request);
|
||||||
|
|
||||||
context.sendBroadcast(intentForApp);
|
context.sendBroadcast(intentForApp);
|
||||||
setResultCode(RESULT_OK);
|
setResultCode(RESULT_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cleanupPostMove(Context context, Intent intent) {
|
private void cleanupPostMove(Context context, Intent intent) {
|
||||||
DownloadRequest request = intent.getParcelableExtra(VendorUtils.EXTRA_REQUEST);
|
DownloadRequest request = intent.getParcelableExtra(
|
||||||
|
MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_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;
|
||||||
@@ -404,63 +430,22 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String calculateDestinationFileRelativePath(DownloadRequest request,
|
|
||||||
FileInfo info) {
|
|
||||||
List<String> filePathComponents = info.getUri().getPathSegments();
|
|
||||||
List<String> requestPathComponents = request.getSourceUri().getPathSegments();
|
|
||||||
Iterator<String> filePathIter = filePathComponents.iterator();
|
|
||||||
Iterator<String> requestPathIter = requestPathComponents.iterator();
|
|
||||||
|
|
||||||
StringBuilder pathBuilder = new StringBuilder();
|
|
||||||
// Iterate through the segments of the carrier's URI to the file, along with the segments
|
|
||||||
// of the source URI specified in the download request. The relative path is calculated
|
|
||||||
// as the tail of the file's URI that does not match the path segments in the source URI.
|
|
||||||
while (filePathIter.hasNext()) {
|
|
||||||
String currFilePathComponent = filePathIter.next();
|
|
||||||
if (requestPathIter.hasNext()) {
|
|
||||||
String requestFilePathComponent = requestPathIter.next();
|
|
||||||
if (requestFilePathComponent.equals(currFilePathComponent)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pathBuilder.append(currFilePathComponent);
|
|
||||||
pathBuilder.append('/');
|
|
||||||
}
|
|
||||||
// remove the trailing slash
|
|
||||||
if (pathBuilder.length() > 0) {
|
|
||||||
pathBuilder.deleteCharAt(pathBuilder.length() - 1);
|
|
||||||
}
|
|
||||||
return pathBuilder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Moves a tempfile located at fromPath to a new location at toPath. If
|
* Moves a tempfile located at fromPath to a new location in the staging directory.
|
||||||
* toPath is a directory, the destination file will be located at relativePath
|
|
||||||
* underneath toPath.
|
|
||||||
*/
|
*/
|
||||||
private static Uri moveTempFile(Uri fromPath, Uri toPath, String relativePath) {
|
private static Uri stageTempFile(Uri fromPath, Path stagingDirectory) throws IOException {
|
||||||
if (!ContentResolver.SCHEME_FILE.equals(fromPath.getScheme())) {
|
if (!ContentResolver.SCHEME_FILE.equals(fromPath.getScheme())) {
|
||||||
Log.w(LOG_TAG, "Moving source uri " + fromPath+ " does not have a file scheme");
|
Log.w(LOG_TAG, "Moving source uri " + fromPath+ " does not have a file scheme");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!ContentResolver.SCHEME_FILE.equals(toPath.getScheme())) {
|
|
||||||
Log.w(LOG_TAG, "Moving destination uri " + toPath + " does not have a file scheme");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
File fromFile = new File(fromPath.getSchemeSpecificPart());
|
Path fromFile = FileSystems.getDefault().getPath(fromPath.getPath());
|
||||||
File toFile = new File(toPath.getSchemeSpecificPart());
|
if (!Files.isDirectory(stagingDirectory)) {
|
||||||
if (toFile.isDirectory()) {
|
Files.createDirectory(stagingDirectory);
|
||||||
toFile = new File(toFile, relativePath);
|
|
||||||
}
|
}
|
||||||
toFile.getParentFile().mkdirs();
|
Path result = Files.move(fromFile, stagingDirectory.resolve(fromFile.getFileName()));
|
||||||
|
|
||||||
if (fromFile.renameTo(toFile)) {
|
return Uri.fromFile(result.toFile());
|
||||||
return Uri.fromFile(toFile);
|
|
||||||
} else if (manualMove(fromFile, toFile)) {
|
|
||||||
return Uri.fromFile(toFile);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean verifyTempFilePath(Context context, String serviceId,
|
private static boolean verifyTempFilePath(Context context, String serviceId,
|
||||||
@@ -512,7 +497,7 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
|
|||||||
private String getMiddlewarePackageCached(Context context) {
|
private String getMiddlewarePackageCached(Context context) {
|
||||||
if (mMiddlewarePackageNameCache == null) {
|
if (mMiddlewarePackageNameCache == null) {
|
||||||
mMiddlewarePackageNameCache = MbmsUtils.getMiddlewareServiceInfo(context,
|
mMiddlewarePackageNameCache = MbmsUtils.getMiddlewareServiceInfo(context,
|
||||||
MbmsDownloadManager.MBMS_DOWNLOAD_SERVICE_ACTION).packageName;
|
MbmsDownloadSession.MBMS_DOWNLOAD_SERVICE_ACTION).packageName;
|
||||||
}
|
}
|
||||||
return mMiddlewarePackageNameCache;
|
return mMiddlewarePackageNameCache;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package android.telephony.mbms;
|
package android.telephony.mbms;
|
||||||
|
|
||||||
import android.telephony.MbmsDownloadManager;
|
import android.telephony.MbmsDownloadSession;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -25,11 +25,11 @@ import java.util.List;
|
|||||||
* cell-broadcast.
|
* cell-broadcast.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class MbmsDownloadManagerCallback {
|
public class MbmsDownloadSessionCallback {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the middleware has encountered an asynchronous error.
|
* Indicates that the middleware has encountered an asynchronous error.
|
||||||
* @param errorCode Any error code listed in {@link MbmsException}
|
* @param errorCode Any error code listed in {@link MbmsErrors}
|
||||||
* @param message A message, intended for debugging purposes, describing the error in further
|
* @param message A message, intended for debugging purposes, describing the error in further
|
||||||
* detail.
|
* detail.
|
||||||
*/
|
*/
|
||||||
@@ -42,8 +42,9 @@ public class MbmsDownloadManagerCallback {
|
|||||||
*
|
*
|
||||||
* This will only be called after the application has requested a list of file services and
|
* This will only be called after the application has requested a list of file services and
|
||||||
* specified a service class list of interest via
|
* specified a service class list of interest via
|
||||||
* {@link MbmsDownloadManager#getFileServices(List)}. If there are subsequent calls to
|
* {@link MbmsDownloadSession#requestUpdateFileServices(List)}. If there are subsequent calls to
|
||||||
* {@link MbmsDownloadManager#getFileServices(List)}, this method may not be called again if
|
* {@link MbmsDownloadSession#requestUpdateFileServices(List)},
|
||||||
|
* this method may not be called again if
|
||||||
* the list of service classes would remain the same.
|
* the list of service classes would remain the same.
|
||||||
*
|
*
|
||||||
* @param services The most recently updated list of available file services.
|
* @param services The most recently updated list of available file services.
|
||||||
@@ -56,9 +57,9 @@ public class MbmsDownloadManagerCallback {
|
|||||||
* Called to indicate that the middleware has been initialized and is ready.
|
* Called to indicate that the middleware has been initialized and is ready.
|
||||||
*
|
*
|
||||||
* Before this method is called, calling any method on an instance of
|
* Before this method is called, calling any method on an instance of
|
||||||
* {@link android.telephony.MbmsDownloadManager} will result in an {@link MbmsException}
|
* {@link MbmsDownloadSession} will result in an {@link IllegalStateException}
|
||||||
* being thrown with error code {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
|
* being thrown or {@link #onError(int, String)} being called with error code
|
||||||
* or {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}
|
* {@link MbmsErrors.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}
|
||||||
*/
|
*/
|
||||||
public void onMiddlewareReady() {
|
public void onMiddlewareReady() {
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
@@ -16,8 +16,10 @@
|
|||||||
|
|
||||||
package android.telephony.mbms;
|
package android.telephony.mbms;
|
||||||
|
|
||||||
|
import android.telephony.MbmsStreamingSession;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public class MbmsException extends Exception {
|
public class MbmsErrors {
|
||||||
/** Indicates that the operation was successful. */
|
/** Indicates that the operation was successful. */
|
||||||
public static final int SUCCESS = 0;
|
public static final int SUCCESS = 0;
|
||||||
|
|
||||||
@@ -31,8 +33,8 @@ 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
|
||||||
* TODO link android.telephony.MbmsDownloadManager or
|
* {@link android.telephony.MbmsDownloadSession} or
|
||||||
* {@link android.telephony.MbmsStreamingManager} without being bound to the middleware.
|
* {@link MbmsStreamingSession} without being bound to the middleware.
|
||||||
*/
|
*/
|
||||||
public static final int ERROR_MIDDLEWARE_NOT_BOUND = 2;
|
public static final int ERROR_MIDDLEWARE_NOT_BOUND = 2;
|
||||||
|
|
||||||
@@ -47,8 +49,7 @@ public class MbmsException extends Exception {
|
|||||||
private 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 MbmsStreamingSession} or {@link android.telephony.MbmsDownloadSession}.
|
||||||
* 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.*/
|
||||||
@@ -65,8 +66,8 @@ public class MbmsException extends Exception {
|
|||||||
private 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#onMiddlewareReady()}
|
* that the middleware is ready via {@link MbmsStreamingSessionCallback#onMiddlewareReady()}
|
||||||
* or TODO: link MbmsDownloadManagerCallback#middlewareReady
|
* or {@link MbmsDownloadSessionCallback#onMiddlewareReady()}.
|
||||||
*/
|
*/
|
||||||
public static final int ERROR_MIDDLEWARE_NOT_YET_READY = 201;
|
public static final int ERROR_MIDDLEWARE_NOT_YET_READY = 201;
|
||||||
/**
|
/**
|
||||||
@@ -108,7 +109,7 @@ public class MbmsException extends Exception {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the app called
|
* Indicates that the app called
|
||||||
* {@link android.telephony.MbmsStreamingManager#startStreaming(
|
* {@link MbmsStreamingSession#startStreaming(
|
||||||
* StreamingServiceInfo, StreamingServiceCallback, android.os.Handler)}
|
* StreamingServiceInfo, StreamingServiceCallback, android.os.Handler)}
|
||||||
* more than once for the same {@link StreamingServiceInfo}.
|
* more than once for the same {@link StreamingServiceInfo}.
|
||||||
*/
|
*/
|
||||||
@@ -130,15 +131,5 @@ public class MbmsException extends Exception {
|
|||||||
public static final int ERROR_UNKNOWN_DOWNLOAD_REQUEST = 402;
|
public static final int ERROR_UNKNOWN_DOWNLOAD_REQUEST = 402;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final int mErrorCode;
|
private MbmsErrors() {}
|
||||||
|
|
||||||
/** @hide */
|
|
||||||
public MbmsException(int errorCode) {
|
|
||||||
super();
|
|
||||||
mErrorCode = errorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getErrorCode() {
|
|
||||||
return mErrorCode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -16,26 +16,27 @@
|
|||||||
|
|
||||||
package android.telephony.mbms;
|
package android.telephony.mbms;
|
||||||
|
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.RemoteException;
|
import android.os.Handler;
|
||||||
import android.telephony.MbmsStreamingManager;
|
import android.telephony.MbmsStreamingSession;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A callback class that is used to receive information from the middleware on MBMS streaming
|
* 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
|
* services. An instance of this object should be passed into
|
||||||
* {@link android.telephony.MbmsStreamingManager#create(Context, MbmsStreamingManagerCallback)}.
|
* {@link MbmsStreamingSession#create(Context, MbmsStreamingSessionCallback, int, Handler)}.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class MbmsStreamingManagerCallback {
|
public class MbmsStreamingSessionCallback {
|
||||||
/**
|
/**
|
||||||
* Called by the middleware when it has detected an error condition. The possible error codes
|
* Called by the middleware when it has detected an error condition. The possible error codes
|
||||||
* are listed in {@link MbmsException}.
|
* are listed in {@link MbmsErrors}.
|
||||||
* @param errorCode The error code.
|
* @param errorCode The error code.
|
||||||
* @param message A human-readable message generated by the middleware for debugging purposes.
|
* @param message A human-readable message generated by the middleware for debugging purposes.
|
||||||
*/
|
*/
|
||||||
public void onError(int errorCode, String message) {
|
public void onError(int errorCode, @Nullable String message) {
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,8 +49,7 @@ public class MbmsStreamingManagerCallback {
|
|||||||
* call with the same service class list would return different
|
* call with the same service class list would return different
|
||||||
* results.
|
* results.
|
||||||
*
|
*
|
||||||
* @param services a List of StreamingServiceInfos
|
* @param services The list of available services.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void onStreamingServicesUpdated(List<StreamingServiceInfo> services) {
|
public void onStreamingServicesUpdated(List<StreamingServiceInfo> services) {
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
@@ -59,9 +59,9 @@ public class MbmsStreamingManagerCallback {
|
|||||||
* Called to indicate that the middleware has been initialized and is ready.
|
* Called to indicate that the middleware has been initialized and is ready.
|
||||||
*
|
*
|
||||||
* Before this method is called, calling any method on an instance of
|
* Before this method is called, calling any method on an instance of
|
||||||
* {@link android.telephony.MbmsStreamingManager} will result in an {@link MbmsException}
|
* {@link MbmsStreamingSession} will result in an {@link IllegalStateException} or an error
|
||||||
* being thrown with error code {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
|
* delivered via {@link #onError(int, String)} with error code
|
||||||
* or {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}
|
* {@link MbmsErrors.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}.
|
||||||
*/
|
*/
|
||||||
public void onMiddlewareReady() {
|
public void onMiddlewareReady() {
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
@@ -27,7 +27,7 @@ import android.content.pm.ProviderInfo;
|
|||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.telephony.MbmsDownloadManager;
|
import android.telephony.MbmsDownloadSession;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@@ -181,7 +181,7 @@ public class MbmsTempFileProvider extends ContentProvider {
|
|||||||
return new File(storedTempFileRoot).getCanonicalFile();
|
return new File(storedTempFileRoot).getCanonicalFile();
|
||||||
} else {
|
} else {
|
||||||
return new File(context.getFilesDir(),
|
return new File(context.getFilesDir(),
|
||||||
MbmsDownloadManager.DEFAULT_TOP_LEVEL_TEMP_DIRECTORY).getCanonicalFile();
|
MbmsDownloadSession.DEFAULT_TOP_LEVEL_TEMP_DIRECTORY).getCanonicalFile();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("Unable to canonicalize temp file root path " + e);
|
throw new RuntimeException("Unable to canonicalize temp file root path " + e);
|
||||||
|
|||||||
@@ -68,19 +68,20 @@ public class MbmsUtils {
|
|||||||
return downloadServices.get(0).serviceInfo;
|
return downloadServices.get(0).serviceInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void startBinding(Context context, String serviceAction,
|
public static int startBinding(Context context, String serviceAction,
|
||||||
ServiceConnection serviceConnection) throws MbmsException {
|
ServiceConnection serviceConnection) {
|
||||||
Intent bindIntent = new Intent();
|
Intent bindIntent = new Intent();
|
||||||
ServiceInfo mbmsServiceInfo =
|
ServiceInfo mbmsServiceInfo =
|
||||||
MbmsUtils.getMiddlewareServiceInfo(context, serviceAction);
|
MbmsUtils.getMiddlewareServiceInfo(context, serviceAction);
|
||||||
|
|
||||||
if (mbmsServiceInfo == null) {
|
if (mbmsServiceInfo == null) {
|
||||||
throw new MbmsException(MbmsException.ERROR_NO_UNIQUE_MIDDLEWARE);
|
return MbmsErrors.ERROR_NO_UNIQUE_MIDDLEWARE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bindIntent.setComponent(MbmsUtils.toComponentName(mbmsServiceInfo));
|
bindIntent.setComponent(MbmsUtils.toComponentName(mbmsServiceInfo));
|
||||||
|
|
||||||
context.bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE);
|
context.bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE);
|
||||||
|
return MbmsErrors.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package android.telephony.mbms;
|
package android.telephony.mbms;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@@ -26,12 +28,13 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes a cell-broadcast service. This class should not be instantiated directly -- use
|
* Describes a cell-broadcast service. This class should not be instantiated directly -- use
|
||||||
* {@link StreamingServiceInfo} or TODO link FileServiceInfo
|
* {@link StreamingServiceInfo} or {@link FileServiceInfo}
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class ServiceInfo {
|
public class ServiceInfo {
|
||||||
@@ -59,6 +62,13 @@ public class ServiceInfo {
|
|||||||
if (newLocales.size() > MAP_LIMIT) {
|
if (newLocales.size() > MAP_LIMIT) {
|
||||||
throw new RuntimeException("bad locales length " + newLocales.size());
|
throw new RuntimeException("bad locales length " + newLocales.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Locale l : newLocales) {
|
||||||
|
if (!newNames.containsKey(l)) {
|
||||||
|
throw new IllegalArgumentException("A name must be provided for each locale");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
names = new HashMap(newNames.size());
|
names = new HashMap(newNames.size());
|
||||||
names.putAll(newNames);
|
names.putAll(newNames);
|
||||||
className = newClassName;
|
className = newClassName;
|
||||||
@@ -115,16 +125,25 @@ public class ServiceInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User displayable names listed by language. Do not modify the map returned from this method.
|
* Get the user-displayable name for this cell-broadcast service corresponding to the
|
||||||
|
* provided {@link Locale}.
|
||||||
|
* @param locale The {@link Locale} in which you want the name of the service. This must be a
|
||||||
|
* value from the list returned by {@link #getLocales()} -- an
|
||||||
|
* {@link java.util.NoSuchElementException} may be thrown otherwise.
|
||||||
|
* @return The {@link CharSequence} providing the name of the service in the given
|
||||||
|
* {@link Locale}
|
||||||
*/
|
*/
|
||||||
public Map<Locale, String> getNames() {
|
public @NonNull CharSequence getNameForLocale(@NonNull Locale locale) {
|
||||||
return names;
|
if (!names.containsKey(locale)) {
|
||||||
|
throw new NoSuchElementException("Locale not supported");
|
||||||
|
}
|
||||||
|
return names.get(locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class name for this service - used to categorize and filter
|
* The class name for this service - used to categorize and filter
|
||||||
*/
|
*/
|
||||||
public String getClassName() {
|
public String getServiceClassName() {
|
||||||
return className;
|
return className;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,10 @@
|
|||||||
package android.telephony.mbms;
|
package android.telephony.mbms;
|
||||||
|
|
||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.telephony.MbmsStreamingSession;
|
||||||
import android.telephony.mbms.vendor.IMbmsStreamingService;
|
import android.telephony.mbms.vendor.IMbmsStreamingService;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@@ -27,7 +29,7 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to represent a single MBMS stream. After a stream has been started with
|
* Class used to represent a single MBMS stream. After a stream has been started with
|
||||||
* {@link android.telephony.MbmsStreamingManager#startStreaming(StreamingServiceInfo,
|
* {@link MbmsStreamingSession#startStreaming(StreamingServiceInfo,
|
||||||
* StreamingServiceCallback, android.os.Handler)},
|
* StreamingServiceCallback, android.os.Handler)},
|
||||||
* this class is used to hold information about the stream and control it.
|
* this class is used to hold information about the stream and control it.
|
||||||
* @hide
|
* @hide
|
||||||
@@ -64,7 +66,7 @@ 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,
|
* {@link MbmsStreamingSession#startStreaming(StreamingServiceInfo,
|
||||||
* StreamingServiceCallback, android.os.Handler)}
|
* StreamingServiceCallback, android.os.Handler)}
|
||||||
*/
|
*/
|
||||||
public static final int REASON_BY_USER_REQUEST = 1;
|
public static final int REASON_BY_USER_REQUEST = 1;
|
||||||
@@ -102,6 +104,7 @@ public class StreamingService {
|
|||||||
public final static int UNICAST_METHOD = 2;
|
public final static int UNICAST_METHOD = 2;
|
||||||
|
|
||||||
private final int mSubscriptionId;
|
private final int mSubscriptionId;
|
||||||
|
private final MbmsStreamingSession mParentSession;
|
||||||
private final StreamingServiceInfo mServiceInfo;
|
private final StreamingServiceInfo mServiceInfo;
|
||||||
private final InternalStreamingServiceCallback mCallback;
|
private final InternalStreamingServiceCallback mCallback;
|
||||||
|
|
||||||
@@ -112,25 +115,25 @@ public class StreamingService {
|
|||||||
*/
|
*/
|
||||||
public StreamingService(int subscriptionId,
|
public StreamingService(int subscriptionId,
|
||||||
IMbmsStreamingService service,
|
IMbmsStreamingService service,
|
||||||
|
MbmsStreamingSession session,
|
||||||
StreamingServiceInfo streamingServiceInfo,
|
StreamingServiceInfo streamingServiceInfo,
|
||||||
InternalStreamingServiceCallback callback) {
|
InternalStreamingServiceCallback callback) {
|
||||||
mSubscriptionId = subscriptionId;
|
mSubscriptionId = subscriptionId;
|
||||||
|
mParentSession = session;
|
||||||
mService = service;
|
mService = service;
|
||||||
mServiceInfo = streamingServiceInfo;
|
mServiceInfo = streamingServiceInfo;
|
||||||
mCallback = callback;
|
mCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retreive the Uri used to play this stream.
|
* Retrieve the Uri used to play this stream.
|
||||||
*
|
*
|
||||||
* This may throw a {@link MbmsException} with the error code
|
* May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}.
|
||||||
* {@link MbmsException#ERROR_MIDDLEWARE_LOST}
|
|
||||||
*
|
*
|
||||||
* May also throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
|
* @return The {@link Uri} to pass to the streaming client, or {@code null} if an error
|
||||||
*
|
* occurred.
|
||||||
* @return The {@link Uri} to pass to the streaming client.
|
|
||||||
*/
|
*/
|
||||||
public Uri getPlaybackUri() throws MbmsException {
|
public @Nullable Uri getPlaybackUri() {
|
||||||
if (mService == null) {
|
if (mService == null) {
|
||||||
throw new IllegalStateException("No streaming service attached");
|
throw new IllegalStateException("No streaming service attached");
|
||||||
}
|
}
|
||||||
@@ -140,25 +143,26 @@ public class StreamingService {
|
|||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(LOG_TAG, "Remote process died");
|
Log.w(LOG_TAG, "Remote process died");
|
||||||
mService = null;
|
mService = null;
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
mParentSession.onStreamingServiceStopped(this);
|
||||||
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retreive the info for this StreamingService.
|
* Retrieve the {@link StreamingServiceInfo} corresponding to this stream.
|
||||||
*/
|
*/
|
||||||
public StreamingServiceInfo getInfo() {
|
public StreamingServiceInfo getInfo() {
|
||||||
return mServiceInfo;
|
return mServiceInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop streaming this service.
|
* Stop streaming this service. Further operations on this object will fail with an
|
||||||
* This may throw a {@link MbmsException} with the error code
|
* {@link IllegalStateException}.
|
||||||
* {@link MbmsException#ERROR_MIDDLEWARE_LOST}
|
|
||||||
*
|
*
|
||||||
* May also throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
|
* May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
|
||||||
*/
|
*/
|
||||||
public void stopStreaming() throws MbmsException {
|
public void stopStreaming() {
|
||||||
if (mService == null) {
|
if (mService == null) {
|
||||||
throw new IllegalStateException("No streaming service attached");
|
throw new IllegalStateException("No streaming service attached");
|
||||||
}
|
}
|
||||||
@@ -168,32 +172,22 @@ public class StreamingService {
|
|||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(LOG_TAG, "Remote process died");
|
Log.w(LOG_TAG, "Remote process died");
|
||||||
mService = null;
|
mService = null;
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||||
|
} finally {
|
||||||
|
mParentSession.onStreamingServiceStopped(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @hide */
|
||||||
* Disposes of this stream. Further operations on this object will fail with an
|
public InternalStreamingServiceCallback getCallback() {
|
||||||
* {@link IllegalStateException}.
|
return mCallback;
|
||||||
*
|
}
|
||||||
* This may throw a {@link MbmsException} with the error code
|
|
||||||
* {@link MbmsException#ERROR_MIDDLEWARE_LOST}
|
|
||||||
* May also throw an {@link IllegalStateException}
|
|
||||||
*/
|
|
||||||
public void dispose() throws MbmsException {
|
|
||||||
if (mService == null) {
|
|
||||||
throw new IllegalStateException("No streaming service attached");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private void sendErrorToApp(int errorCode, String message) {
|
||||||
try {
|
try {
|
||||||
mService.disposeStream(mSubscriptionId, mServiceInfo.getServiceId());
|
mCallback.onError(errorCode, message);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(LOG_TAG, "Remote process died");
|
// Ignore, should not happen locally.
|
||||||
throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new IllegalStateException("StreamingService state inconsistent with middleware");
|
|
||||||
} finally {
|
|
||||||
mService = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package android.telephony.mbms;
|
package android.telephony.mbms;
|
||||||
|
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A callback class for use when the application is actively streaming content. The middleware
|
* 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.
|
* will provide updates on the status of the stream via this callback.
|
||||||
@@ -34,11 +36,11 @@ public class StreamingServiceCallback {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the middleware when it has detected an error condition in this stream. The
|
* Called by the middleware when it has detected an error condition in this stream. The
|
||||||
* possible error codes are listed in {@link MbmsException}.
|
* possible error codes are listed in {@link MbmsErrors}.
|
||||||
* @param errorCode The error code.
|
* @param errorCode The error code.
|
||||||
* @param message A human-readable message generated by the middleware for debugging purposes.
|
* @param message A human-readable message generated by the middleware for debugging purposes.
|
||||||
*/
|
*/
|
||||||
public void onError(int errorCode, String message) {
|
public void onError(int errorCode, @Nullable String message) {
|
||||||
// default implementation empty
|
// default implementation empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import android.app.PendingIntent;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.telephony.mbms.DownloadRequest;
|
import android.telephony.mbms.DownloadRequest;
|
||||||
import android.telephony.mbms.FileInfo;
|
import android.telephony.mbms.FileInfo;
|
||||||
import android.telephony.mbms.IMbmsDownloadManagerCallback;
|
import android.telephony.mbms.IMbmsDownloadSessionCallback;
|
||||||
import android.telephony.mbms.IDownloadStateCallback;
|
import android.telephony.mbms.IDownloadStateCallback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,13 +28,18 @@ import android.telephony.mbms.IDownloadStateCallback;
|
|||||||
*/
|
*/
|
||||||
interface IMbmsDownloadService
|
interface IMbmsDownloadService
|
||||||
{
|
{
|
||||||
int initialize(int subId, IMbmsDownloadManagerCallback listener);
|
int initialize(int subId, IMbmsDownloadSessionCallback listener);
|
||||||
|
|
||||||
int getFileServices(int subId, in List<String> serviceClasses);
|
int requestUpdateFileServices(int subId, in List<String> serviceClasses);
|
||||||
|
|
||||||
int setTempFileRootDirectory(int subId, String rootDirectoryPath);
|
int setTempFileRootDirectory(int subId, String rootDirectoryPath);
|
||||||
|
|
||||||
int download(in DownloadRequest downloadRequest, IDownloadStateCallback listener);
|
int download(in DownloadRequest downloadRequest);
|
||||||
|
|
||||||
|
int registerStateCallback(in DownloadRequest downloadRequest, IDownloadStateCallback listener);
|
||||||
|
|
||||||
|
int unregisterStateCallback(in DownloadRequest downloadRequest,
|
||||||
|
IDownloadStateCallback listener);
|
||||||
|
|
||||||
List<DownloadRequest> listPendingDownloads(int subscriptionId);
|
List<DownloadRequest> listPendingDownloads(int subscriptionId);
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
package android.telephony.mbms.vendor;
|
package android.telephony.mbms.vendor;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.telephony.mbms.IMbmsStreamingManagerCallback;
|
import android.telephony.mbms.IMbmsStreamingSessionCallback;
|
||||||
import android.telephony.mbms.IStreamingServiceCallback;
|
import android.telephony.mbms.IStreamingServiceCallback;
|
||||||
import android.telephony.mbms.StreamingServiceInfo;
|
import android.telephony.mbms.StreamingServiceInfo;
|
||||||
|
|
||||||
@@ -26,18 +26,16 @@ import android.telephony.mbms.StreamingServiceInfo;
|
|||||||
*/
|
*/
|
||||||
interface IMbmsStreamingService
|
interface IMbmsStreamingService
|
||||||
{
|
{
|
||||||
int initialize(IMbmsStreamingManagerCallback listener, int subId);
|
int initialize(IMbmsStreamingSessionCallback callback, int subId);
|
||||||
|
|
||||||
int getStreamingServices(int subId, in List<String> serviceClasses);
|
int requestUpdateStreamingServices(int subId, in List<String> serviceClasses);
|
||||||
|
|
||||||
int startStreaming(int subId, String serviceId,
|
int startStreaming(int subId, String serviceId,
|
||||||
IStreamingServiceCallback listener);
|
IStreamingServiceCallback callback);
|
||||||
|
|
||||||
Uri getPlaybackUri(int subId, String serviceId);
|
Uri getPlaybackUri(int subId, String serviceId);
|
||||||
|
|
||||||
void stopStreaming(int subId, String serviceId);
|
void stopStreaming(int subId, String serviceId);
|
||||||
|
|
||||||
void disposeStream(int subId, String serviceId);
|
|
||||||
|
|
||||||
void dispose(int subId);
|
void dispose(int subId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,17 +20,21 @@ import android.annotation.NonNull;
|
|||||||
import android.annotation.SystemApi;
|
import android.annotation.SystemApi;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.telephony.mbms.DownloadStateCallback;
|
import android.telephony.MbmsDownloadSession;
|
||||||
import android.telephony.mbms.DownloadRequest;
|
import android.telephony.mbms.DownloadRequest;
|
||||||
|
import android.telephony.mbms.DownloadStateCallback;
|
||||||
import android.telephony.mbms.FileInfo;
|
import android.telephony.mbms.FileInfo;
|
||||||
import android.telephony.mbms.FileServiceInfo;
|
import android.telephony.mbms.FileServiceInfo;
|
||||||
import android.telephony.mbms.IDownloadStateCallback;
|
import android.telephony.mbms.IDownloadStateCallback;
|
||||||
import android.telephony.mbms.IMbmsDownloadManagerCallback;
|
import android.telephony.mbms.IMbmsDownloadSessionCallback;
|
||||||
import android.telephony.mbms.MbmsDownloadManagerCallback;
|
import android.telephony.mbms.MbmsDownloadSessionCallback;
|
||||||
import android.telephony.mbms.MbmsException;
|
import android.telephony.mbms.MbmsErrors;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for MbmsDownloadService. The middleware should return an instance of this object from
|
* Base class for MbmsDownloadService. The middleware should return an instance of this object from
|
||||||
@@ -39,21 +43,24 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
//@SystemApi
|
//@SystemApi
|
||||||
public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
||||||
|
private final Map<IBinder, DownloadStateCallback> mDownloadCallbackBinderMap = new HashMap<>();
|
||||||
|
private final Map<IBinder, DeathRecipient> mDownloadCallbackDeathRecipients = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the download service for this app and subId, registering the listener.
|
* Initialize the download 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 an {@link IllegalStateException}, 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 MbmsErrors.InitializationErrors#ERROR_UNABLE_TO_INITIALIZE}
|
||||||
*
|
*
|
||||||
* May return any value from {@link android.telephony.mbms.MbmsException.InitializationErrors}
|
* May return any value from {@link MbmsErrors.InitializationErrors}
|
||||||
* or {@link MbmsException#SUCCESS}. Non-successful error codes will be passed to the app via
|
* or {@link MbmsErrors#SUCCESS}. Non-successful error codes will be passed to the app via
|
||||||
* {@link IMbmsDownloadManagerCallback#error(int, String)}.
|
* {@link IMbmsDownloadSessionCallback#onError(int, String)}.
|
||||||
*
|
*
|
||||||
* @param callback 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)
|
public int initialize(int subscriptionId, MbmsDownloadSessionCallback callback)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -64,7 +71,7 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final int initialize(final int subscriptionId,
|
public final int initialize(final int subscriptionId,
|
||||||
final IMbmsDownloadManagerCallback callback) throws RemoteException {
|
final IMbmsDownloadSessionCallback callback) throws RemoteException {
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
callback.asBinder().linkToDeath(new DeathRecipient() {
|
callback.asBinder().linkToDeath(new DeathRecipient() {
|
||||||
@Override
|
@Override
|
||||||
@@ -73,11 +80,11 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
}
|
}
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
return initialize(subscriptionId, new MbmsDownloadManagerCallback() {
|
return initialize(subscriptionId, new MbmsDownloadSessionCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onError(int errorCode, String message) {
|
public void onError(int errorCode, String message) {
|
||||||
try {
|
try {
|
||||||
callback.error(errorCode, message);
|
callback.onError(errorCode, message);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
onAppCallbackDied(uid, subscriptionId);
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
}
|
}
|
||||||
@@ -86,7 +93,7 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public void onFileServicesUpdated(List<FileServiceInfo> services) {
|
public void onFileServicesUpdated(List<FileServiceInfo> services) {
|
||||||
try {
|
try {
|
||||||
callback.fileServicesUpdated(services);
|
callback.onFileServicesUpdated(services);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
onAppCallbackDied(uid, subscriptionId);
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
}
|
}
|
||||||
@@ -95,7 +102,7 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public void onMiddlewareReady() {
|
public void onMiddlewareReady() {
|
||||||
try {
|
try {
|
||||||
callback.middlewareReady();
|
callback.onMiddlewareReady();
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
onAppCallbackDied(uid, subscriptionId);
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
}
|
}
|
||||||
@@ -106,7 +113,7 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
/**
|
/**
|
||||||
* 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
|
||||||
* later via {@link IMbmsDownloadManagerCallback#fileServicesUpdated(List)}
|
* later via {@link IMbmsDownloadSessionCallback#onFileServicesUpdated(List)}
|
||||||
*
|
*
|
||||||
* Note that subsequent calls with the same uid and subId will replace
|
* Note that subsequent calls with the same uid and subId will replace
|
||||||
* the service class list.
|
* the service class list.
|
||||||
@@ -117,11 +124,11 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
* @param serviceClasses The service classes that the app wishes to get info on. The strings
|
* @param serviceClasses The service classes that the app wishes to get info on. The strings
|
||||||
* may contain arbitrary data as negotiated between the app and the
|
* may contain arbitrary data as negotiated between the app and the
|
||||||
* carrier.
|
* carrier.
|
||||||
* @return One of {@link MbmsException#SUCCESS} or
|
* @return One of {@link MbmsErrors#SUCCESS} or
|
||||||
* {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY},
|
* {@link MbmsErrors.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY},
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int getFileServices(int subscriptionId, List<String> serviceClasses)
|
public int requestUpdateFileServices(int subscriptionId, List<String> serviceClasses)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -133,13 +140,13 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
*
|
*
|
||||||
* If the calling app (as identified by the calling UID) currently has any pending download
|
* If the calling app (as identified by the calling UID) currently has any pending download
|
||||||
* requests that have not been canceled, the middleware must return
|
* requests that have not been canceled, the middleware must return
|
||||||
* {@link MbmsException.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT} here.
|
* {@link MbmsErrors.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT} here.
|
||||||
*
|
*
|
||||||
* @param subscriptionId The subscription id the download is operating under.
|
* @param subscriptionId The subscription id the download is operating under.
|
||||||
* @param rootDirectoryPath The path to the app's temp file root directory.
|
* @param rootDirectoryPath The path to the app's temp file root directory.
|
||||||
* @return {@link MbmsException#SUCCESS},
|
* @return {@link MbmsErrors#SUCCESS},
|
||||||
* {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY} or
|
* {@link MbmsErrors.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY} or
|
||||||
* {@link MbmsException.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT}
|
* {@link MbmsErrors.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int setTempFileRootDirectory(int subscriptionId,
|
public int setTempFileRootDirectory(int subscriptionId,
|
||||||
@@ -155,12 +162,32 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
* this is not the case, an {@link IllegalStateException} may be thrown.
|
* this is not the case, an {@link IllegalStateException} may be thrown.
|
||||||
*
|
*
|
||||||
* @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 callback A callback through which the middleware can provide progress updates to
|
* @return Any error from {@link MbmsErrors.GeneralErrors}
|
||||||
* the app while both are still running.
|
* or {@link MbmsErrors#SUCCESS}
|
||||||
* @return Any error from {@link android.telephony.mbms.MbmsException.GeneralErrors}
|
|
||||||
* or {@link MbmsException#SUCCESS}
|
|
||||||
*/
|
*/
|
||||||
public int download(DownloadRequest downloadRequest, DownloadStateCallback callback) {
|
@Override
|
||||||
|
public int download(DownloadRequest downloadRequest) throws RemoteException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a download state callbacks for the provided {@link DownloadRequest}.
|
||||||
|
*
|
||||||
|
* This method is called by the app when it wants to request updates on the progress or
|
||||||
|
* status of the download.
|
||||||
|
*
|
||||||
|
* If the middleware is not aware of a download having been requested with the provided
|
||||||
|
*
|
||||||
|
* {@link DownloadRequest} in the past,
|
||||||
|
* {@link MbmsErrors.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST}
|
||||||
|
* must be returned.
|
||||||
|
*
|
||||||
|
* @param downloadRequest The {@link DownloadRequest} that was used to initiate the download
|
||||||
|
* for which progress updates are being requested.
|
||||||
|
* @param callback The callback object to use.
|
||||||
|
*/
|
||||||
|
public int registerStateCallback(DownloadRequest downloadRequest,
|
||||||
|
DownloadStateCallback callback) throws RemoteException {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,36 +196,101 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final int download(DownloadRequest downloadRequest, IDownloadStateCallback callback)
|
public final int registerStateCallback(
|
||||||
|
final DownloadRequest downloadRequest, final IDownloadStateCallback callback)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
callback.asBinder().linkToDeath(new DeathRecipient() {
|
DeathRecipient deathRecipient = new DeathRecipient() {
|
||||||
@Override
|
@Override
|
||||||
public void binderDied() {
|
public void binderDied() {
|
||||||
onAppCallbackDied(uid, downloadRequest.getSubscriptionId());
|
onAppCallbackDied(uid, downloadRequest.getSubscriptionId());
|
||||||
|
mDownloadCallbackBinderMap.remove(callback.asBinder());
|
||||||
|
mDownloadCallbackDeathRecipients.remove(callback.asBinder());
|
||||||
}
|
}
|
||||||
}, 0);
|
};
|
||||||
|
mDownloadCallbackDeathRecipients.put(callback.asBinder(), deathRecipient);
|
||||||
|
callback.asBinder().linkToDeath(deathRecipient, 0);
|
||||||
|
|
||||||
return download(downloadRequest, new DownloadStateCallback() {
|
DownloadStateCallback exposedCallback = new DownloadStateCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo, int
|
public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo, int
|
||||||
currentDownloadSize, int fullDownloadSize, int currentDecodedSize, int
|
currentDownloadSize, int fullDownloadSize, int currentDecodedSize, int
|
||||||
fullDecodedSize) {
|
fullDecodedSize) {
|
||||||
try {
|
try {
|
||||||
callback.progress(request, fileInfo, currentDownloadSize, fullDownloadSize,
|
callback.onProgressUpdated(request, fileInfo, currentDownloadSize,
|
||||||
|
fullDownloadSize,
|
||||||
currentDecodedSize, fullDecodedSize);
|
currentDecodedSize, fullDecodedSize);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
onAppCallbackDied(uid, downloadRequest.getSubscriptionId());
|
onAppCallbackDied(uid, downloadRequest.getSubscriptionId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
@Override
|
||||||
|
public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
|
||||||
|
@MbmsDownloadSession.DownloadStatus int state) {
|
||||||
|
try {
|
||||||
|
callback.onStateUpdated(request, fileInfo, state);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
onAppCallbackDied(uid, downloadRequest.getSubscriptionId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mDownloadCallbackBinderMap.put(callback.asBinder(), exposedCallback);
|
||||||
|
|
||||||
|
return registerStateCallback(downloadRequest, exposedCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Un-registers a download state callbacks for the provided {@link DownloadRequest}.
|
||||||
|
*
|
||||||
|
* This method is called by the app when it no longer wants to request updates on the
|
||||||
|
* download.
|
||||||
|
*
|
||||||
|
* If the middleware is not aware of a download having been requested with the provided
|
||||||
|
* {@link DownloadRequest} in the past,
|
||||||
|
* {@link MbmsErrors.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST}
|
||||||
|
* must be returned.
|
||||||
|
*
|
||||||
|
* @param downloadRequest The {@link DownloadRequest} that was used to register the callback
|
||||||
|
* @param callback The callback object that
|
||||||
|
* {@link #registerStateCallback(DownloadRequest, DownloadStateCallback)}
|
||||||
|
* was called with.
|
||||||
|
*/
|
||||||
|
public int unregisterStateCallback(DownloadRequest downloadRequest,
|
||||||
|
DownloadStateCallback callback) throws RemoteException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actual AIDL implementation -- hides the callback AIDL from the API.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final int unregisterStateCallback(
|
||||||
|
final DownloadRequest downloadRequest, final IDownloadStateCallback callback)
|
||||||
|
throws RemoteException {
|
||||||
|
DeathRecipient deathRecipient =
|
||||||
|
mDownloadCallbackDeathRecipients.remove(callback.asBinder());
|
||||||
|
if (deathRecipient == null) {
|
||||||
|
throw new IllegalArgumentException("Unknown callback");
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.asBinder().unlinkToDeath(deathRecipient, 0);
|
||||||
|
|
||||||
|
DownloadStateCallback exposedCallback =
|
||||||
|
mDownloadCallbackBinderMap.remove(callback.asBinder());
|
||||||
|
if (exposedCallback == null) {
|
||||||
|
throw new IllegalArgumentException("Unknown callback");
|
||||||
|
}
|
||||||
|
|
||||||
|
return unregisterStateCallback(downloadRequest, exposedCallback);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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, DownloadStateCallback)} but not cancelled through
|
* {@link #download(DownloadRequest)} 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}.
|
||||||
@@ -214,13 +306,13 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
* Issues a request to cancel the specified download request.
|
* Issues a request to cancel the specified download request.
|
||||||
*
|
*
|
||||||
* If the middleware is unable to cancel the request for whatever reason, it should return
|
* If the middleware is unable to cancel the request for whatever reason, it should return
|
||||||
* synchronously with an error. If this method returns {@link MbmsException#SUCCESS}, the app
|
* synchronously with an error. If this method returns {@link MbmsErrors#SUCCESS}, the app
|
||||||
* will no longer be expecting any more file-completed intents from the middleware for this
|
* will no longer be expecting any more file-completed intents from the middleware for this
|
||||||
* {@link DownloadRequest}.
|
* {@link DownloadRequest}.
|
||||||
* @param downloadRequest The request to cancel
|
* @param downloadRequest The request to cancel
|
||||||
* @return {@link MbmsException#SUCCESS},
|
* @return {@link MbmsErrors#SUCCESS},
|
||||||
* {@link MbmsException.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST},
|
* {@link MbmsErrors.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST},
|
||||||
* {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}
|
* {@link MbmsErrors.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int cancelDownload(DownloadRequest downloadRequest) throws RemoteException {
|
public int cancelDownload(DownloadRequest downloadRequest) throws RemoteException {
|
||||||
@@ -232,7 +324,7 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
*
|
*
|
||||||
* If the middleware has not yet been properly initialized or if it has no records of the
|
* If the middleware has not yet been properly initialized or if it has no records of the
|
||||||
* file indicated by {@code fileInfo} being associated with {@code downloadRequest},
|
* file indicated by {@code fileInfo} being associated with {@code downloadRequest},
|
||||||
* {@link android.telephony.MbmsDownloadManager#STATUS_UNKNOWN} must be returned.
|
* {@link MbmsDownloadSession#STATUS_UNKNOWN} must be returned.
|
||||||
*
|
*
|
||||||
* @param downloadRequest The download request to query.
|
* @param downloadRequest The download request to query.
|
||||||
* @param fileInfo The particular file within the request to get information on.
|
* @param fileInfo The particular file within the request to get information on.
|
||||||
@@ -252,7 +344,7 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
* In addition, current in-progress downloads must not be interrupted.
|
* In addition, current in-progress downloads must not be interrupted.
|
||||||
*
|
*
|
||||||
* If the middleware is not aware of the specified download request, return
|
* If the middleware is not aware of the specified download request, return
|
||||||
* {@link MbmsException.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST}.
|
* {@link MbmsErrors.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST}.
|
||||||
*
|
*
|
||||||
* @param downloadRequest The request to re-download files for.
|
* @param downloadRequest The request to re-download files for.
|
||||||
*/
|
*/
|
||||||
@@ -266,7 +358,7 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
|
|||||||
* Signals that the app wishes to dispose of the session identified by the
|
* Signals that the app wishes to dispose of the session identified by the
|
||||||
* {@code subscriptionId} argument and the caller's uid. No notification back to the
|
* {@code subscriptionId} argument and the caller's uid. No notification back to the
|
||||||
* app is required for this operation, and the corresponding callback provided via
|
* app is required for this operation, and the corresponding callback provided via
|
||||||
* {@link #initialize(int, IMbmsDownloadManagerCallback)} should no longer be used
|
* {@link #initialize(int, IMbmsDownloadSessionCallback)} should no longer be used
|
||||||
* after this method has been called by the app.
|
* after this method has been called by the app.
|
||||||
*
|
*
|
||||||
* Any download requests issued by the app should remain in effect until the app calls
|
* Any download requests issued by the app should remain in effect until the app calls
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ import android.content.Intent;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.telephony.mbms.IMbmsStreamingManagerCallback;
|
import android.telephony.mbms.IMbmsStreamingSessionCallback;
|
||||||
import android.telephony.mbms.IStreamingServiceCallback;
|
import android.telephony.mbms.IStreamingServiceCallback;
|
||||||
import android.telephony.mbms.MbmsException;
|
import android.telephony.mbms.MbmsErrors;
|
||||||
import android.telephony.mbms.MbmsStreamingManagerCallback;
|
import android.telephony.mbms.MbmsStreamingSessionCallback;
|
||||||
import android.telephony.mbms.StreamingService;
|
import android.telephony.mbms.StreamingService;
|
||||||
import android.telephony.mbms.StreamingServiceCallback;
|
import android.telephony.mbms.StreamingServiceCallback;
|
||||||
import android.telephony.mbms.StreamingServiceInfo;
|
import android.telephony.mbms.StreamingServiceInfo;
|
||||||
@@ -44,16 +44,16 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
|||||||
*
|
*
|
||||||
* May throw an {@link IllegalArgumentException} or a {@link SecurityException}, 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 MbmsErrors.InitializationErrors#ERROR_UNABLE_TO_INITIALIZE}
|
||||||
*
|
*
|
||||||
* May return any value from {@link android.telephony.mbms.MbmsException.InitializationErrors}
|
* May return any value from {@link MbmsErrors.InitializationErrors}
|
||||||
* or {@link MbmsException#SUCCESS}. Non-successful error codes will be passed to the app via
|
* or {@link MbmsErrors#SUCCESS}. Non-successful error codes will be passed to the app via
|
||||||
* {@link IMbmsStreamingManagerCallback#error(int, String)}.
|
* {@link IMbmsStreamingSessionCallback#onError(int, String)}.
|
||||||
*
|
*
|
||||||
* @param callback 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(MbmsStreamingManagerCallback callback, int subscriptionId)
|
public int initialize(MbmsStreamingSessionCallback callback, int subscriptionId)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final int initialize(final IMbmsStreamingManagerCallback callback,
|
public final int initialize(final IMbmsStreamingSessionCallback callback,
|
||||||
final int subscriptionId) throws RemoteException {
|
final int subscriptionId) throws RemoteException {
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
callback.asBinder().linkToDeath(new DeathRecipient() {
|
callback.asBinder().linkToDeath(new DeathRecipient() {
|
||||||
@@ -73,20 +73,20 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
|||||||
}
|
}
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
return initialize(new MbmsStreamingManagerCallback() {
|
return initialize(new MbmsStreamingSessionCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onError(int errorCode, String message) {
|
public void onError(final int errorCode, final String message) {
|
||||||
try {
|
try {
|
||||||
callback.error(errorCode, message);
|
callback.onError(errorCode, message);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
onAppCallbackDied(uid, subscriptionId);
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStreamingServicesUpdated(List<StreamingServiceInfo> services) {
|
public void onStreamingServicesUpdated(final List<StreamingServiceInfo> services) {
|
||||||
try {
|
try {
|
||||||
callback.streamingServicesUpdated(services);
|
callback.onStreamingServicesUpdated(services);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
onAppCallbackDied(uid, subscriptionId);
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
}
|
}
|
||||||
@@ -95,7 +95,7 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public void onMiddlewareReady() {
|
public void onMiddlewareReady() {
|
||||||
try {
|
try {
|
||||||
callback.middlewareReady();
|
callback.onMiddlewareReady();
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
onAppCallbackDied(uid, subscriptionId);
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
}
|
}
|
||||||
@@ -107,7 +107,7 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
|||||||
/**
|
/**
|
||||||
* 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
|
||||||
* later via {@link IMbmsStreamingManagerCallback#streamingServicesUpdated(List)}
|
* later via {@link IMbmsStreamingSessionCallback#onStreamingServicesUpdated(List)}
|
||||||
*
|
*
|
||||||
* Note that subsequent calls with the same uid and subId will replace
|
* Note that subsequent calls with the same uid and subId will replace
|
||||||
* the service class list.
|
* the service class list.
|
||||||
@@ -118,11 +118,11 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
|||||||
* @param serviceClasses The service classes that the app wishes to get info on. The strings
|
* @param serviceClasses The service classes that the app wishes to get info on. The strings
|
||||||
* may contain arbitrary data as negotiated between the app and the
|
* may contain arbitrary data as negotiated between the app and the
|
||||||
* carrier.
|
* carrier.
|
||||||
* @return {@link MbmsException#SUCCESS} or any of the errors in
|
* @return {@link MbmsErrors#SUCCESS} or any of the errors in
|
||||||
* {@link android.telephony.mbms.MbmsException.GeneralErrors}
|
* {@link MbmsErrors.GeneralErrors}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int getStreamingServices(int subscriptionId,
|
public int requestUpdateStreamingServices(int subscriptionId,
|
||||||
List<String> serviceClasses) throws RemoteException {
|
List<String> serviceClasses) throws RemoteException {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -130,14 +130,14 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
|||||||
/**
|
/**
|
||||||
* Starts streaming on a particular service. This method may perform asynchronous work. When
|
* Starts streaming on a particular service. This method may perform asynchronous work. When
|
||||||
* the middleware is ready to send bits to the frontend, it should inform the app via
|
* the middleware is ready to send bits to the frontend, it should inform the app via
|
||||||
* {@link IStreamingServiceCallback#streamStateUpdated(int, int)}.
|
* {@link IStreamingServiceCallback#onStreamStateUpdated(int, int)}.
|
||||||
*
|
*
|
||||||
* May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
|
* May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
|
||||||
*
|
*
|
||||||
* @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 callback The callback 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 MbmsErrors.GeneralErrors}
|
||||||
*/
|
*/
|
||||||
public int startStreaming(int subscriptionId, String serviceId,
|
public int startStreaming(int subscriptionId, String serviceId,
|
||||||
StreamingServiceCallback callback) throws RemoteException {
|
StreamingServiceCallback callback) throws RemoteException {
|
||||||
@@ -150,8 +150,8 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int startStreaming(int subscriptionId, String serviceId,
|
public int startStreaming(final int subscriptionId, String serviceId,
|
||||||
IStreamingServiceCallback callback) throws RemoteException {
|
final IStreamingServiceCallback callback) throws RemoteException {
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
callback.asBinder().linkToDeath(new DeathRecipient() {
|
callback.asBinder().linkToDeath(new DeathRecipient() {
|
||||||
@Override
|
@Override
|
||||||
@@ -162,19 +162,19 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
|||||||
|
|
||||||
return startStreaming(subscriptionId, serviceId, new StreamingServiceCallback() {
|
return startStreaming(subscriptionId, serviceId, new StreamingServiceCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onError(int errorCode, String message) {
|
public void onError(final int errorCode, final String message) {
|
||||||
try {
|
try {
|
||||||
callback.error(errorCode, message);
|
callback.onError(errorCode, message);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
onAppCallbackDied(uid, subscriptionId);
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStreamStateUpdated(@StreamingService.StreamingState int state,
|
public void onStreamStateUpdated(@StreamingService.StreamingState final int state,
|
||||||
@StreamingService.StreamingStateChangeReason int reason) {
|
@StreamingService.StreamingStateChangeReason final int reason) {
|
||||||
try {
|
try {
|
||||||
callback.streamStateUpdated(state, reason);
|
callback.onStreamStateUpdated(state, reason);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
onAppCallbackDied(uid, subscriptionId);
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
}
|
}
|
||||||
@@ -183,25 +183,25 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public void onMediaDescriptionUpdated() {
|
public void onMediaDescriptionUpdated() {
|
||||||
try {
|
try {
|
||||||
callback.mediaDescriptionUpdated();
|
callback.onMediaDescriptionUpdated();
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
onAppCallbackDied(uid, subscriptionId);
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBroadcastSignalStrengthUpdated(int signalStrength) {
|
public void onBroadcastSignalStrengthUpdated(final int signalStrength) {
|
||||||
try {
|
try {
|
||||||
callback.broadcastSignalStrengthUpdated(signalStrength);
|
callback.onBroadcastSignalStrengthUpdated(signalStrength);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
onAppCallbackDied(uid, subscriptionId);
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStreamMethodUpdated(int methodType) {
|
public void onStreamMethodUpdated(final int methodType) {
|
||||||
try {
|
try {
|
||||||
callback.streamMethodUpdated(methodType);
|
callback.onStreamMethodUpdated(methodType);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
onAppCallbackDied(uid, subscriptionId);
|
onAppCallbackDied(uid, subscriptionId);
|
||||||
}
|
}
|
||||||
@@ -228,7 +228,11 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
|||||||
/**
|
/**
|
||||||
* Stop streaming the stream identified by {@code serviceId}. Notification of the resulting
|
* Stop streaming the stream identified by {@code serviceId}. Notification of the resulting
|
||||||
* stream state change should be reported to the app via
|
* stream state change should be reported to the app via
|
||||||
* {@link IStreamingServiceCallback#streamStateUpdated(int, int)}.
|
* {@link IStreamingServiceCallback#onStreamStateUpdated(int, int)}.
|
||||||
|
*
|
||||||
|
* In addition, the callback provided via
|
||||||
|
* {@link #startStreaming(int, String, IStreamingServiceCallback)} should no longer be
|
||||||
|
* used after this method has called by the app.
|
||||||
*
|
*
|
||||||
* May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
|
* May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
|
||||||
*
|
*
|
||||||
@@ -240,28 +244,11 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
|
|||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispose of the stream identified by {@code serviceId} for the app identified by the
|
|
||||||
* {@code appName} and {@code subscriptionId} arguments along with the caller's uid.
|
|
||||||
* No notification back to the app is required for this operation, and the callback provided via
|
|
||||||
* {@link #startStreaming(int, String, IStreamingServiceCallback)} should no longer be
|
|
||||||
* used after this method has called by the app.
|
|
||||||
*
|
|
||||||
* May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
|
|
||||||
*
|
|
||||||
* @param subscriptionId The subscription id to use.
|
|
||||||
* @param serviceId The ID of the streaming service that the app wishes to dispose of.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void disposeStream(int subscriptionId, String serviceId)
|
|
||||||
throws RemoteException {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals that the app wishes to dispose of the session identified by the
|
* Signals that the app wishes to dispose of the session identified by the
|
||||||
* {@code subscriptionId} argument and the caller's uid. No notification back to the
|
* {@code subscriptionId} argument and the caller's uid. No notification back to the
|
||||||
* app is required for this operation, and the corresponding callback provided via
|
* app is required for this operation, and the corresponding callback provided via
|
||||||
* {@link #initialize(IMbmsStreamingManagerCallback, int)} should no longer be used
|
* {@link #initialize(IMbmsStreamingSessionCallback, int)} should no longer be used
|
||||||
* after this method has been called by the app.
|
* after this method has been called by the app.
|
||||||
*
|
*
|
||||||
* May throw an {@link IllegalStateException}
|
* May throw an {@link IllegalStateException}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.telephony.mbms.DownloadRequest;
|
import android.telephony.MbmsDownloadSession;
|
||||||
import android.telephony.mbms.MbmsDownloadReceiver;
|
import android.telephony.mbms.MbmsDownloadReceiver;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -39,9 +39,9 @@ public class VendorUtils {
|
|||||||
/**
|
/**
|
||||||
* The MBMS middleware should send this when a download of single file has completed or
|
* The MBMS middleware should send this when a download of single file has completed or
|
||||||
* failed. Mandatory extras are
|
* failed. Mandatory extras are
|
||||||
* {@link android.telephony.MbmsDownloadManager#EXTRA_MBMS_DOWNLOAD_RESULT}
|
* {@link MbmsDownloadSession#EXTRA_MBMS_DOWNLOAD_RESULT}
|
||||||
* {@link android.telephony.MbmsDownloadManager#EXTRA_MBMS_FILE_INFO}
|
* {@link MbmsDownloadSession#EXTRA_MBMS_FILE_INFO}
|
||||||
* {@link #EXTRA_REQUEST}
|
* {@link MbmsDownloadSession#EXTRA_MBMS_DOWNLOAD_REQUEST}
|
||||||
* {@link #EXTRA_TEMP_LIST}
|
* {@link #EXTRA_TEMP_LIST}
|
||||||
* {@link #EXTRA_FINAL_URI}
|
* {@link #EXTRA_FINAL_URI}
|
||||||
*/
|
*/
|
||||||
@@ -120,12 +120,6 @@ public class VendorUtils {
|
|||||||
public static final String EXTRA_TEMP_FILES_IN_USE =
|
public static final String EXTRA_TEMP_FILES_IN_USE =
|
||||||
"android.telephony.mbms.extra.TEMP_FILES_IN_USE";
|
"android.telephony.mbms.extra.TEMP_FILES_IN_USE";
|
||||||
|
|
||||||
/**
|
|
||||||
* Extra containing 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
|
* Extra containing a single {@link Uri} indicating the path to the temp file in which the
|
||||||
* decoded downloaded file resides. Must not be null.
|
* decoded downloaded file resides. Must not be null.
|
||||||
|
|||||||
Reference in New Issue
Block a user