summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/providers/downloads/Constants.java3
-rw-r--r--src/com/android/providers/downloads/DownloadNotifier.java31
-rw-r--r--src/com/android/providers/downloads/DownloadReceiver.java28
-rw-r--r--tests/src/com/android/providers/downloads/AbstractDownloadProviderFunctionalTest.java11
-rw-r--r--tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java22
5 files changed, 93 insertions, 2 deletions
diff --git a/src/com/android/providers/downloads/Constants.java b/src/com/android/providers/downloads/Constants.java
index 7b8fcd24..6cea8086 100644
--- a/src/com/android/providers/downloads/Constants.java
+++ b/src/com/android/providers/downloads/Constants.java
@@ -54,6 +54,9 @@ public class Constants {
/** the intent that gets sent when clicking an incomplete/failed download */
public static final String ACTION_LIST = "android.intent.action.DOWNLOAD_LIST";
+ /** the intent that gets sent when canceling a download */
+ public static final String ACTION_CANCEL = "android.intent.action.DOWNLOAD_CANCEL";
+
/** the intent that gets sent when deleting the notification of a completed download */
public static final String ACTION_HIDE = "android.intent.action.DOWNLOAD_HIDE";
diff --git a/src/com/android/providers/downloads/DownloadNotifier.java b/src/com/android/providers/downloads/DownloadNotifier.java
index 60c249f9..2ff8b634 100644
--- a/src/com/android/providers/downloads/DownloadNotifier.java
+++ b/src/com/android/providers/downloads/DownloadNotifier.java
@@ -122,6 +122,15 @@ public class DownloadNotifier {
}
}
+ private static boolean isClusterDeleted(Collection<DownloadInfo> cluster) {
+ boolean wasDeleted = true;
+ for (DownloadInfo info : cluster) {
+ wasDeleted = wasDeleted && info.mDeleted;
+ }
+
+ return wasDeleted;
+ }
+
private void updateWithLocked(Collection<DownloadInfo> downloads) {
final Resources res = mContext.getResources();
@@ -139,6 +148,11 @@ public class DownloadNotifier {
final int type = getNotificationTagType(tag);
final Collection<DownloadInfo> cluster = clustered.get(tag);
+ // If each of the downloads was canceled, don't show notification for the cluster
+ if (isClusterDeleted(cluster)) {
+ continue;
+ }
+
final Notification.Builder builder = new Notification.Builder(mContext);
builder.setColor(res.getColor(
com.android.internal.R.color.system_notification_accent_color));
@@ -164,16 +178,31 @@ public class DownloadNotifier {
// Build action intents
if (type == TYPE_ACTIVE || type == TYPE_WAITING) {
+ long[] downloadIds = getDownloadIds(cluster);
+
// build a synthetic uri for intent identification purposes
final Uri uri = new Uri.Builder().scheme("active-dl").appendPath(tag).build();
final Intent intent = new Intent(Constants.ACTION_LIST,
uri, mContext, DownloadReceiver.class);
intent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS,
- getDownloadIds(cluster));
+ downloadIds);
builder.setContentIntent(PendingIntent.getBroadcast(mContext,
0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
builder.setOngoing(true);
+ // Add a Cancel action
+ final Uri cancelUri = new Uri.Builder().scheme("cancel-dl").appendPath(tag).build();
+ final Intent cancelIntent = new Intent(Constants.ACTION_CANCEL,
+ cancelUri, mContext, DownloadReceiver.class);
+ cancelIntent.putExtra(DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_IDS, downloadIds);
+ cancelIntent.putExtra(DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_NOTIFICATION_TAG, tag);
+
+ builder.addAction(
+ android.R.drawable.ic_menu_close_clear_cancel,
+ res.getString(R.string.button_cancel_download),
+ PendingIntent.getBroadcast(mContext,
+ 0, cancelIntent, PendingIntent.FLAG_UPDATE_CURRENT));
+
} else if (type == TYPE_COMPLETE) {
final DownloadInfo info = cluster.iterator().next();
final Uri uri = ContentUris.withAppendedId(
diff --git a/src/com/android/providers/downloads/DownloadReceiver.java b/src/com/android/providers/downloads/DownloadReceiver.java
index 28e2a673..2f50dcf6 100644
--- a/src/com/android/providers/downloads/DownloadReceiver.java
+++ b/src/com/android/providers/downloads/DownloadReceiver.java
@@ -21,6 +21,7 @@ import static android.app.DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_ONLY
import static com.android.providers.downloads.Constants.TAG;
import android.app.DownloadManager;
+import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -45,6 +46,21 @@ import com.google.common.annotations.VisibleForTesting;
* Receives system broadcasts (boot, network connectivity)
*/
public class DownloadReceiver extends BroadcastReceiver {
+ /**
+ * Intent extra included with {@link #ACTION_CANCEL} intents, indicating the IDs (as array of
+ * long) of the downloads that were canceled.
+ */
+ public static final String EXTRA_CANCELED_DOWNLOAD_IDS =
+ "com.android.providers.downloads.extra.CANCELED_DOWNLOAD_IDS";
+
+ /**
+ * Intent extra included with {@link #ACTION_CANCEL} intents, indicating the tag of the
+ * notification corresponding to the download(s) that were canceled; this notification must be
+ * canceled.
+ */
+ public static final String EXTRA_CANCELED_DOWNLOAD_NOTIFICATION_TAG =
+ "com.android.providers.downloads.extra.CANCELED_DOWNLOAD_NOTIFICATION_TAG";
+
private static Handler sAsyncHandler;
static {
@@ -107,6 +123,18 @@ public class DownloadReceiver extends BroadcastReceiver {
}
});
}
+ } else if (Constants.ACTION_CANCEL.equals(action)) {
+ long[] downloadIds = intent.getLongArrayExtra(
+ DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_IDS);
+ DownloadManager manager = (DownloadManager) context.getSystemService(
+ Context.DOWNLOAD_SERVICE);
+ manager.remove(downloadIds);
+
+ String notifTag = intent.getStringExtra(
+ DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_NOTIFICATION_TAG);
+ NotificationManager notifManager = (NotificationManager) context.getSystemService(
+ Context.NOTIFICATION_SERVICE);
+ notifManager.cancel(notifTag, 0);
}
}
diff --git a/tests/src/com/android/providers/downloads/AbstractDownloadProviderFunctionalTest.java b/tests/src/com/android/providers/downloads/AbstractDownloadProviderFunctionalTest.java
index 28c5dc7d..6934b86d 100644
--- a/tests/src/com/android/providers/downloads/AbstractDownloadProviderFunctionalTest.java
+++ b/tests/src/com/android/providers/downloads/AbstractDownloadProviderFunctionalTest.java
@@ -18,11 +18,13 @@ package com.android.providers.downloads;
import static org.mockito.Mockito.mock;
+import android.app.DownloadManager;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ProviderInfo;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
@@ -99,6 +101,7 @@ public abstract class AbstractDownloadProviderFunctionalTest extends
private final ContentResolver mResolver;
private final NotificationManager mNotifManager;
+ private final DownloadManager mDownloadManager;
boolean mHasServiceBeenStarted = false;
@@ -106,6 +109,7 @@ public abstract class AbstractDownloadProviderFunctionalTest extends
super(realContext, FILENAME_PREFIX);
mResolver = new MockContentResolverWithNotify(this);
mNotifManager = mock(NotificationManager.class);
+ mDownloadManager = mock(DownloadManager.class);
}
/**
@@ -123,6 +127,8 @@ public abstract class AbstractDownloadProviderFunctionalTest extends
public Object getSystemService(String name) {
if (Context.NOTIFICATION_SERVICE.equals(name)) {
return mNotifManager;
+ } else if (Context.DOWNLOAD_SERVICE.equals(name)) {
+ return mDownloadManager;
}
return super.getSystemService(name);
@@ -162,7 +168,10 @@ public abstract class AbstractDownloadProviderFunctionalTest extends
final DownloadProvider provider = new DownloadProvider();
provider.mSystemFacade = mSystemFacade;
- provider.attachInfo(mTestContext, null);
+
+ ProviderInfo info = new ProviderInfo();
+ info.authority = "downloads";
+ provider.attachInfo(mTestContext, info);
mResolver.addProvider(PROVIDER_AUTHORITY, provider);
diff --git a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java
index d1048b02..17fed6d0 100644
--- a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java
+++ b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java
@@ -49,6 +49,8 @@ import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.Suppress;
import android.text.format.DateUtils;
+import com.android.providers.downloads.Constants;
+import com.android.providers.downloads.DownloadReceiver;
import com.google.mockwebserver.MockResponse;
import com.google.mockwebserver.RecordedRequest;
import com.google.mockwebserver.SocketPolicy;
@@ -71,6 +73,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
protected File mTestDirectory;
private NotificationManager mNotifManager;
+ private DownloadManager mDownloadManager;
public PublicApiFunctionalTest() {
super(new FakeSystemFacade());
@@ -82,6 +85,8 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
mNotifManager = (NotificationManager) getContext()
.getSystemService(Context.NOTIFICATION_SERVICE);
+ mDownloadManager = (DownloadManager) getContext()
+ .getSystemService(Context.DOWNLOAD_SERVICE);
mTestDirectory = new File(Environment.getExternalStorageDirectory() + File.separator
+ "download_manager_functional_test");
@@ -552,6 +557,23 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
assertEquals(PACKAGE_NAME, broadcast.getPackage());
}
+ public void testNotificationCancelDownloadClicked() throws Exception {
+ Download download = enqueueRequest(getRequest());
+
+ DownloadReceiver receiver = new DownloadReceiver();
+ receiver.mSystemFacade = mSystemFacade;
+ Intent intent = new Intent(Constants.ACTION_CANCEL);
+ intent.setData(Uri.parse(Downloads.Impl.CONTENT_URI + "/" + download.mId));
+
+ long[] downloadIds = {download.mId};
+ intent.putExtra(DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_IDS, downloadIds);
+ intent.putExtra(DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_NOTIFICATION_TAG, "tag");
+ receiver.onReceive(mContext, intent);
+
+ verify(mNotifManager, times(1)).cancel("tag", 0);
+ verify(mDownloadManager, times(1)).remove(downloadIds);
+ }
+
public void testBasicConnectivityChanges() throws Exception {
enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));