Split the DownloadStateCallback class into two

Use individually-registered DownloadStatusListener and
DownloadProgressListener instead to listen for download status and
progress, respectively.

Bug: 74409377
Test: cts
Change-Id: Ifd5289038ffd66eef8bd7916f5256205b49be5f9
This commit is contained in:
Hall Liu
2018-03-19 18:12:23 -07:00
parent 0efaf2088d
commit 7953997160
14 changed files with 533 additions and 274 deletions

View File

@@ -501,7 +501,8 @@ java_library {
"telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl",
"telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl",
"telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl",
"telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl",
"telephony/java/android/telephony/mbms/IDownloadStatusListener.aidl",
"telephony/java/android/telephony/mbms/IDownloadProgressListener.aidl",
"telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl",
"telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl",
"telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl",

View File

@@ -42603,6 +42603,8 @@ package android.telephony {
}
public class MbmsDownloadSession implements java.lang.AutoCloseable {
method public int addProgressListener(android.telephony.mbms.DownloadRequest, java.util.concurrent.Executor, android.telephony.mbms.DownloadProgressListener);
method public int addStatusListener(android.telephony.mbms.DownloadRequest, java.util.concurrent.Executor, android.telephony.mbms.DownloadStatusListener);
method public int cancelDownload(android.telephony.mbms.DownloadRequest);
method public void close();
method public static android.telephony.MbmsDownloadSession create(android.content.Context, java.util.concurrent.Executor, android.telephony.mbms.MbmsDownloadSessionCallback);
@@ -42610,12 +42612,12 @@ package android.telephony {
method public int download(android.telephony.mbms.DownloadRequest);
method public java.io.File getTempFileRootDirectory();
method public java.util.List<android.telephony.mbms.DownloadRequest> listPendingDownloads();
method public int registerStateCallback(android.telephony.mbms.DownloadRequest, java.util.concurrent.Executor, android.telephony.mbms.DownloadStateCallback);
method public int removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener);
method public int removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener);
method public void requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo);
method public void requestUpdateFileServices(java.util.List<java.lang.String>);
method public void resetDownloadKnowledge(android.telephony.mbms.DownloadRequest);
method public void setTempFileRootDirectory(java.io.File);
method public int unregisterStateCallback(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStateCallback);
field public static final java.lang.String DEFAULT_TOP_LEVEL_TEMP_DIRECTORY = "androidMbmsTempFileRoot";
field public static final java.lang.String EXTRA_MBMS_COMPLETED_FILE_URI = "android.telephony.extra.MBMS_COMPLETED_FILE_URI";
field public static final java.lang.String EXTRA_MBMS_DOWNLOAD_REQUEST = "android.telephony.extra.MBMS_DOWNLOAD_REQUEST";
@@ -43513,6 +43515,11 @@ package android.telephony.gsm {
package android.telephony.mbms {
public class DownloadProgressListener {
ctor public DownloadProgressListener();
method public void onProgressUpdated(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo, int, int, int, int);
}
public final class DownloadRequest implements android.os.Parcelable {
method public int describeContents();
method public android.net.Uri getDestinationUri();
@@ -43536,15 +43543,9 @@ package android.telephony.mbms {
method public android.telephony.mbms.DownloadRequest.Builder setSubscriptionId(int);
}
public class DownloadStateCallback {
ctor public DownloadStateCallback();
ctor public DownloadStateCallback(int);
method public final boolean isFilterFlagSet(int);
method public void onProgressUpdated(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo, int, int, int, int);
method public void onStateUpdated(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo, int);
field public static final int ALL_UPDATES = 0; // 0x0
field public static final int PROGRESS_UPDATES = 1; // 0x1
field public static final int STATE_UPDATES = 2; // 0x2
public class DownloadStatusListener {
ctor public DownloadStatusListener();
method public void onStatusUpdated(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo, int);
}
public final class FileInfo implements android.os.Parcelable {

View File

@@ -6223,18 +6223,20 @@ package android.telephony.mbms.vendor {
public class MbmsDownloadServiceBase extends android.os.Binder {
ctor public MbmsDownloadServiceBase();
method public int addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
method public int addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
method public int cancelDownload(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
method public void dispose(int) throws android.os.RemoteException;
method public int download(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
method public int initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback) throws android.os.RemoteException;
method public java.util.List<android.telephony.mbms.DownloadRequest> listPendingDownloads(int) throws android.os.RemoteException;
method public void onAppCallbackDied(int, int);
method public int registerStateCallback(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStateCallback) throws android.os.RemoteException;
method public int removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
method public int removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
method public int requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException;
method public int requestUpdateFileServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException;
method public int resetDownloadKnowledge(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
method public int setTempFileRootDirectory(int, java.lang.String) throws android.os.RemoteException;
method public int unregisterStateCallback(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStateCallback) throws android.os.RemoteException;
}
public class MbmsStreamingServiceBase extends android.os.Binder {

View File

@@ -782,18 +782,20 @@ package android.telephony.mbms.vendor {
public class MbmsDownloadServiceBase extends android.os.Binder {
ctor public MbmsDownloadServiceBase();
method public int addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
method public int addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
method public int cancelDownload(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
method public void dispose(int) throws android.os.RemoteException;
method public int download(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
method public int initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback) throws android.os.RemoteException;
method public java.util.List<android.telephony.mbms.DownloadRequest> listPendingDownloads(int) throws android.os.RemoteException;
method public void onAppCallbackDied(int, int);
method public int registerStateCallback(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStateCallback) throws android.os.RemoteException;
method public int removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
method public int removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
method public int requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException;
method public int requestUpdateFileServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException;
method public int resetDownloadKnowledge(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
method public int setTempFileRootDirectory(int, java.lang.String) throws android.os.RemoteException;
method public int unregisterStateCallback(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStateCallback) throws android.os.RemoteException;
}
public class MbmsStreamingServiceBase extends android.os.Binder {

View File

@@ -31,11 +31,13 @@ import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.telephony.mbms.DownloadStateCallback;
import android.telephony.mbms.DownloadProgressListener;
import android.telephony.mbms.DownloadStatusListener;
import android.telephony.mbms.FileInfo;
import android.telephony.mbms.DownloadRequest;
import android.telephony.mbms.InternalDownloadProgressListener;
import android.telephony.mbms.InternalDownloadSessionCallback;
import android.telephony.mbms.InternalDownloadStateCallback;
import android.telephony.mbms.InternalDownloadStatusListener;
import android.telephony.mbms.MbmsDownloadSessionCallback;
import android.telephony.mbms.MbmsDownloadReceiver;
import android.telephony.mbms.MbmsErrors;
@@ -232,8 +234,10 @@ public class MbmsDownloadSession implements AutoCloseable {
private AtomicReference<IMbmsDownloadService> mService = new AtomicReference<>(null);
private final InternalDownloadSessionCallback mInternalCallback;
private final Map<DownloadStateCallback, InternalDownloadStateCallback>
mInternalDownloadCallbacks = new HashMap<>();
private final Map<DownloadStatusListener, InternalDownloadStatusListener>
mInternalDownloadStatusListeners = new HashMap<>();
private final Map<DownloadProgressListener, InternalDownloadProgressListener>
mInternalDownloadProgressListeners = new HashMap<>();
private MbmsDownloadSession(Context context, Executor executor, int subscriptionId,
MbmsDownloadSessionCallback callback) {
@@ -561,34 +565,33 @@ public class MbmsDownloadSession implements AutoCloseable {
}
/**
* Registers a callback for a {@link DownloadRequest} previously requested via
* Registers a download status listener 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.
* provided {@link DownloadStatusListener} 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 executor The {@link Executor} on which calls to {@code callback} should be executed.
* @param callback The callback that should be called when the middleware has information to
* share on the download.
* @param executor The {@link Executor} on which calls to {@code listener } should be executed.
* @param listener The listener that should be called when the middleware has information to
* share on the status download.
* @return {@link MbmsErrors#SUCCESS} if the operation did not encounter a synchronous error,
* and some other error code otherwise.
*/
public int registerStateCallback(@NonNull DownloadRequest request,
@NonNull Executor executor, @NonNull DownloadStateCallback callback) {
public int addStatusListener(@NonNull DownloadRequest request,
@NonNull Executor executor, @NonNull DownloadStatusListener listener) {
IMbmsDownloadService downloadService = mService.get();
if (downloadService == null) {
throw new IllegalStateException("Middleware not yet bound");
}
InternalDownloadStateCallback internalCallback =
new InternalDownloadStateCallback(callback, executor);
InternalDownloadStatusListener internalListener =
new InternalDownloadStatusListener(listener, executor);
try {
int result = downloadService.registerStateCallback(request, internalCallback,
callback.getCallbackFilterFlags());
int result = downloadService.addStatusListener(request, internalListener);
if (result != MbmsErrors.SUCCESS) {
if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
throw new IllegalArgumentException("Unknown download request.");
@@ -600,40 +603,41 @@ public class MbmsDownloadSession implements AutoCloseable {
sIsInitialized.set(false);
return MbmsErrors.ERROR_MIDDLEWARE_LOST;
}
mInternalDownloadCallbacks.put(callback, internalCallback);
mInternalDownloadStatusListeners.put(listener, internalListener);
return MbmsErrors.SUCCESS;
}
/**
* Un-register a callback previously registered via
* {@link #registerStateCallback(DownloadRequest, Executor, DownloadStateCallback)}. After
* this method is called, no further callbacks will be enqueued on the {@link Handler}
* Un-register a listener previously registered via
* {@link #addStatusListener(DownloadRequest, Executor, DownloadStatusListener)}. After
* this method is called, no further calls will be enqueued on the {@link Executor}
* 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.
* @param listener The listener provided during registration.
* @return {@link MbmsErrors#SUCCESS} if the operation did not encounter a synchronous error,
* and some other error code otherwise.
*/
public int unregisterStateCallback(@NonNull DownloadRequest request,
@NonNull DownloadStateCallback callback) {
public int removeStatusListener(@NonNull DownloadRequest request,
@NonNull DownloadStatusListener listener) {
try {
IMbmsDownloadService downloadService = mService.get();
if (downloadService == null) {
throw new IllegalStateException("Middleware not yet bound");
}
InternalDownloadStateCallback internalCallback =
mInternalDownloadCallbacks.get(callback);
if (internalCallback == null) {
throw new IllegalArgumentException("Provided callback was never registered");
InternalDownloadStatusListener internalListener =
mInternalDownloadStatusListeners.get(listener);
if (internalListener == null) {
throw new IllegalArgumentException("Provided listener was never registered");
}
try {
int result = downloadService.unregisterStateCallback(request, internalCallback);
int result = downloadService.removeStatusListener(request, internalListener);
if (result != MbmsErrors.SUCCESS) {
if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
throw new IllegalArgumentException("Unknown download request.");
@@ -646,8 +650,102 @@ public class MbmsDownloadSession implements AutoCloseable {
return MbmsErrors.ERROR_MIDDLEWARE_LOST;
}
} finally {
InternalDownloadStateCallback internalCallback =
mInternalDownloadCallbacks.remove(callback);
InternalDownloadStatusListener internalCallback =
mInternalDownloadStatusListeners.remove(listener);
if (internalCallback != null) {
internalCallback.stop();
}
}
return MbmsErrors.SUCCESS;
}
/**
* Registers a progress listener for a {@link DownloadRequest} previously requested via
* {@link #download(DownloadRequest)}. This listener 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 DownloadProgressListener} 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 executor The {@link Executor} on which calls to {@code listener} should be executed.
* @param listener The listener that should be called when the middleware has information to
* share on the progress of the download.
* @return {@link MbmsErrors#SUCCESS} if the operation did not encounter a synchronous error,
* and some other error code otherwise.
*/
public int addProgressListener(@NonNull DownloadRequest request,
@NonNull Executor executor, @NonNull DownloadProgressListener listener) {
IMbmsDownloadService downloadService = mService.get();
if (downloadService == null) {
throw new IllegalStateException("Middleware not yet bound");
}
InternalDownloadProgressListener internalListener =
new InternalDownloadProgressListener(listener, executor);
try {
int result = downloadService.addProgressListener(request, internalListener);
if (result != MbmsErrors.SUCCESS) {
if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
throw new IllegalArgumentException("Unknown download request.");
}
return result;
}
} catch (RemoteException e) {
mService.set(null);
sIsInitialized.set(false);
return MbmsErrors.ERROR_MIDDLEWARE_LOST;
}
mInternalDownloadProgressListeners.put(listener, internalListener);
return MbmsErrors.SUCCESS;
}
/**
* Un-register a listener previously registered via
* {@link #addProgressListener(DownloadRequest, Executor, DownloadProgressListener)}. 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 listener The listener provided during registration.
* @return {@link MbmsErrors#SUCCESS} if the operation did not encounter a synchronous error,
* and some other error code otherwise.
*/
public int removeProgressListener(@NonNull DownloadRequest request,
@NonNull DownloadProgressListener listener) {
try {
IMbmsDownloadService downloadService = mService.get();
if (downloadService == null) {
throw new IllegalStateException("Middleware not yet bound");
}
InternalDownloadProgressListener internalListener =
mInternalDownloadProgressListeners.get(listener);
if (internalListener == null) {
throw new IllegalArgumentException("Provided listener was never registered");
}
try {
int result = downloadService.removeProgressListener(request, internalListener);
if (result != MbmsErrors.SUCCESS) {
if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
throw new IllegalArgumentException("Unknown download request.");
}
return result;
}
} catch (RemoteException e) {
mService.set(null);
sIsInitialized.set(false);
return MbmsErrors.ERROR_MIDDLEWARE_LOST;
}
} finally {
InternalDownloadProgressListener internalCallback =
mInternalDownloadProgressListeners.remove(listener);
if (internalCallback != null) {
internalCallback.stop();
}
@@ -692,9 +790,9 @@ public class MbmsDownloadSession implements AutoCloseable {
* Requests information about the state of a file pending download.
*
* The state will be delivered as a callback via
* {@link DownloadStateCallback#onStateUpdated(DownloadRequest, FileInfo, int)}. If no such
* {@link DownloadStatusListener#onStatusUpdated(DownloadRequest, FileInfo, int)}. If no such
* callback has been registered via
* {@link #registerStateCallback(DownloadRequest, Executor, DownloadStateCallback)}, this
* {@link #addProgressListener(DownloadRequest, Executor, DownloadProgressListener)}, this
* method will be a no-op.
*
* If the middleware has no record of the

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package android.telephony.mbms;
import android.telephony.MbmsDownloadSession;
/**
* A optional listener class used by download clients to track progress. Apps should extend this
* class and pass an instance into
* {@link MbmsDownloadSession#download(DownloadRequest)}
*
* This is optionally specified when requesting a download and will only be called while the app
* is running.
*/
public class DownloadProgressListener {
/**
* Called when the middleware wants to report progress for a file in a {@link DownloadRequest}.
*
* @param request a {@link DownloadRequest}, indicating which download is being referenced.
* @param fileInfo a {@link FileInfo} specifying the file to report progress on. Note that
* the request may result in many files being downloaded and the client
* may not have been able to get a list of them in advance.
* @param currentDownloadSize is the current amount downloaded.
* @param fullDownloadSize is the total number of bytes that make up the downloaded content.
* This may be different from the decoded final size, but is useful in gauging download
* progress.
* @param currentDecodedSize is the number of bytes that have been decoded.
* @param fullDecodedSize is the total number of bytes that make up the final decoded content.
*/
public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
int currentDownloadSize, int fullDownloadSize,
int currentDecodedSize, int fullDecodedSize) {
}
}

View File

@@ -1,131 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.mbms;
import android.annotation.IntDef;
import android.telephony.MbmsDownloadSession;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* A optional listener class used by download clients to track progress. Apps should extend this
* class and pass an instance into
* {@link MbmsDownloadSession#download(DownloadRequest)}
*
* This is optionally specified when requesting a download and will only be called while the app
* is running.
*/
public class DownloadStateCallback {
/**
* Bitmask flags used for filtering out callback methods. Used when constructing the
* DownloadStateCallback as an optional parameter.
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag = true, value = {ALL_UPDATES, PROGRESS_UPDATES, STATE_UPDATES})
public @interface FilterFlag {}
/**
* Receive all callbacks.
* Default value.
*/
public static final int ALL_UPDATES = 0x00;
/**
* Receive callbacks for {@link #onProgressUpdated}.
*/
public static final int PROGRESS_UPDATES = 0x01;
/**
* Receive callbacks for {@link #onStateUpdated}.
*/
public static final int STATE_UPDATES = 0x02;
private final int mCallbackFilterFlags;
/**
* Creates a DownloadStateCallback that will receive all callbacks.
*/
public DownloadStateCallback() {
mCallbackFilterFlags = ALL_UPDATES;
}
/**
* Creates a DownloadStateCallback that will only receive callbacks for the methods specified
* via the filterFlags parameter.
* @param filterFlags A bitmask of filter flags that will specify which callback this instance
* is interested in.
*/
public DownloadStateCallback(int filterFlags) {
mCallbackFilterFlags = filterFlags;
}
/**
* Return the currently set filter flags.
* @return An integer containing the bitmask of flags that this instance is interested in.
* @hide
*/
public int getCallbackFilterFlags() {
return mCallbackFilterFlags;
}
/**
* Returns true if a filter flag is set for a particular callback method. If the flag is set,
* the callback will be delivered to the listening process.
* @param flag A filter flag specifying whether or not a callback method is registered to
* receive callbacks.
* @return true if registered to receive callbacks in the listening process, false if not.
*/
public final boolean isFilterFlagSet(@FilterFlag int flag) {
if (mCallbackFilterFlags == ALL_UPDATES) {
return true;
}
return (mCallbackFilterFlags & flag) > 0;
}
/**
* Called when the middleware wants to report progress for a file in a {@link DownloadRequest}.
*
* @param request a {@link DownloadRequest}, indicating which download is being referenced.
* @param fileInfo a {@link FileInfo} specifying the file to report progress on. Note that
* the request may result in many files being downloaded and the client
* may not have been able to get a list of them in advance.
* @param currentDownloadSize is the current amount downloaded.
* @param fullDownloadSize is the total number of bytes that make up the downloaded content.
* This may be different from the decoded final size, but is useful in gauging download
* progress.
* @param currentDecodedSize is the number of bytes that have been decoded.
* @param fullDecodedSize is the total number of bytes that make up the final decoded content.
*/
public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
int currentDownloadSize, int fullDownloadSize,
int currentDecodedSize, int fullDecodedSize) {
}
/**
* Gives download state callbacks for a file in a {@link DownloadRequest}.
*
* @param request a {@link DownloadRequest}, indicating which download is being referenced.
* @param fileInfo a {@link FileInfo} specifying the file to report progress on. Note that
* the request may result in many files being downloaded and the client
* may not have been able to get a list of them in advance.
* @param state The current state of the download.
*/
public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
@MbmsDownloadSession.DownloadStatus int state) {
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.mbms;
import android.annotation.IntDef;
import android.telephony.MbmsDownloadSession;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* A optional listener class used by download clients to track progress. Apps should extend this
* class and pass an instance into
* {@link MbmsDownloadSession#download(DownloadRequest)}
*
* This is optionally specified when requesting a download and will only be called while the app
* is running.
*/
public class DownloadStatusListener {
/**
* Gives download status callbacks for a file in a {@link DownloadRequest}.
*
* @param request a {@link DownloadRequest}, indicating which download is being referenced.
* @param fileInfo a {@link FileInfo} specifying the file to report progress on. Note that
* the request may result in many files being downloaded and the client
* may not have been able to get a list of them in advance.
* @param status The current status of the download.
*/
public void onStatusUpdated(DownloadRequest request, FileInfo fileInfo,
@MbmsDownloadSession.DownloadStatus int status) {
}
}

View File

@@ -23,7 +23,7 @@ import android.telephony.mbms.FileInfo;
* The optional interface used by download clients to track progress.
* @hide
*/
interface IDownloadStateCallback
interface IDownloadProgressListener
{
/**
* Gives progress callbacks for a given DownloadRequest. Includes a FileInfo
@@ -32,6 +32,4 @@ interface IDownloadStateCallback
void onProgressUpdated(in DownloadRequest request, in FileInfo fileInfo,
int currentDownloadSize, int fullDownloadSize,
int currentDecodedSize, int fullDecodedSize);
void onStateUpdated(in DownloadRequest request, in FileInfo fileInfo, int state);
}

View File

@@ -0,0 +1,29 @@
/*
** Copyright 2017, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
package android.telephony.mbms;
import android.telephony.mbms.DownloadRequest;
import android.telephony.mbms.FileInfo;
/**
* The optional interface used by download clients to track download status.
* @hide
*/
interface IDownloadStatusListener
{
void onStatusUpdated(in DownloadRequest request, in FileInfo fileInfo, int status);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 The Android Open Source Project
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,13 +24,14 @@ import java.util.concurrent.Executor;
/**
* @hide
*/
public class InternalDownloadStateCallback extends IDownloadStateCallback.Stub {
public class InternalDownloadProgressListener extends IDownloadProgressListener.Stub {
private final Executor mExecutor;
private final DownloadStateCallback mAppCallback;
private final DownloadProgressListener mAppListener;
private volatile boolean mIsStopped = false;
public InternalDownloadStateCallback(DownloadStateCallback appCallback, Executor executor) {
mAppCallback = appCallback;
public InternalDownloadProgressListener(DownloadProgressListener appListener,
Executor executor) {
mAppListener = appListener;
mExecutor = executor;
}
@@ -47,7 +48,7 @@ public class InternalDownloadStateCallback extends IDownloadStateCallback.Stub {
public void run() {
long token = Binder.clearCallingIdentity();
try {
mAppCallback.onProgressUpdated(request, fileInfo, currentDownloadSize,
mAppListener.onProgressUpdated(request, fileInfo, currentDownloadSize,
fullDownloadSize, currentDecodedSize, fullDecodedSize);
} finally {
Binder.restoreCallingIdentity(token);
@@ -56,26 +57,6 @@ public class InternalDownloadStateCallback extends IDownloadStateCallback.Stub {
});
}
@Override
public void onStateUpdated(final DownloadRequest request, final FileInfo fileInfo,
final int state) throws RemoteException {
if (mIsStopped) {
return;
}
mExecutor.execute(new Runnable() {
@Override
public void run() {
long token = Binder.clearCallingIdentity();
try {
mAppCallback.onStateUpdated(request, fileInfo, state);
} finally {
Binder.restoreCallingIdentity(token);
}
}
});
}
public void stop() {
mIsStopped = true;
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package android.telephony.mbms;
import android.os.Binder;
import android.os.RemoteException;
import android.telephony.MbmsDownloadSession;
import java.util.concurrent.Executor;
/**
* @hide
*/
public class InternalDownloadStatusListener extends IDownloadStatusListener.Stub {
private final Executor mExecutor;
private final DownloadStatusListener mAppListener;
private volatile boolean mIsStopped = false;
public InternalDownloadStatusListener(DownloadStatusListener appCallback, Executor executor) {
mAppListener = appCallback;
mExecutor = executor;
}
@Override
public void onStatusUpdated(final DownloadRequest request, final FileInfo fileInfo,
@MbmsDownloadSession.DownloadStatus final int status) throws RemoteException {
if (mIsStopped) {
return;
}
mExecutor.execute(new Runnable() {
@Override
public void run() {
long token = Binder.clearCallingIdentity();
try {
mAppListener.onStatusUpdated(request, fileInfo, status);
} finally {
Binder.restoreCallingIdentity(token);
}
}
});
}
public void stop() {
mIsStopped = true;
}
}

View File

@@ -20,8 +20,9 @@ import android.app.PendingIntent;
import android.net.Uri;
import android.telephony.mbms.DownloadRequest;
import android.telephony.mbms.FileInfo;
import android.telephony.mbms.IDownloadProgressListener;
import android.telephony.mbms.IDownloadStatusListener;
import android.telephony.mbms.IMbmsDownloadSessionCallback;
import android.telephony.mbms.IDownloadStateCallback;
/**
* @hide
@@ -36,11 +37,17 @@ interface IMbmsDownloadService
int download(in DownloadRequest downloadRequest);
int registerStateCallback(in DownloadRequest downloadRequest, IDownloadStateCallback listener,
int flags);
int addStatusListener(in DownloadRequest downloadRequest,
IDownloadStatusListener listener);
int unregisterStateCallback(in DownloadRequest downloadRequest,
IDownloadStateCallback listener);
int removeStatusListener(in DownloadRequest downloadRequest,
IDownloadStatusListener listener);
int addProgressListener(in DownloadRequest downloadRequest,
IDownloadProgressListener listener);
int removeProgressListener(in DownloadRequest downloadRequest,
IDownloadProgressListener listener);
List<DownloadRequest> listPendingDownloads(int subscriptionId);

View File

@@ -24,11 +24,13 @@ import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.telephony.MbmsDownloadSession;
import android.telephony.mbms.DownloadProgressListener;
import android.telephony.mbms.DownloadRequest;
import android.telephony.mbms.DownloadStateCallback;
import android.telephony.mbms.DownloadStatusListener;
import android.telephony.mbms.FileInfo;
import android.telephony.mbms.FileServiceInfo;
import android.telephony.mbms.IDownloadStateCallback;
import android.telephony.mbms.IDownloadProgressListener;
import android.telephony.mbms.IDownloadStatusListener;
import android.telephony.mbms.IMbmsDownloadSessionCallback;
import android.telephony.mbms.MbmsDownloadSessionCallback;
import android.telephony.mbms.MbmsErrors;
@@ -45,47 +47,50 @@ import java.util.Map;
@SystemApi
@TestApi
public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
private final Map<IBinder, DownloadStateCallback> mDownloadCallbackBinderMap = new HashMap<>();
private final Map<IBinder, DownloadStatusListener> mDownloadStatusListenerBinderMap =
new HashMap<>();
private final Map<IBinder, DownloadProgressListener> mDownloadProgressListenerBinderMap =
new HashMap<>();
private final Map<IBinder, DeathRecipient> mDownloadCallbackDeathRecipients = new HashMap<>();
private abstract static class VendorDownloadStatusListener extends DownloadStatusListener {
private final IDownloadStatusListener mListener;
public VendorDownloadStatusListener(IDownloadStatusListener listener) {
mListener = listener;
}
// Filters the DownloadStateCallbacks by its configuration from the app.
private abstract static class FilteredDownloadStateCallback extends DownloadStateCallback {
@Override
public void onStatusUpdated(DownloadRequest request, FileInfo fileInfo,
@MbmsDownloadSession.DownloadStatus int state) {
try {
mListener.onStatusUpdated(request, fileInfo, state);
} catch (RemoteException e) {
onRemoteException(e);
}
}
private final IDownloadStateCallback mCallback;
public FilteredDownloadStateCallback(IDownloadStateCallback callback, int callbackFlags) {
super(callbackFlags);
mCallback = callback;
protected abstract void onRemoteException(RemoteException e);
}
private abstract static class VendorDownloadProgressListener extends DownloadProgressListener {
private final IDownloadProgressListener mListener;
public VendorDownloadProgressListener(IDownloadProgressListener listener) {
mListener = listener;
}
@Override
public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
int currentDownloadSize, int fullDownloadSize, int currentDecodedSize,
int fullDecodedSize) {
if (!isFilterFlagSet(PROGRESS_UPDATES)) {
return;
}
try {
mCallback.onProgressUpdated(request, fileInfo, currentDownloadSize,
mListener.onProgressUpdated(request, fileInfo, currentDownloadSize,
fullDownloadSize, currentDecodedSize, fullDecodedSize);
} catch (RemoteException e) {
onRemoteException(e);
}
}
@Override
public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
@MbmsDownloadSession.DownloadStatus int state) {
if (!isFilterFlagSet(STATE_UPDATES)) {
return;
}
try {
mCallback.onStateUpdated(request, fileInfo, state);
} catch (RemoteException e) {
onRemoteException(e);
}
}
protected abstract void onRemoteException(RemoteException e);
}
@@ -223,71 +228,70 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
}
/**
* Registers a download state callbacks for the provided {@link DownloadRequest}.
* Registers a download status listener 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.
* This method is called by the app when it wants to request updates on the 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.
* @param listener The listener object to use.
*/
public int registerStateCallback(DownloadRequest downloadRequest,
DownloadStateCallback callback) throws RemoteException {
public int addStatusListener(DownloadRequest downloadRequest,
DownloadStatusListener listener) throws RemoteException {
return 0;
}
/**
* Actual AIDL implementation -- hides the callback AIDL from the API.
* Actual AIDL implementation -- hides the listener AIDL from the API.
* @hide
*/
@Override
public final int registerStateCallback(final DownloadRequest downloadRequest,
final IDownloadStateCallback callback, int flags) throws RemoteException {
public final int addStatusListener(final DownloadRequest downloadRequest,
final IDownloadStatusListener listener) throws RemoteException {
final int uid = Binder.getCallingUid();
if (downloadRequest == null) {
throw new NullPointerException("Download request must not be null");
}
if (callback == null) {
if (listener == null) {
throw new NullPointerException("Callback must not be null");
}
DownloadStateCallback exposedCallback = new FilteredDownloadStateCallback(callback, flags) {
DownloadStatusListener exposedCallback = new VendorDownloadStatusListener(listener) {
@Override
protected void onRemoteException(RemoteException e) {
onAppCallbackDied(uid, downloadRequest.getSubscriptionId());
}
};
int result = registerStateCallback(downloadRequest, exposedCallback);
int result = addStatusListener(downloadRequest, exposedCallback);
if (result == MbmsErrors.SUCCESS) {
DeathRecipient deathRecipient = new DeathRecipient() {
@Override
public void binderDied() {
onAppCallbackDied(uid, downloadRequest.getSubscriptionId());
mDownloadCallbackBinderMap.remove(callback.asBinder());
mDownloadCallbackDeathRecipients.remove(callback.asBinder());
mDownloadStatusListenerBinderMap.remove(listener.asBinder());
mDownloadCallbackDeathRecipients.remove(listener.asBinder());
}
};
mDownloadCallbackDeathRecipients.put(callback.asBinder(), deathRecipient);
callback.asBinder().linkToDeath(deathRecipient, 0);
mDownloadCallbackBinderMap.put(callback.asBinder(), exposedCallback);
mDownloadCallbackDeathRecipients.put(listener.asBinder(), deathRecipient);
listener.asBinder().linkToDeath(deathRecipient, 0);
mDownloadStatusListenerBinderMap.put(listener.asBinder(), exposedCallback);
}
return result;
}
/**
* Un-registers a download state callbacks for the provided {@link DownloadRequest}.
* Un-registers a download status listener for the provided {@link DownloadRequest}.
*
* This method is called by the app when it no longer wants to request updates on the
* This method is called by the app when it no longer wants to request status updates on the
* download.
*
* If the middleware is not aware of a download having been requested with the provided
@@ -296,45 +300,157 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
* 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)}
* @param listener The callback object that
* {@link #addStatusListener(DownloadRequest, DownloadStatusListener)}
* was called with.
*/
public int unregisterStateCallback(DownloadRequest downloadRequest,
DownloadStateCallback callback) throws RemoteException {
public int removeStatusListener(DownloadRequest downloadRequest,
DownloadStatusListener listener) throws RemoteException {
return 0;
}
/**
* Actual AIDL implementation -- hides the callback AIDL from the API.
* Actual AIDL implementation -- hides the listener AIDL from the API.
* @hide
*/
@Override
public final int unregisterStateCallback(
final DownloadRequest downloadRequest, final IDownloadStateCallback callback)
public final int removeStatusListener(
final DownloadRequest downloadRequest, final IDownloadStatusListener listener)
throws RemoteException {
if (downloadRequest == null) {
throw new NullPointerException("Download request must not be null");
}
if (callback == null) {
if (listener == null) {
throw new NullPointerException("Callback must not be null");
}
DeathRecipient deathRecipient =
mDownloadCallbackDeathRecipients.remove(callback.asBinder());
mDownloadCallbackDeathRecipients.remove(listener.asBinder());
if (deathRecipient == null) {
throw new IllegalArgumentException("Unknown callback");
throw new IllegalArgumentException("Unknown listener");
}
callback.asBinder().unlinkToDeath(deathRecipient, 0);
listener.asBinder().unlinkToDeath(deathRecipient, 0);
DownloadStateCallback exposedCallback =
mDownloadCallbackBinderMap.remove(callback.asBinder());
DownloadStatusListener exposedCallback =
mDownloadStatusListenerBinderMap.remove(listener.asBinder());
if (exposedCallback == null) {
throw new IllegalArgumentException("Unknown callback");
throw new IllegalArgumentException("Unknown listener");
}
return unregisterStateCallback(downloadRequest, exposedCallback);
return removeStatusListener(downloadRequest, exposedCallback);
}
/**
* Registers a download progress listener for the provided {@link DownloadRequest}.
*
* This method is called by the app when it wants to request updates on the progress 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 listener The listener object to use.
*/
public int addProgressListener(DownloadRequest downloadRequest,
DownloadProgressListener listener) throws RemoteException {
return 0;
}
/**
* Actual AIDL implementation -- hides the listener AIDL from the API.
* @hide
*/
@Override
public final int addProgressListener(final DownloadRequest downloadRequest,
final IDownloadProgressListener listener) throws RemoteException {
final int uid = Binder.getCallingUid();
if (downloadRequest == null) {
throw new NullPointerException("Download request must not be null");
}
if (listener == null) {
throw new NullPointerException("Callback must not be null");
}
DownloadProgressListener exposedCallback = new VendorDownloadProgressListener(listener) {
@Override
protected void onRemoteException(RemoteException e) {
onAppCallbackDied(uid, downloadRequest.getSubscriptionId());
}
};
int result = addProgressListener(downloadRequest, exposedCallback);
if (result == MbmsErrors.SUCCESS) {
DeathRecipient deathRecipient = new DeathRecipient() {
@Override
public void binderDied() {
onAppCallbackDied(uid, downloadRequest.getSubscriptionId());
mDownloadProgressListenerBinderMap.remove(listener.asBinder());
mDownloadCallbackDeathRecipients.remove(listener.asBinder());
}
};
mDownloadCallbackDeathRecipients.put(listener.asBinder(), deathRecipient);
listener.asBinder().linkToDeath(deathRecipient, 0);
mDownloadProgressListenerBinderMap.put(listener.asBinder(), exposedCallback);
}
return result;
}
/**
* Un-registers a download progress listener for the provided {@link DownloadRequest}.
*
* This method is called by the app when it no longer wants to request progress 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 listener The callback object that
* {@link #addProgressListener(DownloadRequest, DownloadProgressListener)}
* was called with.
*/
public int removeProgressListener(DownloadRequest downloadRequest,
DownloadProgressListener listener) throws RemoteException {
return 0;
}
/**
* Actual AIDL implementation -- hides the listener AIDL from the API.
* @hide
*/
public final int removeProgressListener(
final DownloadRequest downloadRequest, final IDownloadProgressListener listener)
throws RemoteException {
if (downloadRequest == null) {
throw new NullPointerException("Download request must not be null");
}
if (listener == null) {
throw new NullPointerException("Callback must not be null");
}
DeathRecipient deathRecipient =
mDownloadCallbackDeathRecipients.remove(listener.asBinder());
if (deathRecipient == null) {
throw new IllegalArgumentException("Unknown listener");
}
listener.asBinder().unlinkToDeath(deathRecipient, 0);
DownloadProgressListener exposedCallback =
mDownloadProgressListenerBinderMap.remove(listener.asBinder());
if (exposedCallback == null) {
throw new IllegalArgumentException("Unknown listener");
}
return removeProgressListener(downloadRequest, exposedCallback);
}
/**