From 7953997160c032d1fa1d2b09636cd38787ba2909 Mon Sep 17 00:00:00 2001 From: Hall Liu Date: Mon, 19 Mar 2018 18:12:23 -0700 Subject: [PATCH] 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 --- Android.bp | 3 +- api/current.txt | 23 +- api/system-current.txt | 6 +- api/test-current.txt | 6 +- .../telephony/MbmsDownloadSession.java | 160 +++++++++--- .../mbms/DownloadProgressListener.java | 48 ++++ .../telephony/mbms/DownloadStateCallback.java | 131 ---------- .../mbms/DownloadStatusListener.java | 46 ++++ ...ck.aidl => IDownloadProgressListener.aidl} | 4 +- .../mbms/IDownloadStatusListener.aidl | 29 +++ ... => InternalDownloadProgressListener.java} | 33 +-- .../mbms/InternalDownloadStatusListener.java | 61 +++++ .../mbms/vendor/IMbmsDownloadService.aidl | 17 +- .../mbms/vendor/MbmsDownloadServiceBase.java | 240 +++++++++++++----- 14 files changed, 533 insertions(+), 274 deletions(-) create mode 100644 telephony/java/android/telephony/mbms/DownloadProgressListener.java delete mode 100644 telephony/java/android/telephony/mbms/DownloadStateCallback.java create mode 100644 telephony/java/android/telephony/mbms/DownloadStatusListener.java rename telephony/java/android/telephony/mbms/{IDownloadStateCallback.aidl => IDownloadProgressListener.aidl} (90%) create mode 100755 telephony/java/android/telephony/mbms/IDownloadStatusListener.aidl rename telephony/java/android/telephony/mbms/{InternalDownloadStateCallback.java => InternalDownloadProgressListener.java} (62%) create mode 100644 telephony/java/android/telephony/mbms/InternalDownloadStatusListener.java diff --git a/Android.bp b/Android.bp index 1b9210cc39f23..dd3c494fdbc17 100644 --- a/Android.bp +++ b/Android.bp @@ -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", diff --git a/api/current.txt b/api/current.txt index 2113d5d54f599..8ed664dc43987 100644 --- a/api/current.txt +++ b/api/current.txt @@ -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 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); 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 { diff --git a/api/system-current.txt b/api/system-current.txt index 0555263090932..6de3bd5cf763f 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -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 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) 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 { diff --git a/api/test-current.txt b/api/test-current.txt index 2559d24f3452f..7a447596900f0 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -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 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) 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 { diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java index ce1b80c2c8605..b6cdb3bc8edee 100644 --- a/telephony/java/android/telephony/MbmsDownloadSession.java +++ b/telephony/java/android/telephony/MbmsDownloadSession.java @@ -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 mService = new AtomicReference<>(null); private final InternalDownloadSessionCallback mInternalCallback; - private final Map - mInternalDownloadCallbacks = new HashMap<>(); + private final Map + mInternalDownloadStatusListeners = new HashMap<>(); + private final Map + 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 diff --git a/telephony/java/android/telephony/mbms/DownloadProgressListener.java b/telephony/java/android/telephony/mbms/DownloadProgressListener.java new file mode 100644 index 0000000000000..4301cb1de0148 --- /dev/null +++ b/telephony/java/android/telephony/mbms/DownloadProgressListener.java @@ -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) { + } +} diff --git a/telephony/java/android/telephony/mbms/DownloadStateCallback.java b/telephony/java/android/telephony/mbms/DownloadStateCallback.java deleted file mode 100644 index 9f60cc36a3069..0000000000000 --- a/telephony/java/android/telephony/mbms/DownloadStateCallback.java +++ /dev/null @@ -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) { - } -} diff --git a/telephony/java/android/telephony/mbms/DownloadStatusListener.java b/telephony/java/android/telephony/mbms/DownloadStatusListener.java new file mode 100644 index 0000000000000..ca77932fdefdb --- /dev/null +++ b/telephony/java/android/telephony/mbms/DownloadStatusListener.java @@ -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) { + } +} diff --git a/telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl b/telephony/java/android/telephony/mbms/IDownloadProgressListener.aidl similarity index 90% rename from telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl rename to telephony/java/android/telephony/mbms/IDownloadProgressListener.aidl index cebc70d3e884e..d0adcb5f4862b 100755 --- a/telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl +++ b/telephony/java/android/telephony/mbms/IDownloadProgressListener.aidl @@ -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); } diff --git a/telephony/java/android/telephony/mbms/IDownloadStatusListener.aidl b/telephony/java/android/telephony/mbms/IDownloadStatusListener.aidl new file mode 100755 index 0000000000000..799290afc9b78 --- /dev/null +++ b/telephony/java/android/telephony/mbms/IDownloadStatusListener.aidl @@ -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); +} diff --git a/telephony/java/android/telephony/mbms/InternalDownloadStateCallback.java b/telephony/java/android/telephony/mbms/InternalDownloadProgressListener.java similarity index 62% rename from telephony/java/android/telephony/mbms/InternalDownloadStateCallback.java rename to telephony/java/android/telephony/mbms/InternalDownloadProgressListener.java index f30ae27b19b1e..403f758a1996c 100644 --- a/telephony/java/android/telephony/mbms/InternalDownloadStateCallback.java +++ b/telephony/java/android/telephony/mbms/InternalDownloadProgressListener.java @@ -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; } diff --git a/telephony/java/android/telephony/mbms/InternalDownloadStatusListener.java b/telephony/java/android/telephony/mbms/InternalDownloadStatusListener.java new file mode 100644 index 0000000000000..ad6bb54ad8fa2 --- /dev/null +++ b/telephony/java/android/telephony/mbms/InternalDownloadStatusListener.java @@ -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; + } +} diff --git a/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl b/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl index 7d9845ff46d21..445087fb78d57 100755 --- a/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl +++ b/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl @@ -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 listPendingDownloads(int subscriptionId); diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java index 86b1b7aff82c1..f9d7161021e91 100644 --- a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java +++ b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java @@ -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 mDownloadCallbackBinderMap = new HashMap<>(); + private final Map mDownloadStatusListenerBinderMap = + new HashMap<>(); + private final Map mDownloadProgressListenerBinderMap = + new HashMap<>(); private final Map 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); } /**